339 lines
10 KiB
C++
339 lines
10 KiB
C++
//
|
|
// C++ Implementation: controller
|
|
//
|
|
// Description:
|
|
//
|
|
//
|
|
// Author: Micke Prag <micke.prag@telldus.se>, (C) 2009
|
|
//
|
|
// Copyright: See COPYING file that comes with this distribution
|
|
//
|
|
//
|
|
#include "Manager.h"
|
|
#include "Device.h"
|
|
|
|
#include "DeviceBrateck.h"
|
|
#include "DeviceEverflourish.h"
|
|
#include "DeviceGroup.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"
|
|
#ifdef TELLSTICK_DUO
|
|
#include "TellStick.h"
|
|
#endif
|
|
#include "common.h"
|
|
#include "config.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#ifdef _WINDOWS
|
|
#define strcasecmp _stricmp
|
|
#endif
|
|
|
|
|
|
using namespace TelldusCore;
|
|
|
|
Manager *Manager::instance = 0;
|
|
|
|
Manager::Manager()
|
|
: lastCallbackId(0)
|
|
{
|
|
#ifdef TELLSTICK_DUO
|
|
/* Controller *controller = TellStick::findFirstDevice();
|
|
if (controller) {
|
|
controllers[1] = controller;
|
|
}*/
|
|
#endif
|
|
}
|
|
|
|
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 );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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{
|
|
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 (0) {
|
|
#ifdef PROTOCOL_ARCTECH
|
|
} else 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"));
|
|
#endif
|
|
#ifdef PROTOCOL_BRATECK
|
|
} else if (strcasecmp(protocol.c_str(), "brateck") == 0) {
|
|
dev = new DeviceBrateck(intDeviceId, strModel, strName);
|
|
((DeviceBrateck*)dev)->setHouse(settings.getDeviceParameter(intDeviceId, "house"));
|
|
#endif
|
|
#ifdef PROTOCOL_EVERFLOURISH
|
|
} 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"));
|
|
#endif
|
|
#ifdef PROTOCOL_GROUP
|
|
} else if (strcasecmp(protocol.c_str(), "group") == 0) {
|
|
dev = new DeviceGroup(intDeviceId, strModel, strName);
|
|
((DeviceGroup*)dev)->setDevices(settings.getDeviceParameter(intDeviceId, "devices"));
|
|
#endif
|
|
#ifdef PROTOCOL_RISINGSUN
|
|
} 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"));
|
|
#endif
|
|
#ifdef PROTOCOL_WAVEMAN
|
|
} 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"));
|
|
#endif
|
|
#ifdef PROTOCOL_SARTANO
|
|
} else if (strcasecmp(protocol.c_str(), "Sartano") == 0) {
|
|
dev = new DeviceSartano(intDeviceId, strModel, strName);
|
|
((DeviceSartano*)dev)->setCode(settings.getDeviceParameter(intDeviceId, "code"));
|
|
#endif
|
|
#ifdef PROTOCOL_IKEA
|
|
} 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"));
|
|
#endif
|
|
#ifdef PROTOCOL_UPM
|
|
} 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"));
|
|
#endif
|
|
#ifdef PROTOCOL_X10
|
|
} 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"));
|
|
#endif
|
|
} 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) {
|
|
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 );
|
|
|
|
// 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;
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
bool Manager::setDeviceModel(int intDeviceId, const std::string &strModel) {
|
|
return settings.setModel(intDeviceId, strModel);
|
|
}
|
|
|
|
bool Manager::setDeviceState( int intDeviceId, int intDeviceState, const std::string &strDeviceStateValue ) {
|
|
if (intDeviceState != TELLSTICK_BELL &&
|
|
intDeviceState != TELLSTICK_LEARN
|
|
) {
|
|
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 {
|
|
DeviceMap::const_iterator iterator = devices.find(deviceId);
|
|
if (iterator == devices.end()) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void Manager::parseMessage( const std::string &message ) {
|
|
loadAllDevices(); //Make sure all devices is loaded before we iterator the list.
|
|
|
|
std::map<std::string, std::string> 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() & method)) {
|
|
continue;
|
|
}
|
|
bool found = true;
|
|
for (std::map<std::string, std::string>::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) {
|
|
//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(), (*it).id, (*it).context);
|
|
}
|
|
}
|
|
|
|
int Manager::registerDeviceEvent( TDDeviceEvent eventFunction, void *context ) {
|
|
int id = ++lastCallbackId;
|
|
CallbackStruct callback = {eventFunction, id, context};
|
|
callbacks.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;
|
|
}
|
|
|
|
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() {
|
|
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);
|
|
}
|
|
|