Merge branch 't103'
This commit is contained in:
commit
712cb9bbd8
11 changed files with 321 additions and 22 deletions
|
@ -158,3 +158,48 @@ std::string TelldusCore::wideToString(const std::wstring &input) {
|
|||
return retval;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string TelldusCore::formatf(const char *format, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
std::string retval = sformatf(format, ap);
|
||||
va_end(ap);
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::string TelldusCore::sformatf(const char *format, va_list ap) {
|
||||
//This code is based on code from the Linux man-pages project (man vsprintf)
|
||||
int n;
|
||||
int size = 100; /* Guess we need no more than 100 bytes. */
|
||||
char *p, *np;
|
||||
|
||||
if ((p = (char*)malloc(size)) == NULL) {
|
||||
return "";
|
||||
}
|
||||
|
||||
while (1) {
|
||||
/* Try to print in the allocated space. */
|
||||
n = vsnprintf(p, size, format, ap);
|
||||
|
||||
/* If that worked, return the string. */
|
||||
if (n > -1 && n < size) {
|
||||
std::string retval(p);
|
||||
free(p);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* Else try again with more space. */
|
||||
|
||||
if (n > -1) { /* glibc 2.1 */
|
||||
size = n+1; /* precisely what is needed */
|
||||
} else { /* glibc 2.0 */
|
||||
size *= 2; /* twice the old size */
|
||||
}
|
||||
if ((np = (char *)realloc (p, size)) == NULL) {
|
||||
free(p);
|
||||
return "";
|
||||
} else {
|
||||
p = np;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,9 @@ namespace TelldusCore {
|
|||
std::string wideToString(const std::wstring &input);
|
||||
|
||||
int wideToInteger(const std::wstring &input);
|
||||
|
||||
std::string formatf(const char *format, ...);
|
||||
std::string sformatf(const char *format, va_list ap);
|
||||
}
|
||||
|
||||
#endif //STRING_H
|
||||
|
|
|
@ -19,6 +19,7 @@ SET( telldus-service_SRCS
|
|||
Device.cpp
|
||||
DeviceManager.cpp
|
||||
Event.cpp
|
||||
Log.cpp
|
||||
Sensor.cpp
|
||||
Settings.cpp
|
||||
TelldusMain.cpp
|
||||
|
@ -78,6 +79,7 @@ SET( telldus-service_HDRS
|
|||
DeviceManager.h
|
||||
Event.h
|
||||
EventHandler.h
|
||||
Log.h
|
||||
Sensor.h
|
||||
Settings.h
|
||||
TelldusMain.h
|
||||
|
@ -135,15 +137,27 @@ ELSEIF (WIN32) #### Windows ####
|
|||
main_win.cpp
|
||||
SettingsWinRegistry.cpp
|
||||
TelldusWinService_win.cpp
|
||||
Messages.mc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Messages.rc
|
||||
${CMAKE_CURRENT_BINARY_DIR}/Messages.h
|
||||
)
|
||||
LIST(APPEND telldus-service_HDRS
|
||||
TelldusWinService_win.h
|
||||
)
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT Messages.rc Messages.h
|
||||
COMMAND mc.exe -u -r ${CMAKE_CURRENT_BINARY_DIR} -h ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Messages.mc
|
||||
DEPENDS Messages.rc
|
||||
COMMENT "Compiling Messages Resource"
|
||||
)
|
||||
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} )
|
||||
|
||||
ELSE (APPLE) #### Linux ####
|
||||
SET(DEFAULT_FTDI_ENGINE "libftdi")
|
||||
FIND_LIBRARY(CONFUSE_LIBRARY confuse)
|
||||
ADD_DEFINITIONS( -D_CONFUSE )
|
||||
ADD_DEFINITIONS( -D_LINUX )
|
||||
|
||||
SET( telldus-service_TARGET telldusd )
|
||||
LIST(APPEND telldus-service_SRCS
|
||||
|
|
180
telldus-core/service/Log.cpp
Normal file
180
telldus-core/service/Log.cpp
Normal file
|
@ -0,0 +1,180 @@
|
|||
#include "Log.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#if defined(_LINUX)
|
||||
#include <syslog.h>
|
||||
#elif defined(_WINDOWS)
|
||||
#include <windows.h>
|
||||
#include "Strings.h"
|
||||
#include "Messages.h"
|
||||
#endif
|
||||
|
||||
class Log::PrivateData {
|
||||
public:
|
||||
PrivateData() : logOutput(Log::System), debug(false) {}
|
||||
|
||||
Log::LogOutput logOutput;
|
||||
bool debug;
|
||||
|
||||
static Log *instance;
|
||||
#ifdef _WINDOWS
|
||||
HANDLE eventSource;
|
||||
#endif
|
||||
};
|
||||
|
||||
Log *Log::PrivateData::instance = 0;
|
||||
|
||||
Log::Log()
|
||||
:d(new PrivateData)
|
||||
{
|
||||
#if defined(_LINUX)
|
||||
setlogmask(LOG_UPTO(LOG_INFO));
|
||||
openlog("telldusd", LOG_CONS, LOG_USER);
|
||||
#elif defined(_MACOSX)
|
||||
d->logOutput = Log::StdOut;
|
||||
#elif defined(_WINDOWS)
|
||||
//Add ourselves to the registy
|
||||
HKEY hRegKey = NULL;
|
||||
DWORD dwError = 0;
|
||||
TCHAR filePath[MAX_PATH];
|
||||
|
||||
std::wstring path(L"SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\TelldusService");
|
||||
dwError = RegCreateKey( HKEY_LOCAL_MACHINE, path.c_str(), &hRegKey );
|
||||
|
||||
GetModuleFileName( NULL, filePath, MAX_PATH );
|
||||
dwError = RegSetValueEx( hRegKey, L"EventMessageFile", 0,
|
||||
REG_EXPAND_SZ, (PBYTE) filePath,
|
||||
(DWORD)(wcslen(filePath) + 1) * sizeof TCHAR );
|
||||
|
||||
DWORD dwTypes = LOG_DEBUG | LOG_NOTICE | LOG_WARNING | LOG_ERR;
|
||||
dwError = RegSetValueEx( hRegKey, L"TypesSupported",
|
||||
0, REG_DWORD, (LPBYTE) &dwTypes, sizeof dwTypes );
|
||||
|
||||
RegCloseKey(hRegKey);
|
||||
|
||||
d->eventSource = RegisterEventSource(NULL, L"TelldusService");
|
||||
#endif
|
||||
}
|
||||
|
||||
Log::~Log() {
|
||||
#if defined(_LINUX)
|
||||
closelog();
|
||||
#elif defined(_WINDOWS)
|
||||
if (d->eventSource != NULL) {
|
||||
DeregisterEventSource(d->eventSource);
|
||||
}
|
||||
#endif
|
||||
delete d;
|
||||
}
|
||||
|
||||
void Log::destroy() {
|
||||
if (PrivateData::instance == 0) {
|
||||
return;
|
||||
}
|
||||
delete PrivateData::instance;
|
||||
PrivateData::instance = 0;
|
||||
}
|
||||
|
||||
void Log::debug(const char *fmt, ...) {
|
||||
Log *log = Log::instance();
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
log->message(Debug, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Log::notice(const char *fmt, ...) {
|
||||
Log *log = Log::instance();
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
log->message(Notice, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Log::warning(const char *fmt, ...) {
|
||||
Log *log = Log::instance();
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
log->message(Warning, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Log::error(const char *fmt, ...) {
|
||||
Log *log = Log::instance();
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
log->message(Error, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
void Log::setDebug() {
|
||||
Log *log = Log::instance();
|
||||
log->d->debug = true;
|
||||
}
|
||||
|
||||
void Log::setLogOutput(LogOutput logOutput) {
|
||||
#ifdef _MACOSX
|
||||
//Always stdout
|
||||
return;
|
||||
#endif
|
||||
Log *log = Log::instance();
|
||||
log->d->logOutput = logOutput;
|
||||
}
|
||||
|
||||
void Log::message(Log::LogLevel logLevel, const char *format, va_list ap) const {
|
||||
if (logLevel == Debug && d->debug == false) {
|
||||
return;
|
||||
}
|
||||
if (d->logOutput == StdOut) {
|
||||
FILE *stream = stdout;
|
||||
if (logLevel == Warning || logLevel == Error) {
|
||||
stream = stderr;
|
||||
}
|
||||
vfprintf(stream, format, ap);
|
||||
fprintf(stream, "\n");
|
||||
fflush(stream);
|
||||
} else {
|
||||
#if defined(_LINUX)
|
||||
switch (logLevel) {
|
||||
case Debug:
|
||||
vsyslog(LOG_DEBUG, format, ap);
|
||||
break;
|
||||
case Notice:
|
||||
vsyslog(LOG_NOTICE, format, ap);
|
||||
break;
|
||||
case Warning:
|
||||
vsyslog(LOG_WARNING, format, ap);
|
||||
break;
|
||||
case Error:
|
||||
vsyslog(LOG_ERR, format, ap);
|
||||
break;
|
||||
}
|
||||
#elif defined(_WINDOWS)
|
||||
LPWSTR pInsertStrings[2] = {NULL, NULL};
|
||||
std::wstring str = TelldusCore::charToWstring(TelldusCore::sformatf(format, ap).c_str());
|
||||
pInsertStrings[0] = (LPWSTR)str.c_str();
|
||||
|
||||
switch (logLevel) {
|
||||
case Debug:
|
||||
ReportEvent(d->eventSource, EVENTLOG_SUCCESS, NULL, LOG_DEBUG, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL);
|
||||
break;
|
||||
case Notice:
|
||||
ReportEvent(d->eventSource, EVENTLOG_INFORMATION_TYPE, NULL, LOG_NOTICE, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL);
|
||||
break;
|
||||
case Warning:
|
||||
ReportEvent(d->eventSource, EVENTLOG_WARNING_TYPE, NULL, LOG_WARNING, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL);
|
||||
break;
|
||||
case Error:
|
||||
ReportEvent(d->eventSource, EVENTLOG_ERROR_TYPE, NULL, LOG_ERR, NULL, 1, 0, (LPCWSTR*)pInsertStrings, NULL);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
Log *Log::instance() {
|
||||
if (PrivateData::instance == 0) {
|
||||
PrivateData::instance = new Log();
|
||||
}
|
||||
return PrivateData::instance;
|
||||
}
|
33
telldus-core/service/Log.h
Normal file
33
telldus-core/service/Log.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
class Log {
|
||||
public:
|
||||
enum LogLevel { Debug, Notice, Warning, Error };
|
||||
enum LogOutput { StdOut, System };
|
||||
virtual ~Log();
|
||||
|
||||
static void destroy();
|
||||
|
||||
static void debug(const char *fmt, ...);
|
||||
static void notice(const char *fmt, ...);
|
||||
static void warning(const char *fmt, ...);
|
||||
static void error(const char *fmt, ...);
|
||||
|
||||
static void setDebug();
|
||||
static void setLogOutput(LogOutput logOutput);
|
||||
|
||||
protected:
|
||||
Log();
|
||||
void message(LogLevel logLevel, const char *format, va_list ap) const;
|
||||
static Log *instance();
|
||||
|
||||
private:
|
||||
class PrivateData;
|
||||
PrivateData *d;
|
||||
};
|
||||
|
||||
|
||||
#endif //LOG_H
|
BIN
telldus-core/service/Messages.mc
Normal file
BIN
telldus-core/service/Messages.mc
Normal file
Binary file not shown.
|
@ -12,6 +12,7 @@
|
|||
#include "TellStick.h"
|
||||
#include "Mutex.h"
|
||||
#include "Strings.h"
|
||||
#include "Log.h"
|
||||
#include "../client/telldus-core.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -61,6 +62,7 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &
|
|||
strcpy(tempSerial, td.serial.c_str());
|
||||
FT_SetVIDPID(td.vid, td.pid);
|
||||
#endif
|
||||
Log::notice("Connecting to TellStick (%X/%X) with serial %s", d->vid, d->pid, d->serial.c_str());
|
||||
FT_STATUS ftStatus = FT_OpenEx(tempSerial, FT_OPEN_BY_SERIAL_NUMBER, &d->ftHandle);
|
||||
delete tempSerial;
|
||||
if (ftStatus == FT_OK) {
|
||||
|
@ -76,10 +78,13 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &
|
|||
setBaud(4800);
|
||||
}
|
||||
this->start();
|
||||
} else {
|
||||
Log::warning("Failed to open TellStick");
|
||||
}
|
||||
}
|
||||
|
||||
TellStick::~TellStick() {
|
||||
Log::warning("Disconnected TellStick (%X/%X) with serial %s", d->vid, d->pid, d->serial.c_str());
|
||||
if (d->running) {
|
||||
TelldusCore::MutexLocker locker(&d->mutex);
|
||||
d->running = false;
|
||||
|
|
|
@ -54,6 +54,7 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &
|
|||
ftdi_init(&d->ftHandle);
|
||||
ftdi_set_interface(&d->ftHandle, INTERFACE_ANY);
|
||||
|
||||
Log::notice("Connecting to TellStick (%X/%X) with serial %s", d->vid, d->pid, d->serial.c_str());
|
||||
int ret = ftdi_usb_open_desc(&d->ftHandle, td.vid, td.pid, NULL, td.serial.c_str());
|
||||
if (ret < 0) {
|
||||
ftdi_deinit(&d->ftHandle);
|
||||
|
@ -71,10 +72,13 @@ TellStick::TellStick(int controllerId, Event *event, const TellStickDescriptor &
|
|||
this->setBaud(4800);
|
||||
}
|
||||
this->start();
|
||||
} else {
|
||||
Log::warning("Failed to open TellStick");
|
||||
}
|
||||
}
|
||||
|
||||
TellStick::~TellStick() {
|
||||
Log::warning("Disconnected TellStick (%X/%X) with serial %s", d->vid, d->pid, d->serial.c_str());
|
||||
if (d->running) {
|
||||
stop();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "TelldusWinService_win.h"
|
||||
#include "TelldusMain.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <Dbt.h>
|
||||
#include <string>
|
||||
|
@ -111,6 +112,13 @@ DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD
|
|||
void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) {
|
||||
TelldusWinService instance;
|
||||
|
||||
//Enable debug if we hade this supplied
|
||||
for(unsigned int i = 1; i < argc; ++i) {
|
||||
if (wcscmp(argv[i], L"--debug") == 0) {
|
||||
Log::setDebug();
|
||||
}
|
||||
}
|
||||
|
||||
// initialise service status
|
||||
instance.serviceStatus.dwServiceType = SERVICE_WIN32;
|
||||
instance.serviceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
|
@ -140,9 +148,14 @@ void WINAPI TelldusWinService::serviceMain( DWORD argc, TCHAR* argv[] ) {
|
|||
devInterface.dbcc_classguid = GUID_DEVINTERFACE_USBRAW;
|
||||
HDEVNOTIFY deviceNotificationHandle = RegisterDeviceNotificationW(instance.serviceStatusHandle, &devInterface, DEVICE_NOTIFY_SERVICE_HANDLE);
|
||||
|
||||
Log::notice("TelldusService started");
|
||||
|
||||
//Start our main-loop
|
||||
instance.tm->start();
|
||||
|
||||
Log::notice("TelldusService stopping");
|
||||
Log::destroy();
|
||||
|
||||
// service was stopped
|
||||
instance.serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
||||
SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus );
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
#include "TelldusMain.h"
|
||||
#include "Log.h"
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
TelldusMain tm;
|
||||
|
||||
void shutdownHandler(int onSignal) {
|
||||
printf("Shutting down\n");
|
||||
Log::notice("Shutting down");
|
||||
tm.stop();
|
||||
}
|
||||
|
||||
void sigpipeHandler(int onSignal) {
|
||||
printf("SIGPIPE received\n");
|
||||
Log::notice("SIGPIPE received");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
@ -19,7 +19,10 @@ int main(int argc, char **argv) {
|
|||
signal(SIGINT, shutdownHandler);
|
||||
signal(SIGPIPE, sigpipeHandler);
|
||||
|
||||
Log::notice("telldusd started");
|
||||
tm.start();
|
||||
printf("telldusd stopped gracefully\n");
|
||||
Log::notice("telldusd stopped gracefully");
|
||||
|
||||
Log::destroy();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
|
@ -12,6 +11,7 @@
|
|||
|
||||
#include "Settings.h"
|
||||
#include "Strings.h"
|
||||
#include "Log.h"
|
||||
|
||||
#define DAEMON_NAME "telldusd"
|
||||
#define PID_FILE "/var/run/" DAEMON_NAME ".pid"
|
||||
|
@ -21,19 +21,19 @@ TelldusMain tm;
|
|||
void signalHandler(int sig) {
|
||||
switch(sig) {
|
||||
case SIGHUP:
|
||||
syslog(LOG_WARNING, "Received SIGHUP signal.");
|
||||
Log::warning("Received SIGHUP signal.");
|
||||
break;
|
||||
case SIGTERM:
|
||||
case SIGINT:
|
||||
syslog(LOG_WARNING, "Received SIGTERM or SIGINT signal.");
|
||||
syslog(LOG_WARNING, "Shutting down");
|
||||
Log::warning("Received SIGTERM or SIGINT signal.");
|
||||
Log::warning("Shutting down");
|
||||
tm.stop();
|
||||
break;
|
||||
case SIGPIPE:
|
||||
syslog(LOG_WARNING, "Received SIGPIPE signal.");
|
||||
Log::warning("Received SIGPIPE signal.");
|
||||
break;
|
||||
default:
|
||||
syslog(LOG_WARNING, "Unhandled signal (%d) %s", sig, strsignal(sig));
|
||||
Log::warning("Unhandled signal (%d) %s", sig, strsignal(sig));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -46,17 +46,19 @@ int main(int argc, char **argv) {
|
|||
for (int i = 1; i < argc; ++i) {
|
||||
if (strcmp(argv[i], "--nodaemon") == 0) {
|
||||
deamonize = false;
|
||||
}
|
||||
if (strcmp(argv[i], "--help") == 0) {
|
||||
Log::setLogOutput(Log::StdOut);
|
||||
} else if (strcmp(argv[i], "--help") == 0) {
|
||||
printf("Telldus TellStick background service\n\nStart with --nodaemon to not run as daemon\n\n");
|
||||
printf("Report bugs to <info.tech@telldus.com>\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
if (strcmp(argv[i], "--version") == 0) {
|
||||
} else if (strcmp(argv[i], "--version") == 0) {
|
||||
printf("telldusd " VERSION "\n\n");
|
||||
printf("Copyright (C) 2011 Telldus Technologies AB\n\n");
|
||||
printf("Written by Micke Prag <micke.prag@telldus.se>\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
} else {
|
||||
printf("Unknown option %s\n", argv[i]);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,17 +78,14 @@ int main(int argc, char **argv) {
|
|||
fprintf(fd,"%d\n",pid);
|
||||
fclose(fd);
|
||||
} else {
|
||||
syslog(LOG_ERR, "Could not open pid file %s: %s", PID_FILE, strerror(errno));
|
||||
Log::error("Could not open pid file %s: %s", PID_FILE, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
setlogmask(LOG_UPTO(LOG_INFO));
|
||||
openlog(DAEMON_NAME, LOG_CONS, LOG_USER);
|
||||
|
||||
syslog(LOG_NOTICE, "%s daemon starting up", DAEMON_NAME);
|
||||
Log::notice("%s daemon starting up", DAEMON_NAME);
|
||||
|
||||
if (deamonize) {
|
||||
/* Change the file mode mask */
|
||||
|
@ -115,14 +114,14 @@ int main(int argc, char **argv) {
|
|||
if (grp) {
|
||||
setgid(grp->gr_gid);
|
||||
} else {
|
||||
syslog(LOG_WARNING, "Group %s could not be found", group.c_str());
|
||||
Log::warning("Group %s could not be found", group.c_str());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
struct passwd *pw = getpwnam(user.c_str());
|
||||
if (pw) {
|
||||
setuid( pw->pw_uid );
|
||||
} else {
|
||||
syslog(LOG_WARNING, "User %s could not be found", user.c_str());
|
||||
Log::warning("User %s could not be found", user.c_str());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
@ -139,6 +138,6 @@ int main(int argc, char **argv) {
|
|||
|
||||
tm.start();
|
||||
|
||||
syslog(LOG_NOTICE, "%s daemon exited", DAEMON_NAME);
|
||||
Log::notice("%s daemon exited", DAEMON_NAME);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue