
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.
339 lines
9.9 KiB
C++
339 lines
9.9 KiB
C++
#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 <map>
|
|
#include <stdio.h>
|
|
|
|
class ControllerDescriptor {
|
|
public:
|
|
std::wstring name, serial;
|
|
int type;
|
|
Controller *controller;
|
|
};
|
|
|
|
typedef std::map<int, ControllerDescriptor> 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<TellStick*>(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<TellStickDescriptor> list = TellStick::findAll();
|
|
|
|
std::list<TellStickDescriptor>::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<TellStick*>(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<TellStick *> 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<TellStick*>(it->second.controller);
|
|
if (tellstick) {
|
|
tellStickControllers.push_back(tellstick);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool reloadControllers = false;
|
|
std::string noop = "N+";
|
|
for(std::list<TellStick *>::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<TellStick*>(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"name") {
|
|
return it->second.name;
|
|
} 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);
|
|
}
|