telldus/driver/libtelldus-core/DeviceNexa.cpp

295 lines
6.6 KiB
C++

// #include "StdAfx.h"
#include "DeviceNexa.h"
#include <string.h>
#include <algorithm>
#include <bitset>
#include <iostream>
#include <fstream>
#include "common.h"
using namespace TelldusCore;
const char START[] = {'T',127,255,24,1,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(void){
if (strcasecmp(this->getModel().c_str(), "bell") == 0) {
return bell();
}
try{
std::string strCode = "";
if (isDimmer()) {
return dim(255);
} 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 Device::send(strCode);
}
catch(...){
throw;
}
return TELLSTICK_ERROR_UNKNOWN;
}
/*
* Turn off this device
*/
int DeviceNexa::turnOff(void){
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 Device::send(strCode);
}
catch(...){
throw;
}
return TELLSTICK_ERROR_UNKNOWN;
}
/*
* Dim this device
*/
int DeviceNexa::dim(unsigned char level) {
try{
std::string strMessage = "";
strMessage.append( 1, 'R' );
strMessage.append( 1, 5 );
strMessage.append(getStringSelflearning(true, level));
return Device::send(strMessage);
}
catch(...){
throw;
}
return TELLSTICK_ERROR_UNKNOWN;
}
/*
* Send a bell
*/
int DeviceNexa::bell(void){
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 Device::send(strCode);
}
catch(...){
throw;
}
return TELLSTICK_ERROR_UNKNOWN;
}
int DeviceNexa::learn(void){
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 = Device::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;
int v = 0;
if (m[i] == '1') {
code |= 8; //b1000
} else {
code |= 10; //b1010;
}
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 (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?
*/
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";
}