random ai stuff
This commit is contained in:
259
telldus-core/service/EventUpdateManager.cpp
Normal file
259
telldus-core/service/EventUpdateManager.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#include "service/EventUpdateManager.h"
|
||||
|
||||
#ifdef _LINUX
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#endif // _LINUX
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#ifdef _LINUX
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#endif // _LINUX
|
||||
|
||||
#include "common/EventHandler.h"
|
||||
#include "common/Message.h"
|
||||
#include "common/Socket.h"
|
||||
#include "common/Strings.h"
|
||||
#include "service/config.h"
|
||||
#include "service/ConnectionListener.h"
|
||||
#include "service/Log.h"
|
||||
|
||||
typedef std::list<TelldusCore::Socket *> SocketList;
|
||||
typedef std::list<std::string> StringList;
|
||||
|
||||
class EventUpdateManager::PrivateData {
|
||||
public:
|
||||
TelldusCore::EventHandler eventHandler;
|
||||
TelldusCore::EventRef stopEvent, updateEvent, clientConnectEvent;
|
||||
SocketList clients;
|
||||
ConnectionListener *eventUpdateClientListener;
|
||||
#ifdef _LINUX
|
||||
std::map<std::string, StringList> fileList;
|
||||
#endif // _LINUX
|
||||
};
|
||||
|
||||
EventUpdateManager::EventUpdateManager()
|
||||
:Thread() {
|
||||
d = new PrivateData;
|
||||
d->stopEvent = d->eventHandler.addEvent();
|
||||
d->updateEvent = d->eventHandler.addEvent();
|
||||
d->clientConnectEvent = d->eventHandler.addEvent();
|
||||
d->eventUpdateClientListener = new ConnectionListener(L"TelldusEvents", d->clientConnectEvent);
|
||||
#ifdef _LINUX
|
||||
loadScripts("deviceevent");
|
||||
loadScripts("devicechangeevent");
|
||||
loadScripts("rawdeviceevent");
|
||||
loadScripts("sensorevent");
|
||||
loadScripts("controllerevent");
|
||||
#endif // _LINUX
|
||||
}
|
||||
|
||||
EventUpdateManager::~EventUpdateManager(void) {
|
||||
d->stopEvent->signal();
|
||||
wait();
|
||||
delete d->eventUpdateClientListener;
|
||||
|
||||
for (SocketList::iterator it = d->clients.begin(); it != d->clients.end(); ++it) {
|
||||
delete(*it);
|
||||
}
|
||||
|
||||
delete d;
|
||||
}
|
||||
|
||||
TelldusCore::EventRef EventUpdateManager::retrieveUpdateEvent() {
|
||||
return d->updateEvent;
|
||||
}
|
||||
|
||||
void EventUpdateManager::run() {
|
||||
while(!d->stopEvent->isSignaled()) {
|
||||
if (!d->eventHandler.waitForAny()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(d->clientConnectEvent->isSignaled()) {
|
||||
// new client added
|
||||
TelldusCore::EventDataRef eventData = d->clientConnectEvent->takeSignal();
|
||||
ConnectionListenerEventData *data = dynamic_cast<ConnectionListenerEventData*>(eventData.get());
|
||||
if(data) {
|
||||
d->clients.push_back(data->socket);
|
||||
}
|
||||
} else if(d->updateEvent->isSignaled()) {
|
||||
// device event, signal all clients
|
||||
TelldusCore::EventDataRef eventData = d->updateEvent->takeSignal();
|
||||
EventUpdateData *data = reinterpret_cast<EventUpdateData*>(eventData.get());
|
||||
if(data) {
|
||||
sendMessageToClients(data);
|
||||
executeScripts(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventUpdateManager::loadScripts(const std::string &folder) {
|
||||
#ifdef _LINUX
|
||||
std::string path = TelldusCore::formatf("%s/%s", SCRIPT_PATH, folder.c_str());
|
||||
struct dirent **namelist;
|
||||
int count = scandir(path.c_str(), &namelist, NULL, alphasort);
|
||||
if (count < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = 0; i < count; ++i) {
|
||||
if (strcmp(namelist[i]->d_name, ".") != 0 && strcmp(namelist[i]->d_name, "..") != 0) {
|
||||
d->fileList[folder].push_back(namelist[i]->d_name);
|
||||
}
|
||||
free(namelist[i]);
|
||||
}
|
||||
free(namelist);
|
||||
#endif // _LINUX
|
||||
}
|
||||
|
||||
void EventUpdateManager::sendMessageToClients(EventUpdateData *data) {
|
||||
int connected = 0;
|
||||
for(SocketList::iterator it = d->clients.begin(); it != d->clients.end();) {
|
||||
if((*it)->isConnected()) {
|
||||
connected++;
|
||||
TelldusCore::Message msg;
|
||||
|
||||
if(data->messageType == L"TDDeviceEvent") {
|
||||
msg.addArgument("TDDeviceEvent");
|
||||
msg.addArgument(data->deviceId);
|
||||
msg.addArgument(data->eventState);
|
||||
msg.addArgument(data->eventValue); // string
|
||||
} else if(data->messageType == L"TDDeviceChangeEvent") {
|
||||
msg.addArgument("TDDeviceChangeEvent");
|
||||
msg.addArgument(data->deviceId);
|
||||
msg.addArgument(data->eventDeviceChanges);
|
||||
msg.addArgument(data->eventChangeType);
|
||||
} else if(data->messageType == L"TDRawDeviceEvent") {
|
||||
msg.addArgument("TDRawDeviceEvent");
|
||||
msg.addArgument(data->eventValue); // string
|
||||
msg.addArgument(data->controllerId);
|
||||
} else if(data->messageType == L"TDSensorEvent") {
|
||||
msg.addArgument("TDSensorEvent");
|
||||
msg.addArgument(data->protocol);
|
||||
msg.addArgument(data->model);
|
||||
msg.addArgument(data->sensorId);
|
||||
msg.addArgument(data->dataType);
|
||||
msg.addArgument(data->value);
|
||||
msg.addArgument(data->timestamp);
|
||||
} else if(data->messageType == L"TDControllerEvent") {
|
||||
msg.addArgument("TDControllerEvent");
|
||||
msg.addArgument(data->controllerId);
|
||||
msg.addArgument(data->eventState);
|
||||
msg.addArgument(data->eventChangeType);
|
||||
msg.addArgument(data->eventValue);
|
||||
}
|
||||
|
||||
(*it)->write(msg);
|
||||
|
||||
it++;
|
||||
} else {
|
||||
// connection is dead, remove it
|
||||
delete *it;
|
||||
it = d->clients.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventUpdateManager::executeScripts(EventUpdateData *data) {
|
||||
#ifdef _LINUX
|
||||
std::string dir;
|
||||
std::vector<std::string> env;
|
||||
|
||||
// Create a copy of the environment
|
||||
unsigned int size = 0;
|
||||
for(; ; ++size) {
|
||||
if (environ[size] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
env.reserve(size + 6); // 6 is the most used extra environmental variables any event uses
|
||||
for(unsigned int i = 0; i < size; ++i) {
|
||||
env.push_back(environ[i]);
|
||||
}
|
||||
|
||||
if(data->messageType == L"TDDeviceEvent") {
|
||||
dir = "deviceevent";
|
||||
env.push_back(TelldusCore::formatf("DEVICEID=%i", data->deviceId));
|
||||
env.push_back(TelldusCore::formatf("METHOD=%i", data->eventState));
|
||||
env.push_back(TelldusCore::formatf("METHODDATA=%s", TelldusCore::wideToString(data->eventValue).c_str()));
|
||||
} else if(data->messageType == L"TDDeviceChangeEvent") {
|
||||
dir = "devicechangeevent";
|
||||
env.push_back(TelldusCore::formatf("DEVICEID=%i", data->deviceId));
|
||||
env.push_back(TelldusCore::formatf("CHANGEEVENT=%i", data->eventDeviceChanges));
|
||||
env.push_back(TelldusCore::formatf("CHANGETYPE=%i", data->eventChangeType));
|
||||
} else if(data->messageType == L"TDRawDeviceEvent") {
|
||||
dir = "rawdeviceevent";
|
||||
env.push_back(TelldusCore::formatf("RAWDATA=%s", TelldusCore::wideToString(data->eventValue).c_str())); // string
|
||||
env.push_back(TelldusCore::formatf("CONTROLLERID=%i", data->controllerId));
|
||||
} else if (data->messageType == L"TDSensorEvent") {
|
||||
dir = "sensorevent";
|
||||
env.push_back(TelldusCore::formatf("PROTOCOL=%s", TelldusCore::wideToString(data->protocol).c_str()));
|
||||
env.push_back(TelldusCore::formatf("MODEL=%s", TelldusCore::wideToString(data->model).c_str()));
|
||||
env.push_back(TelldusCore::formatf("SENSORID=%i", data->sensorId));
|
||||
env.push_back(TelldusCore::formatf("DATATYPE=%i", data->dataType));
|
||||
env.push_back(TelldusCore::formatf("VALUE=%s", TelldusCore::wideToString(data->value).c_str()));
|
||||
env.push_back(TelldusCore::formatf("TIMESTAMP=%i", data->timestamp));
|
||||
} else if(data->messageType == L"TDControllerEvent") {
|
||||
dir = "controllerevent";
|
||||
env.push_back(TelldusCore::formatf("CONTROLLERID=%i", data->controllerId));
|
||||
env.push_back(TelldusCore::formatf("CHANGEEVENT=%i", data->eventState));
|
||||
env.push_back(TelldusCore::formatf("CHANGETYPE=%i", data->eventChangeType));
|
||||
env.push_back(TelldusCore::formatf("VALUE=%s", TelldusCore::wideToString(data->eventValue).c_str()));
|
||||
} else {
|
||||
// Unknown event, should not happen
|
||||
return;
|
||||
}
|
||||
|
||||
char *newEnv[env.size()+1]; // +1 for the last stop element
|
||||
for(int i = 0; i < env.size(); ++i) {
|
||||
newEnv[i] = new char[env.at(i).length()+1];
|
||||
snprintf(newEnv[i], env.at(i).length()+1, "%s", env.at(i).c_str());
|
||||
}
|
||||
newEnv[env.size()] = NULL; // Mark end of array
|
||||
|
||||
for(StringList::iterator it = d->fileList[dir].begin(); it != d->fileList[dir].end(); ++it) {
|
||||
executeScript(TelldusCore::formatf("%s/%s/%s", SCRIPT_PATH, dir.c_str(), (*it).c_str()), (*it), newEnv);
|
||||
}
|
||||
// Cleanup
|
||||
for(int i = 0; newEnv[i] != 0; ++i) {
|
||||
delete[] newEnv[i];
|
||||
}
|
||||
#endif // _LINUX
|
||||
}
|
||||
|
||||
void EventUpdateManager::executeScript(std::string script, const std::string &name, char ** env) {
|
||||
#ifdef _LINUX
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) {
|
||||
Log::error("Could not fork() to execute script %s", script.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
char *n = new char[name.length()+1];
|
||||
snprintf(n, name.length()+1, "%s", name.c_str());
|
||||
static char * argv[] = { n, NULL };
|
||||
execve(script.c_str(), argv, env);
|
||||
delete[] n;
|
||||
Log::error("Could not execute %s (%i): %s", script.c_str(), errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
#endif // _LINUX
|
||||
}
|
||||
Reference in New Issue
Block a user