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