Execute a script from /usr/local/share/telldus/scripts on all events.

Closes #100
This commit is contained in:
Micke Prag 2012-11-22 09:57:59 +01:00
parent 32f2d9f955
commit d48ee1f02b
3 changed files with 124 additions and 0 deletions

View file

@ -6,13 +6,28 @@
//
#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>
#endif // _LINUX
#include <list>
#include <memory>
#ifdef _LINUX
#include <string>
#include <vector>
#endif // _LINUX
#include "service/ConnectionListener.h"
#include "common/EventHandler.h"
#include "common/Message.h"
#include "common/Socket.h"
#include "service/Log.h"
#include "common/Strings.h"
typedef std::list<TelldusCore::Socket *> SocketList;
@ -68,6 +83,7 @@ void EventUpdateManager::run() {
EventUpdateData *data = reinterpret_cast<EventUpdateData*>(eventData.get());
if(data) {
sendMessageToClients(data);
executeScripts(data);
}
}
}
@ -120,3 +136,99 @@ void EventUpdateManager::sendMessageToClients(EventUpdateData *data) {
}
}
}
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()] = 0; // Mark end of array
// List files to execute
std::string path = TelldusCore::formatf("/usr/local/share/telldus/scripts/%s", dir.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) {
continue;
}
executeScript(TelldusCore::formatf("%s/%s", path.c_str(), namelist[i]->d_name), namelist[i]->d_name, newEnv);
}
for(int i = 0; i < count; ++i) {
free(namelist[i]);
}
free(namelist);
#endif // _LINUX
}
void EventUpdateManager::executeScript(std::string script, char *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) {
static char * argv[] = { name };
execve(script.c_str(), argv, env);
Log::error("Could not execute %s (%i): %s", script.c_str(), errno, strerror(errno));
exit(1);
}
#endif // _LINUX
}