From 2c2a030c9bcafa165faee55870a69f50bb8a09e7 Mon Sep 17 00:00:00 2001 From: Stefan Persson Date: Tue, 19 Oct 2010 12:31:32 +0000 Subject: [PATCH] Callback events implemented on client side (not tested for device and raw events) --- telldus-core/client/Client.cpp | 79 ++++++++++++++++++++- telldus-core/client/Client.h | 13 +++- telldus-core/common/Socket.h | 1 + telldus-core/common/Socket_win.cpp | 30 ++++++-- telldus-core/service/DeviceManager.cpp | 2 +- telldus-core/service/EventUpdateManager.cpp | 2 +- telldus-core/service/EventUpdateManager.h | 2 +- telldus-core/service/TelldusMain.cpp | 2 - 8 files changed, 115 insertions(+), 16 deletions(-) diff --git a/telldus-core/client/Client.cpp b/telldus-core/client/Client.cpp index 3e8a2765..c187b072 100644 --- a/telldus-core/client/Client.cpp +++ b/telldus-core/client/Client.cpp @@ -1,5 +1,6 @@ #include "Client.h" #include "Socket.h" +#include "Mutex.h" #include @@ -19,22 +20,33 @@ typedef std::list RawDeviceEventList; class Client::PrivateData { public: - Socket eventSocket; int lastCallbackId; DeviceEventList deviceEventList; DeviceChangeList deviceChangeEventList; + Socket eventSocket; RawDeviceEventList rawDeviceEventList; + bool running; + TelldusCore::Mutex mutex; }; Client *Client::instance = 0; -Client::Client() { +Client::Client() + : Thread() +{ d = new PrivateData; d->lastCallbackId = 0; - d->eventSocket.connect(L"TelldusEvents"); + d->running = true; + start(); } Client::~Client(void) { + stopThread(); + wait(); + { + TelldusCore::MutexLocker locker(&d->mutex); + } + //TODO empty event lists? delete d; } @@ -51,6 +63,27 @@ Client *Client::getInstance() { return Client::instance; } +void Client::callbackDeviceEvent(int deviceId, int deviceState, const std::wstring &deviceStateValue){ + TelldusCore::MutexLocker locker(&d->mutex); + for(DeviceEventList::const_iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { + (*callback_it).event(deviceId, deviceState, Message::wideToString(deviceStateValue).c_str(), (*callback_it).id, (*callback_it).context); + } +} + +void Client::callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int eventChangeType){ + TelldusCore::MutexLocker locker(&d->mutex); + for(DeviceChangeList::const_iterator callback_it = d->deviceChangeEventList.begin(); callback_it != d->deviceChangeEventList.end(); ++callback_it) { + (*callback_it).event(deviceId, eventDeviceChanges, eventChangeType, (*callback_it).id, (*callback_it).context); + } +} + +void Client::callbackRawEvent(std::wstring command, int controllerId){ + TelldusCore::MutexLocker locker(&d->mutex); + for(RawDeviceEventList::const_iterator callback_it = d->rawDeviceEventList.begin(); callback_it != d->rawDeviceEventList.end(); ++callback_it) { + (*callback_it).event(Message::wideToString(command).c_str(), controllerId, (*callback_it).id, (*callback_it).context); + } +} + bool Client::getBoolFromService(const Message &msg) { return getIntegerFromService(msg) == 1; } @@ -66,6 +99,7 @@ std::wstring Client::getWStringFromService(const Message &msg) { } int Client::registerDeviceEvent( TDDeviceEvent eventFunction, void *context ) { + TelldusCore::MutexLocker locker(&d->mutex); int id = ++d->lastCallbackId; DeviceEvent callback = {eventFunction, id, context}; d->deviceEventList.push_back(callback); @@ -73,6 +107,7 @@ int Client::registerDeviceEvent( TDDeviceEvent eventFunction, void *context ) { } int Client::registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ) { + TelldusCore::MutexLocker locker(&d->mutex); int id = ++d->lastCallbackId; DeviceChangeEvent callback = {eventFunction, id, context}; d->deviceChangeEventList.push_back(callback); @@ -80,12 +115,44 @@ int Client::registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void * } int Client::registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ) { + TelldusCore::MutexLocker locker(&d->mutex); int id = ++d->lastCallbackId; RawDeviceEvent callback = {eventFunction, id, context}; d->rawDeviceEventList.push_back(callback); return id; } +void Client::run(){ + //listen here + d->eventSocket.connect(L"TelldusEvents"); + + while(d->running && d->eventSocket.isConnected()){ + //TODO hm, isConnected, never gets the chance of reconnect here... Should maybe retry every something seconds + std::wstring clientMessage = d->eventSocket.read(); + if(clientMessage != L""){ + //a message arrived + std::wstring type = Message::takeString(&clientMessage); + if(type == L"TDDeviceChangeEvent"){ + int deviceId = Message::takeInt(&clientMessage); + int eventDeviceChanges = Message::takeInt(&clientMessage); + int eventChangeType = Message::takeInt(&clientMessage); + callbackDeviceChangeEvent(deviceId, eventDeviceChanges, eventChangeType); + } + else if(type == L"TDDeviceEvent"){ + int deviceId = Message::takeInt(&clientMessage); + int eventState = Message::takeInt(&clientMessage); + std::wstring eventValue = Message::takeString(&clientMessage); + callbackDeviceEvent(deviceId, eventState, eventValue); + } + else if(type == L"TDRawDeviceEvent"){ + std::wstring command = Message::takeString(&clientMessage); + int controllerId = Message::takeInt(&clientMessage); + callbackRawEvent(command, controllerId); + } + } + } +} + std::wstring Client::sendToService(const Message &msg) { Socket s; s.connect(L"TelldusClient"); @@ -94,7 +161,13 @@ std::wstring Client::sendToService(const Message &msg) { return s.read(); } +void Client::stopThread(){ + d->running = false; + d->eventSocket.stopReadWait(); +} + bool Client::unregisterCallback( int callbackId ) { + TelldusCore::MutexLocker locker(&d->mutex); for(DeviceEventList::iterator callback_it = d->deviceEventList.begin(); callback_it != d->deviceEventList.end(); ++callback_it) { if ( (*callback_it).id != callbackId ) { continue; diff --git a/telldus-core/client/Client.h b/telldus-core/client/Client.h index b1e57d1d..ad017212 100644 --- a/telldus-core/client/Client.h +++ b/telldus-core/client/Client.h @@ -3,24 +3,33 @@ #include "Message.h" #include "telldus-core.h" +#include "Thread.h" namespace TelldusCore { - class Client{ + class Client : public Thread + { public: ~Client(void); static Client *getInstance(); static void close(); - + + void callbackDeviceEvent(int deviceId, int deviceState, const std::wstring &deviceStateValue); + void callbackDeviceChangeEvent(int deviceId, int eventDeviceChanges, int eventChangeType); + void callbackRawEvent(std::wstring command, int controllerId); int registerDeviceEvent( TDDeviceEvent eventFunction, void *context ); int registerDeviceChangeEvent( TDDeviceChangeEvent eventFunction, void *context ); int registerRawDeviceEvent( TDRawDeviceEvent eventFunction, void *context ); + void stopThread(void); bool unregisterCallback( int callbackId ); static bool getBoolFromService(const Message &msg); static int getIntegerFromService(const Message &msg); static std::wstring getWStringFromService(const Message &msg); + protected: + void run(void); + private: Client(); static std::wstring sendToService(const Message &msg); diff --git a/telldus-core/common/Socket.h b/telldus-core/common/Socket.h index 3985bf26..a77270a4 100644 --- a/telldus-core/common/Socket.h +++ b/telldus-core/common/Socket.h @@ -21,6 +21,7 @@ namespace TelldusCore { void connect(const std::wstring &server); bool isConnected(); std::wstring read(); + void stopReadWait(); void write(const std::wstring &msg); private: diff --git a/telldus-core/common/Socket_win.cpp b/telldus-core/common/Socket_win.cpp index 5e8bfb4a..99a08234 100644 --- a/telldus-core/common/Socket_win.cpp +++ b/telldus-core/common/Socket_win.cpp @@ -11,13 +11,16 @@ using namespace TelldusCore; class Socket::PrivateData { public: HANDLE hPipe; + HANDLE readEvent; bool connected; + bool running; }; Socket::Socket() { d = new PrivateData; d->hPipe = INVALID_HANDLE_VALUE; d->connected = false; + d->running = true; } Socket::Socket(SOCKET_T hPipe) @@ -25,10 +28,13 @@ Socket::Socket(SOCKET_T hPipe) d = new PrivateData; d->hPipe = hPipe; d->connected = true; + d->running = true; } Socket::~Socket(void){ + d->running = false; + SetEvent(d->readEvent); //signal for break if (d->hPipe != INVALID_HANDLE_VALUE) { CloseHandle(d->hPipe); } @@ -66,33 +72,45 @@ void Socket::connect(const std::wstring &server){ d->connected = true; } +void Socket::stopReadWait(){ + d->running = false; + SetEvent(d->readEvent); +} + std::wstring Socket::read() { wchar_t buf[BUFSIZE]; int result; DWORD cbBytesRead = 0; OVERLAPPED oOverlap; - HANDLE readEvent = CreateEvent(NULL, TRUE, TRUE, NULL); - oOverlap.hEvent = readEvent; + + d->readEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + oOverlap.hEvent = d->readEvent; BOOL fSuccess = false; memset(&buf, 0, BUFSIZE); ReadFile( d->hPipe, &buf, sizeof(wchar_t)*BUFSIZE, &cbBytesRead, &oOverlap); - result = WaitForSingleObject(oOverlap.hEvent, 10000); + result = WaitForSingleObject(oOverlap.hEvent, 20000); + + if(!d->running){ + CloseHandle(d->readEvent); + return L""; + } + if (result == WAIT_TIMEOUT) { - CloseHandle(readEvent); + CloseHandle(d->readEvent); return L""; } fSuccess = GetOverlappedResult(d->hPipe, &oOverlap, &cbBytesRead, false); if (!fSuccess) { DWORD err = GetLastError(); if (err == ERROR_BROKEN_PIPE) { - //TODO: Connection closed + d->connected = false; } buf[0] = 0; } - CloseHandle(readEvent); + CloseHandle(d->readEvent); return buf; } diff --git a/telldus-core/service/DeviceManager.cpp b/telldus-core/service/DeviceManager.cpp index fd4ca387..56995c13 100644 --- a/telldus-core/service/DeviceManager.cpp +++ b/telldus-core/service/DeviceManager.cpp @@ -389,7 +389,7 @@ int DeviceManager::doAction(int deviceId, int action, unsigned char data){ EventUpdateData *eventData = new EventUpdateData(); eventData->messageType = L"TDDeviceEvent"; - eventData->eventMethod = action; + eventData->eventState = action; eventData->deviceId = deviceId; eventData->eventValue = datastring; d->deviceUpdateEvent->signal(eventData); diff --git a/telldus-core/service/EventUpdateManager.cpp b/telldus-core/service/EventUpdateManager.cpp index 41556ef9..09d66b1a 100644 --- a/telldus-core/service/EventUpdateManager.cpp +++ b/telldus-core/service/EventUpdateManager.cpp @@ -83,7 +83,7 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data){ if(data->messageType == L"TDDeviceEvent"){ msg.addArgument("TDDeviceEvent"); msg.addArgument(data->deviceId); - msg.addArgument(data->eventMethod); + msg.addArgument(data->eventState); msg.addArgument(data->eventValue); //string } else if(data->messageType == L"TDDeviceChangeEvent"){ diff --git a/telldus-core/service/EventUpdateManager.h b/telldus-core/service/EventUpdateManager.h index 85904544..c8d565f8 100644 --- a/telldus-core/service/EventUpdateManager.h +++ b/telldus-core/service/EventUpdateManager.h @@ -11,7 +11,7 @@ public: int deviceId; int eventChangeType; int eventDeviceChanges; - int eventMethod; + int eventState; std::wstring eventValue; }; diff --git a/telldus-core/service/TelldusMain.cpp b/telldus-core/service/TelldusMain.cpp index b89f25d3..156b60a6 100644 --- a/telldus-core/service/TelldusMain.cpp +++ b/telldus-core/service/TelldusMain.cpp @@ -8,7 +8,6 @@ #include #include -#include //TODO DEBUG class DeviceEventData : public EventDataBase { public: @@ -44,7 +43,6 @@ void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) { } void TelldusMain::start(void) { - Sleep(6000); Event *clientEvent = d->eventHandler.addEvent(); Event *updateEvent = d->eventHandler.addEvent();