telldus/telldus-core/service/TelldusMain.cpp

147 lines
4.4 KiB
C++

//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/TelldusMain.h"
#include "service/ConnectionListener.h"
#include "common/EventHandler.h"
#include "service/ClientCommunicationHandler.h"
#include "service/DeviceManager.h"
#include "service/ControllerManager.h"
#include "service/ControllerListener.h"
#include "service/EventUpdateManager.h"
#include "service/Timer.h"
#include "service/Log.h"
#include <stdio.h>
#include <list>
#include <memory>
class TelldusMain::PrivateData {
public:
TelldusCore::EventHandler eventHandler;
TelldusCore::EventRef stopEvent, controllerChangeEvent;
};
TelldusMain::TelldusMain(void) {
d = new PrivateData;
d->stopEvent = d->eventHandler.addEvent();
d->controllerChangeEvent = d->eventHandler.addEvent();
}
TelldusMain::~TelldusMain(void) {
delete d;
}
void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) {
ControllerChangeEventData *data = new ControllerChangeEventData;
data->vid = vid;
data->pid = pid;
data->inserted = inserted;
d->controllerChangeEvent->signal(data);
}
void TelldusMain::resume() {
Log::notice("Came back from suspend");
ControllerChangeEventData *data = new ControllerChangeEventData;
data->vid = 0x0;
data->pid = 0x0;
data->inserted = true;
d->controllerChangeEvent->signal(data);
}
void TelldusMain::suspend() {
Log::notice("Preparing for suspend");
ControllerChangeEventData *data = new ControllerChangeEventData;
data->vid = 0x0;
data->pid = 0x0;
data->inserted = false;
d->controllerChangeEvent->signal(data);
}
void TelldusMain::start(void) {
TelldusCore::EventRef clientEvent = d->eventHandler.addEvent();
TelldusCore::EventRef dataEvent = d->eventHandler.addEvent();
TelldusCore::EventRef janitor = d->eventHandler.addEvent(); //Used for regular cleanups
Timer supervisor(janitor); //Tells the janitor to go back to work
supervisor.setInterval(60); //Once every minute
supervisor.start();
EventUpdateManager eventUpdateManager;
TelldusCore::EventRef deviceUpdateEvent = eventUpdateManager.retrieveUpdateEvent();
eventUpdateManager.start();
ControllerManager controllerManager(dataEvent, deviceUpdateEvent);
DeviceManager deviceManager(&controllerManager, deviceUpdateEvent);
ConnectionListener clientListener(L"TelldusClient", clientEvent);
std::list<ClientCommunicationHandler *> clientCommunicationHandlerList;
TelldusCore::EventRef handlerEvent = d->eventHandler.addEvent();
#ifdef _MACOSX
//This is only needed on OS X
ControllerListener controllerListener(d->controllerChangeEvent);
#endif
while(!d->stopEvent->isSignaled()) {
if (!d->eventHandler.waitForAny()) {
continue;
}
if (clientEvent->isSignaled()) {
//New client connection
TelldusCore::EventDataRef eventDataRef = clientEvent->takeSignal();
ConnectionListenerEventData *data = reinterpret_cast<ConnectionListenerEventData*>(eventDataRef.get());
if (data) {
ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager, deviceUpdateEvent, &controllerManager);
clientCommunication->start();
clientCommunicationHandlerList.push_back(clientCommunication);
}
}
if (d->controllerChangeEvent->isSignaled()) {
TelldusCore::EventDataRef eventDataRef = d->controllerChangeEvent->takeSignal();
ControllerChangeEventData *data = reinterpret_cast<ControllerChangeEventData*>(eventDataRef.get());
if (data) {
controllerManager.deviceInsertedOrRemoved(data->vid, data->pid, "", data->inserted);
}
}
if (dataEvent->isSignaled()) {
TelldusCore::EventDataRef eventData = dataEvent->takeSignal();
ControllerEventData *data = reinterpret_cast<ControllerEventData*>(eventData.get());
if (data) {
deviceManager.handleControllerMessage(*data);
}
}
if (handlerEvent->isSignaled()) {
handlerEvent->popSignal();
for ( std::list<ClientCommunicationHandler *>::iterator it = clientCommunicationHandlerList.begin(); it != clientCommunicationHandlerList.end(); ) {
if ((*it)->isDone()) {
delete *it;
it = clientCommunicationHandlerList.erase(it);
} else {
++it;
}
}
}
if (janitor->isSignaled()) {
//Clear all of them if there is more than one
while(janitor->isSignaled()) {
janitor->popSignal();
}
controllerManager.queryControllerStatus();
}
}
supervisor.stop();
}
void TelldusMain::stop(void) {
d->stopEvent->signal();
}