telldus/telldus-core/service/Device.cpp

253 lines
5.7 KiB
C++

#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<std::string> 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<TellStick *>(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;
}