Merge branch 't103'

This commit is contained in:
Micke Prag 2011-12-28 17:36:05 +01:00
commit 712cb9bbd8
11 changed files with 321 additions and 22 deletions

View file

@ -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;
}
}
}

View file

@ -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

View file

@ -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

View 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;
}

View 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

Binary file not shown.

View file

@ -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;

View file

@ -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();
}

View file

@ -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 );

View file

@ -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;
}

View file

@ -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);
}