random ai stuff

This commit is contained in:
matst80
2025-11-21 18:12:55 +01:00
commit 60f5783a26
187 changed files with 25197 additions and 0 deletions

View File

@@ -0,0 +1,278 @@
IF(COMMAND cmake_policy)
CMAKE_POLICY(SET CMP0003 NEW)
ENDIF(COMMAND cmake_policy)
FIND_PACKAGE( SignTool REQUIRED )
SET (telldusd_DESCRIPTION
"background service for Telldus TellStick, must be running to control TellStick"
)
ADD_DEFINITIONS( -DVERSION="${DISPLAYED_VERSION}" )
######## Non configurable options ########
SET( telldus-service_SRCS
ClientCommunicationHandler.cpp
Controller.cpp
ControllerManager.cpp
ControllerMessage.cpp
Device.cpp
DeviceManager.cpp
Log.cpp
Sensor.cpp
Settings.cpp
TelldusMain.cpp
TellStick.cpp
Timer.cpp
EventUpdateManager.cpp
)
SET( telldus-service_protocol_SRCS
Protocol.h
Protocol.cpp
ProtocolBrateck.h
ProtocolBrateck.cpp
ProtocolComen.h
ProtocolComen.cpp
ProtocolEverflourish.h
ProtocolEverflourish.cpp
ProtocolFineoffset.h
ProtocolFineoffset.cpp
ProtocolFuhaote.h
ProtocolFuhaote.cpp
ProtocolGroup.h
ProtocolGroup.cpp
ProtocolHasta.h
ProtocolHasta.cpp
ProtocolIkea.h
ProtocolIkea.cpp
ProtocolMandolyn.h
ProtocolMandolyn.cpp
ProtocolNexa.h
ProtocolNexa.cpp
ProtocolOregon.h
ProtocolOregon.cpp
ProtocolRisingSun.h
ProtocolRisingSun.cpp
ProtocolSartano.h
ProtocolSartano.cpp
ProtocolScene.h
ProtocolScene.cpp
ProtocolSilvanChip.h
ProtocolSilvanChip.cpp
ProtocolUpm.h
ProtocolUpm.cpp
ProtocolWaveman.h
ProtocolWaveman.cpp
ProtocolX10.h
ProtocolX10.cpp
ProtocolYidong.h
ProtocolYidong.cpp
)
SET( telldus-service_HDRS
ClientCommunicationHandler.h
ConnectionListener.h
Controller.h
ControllerListener.h
ControllerManager.h
ControllerMessage.h
Device.h
DeviceManager.h
EventUpdateManager.h
Log.h
Sensor.h
Settings.h
TelldusMain.h
TellStick.h
Timer.h
)
FIND_PACKAGE(Threads REQUIRED)
LIST(APPEND telldus-service_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR})
######## Configurable options for the platform ########
IF (UNIX AND NOT APPLE)
SET(SCRIPT_PATH "/usr/local/share/telldus/scripts" CACHE PATH "The paths for scripts to execute on sensor events")
SET(SYSCONF_INSTALL_DIR "/etc" CACHE PATH "The sysconfig install dir (default prefix/etc)" )
IF (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
SET(DEFAULT_STATE_INSTALL_DIR "/var/spool")
ELSE ()
SET(DEFAULT_STATE_INSTALL_DIR "/var/state")
ENDIF ()
SET(STATE_INSTALL_DIR "${DEFAULT_STATE_INSTALL_DIR}" CACHE PATH "The directory to store state information of the devices")
ENDIF()
######## Platforms-specific, non configurable ########
IF (APPLE) #### Mac OS X ####
SET(DEFAULT_FTDI_ENGINE "ftd2xx")
SET( telldus-service_TARGET TelldusService )
ADD_DEFINITIONS( -D_MACOSX )
FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation)
FIND_LIBRARY(IOKIT_LIBRARY IOKit)
SET( telldus-service_LIBRARIES
${telldus-service_LIBRARIES}
${COREFOUNDATION_LIBRARY}
${IOKIT_LIBRARY}
TelldusCommon
)
LIST(APPEND telldus-service_SRCS
main_mac.cpp
ConnectionListener_unix.cpp
ControllerListener_mac.cpp
SettingsCoreFoundationPreferences.cpp
)
ELSEIF (WIN32) #### Windows ####
SET(DEFAULT_FTDI_ENGINE "ftd2xx")
SET( telldus-service_TARGET TelldusService )
ADD_DEFINITIONS( -DUNICODE )
ADD_DEFINITIONS( /Zc:wchar_t- ) # Treat wchar_t as Built-in Type' = No
SET(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE"
)
LIST(APPEND telldus-service_LIBRARIES
TelldusCommon
)
LIST(APPEND telldus-service_SRCS
ConnectionListener_win.cpp
main_win.cpp
SettingsWinRegistry.cpp
TelldusWinService_win.cpp
Messages.mc
${CMAKE_CURRENT_BINARY_DIR}/Messages.rc
${CMAKE_CURRENT_BINARY_DIR}/service/Messages.h
)
LIST(APPEND telldus-service_HDRS
TelldusWinService_win.h
)
ADD_CUSTOM_COMMAND(
OUTPUT Messages.rc service/Messages.h
COMMAND mc.exe -u -r \"${CMAKE_CURRENT_BINARY_DIR}\" -h \"${CMAKE_CURRENT_BINARY_DIR}/service\" \"${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
ConnectionListener_unix.cpp
main_unix.cpp
SettingsConfuse.cpp
)
LIST(APPEND telldus-service_LIBRARIES
${CONFUSE_LIBRARY}
TelldusCommon
)
ENDIF (APPLE)
SET(FTDI_ENGINE ${DEFAULT_FTDI_ENGINE} CACHE STRING "Which FTDI engine to use. This could be either 'libftdi' or 'ftd2xx'")
IF (FTDI_ENGINE STREQUAL "ftd2xx")
FIND_LIBRARY(FTD2XX_LIBRARY ftd2xx)
ADD_DEFINITIONS( -DLIBFTD2XX )
LIST(APPEND telldus-service_SRCS TellStick_ftd2xx.cpp )
LIST(APPEND telldus-service_LIBRARIES ${FTD2XX_LIBRARY})
ELSE (FTDI_ENGINE STREQUAL "ftd2xx")
FIND_LIBRARY(FTDI_LIBRARY ftdi)
INCLUDE(FindPkgConfig)
PKG_SEARCH_MODULE(FTDI libftdi)
INCLUDE_DIRECTORIES( ${FTDI_INCLUDEDIR} )
ADD_DEFINITIONS( -DLIBFTDI )
LIST(APPEND telldus-service_SRCS TellStick_libftdi.cpp )
LIST(APPEND telldus-service_LIBRARIES ${FTDI_LIBRARY})
ENDIF (FTDI_ENGINE STREQUAL "ftd2xx")
######## Configuring ########
SOURCE_GROUP("Protocol Files" FILES ${telldus-service_protocol_SRCS})
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/service/config.h)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
SET(telldus-service_TARGET ${telldus-service_TARGET} PARENT_SCOPE)
ADD_EXECUTABLE(${telldus-service_TARGET}
${telldus-service_SRCS}
${telldus-service_protocol_SRCS}
${telldus-service_HDRS}
)
ADD_DEPENDENCIES(${telldus-service_TARGET} TelldusCommon)
SET_SOURCE_FILES_PROPERTIES(${telldus-service_RESOURCES} PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
TARGET_LINK_LIBRARIES( ${telldus-service_TARGET} ${telldus-service_LIBRARIES} )
SIGN(${telldus-service_TARGET})
SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
)
IF (APPLE)
SET(TELLDUS_SERVICE_TARGET_PATH "/Library/Telldus" CACHE STRING "Path to install TelldusService")
SET_TARGET_PROPERTIES(${telldus-service_TARGET} PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}
)
INSTALL(TARGETS ${telldus-service_TARGET}
RUNTIME DESTINATION ${TELLDUS_SERVICE_TARGET_PATH}
)
INSTALL(CODE "
INCLUDE(GetPrerequisites)
GET_FILENAME_COMPONENT(DESTDIR \$ENV{DESTDIR} ABSOLUTE)
GET_PREREQUISITES(\"\${DESTDIR}/${TELLDUS_SERVICE_TARGET_PATH}/${telldus-service_TARGET}\" prereqs 1 0 \"\$\" \"\$\")
FOREACH(pr \${prereqs})
GET_FILENAME_COMPONENT(lib \${pr} NAME)
FILE(INSTALL \${pr} DESTINATION ${TELLDUS_SERVICE_TARGET_PATH})
EXECUTE_PROCESS(COMMAND install_name_tool
-change \"\${pr}\" \"${TELLDUS_SERVICE_TARGET_PATH}/\${lib}\" \"\${DESTDIR}/${TELLDUS_SERVICE_TARGET_PATH}/${telldus-service_TARGET}\"
)
ENDFOREACH ()
")
INSTALL(FILES com.telldus.service.plist DESTINATION /Library/LaunchDaemons)
ENDIF (APPLE)
IF (UNIX)
IF (GENERATE_MAN)
ADD_CUSTOM_COMMAND(
TARGET ${telldus-service_TARGET}
POST_BUILD
COMMAND help2man -n ${telldusd_DESCRIPTION} ./telldusd > telldusd.1
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating man file telldusd.1"
)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/telldusd.1 DESTINATION share/man/man1)
ENDIF (GENERATE_MAN)
ENDIF (UNIX)
IF (UNIX AND NOT APPLE)
INSTALL(TARGETS ${telldus-service_TARGET} RUNTIME DESTINATION sbin)
INSTALL(FILES tellstick.conf
DESTINATION ${SYSCONF_INSTALL_DIR}
)
INSTALL(FILES telldus-core.conf
DESTINATION ${STATE_INSTALL_DIR}
PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ GROUP_WRITE WORLD_READ WORLD_WRITE
)
ENDIF (UNIX AND NOT APPLE)
IF(ENABLE_TESTING)
# Build it once more, but as static library so it can be linked by the test-tool
ADD_LIBRARY(TelldusServiceStatic STATIC
${telldus-service_SRCS}
${telldus-service_protocol_SRCS}
${telldus-service_HDRS}
)
TARGET_LINK_LIBRARIES( TelldusServiceStatic ${telldus-service_LIBRARIES} )
IF (UNIX)
SET_TARGET_PROPERTIES( TelldusServiceStatic PROPERTIES COMPILE_FLAGS "-fPIC")
ENDIF (UNIX)
ENDIF()

View File

@@ -0,0 +1,266 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ClientCommunicationHandler.h"
#include <stdlib.h>
#include <string>
#include "common/Message.h"
#include "common/Strings.h"
class ClientCommunicationHandler::PrivateData {
public:
TelldusCore::Socket *clientSocket;
TelldusCore::EventRef event, deviceUpdateEvent;
bool done;
DeviceManager *deviceManager;
ControllerManager *controllerManager;
};
ClientCommunicationHandler::ClientCommunicationHandler() {
}
ClientCommunicationHandler::ClientCommunicationHandler(TelldusCore::Socket *clientSocket, TelldusCore::EventRef event, DeviceManager *deviceManager, TelldusCore::EventRef deviceUpdateEvent, ControllerManager *controllerManager)
:Thread() {
d = new PrivateData;
d->clientSocket = clientSocket;
d->event = event;
d->done = false;
d->deviceManager = deviceManager;
d->deviceUpdateEvent = deviceUpdateEvent;
d->controllerManager = controllerManager;
}
ClientCommunicationHandler::~ClientCommunicationHandler(void) {
wait();
delete(d->clientSocket);
delete d;
}
void ClientCommunicationHandler::run() {
// run thread
std::wstring clientMessage = d->clientSocket->read(2000);
int intReturn;
std::wstring strReturn;
strReturn = L"";
parseMessage(clientMessage, &intReturn, &strReturn);
TelldusCore::Message msg;
if(strReturn == L"") {
msg.addArgument(intReturn);
} else {
msg.addArgument(strReturn);
}
msg.append(L"\n");
d->clientSocket->write(msg);
// We are done, signal for removal
d->done = true;
d->event->signal();
}
bool ClientCommunicationHandler::isDone() {
return d->done;
}
void ClientCommunicationHandler::parseMessage(const std::wstring &clientMessage, int *intReturn, std::wstring *wstringReturn) {
(*intReturn) = 0;
(*wstringReturn) = L"";
std::wstring msg(clientMessage); // Copy
std::wstring function(TelldusCore::Message::takeString(&msg));
if (function == L"tdTurnOn") {
int deviceId = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNON, 0);
} else if (function == L"tdTurnOff") {
int deviceId = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_TURNOFF, 0);
} else if (function == L"tdBell") {
int deviceId = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_BELL, 0);
} else if (function == L"tdDim") {
int deviceId = TelldusCore::Message::takeInt(&msg);
int level = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_DIM, level);
} else if (function == L"tdExecute") {
int deviceId = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_EXECUTE, 0);
} else if (function == L"tdUp") {
int deviceId = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_UP, 0);
} else if (function == L"tdDown") {
int deviceId = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_DOWN, 0);
} else if (function == L"tdStop") {
int deviceId = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_STOP, 0);
} else if (function == L"tdLearn") {
int deviceId = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->doAction(deviceId, TELLSTICK_LEARN, 0);
} else if (function == L"tdLastSentCommand") {
int deviceId = TelldusCore::Message::takeInt(&msg);
int methodsSupported = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->getDeviceLastSentCommand(deviceId, methodsSupported);
} else if (function == L"tdLastSentValue") {
int deviceId = TelldusCore::Message::takeInt(&msg);
(*wstringReturn) = d->deviceManager->getDeviceStateValue(deviceId);
} else if(function == L"tdGetNumberOfDevices") {
(*intReturn) = d->deviceManager->getNumberOfDevices();
} else if (function == L"tdGetDeviceId") {
int deviceIndex = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->getDeviceId(deviceIndex);
} else if (function == L"tdGetDeviceType") {
int deviceId = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->getDeviceType(deviceId);
} else if (function == L"tdGetName") {
int deviceId = TelldusCore::Message::takeInt(&msg);
(*wstringReturn) = d->deviceManager->getDeviceName(deviceId);
} else if (function == L"tdSetName") {
int deviceId = TelldusCore::Message::takeInt(&msg);
std::wstring name = TelldusCore::Message::takeString(&msg);
(*intReturn) = d->deviceManager->setDeviceName(deviceId, name);
sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_NAME);
} else if (function == L"tdGetProtocol") {
int deviceId = TelldusCore::Message::takeInt(&msg);
(*wstringReturn) = d->deviceManager->getDeviceProtocol(deviceId);
} else if (function == L"tdSetProtocol") {
int deviceId = TelldusCore::Message::takeInt(&msg);
std::wstring protocol = TelldusCore::Message::takeString(&msg);
int oldMethods = d->deviceManager->getDeviceMethods(deviceId);
(*intReturn) = d->deviceManager->setDeviceProtocol(deviceId, protocol);
sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_PROTOCOL);
if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)) {
sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD);
}
} else if (function == L"tdGetModel") {
int deviceId = TelldusCore::Message::takeInt(&msg);
(*wstringReturn) = d->deviceManager->getDeviceModel(deviceId);
} else if (function == L"tdSetModel") {
int deviceId = TelldusCore::Message::takeInt(&msg);
std::wstring model = TelldusCore::Message::takeString(&msg);
int oldMethods = d->deviceManager->getDeviceMethods(deviceId);
(*intReturn) = d->deviceManager->setDeviceModel(deviceId, model);
sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_MODEL);
if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)) {
sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD);
}
} else if (function == L"tdGetDeviceParameter") {
int deviceId = TelldusCore::Message::takeInt(&msg);
std::wstring name = TelldusCore::Message::takeString(&msg);
std::wstring defaultValue = TelldusCore::Message::takeString(&msg);
(*wstringReturn) = d->deviceManager->getDeviceParameter(deviceId, name, defaultValue);
} else if (function == L"tdSetDeviceParameter") {
int deviceId = TelldusCore::Message::takeInt(&msg);
std::wstring name = TelldusCore::Message::takeString(&msg);
std::wstring value = TelldusCore::Message::takeString(&msg);
int oldMethods = d->deviceManager->getDeviceMethods(deviceId);
(*intReturn) = d->deviceManager->setDeviceParameter(deviceId, name, value);
if(oldMethods != d->deviceManager->getDeviceMethods(deviceId)) {
sendDeviceSignal(deviceId, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_METHOD);
}
} else if (function == L"tdAddDevice") {
(*intReturn) = d->deviceManager->addDevice();
if((*intReturn) >= 0) {
sendDeviceSignal((*intReturn), TELLSTICK_DEVICE_ADDED, 0);
}
} else if (function == L"tdRemoveDevice") {
int deviceId = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->removeDevice(deviceId);
if((*intReturn) == TELLSTICK_SUCCESS) {
sendDeviceSignal(deviceId, TELLSTICK_DEVICE_REMOVED, 0);
}
} else if (function == L"tdMethods") {
int deviceId = TelldusCore::Message::takeInt(&msg);
int intMethodsSupported = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->getDeviceMethods(deviceId, intMethodsSupported);
} else if (function == L"tdSendRawCommand") {
std::wstring command = TelldusCore::Message::takeString(&msg);
int reserved = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->deviceManager->sendRawCommand(command, reserved);
} else if (function == L"tdConnectTellStickController") {
int vid = TelldusCore::Message::takeInt(&msg);
int pid = TelldusCore::Message::takeInt(&msg);
std::string serial = TelldusCore::wideToString(TelldusCore::Message::takeString(&msg));
d->deviceManager->connectTellStickController(vid, pid, serial);
} else if (function == L"tdDisconnectTellStickController") {
int vid = TelldusCore::Message::takeInt(&msg);
int pid = TelldusCore::Message::takeInt(&msg);
std::string serial = TelldusCore::wideToString(TelldusCore::Message::takeString(&msg));
d->deviceManager->disconnectTellStickController(vid, pid, serial);
} else if (function == L"tdSensor") {
(*wstringReturn) = d->deviceManager->getSensors();
} else if (function == L"tdSensorValue") {
std::wstring protocol = TelldusCore::Message::takeString(&msg);
std::wstring model = TelldusCore::Message::takeString(&msg);
int id = TelldusCore::Message::takeInt(&msg);
int dataType = TelldusCore::Message::takeInt(&msg);
(*wstringReturn) = d->deviceManager->getSensorValue(protocol, model, id, dataType);
} else if (function == L"tdController") {
(*wstringReturn) = d->controllerManager->getControllers();
} else if (function == L"tdControllerValue") {
int id = TelldusCore::Message::takeInt(&msg);
std::wstring name = TelldusCore::Message::takeString(&msg);
(*wstringReturn) = d->controllerManager->getControllerValue(id, name);
} else if (function == L"tdSetControllerValue") {
int id = TelldusCore::Message::takeInt(&msg);
std::wstring name = TelldusCore::Message::takeString(&msg);
std::wstring value = TelldusCore::Message::takeString(&msg);
(*intReturn) = d->controllerManager->setControllerValue(id, name, value);
} else if (function == L"tdRemoveController") {
int controllerId = TelldusCore::Message::takeInt(&msg);
(*intReturn) = d->controllerManager->removeController(controllerId);
} else {
(*intReturn) = TELLSTICK_ERROR_UNKNOWN;
}
}
void ClientCommunicationHandler::sendDeviceSignal(int deviceId, int eventDeviceChanges, int eventChangeType) {
EventUpdateData *eventData = new EventUpdateData();
eventData->messageType = L"TDDeviceChangeEvent";
eventData->deviceId = deviceId;
eventData->eventDeviceChanges = eventDeviceChanges;
eventData->eventChangeType = eventChangeType;
d->deviceUpdateEvent->signal(eventData);
}

View File

@@ -0,0 +1,41 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_CLIENTCOMMUNICATIONHANDLER_H_
#define TELLDUS_CORE_SERVICE_CLIENTCOMMUNICATIONHANDLER_H_
#include <string>
#include "common/Thread.h"
#include "common/Socket.h"
#include "common/Event.h"
#include "service/DeviceManager.h"
#include "service/ControllerManager.h"
class ClientCommunicationHandler : public TelldusCore::Thread {
public:
ClientCommunicationHandler();
ClientCommunicationHandler(
TelldusCore::Socket *clientSocket,
TelldusCore::EventRef event,
DeviceManager *deviceManager,
TelldusCore::EventRef deviceUpdateEvent,
ControllerManager *controllerManager
);
~ClientCommunicationHandler(void);
bool isDone();
protected:
void run();
private:
class PrivateData;
PrivateData *d;
void parseMessage(const std::wstring &clientMessage, int *intReturn, std::wstring *wstringReturn);
void sendDeviceSignal(int deviceId, int eventDeviceChanges, int eventChangeType);
};
#endif // TELLDUS_CORE_SERVICE_CLIENTCOMMUNICATIONHANDLER_H_

View File

@@ -0,0 +1,37 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_CONNECTIONLISTENER_H_
#define TELLDUS_CORE_SERVICE_CONNECTIONLISTENER_H_
#include <string>
#include "common/Thread.h"
#include "common/Event.h"
class Event;
namespace TelldusCore {
class Socket;
};
class ConnectionListenerEventData : public TelldusCore::EventDataBase {
public:
TelldusCore::Socket *socket;
};
class ConnectionListener : public TelldusCore::Thread {
public:
ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent);
virtual ~ConnectionListener(void);
protected:
void run();
private:
class PrivateData;
PrivateData *d;
};
#endif // TELLDUS_CORE_SERVICE_CONNECTIONLISTENER_H_

View File

@@ -0,0 +1,100 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string>
#include "service/ConnectionListener.h"
#include "common/Socket.h"
#if defined(_MACOSX) && !defined(SOCK_CLOEXEC)
#define SOCK_CLOEXEC 0
#endif
class ConnectionListener::PrivateData {
public:
TelldusCore::EventRef waitEvent;
std::string name;
bool running;
};
ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent) {
d = new PrivateData;
d->waitEvent = waitEvent;
d->name = "/tmp/" + std::string(name.begin(), name.end());
d->running = true;
this->start();
}
ConnectionListener::~ConnectionListener(void) {
d->running = false;
this->wait();
unlink(d->name.c_str());
delete d;
}
void ConnectionListener::run() {
struct timeval tv = { 0, 0 };
// Timeout for select
SOCKET_T serverSocket;
struct sockaddr_un name;
serverSocket = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (serverSocket < 0) {
return;
}
#if defined(_MACOSX)
int op = fcntl(serverSocket, F_GETFD);
fcntl(serverSocket, F_SETFD, op | FD_CLOEXEC); // OS X doesn't support SOCK_CLOEXEC yet
#endif
name.sun_family = AF_LOCAL;
memset(name.sun_path, '\0', sizeof(name.sun_path));
strncpy(name.sun_path, d->name.c_str(), sizeof(name.sun_path));
unlink(name.sun_path);
int size = SUN_LEN(&name);
bind(serverSocket, (struct sockaddr *)&name, size);
listen(serverSocket, 5);
// Change permissions to allow everyone
chmod(d->name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
fd_set infds;
FD_ZERO(&infds);
FD_SET(serverSocket, &infds);
while(d->running) {
tv.tv_sec = 5;
int response = select(serverSocket+1, &infds, NULL, NULL, &tv);
if (response == 0) {
FD_SET(serverSocket, &infds);
continue;
} else if (response < 0 ) {
continue;
}
// Make sure it is a new connection
if (!FD_ISSET(serverSocket, &infds)) {
continue;
}
SOCKET_T clientSocket = accept(serverSocket, NULL, NULL);
ConnectionListenerEventData *data = new ConnectionListenerEventData();
data->socket = new TelldusCore::Socket(clientSocket);
d->waitEvent->signal(data);
}
close(serverSocket);
}

View File

@@ -0,0 +1,153 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ConnectionListener.h"
#include <AccCtrl.h>
#include <Aclapi.h>
#include <windows.h>
#include "common/Event.h"
#include "common/Socket.h"
#define BUFSIZE 512
class ConnectionListener::PrivateData {
public:
std::wstring pipename;
SECURITY_ATTRIBUTES sa;
HANDLE hEvent;
bool running;
TelldusCore::EventRef waitEvent;
};
ConnectionListener::ConnectionListener(const std::wstring &name, TelldusCore::EventRef waitEvent) {
d = new PrivateData;
d->hEvent = 0;
d->running = true;
d->waitEvent = waitEvent;
d->pipename = L"\\\\.\\pipe\\" + name;
PSECURITY_DESCRIPTOR pSD = NULL;
PACL pACL = NULL;
EXPLICIT_ACCESS ea;
PSID pEveryoneSID = NULL;
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
pSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (pSD == NULL) {
return;
}
if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) {
LocalFree(pSD);
return;
}
if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID)) {
LocalFree(pSD);
}
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = STANDARD_RIGHTS_ALL;
ea.grfAccessMode = SET_ACCESS;
ea.grfInheritance= NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
ea.Trustee.ptstrName = (LPTSTR) pEveryoneSID;
// Add the ACL to the security descriptor.
if (!SetSecurityDescriptorDacl(pSD,
TRUE, // bDaclPresent flag
pACL,
FALSE)) { // not a default DACL
LocalFree(pSD);
FreeSid(pEveryoneSID);
}
d->sa.nLength = sizeof(SECURITY_ATTRIBUTES);
d->sa.lpSecurityDescriptor = pSD;
d->sa.bInheritHandle = false;
start();
}
ConnectionListener::~ConnectionListener(void) {
d->running = false;
if (d->hEvent) {
SetEvent(d->hEvent);
}
wait();
delete d;
}
void ConnectionListener::run() {
HANDLE hPipe;
OVERLAPPED oOverlap;
DWORD cbBytesRead;
memset(&oOverlap, 0, sizeof(OVERLAPPED));
d->hEvent = CreateEvent(NULL, true, false, NULL);
oOverlap.hEvent = d->hEvent;
bool recreate = true;
while (1) {
BOOL alreadyConnected = false;
if (recreate) {
hPipe = CreateNamedPipe(
(const wchar_t *)d->pipename.c_str(), // pipe name
PIPE_ACCESS_DUPLEX | // read/write access
FILE_FLAG_OVERLAPPED, // Overlapped mode
PIPE_TYPE_MESSAGE | // message type pipe
PIPE_READMODE_MESSAGE | // message-read mode
PIPE_WAIT, // blocking mode
PIPE_UNLIMITED_INSTANCES, // max. instances
BUFSIZE, // output buffer size
BUFSIZE, // input buffer size
0, // client time-out
&d->sa); // default security attribute
if (hPipe == INVALID_HANDLE_VALUE) {
return;
}
ConnectNamedPipe(hPipe, &oOverlap);
alreadyConnected = GetLastError() == ERROR_PIPE_CONNECTED;
recreate = false;
}
if(!alreadyConnected) {
DWORD result = WaitForSingleObject(oOverlap.hEvent, 1000);
if (!d->running) {
CancelIo(hPipe);
WaitForSingleObject(oOverlap.hEvent, INFINITE);
break;
}
if(result == WAIT_TIMEOUT) {
// CloseHandle(hPipe);
continue;
}
BOOL connected = GetOverlappedResult(hPipe, &oOverlap, &cbBytesRead, false);
if (!connected) {
CloseHandle(hPipe);
return;
}
}
ConnectionListenerEventData *data = new ConnectionListenerEventData();
ResetEvent(oOverlap.hEvent);
data->socket = new TelldusCore::Socket(hPipe);
d->waitEvent->signal(data);
recreate = true;
}
CloseHandle(d->hEvent);
CloseHandle(hPipe);
}

View File

@@ -0,0 +1,99 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#define _CRT_RAND_S
#include "service/Controller.h"
#include <stdlib.h>
#include <time.h>
#include <map>
#include <list>
#include <string>
#include "service/Protocol.h"
#include "service/EventUpdateManager.h"
#include "common/Strings.h"
inline int random( unsigned int* seed ) {
#ifdef _WINDOWS
unsigned int randomNumber;
rand_s( &randomNumber ); // no seed needed
return randomNumber;
#else
return rand_r( seed );
#endif
}
class Controller::PrivateData {
public:
TelldusCore::EventRef event, updateEvent;
int id, firmwareVersion;
unsigned int randSeed;
std::map<std::string, time_t> duplicates;
};
Controller::Controller(int id, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent) {
d = new PrivateData;
d->event = event;
d->updateEvent = updateEvent;
d->id = id;
d->firmwareVersion = 0;
d->randSeed = time(NULL);
}
Controller::~Controller() {
delete d;
}
void Controller::publishData(const std::string &msg) const {
ControllerEventData *data = new ControllerEventData;
data->msg = msg;
data->controllerId = d->id;
d->event->signal(data);
}
void Controller::decodePublishData(const std::string &data) const {
// Garbange collect?
if (random(&d->randSeed) % 1000 == 1) {
time_t t = time(NULL);
// Standard associative-container erase idiom
for (std::map<std::string, time_t>::iterator it = d->duplicates.begin(); it != d->duplicates.end(); /* no increment */) {
if ((*it).second != t) {
d->duplicates.erase(it++);
} else {
++it;
}
}
}
// Duplicate check
if (d->duplicates.count(data) > 0) {
time_t t = d->duplicates[data];
if (t == time(NULL)) {
// Duplicate message
return;
}
}
d->duplicates[data] = time(NULL);
std::list<std::string> msgList = Protocol::decodeData(data);
for (std::list<std::string>::iterator msgIt = msgList.begin(); msgIt != msgList.end(); ++msgIt) {
this->publishData(*msgIt);
}
}
int Controller::firmwareVersion() const {
return d->firmwareVersion;
}
void Controller::setFirmwareVersion(int version) {
d->firmwareVersion = version;
EventUpdateData *eventData = new EventUpdateData();
eventData->messageType = L"TDControllerEvent";
eventData->controllerId = d->id;
eventData->eventState = TELLSTICK_DEVICE_CHANGED;
eventData->eventChangeType = TELLSTICK_CHANGE_FIRMWARE;
eventData->eventValue = TelldusCore::intToWstring(version);
d->updateEvent->signal(eventData);
}

View File

@@ -0,0 +1,38 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_CONTROLLER_H_
#define TELLDUS_CORE_SERVICE_CONTROLLER_H_
#include <string>
#include "common/Event.h"
class ControllerEventData : public TelldusCore::EventDataBase {
public:
std::string msg;
int controllerId;
};
class Controller {
public:
virtual ~Controller();
virtual int firmwareVersion() const;
virtual int send( const std::string &message ) = 0;
virtual int reset() = 0;
protected:
Controller(int id, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent);
void publishData(const std::string &data) const;
void decodePublishData(const std::string &data) const;
void setFirmwareVersion(int version);
private:
class PrivateData;
PrivateData *d;
};
#endif // TELLDUS_CORE_SERVICE_CONTROLLER_H_

View File

@@ -0,0 +1,32 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_CONTROLLERLISTENER_H_
#define TELLDUS_CORE_SERVICE_CONTROLLERLISTENER_H_
#include "common/Thread.h"
#include "common/Event.h"
class ControllerChangeEventData : public TelldusCore::EventDataBase {
public:
int vid, pid;
bool inserted;
};
class ControllerListener : public TelldusCore::Thread {
public:
explicit ControllerListener(TelldusCore::EventRef event);
virtual ~ControllerListener();
protected:
void run();
private:
class PrivateData;
PrivateData *d;
};
#endif // TELLDUS_CORE_SERVICE_CONTROLLERLISTENER_H_

View File

@@ -0,0 +1,187 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ControllerListener.h"
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/IOMessage.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/usb/IOUSBLib.h>
#include <string>
class TellStickData {
public:
io_object_t notification;
CFStringRef serialNumber;
UInt32 vid;
UInt32 pid;
TelldusCore::EventRef event;
};
class ControllerListener::PrivateData {
public:
IONotificationPortRef gNotifyPort;
CFRunLoopRef gRunLoop;
io_iterator_t gAddedIter;
TelldusCore::EventRef event;
bool running;
void addUsbFilter(int vid, int pid);
static void DeviceAdded(void *refCon, io_iterator_t iterator);
static void DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument);
};
ControllerListener::ControllerListener(TelldusCore::EventRef event)
:Thread() {
d = new PrivateData;
d->event = event;
d->running = true;
d->gRunLoop = NULL;
this->start();
}
ControllerListener::~ControllerListener() {
d->running = false;
if(d->gRunLoop != NULL)
CFRunLoopStop(d->gRunLoop);
this->wait();
delete d;
}
void ControllerListener::run() {
CFRunLoopSourceRef runLoopSource;
d->gNotifyPort = IONotificationPortCreate(kIOMasterPortDefault);
runLoopSource = IONotificationPortGetRunLoopSource(d->gNotifyPort);
d->gRunLoop = CFRunLoopGetCurrent();
CFRunLoopAddSource(d->gRunLoop, runLoopSource, kCFRunLoopDefaultMode);
d->addUsbFilter(0x1781, 0x0c30);
d->addUsbFilter(0x1781, 0x0c31);
// Race check, if destructor was called really close to thread init,
// running might have gone false. Make sure we don't get stuck
if (d->running) {
CFRunLoopRun();
}
}
void ControllerListener::PrivateData::addUsbFilter(int vid, int pid) {
CFNumberRef numberRef;
CFMutableDictionaryRef matchingDict;
matchingDict = IOServiceMatching(kIOUSBDeviceClassName); // Interested in instances of class
// IOUSBDevice and its subclasses
if (matchingDict == NULL) {
return;
}
// Create a CFNumber for the idVendor and set the value in the dictionary
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vid);
CFDictionarySetValue(matchingDict, CFSTR(kUSBVendorID), numberRef);
CFRelease(numberRef);
// Create a CFNumber for the idProduct and set the value in the dictionary
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pid);
CFDictionarySetValue(matchingDict, CFSTR(kUSBProductID), numberRef);
CFRelease(numberRef);
// Now set up a notification to be called when a device is first matched by I/O Kit.
IOServiceAddMatchingNotification(gNotifyPort, // notifyPort
kIOFirstMatchNotification, // notificationType
matchingDict, // matching
PrivateData::DeviceAdded, // callback
this, // refCon
&gAddedIter // notification
);
// Iterate once to get already-present devices and arm the notification
PrivateData::DeviceAdded(this, gAddedIter);
}
void ControllerListener::PrivateData::DeviceNotification(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) {
if (messageType != kIOMessageServiceIsTerminated) {
return;
}
TellStickData *tsd = reinterpret_cast<TellStickData*> (refCon);
if (!tsd) {
return;
}
CFIndex size = CFStringGetLength(tsd->serialNumber);
char *s = new char[size+1];
CFStringGetCString(tsd->serialNumber, s, size+1, kCFStringEncodingASCII);
std::string serial(s); // Copy the string to the stack
delete[] s;
ControllerChangeEventData *data = new ControllerChangeEventData;
data->vid = tsd->vid;
data->pid = tsd->pid;
data->inserted = false;
tsd->event->signal(data);
// Free the data we're no longer using now that the device is going away
CFRelease(tsd->serialNumber);
IOObjectRelease(tsd->notification);
delete tsd;
}
void ControllerListener::PrivateData::DeviceAdded(void *refCon, io_iterator_t iterator) {
io_service_t usbDevice;
PrivateData *pd = reinterpret_cast<PrivateData*> (refCon);
while ((usbDevice = IOIteratorNext(iterator))) {
TellStickData *tsd = new TellStickData;
tsd->event = pd->event;
// Get the serial number
CFStringRef serialRef = reinterpret_cast<CFStringRef>(IORegistryEntryCreateCFProperty( usbDevice, CFSTR("USB Serial Number" ), kCFAllocatorDefault, 0 ));
if (serialRef == NULL) {
// No serial number, we cannot continue. Sorry
continue;
}
CFNumberRef vidRef = reinterpret_cast<CFNumberRef> (IORegistryEntryCreateCFProperty(usbDevice, CFSTR("idVendor"), kCFAllocatorDefault, 0));
if (vidRef) {
CFNumberGetValue(vidRef, kCFNumberIntType, &(tsd->vid));
CFRelease(vidRef);
}
CFNumberRef pidRef = reinterpret_cast<CFNumberRef> (IORegistryEntryCreateCFProperty(usbDevice, CFSTR("idProduct"), kCFAllocatorDefault, 0));
if (pidRef) {
CFNumberGetValue(pidRef, kCFNumberIntType, &(tsd->pid));
CFRelease(pidRef);
}
CFStringRef serialNumberAsCFString = CFStringCreateCopy(kCFAllocatorDefault, serialRef);
tsd->serialNumber = serialNumberAsCFString;
CFRelease(serialRef);
// Register for an interest notification of this device being removed. Use a reference to our
// private data as the refCon which will be passed to the notification callback.
IOServiceAddInterestNotification(pd->gNotifyPort, usbDevice, kIOGeneralInterest, DeviceNotification, tsd, &(tsd->notification));
CFIndex size = CFStringGetLength(serialNumberAsCFString);
char *s = new char[size+1];
CFStringGetCString(serialNumberAsCFString, s, size+1, kCFStringEncodingASCII);
std::string serial(s); // Copy the string to the stack
delete[] s;
IOObjectRelease(usbDevice);
ControllerChangeEventData *data = new ControllerChangeEventData;
data->vid = tsd->vid;
data->pid = tsd->pid;
data->inserted = true;
tsd->event->signal(data);
}
}

View File

@@ -0,0 +1,374 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ControllerManager.h"
#include <stdio.h>
#include <list>
#include <map>
#include <string>
#include "service/Controller.h"
#include "common/Mutex.h"
#include "service/TellStick.h"
#include "service/Log.h"
#include "common/Message.h"
#include "common/Strings.h"
#include "service/Settings.h"
#include "service/EventUpdateManager.h"
#include "client/telldus-core.h"
class ControllerDescriptor {
public:
std::wstring name, serial;
int type;
Controller *controller;
};
typedef std::map<int, ControllerDescriptor> ControllerMap;
class ControllerManager::PrivateData {
public:
int lastControllerId;
Settings settings;
ControllerMap controllers;
TelldusCore::EventRef event, updateEvent;
TelldusCore::Mutex mutex;
};
ControllerManager::ControllerManager(TelldusCore::EventRef event, TelldusCore::EventRef updateEvent) {
d = new PrivateData;
d->lastControllerId = 0;
d->event = event;
d->updateEvent = updateEvent;
this->loadStoredControllers();
this->loadControllers();
}
ControllerManager::~ControllerManager() {
for (ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) {
if (it->second.controller) {
delete( it->second.controller );
}
}
delete d;
}
int ControllerManager::count() {
unsigned int count = 0;
{
TelldusCore::MutexLocker locker(&d->mutex);
// Find all available controllers
for(ControllerMap::const_iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) {
if (it->second.controller) {
++count;
}
}
}
if (count == 0) {
this->loadControllers();
// Try again
TelldusCore::MutexLocker locker(&d->mutex);
// Find all available controllers
for(ControllerMap::const_iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) {
if (it->second.controller) {
++count;
}
}
}
return count;
}
void ControllerManager::deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted) {
if (vid == 0x0 && pid == 0x0) { // All
if (inserted) {
loadControllers();
} else {
// Disconnect all
TelldusCore::MutexLocker locker(&d->mutex);
while(d->controllers.size()) {
ControllerMap::iterator it = d->controllers.begin();
delete it->second.controller;
it->second.controller = 0;
signalControllerEvent(it->first, TELLSTICK_DEVICE_STATE_CHANGED, TELLSTICK_CHANGE_AVAILABLE, L"0");
}
}
return;
}
if (vid != 0x1781) {
return;
}
if (pid != 0x0C30 && pid != 0x0C31) {
return;
}
if (inserted) {
loadControllers();
} else {
// Autodetect which has been disconnected
TelldusCore::MutexLocker locker(&d->mutex);
for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) {
if (!it->second.controller) {
continue;
}
TellStick *tellstick = reinterpret_cast<TellStick*>(it->second.controller);
if (!tellstick) {
continue;
}
if (serial.compare("") != 0) {
TellStickDescriptor tsd;
tsd.vid = vid;
tsd.pid = pid;
tsd.serial = serial;
if (!tellstick->isSameAsDescriptor(tsd)) {
continue;
}
} else if (tellstick->stillConnected()) {
continue;
}
it->second.controller = 0;
delete tellstick;
signalControllerEvent(it->first, TELLSTICK_DEVICE_STATE_CHANGED, TELLSTICK_CHANGE_AVAILABLE, L"0");
}
}
}
Controller *ControllerManager::getBestControllerById(int id) {
TelldusCore::MutexLocker locker(&d->mutex);
if (!d->controllers.size()) {
return 0;
}
ControllerMap::const_iterator it = d->controllers.find(id);
if (it != d->controllers.end() && it->second.controller) {
return it->second.controller;
}
// Find first available controller
for(it = d->controllers.begin(); it != d->controllers.end(); ++it) {
if (it->second.controller) {
return it->second.controller;
}
}
return 0;
}
void ControllerManager::loadControllers() {
TelldusCore::MutexLocker locker(&d->mutex);
std::list<TellStickDescriptor> list = TellStick::findAll();
std::list<TellStickDescriptor>::iterator it = list.begin();
for(; it != list.end(); ++it) {
// Most backend only report non-opened devices.
// If they don't make sure we don't open them twice
bool found = false;
ControllerMap::const_iterator cit = d->controllers.begin();
for(; cit != d->controllers.end(); ++cit) {
if (!cit->second.controller) {
continue;
}
TellStick *tellstick = reinterpret_cast<TellStick*>(cit->second.controller);
if (!tellstick) {
continue;
}
if (tellstick->isSameAsDescriptor(*it)) {
found = true;
break;
}
}
if (found) {
continue;
}
int type = TELLSTICK_CONTROLLER_TELLSTICK;
if ((*it).pid == 0x0c31) {
type = TELLSTICK_CONTROLLER_TELLSTICK_DUO;
}
int controllerId = 0;
// See if the controller matches one of the loaded, non available controllers
std::wstring serial = TelldusCore::charToWstring((*it).serial.c_str());
for(cit = d->controllers.begin(); cit != d->controllers.end(); ++cit) {
if (cit->second.type == type && cit->second.serial.compare(serial) == 0) {
controllerId = cit->first;
break;
}
}
bool isNew = false;
if (!controllerId) {
controllerId = d->settings.addNode(Settings::Controller);
if(controllerId < 0) {
// TODO(micke): How to handle this?
continue;
}
isNew = true;
d->controllers[controllerId].type = type;
d->settings.setControllerType(controllerId, type);
d->controllers[controllerId].serial = TelldusCore::charToWstring((*it).serial.c_str());
d->settings.setControllerSerial(controllerId, d->controllers[controllerId].serial);
}
// int controllerId = d->lastControllerId+1;
TellStick *controller = new TellStick(controllerId, d->event, d->updateEvent, *it);
if (!controller->isOpen()) {
delete controller;
continue;
}
d->controllers[controllerId].controller = controller;
if (isNew) {
signalControllerEvent(controllerId, TELLSTICK_DEVICE_ADDED, type, L"");
} else {
signalControllerEvent(controllerId, TELLSTICK_DEVICE_STATE_CHANGED, TELLSTICK_CHANGE_AVAILABLE, L"1");
}
}
}
void ControllerManager::loadStoredControllers() {
int numberOfControllers = d->settings.getNumberOfNodes(Settings::Controller);
TelldusCore::MutexLocker locker(&d->mutex);
for (int i = 0; i < numberOfControllers; ++i) {
int id = d->settings.getNodeId(Settings::Controller, i);
d->controllers[id].controller = NULL;
d->controllers[id].name = d->settings.getName(Settings::Controller, id);
const int type = d->settings.getControllerType(id);
d->controllers[id].type = type;
d->controllers[id].serial = d->settings.getControllerSerial(id);
signalControllerEvent(id, TELLSTICK_DEVICE_ADDED, type, L"");
}
}
void ControllerManager::queryControllerStatus() {
std::list<TellStick *> tellStickControllers;
{
TelldusCore::MutexLocker locker(&d->mutex);
for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) {
if (!it->second.controller) {
continue;
}
TellStick *tellstick = reinterpret_cast<TellStick*>(it->second.controller);
if (tellstick) {
tellStickControllers.push_back(tellstick);
}
}
}
bool reloadControllers = false;
std::string noop = "N+";
for(std::list<TellStick *>::iterator it = tellStickControllers.begin(); it != tellStickControllers.end(); ++it) {
int success = (*it)->send(noop);
if(success == TELLSTICK_ERROR_BROKEN_PIPE) {
Log::warning("TellStick query: Error in communication with TellStick, resetting USB");
resetController(*it);
}
if(success == TELLSTICK_ERROR_BROKEN_PIPE || success == TELLSTICK_ERROR_NOT_FOUND) {
reloadControllers = true;
}
}
if(!tellStickControllers.size() || reloadControllers) {
// no tellstick at all found, or controller was reset
Log::debug("TellStick query: Rescanning USB ports"); // only log as debug, since this will happen all the time if no TellStick is connected
loadControllers();
}
}
int ControllerManager::resetController(Controller *controller) {
TellStick *tellstick = reinterpret_cast<TellStick*>(controller);
if (!tellstick) {
return true; // not tellstick, nothing to reset at the moment, just return true
}
int success = tellstick->reset();
deviceInsertedOrRemoved(tellstick->vid(), tellstick->pid(), tellstick->serial(), false); // remove from list and delete
return success;
}
std::wstring ControllerManager::getControllers() const {
TelldusCore::MutexLocker locker(&d->mutex);
TelldusCore::Message msg;
msg.addArgument(static_cast<int>(d->controllers.size()));
for(ControllerMap::iterator it = d->controllers.begin(); it != d->controllers.end(); ++it) {
msg.addArgument(it->first);
msg.addArgument(it->second.type);
msg.addArgument(it->second.name.c_str());
msg.addArgument(it->second.controller ? 1 : 0);
}
return msg;
}
std::wstring ControllerManager::getControllerValue(int id, const std::wstring &name) {
TelldusCore::MutexLocker locker(&d->mutex);
ControllerMap::iterator it = d->controllers.find(id);
if (it == d->controllers.end()) {
return L"";
}
if (name == L"serial") {
return it->second.serial;
} else if (name == L"name") {
return it->second.name;
} else if (name == L"available") {
return it->second.controller ? L"1" : L"0";
} else if (name == L"firmware") {
if (!it->second.controller) {
return L"-1";
}
return TelldusCore::intToWstring(it->second.controller->firmwareVersion());
}
return L"";
}
int ControllerManager::removeController(int id) {
TelldusCore::MutexLocker locker(&d->mutex);
ControllerMap::iterator it = d->controllers.find(id);
if (it == d->controllers.end()) {
return TELLSTICK_ERROR_NOT_FOUND;
}
if (it->second.controller) {
// Still connected
return TELLSTICK_ERROR_PERMISSION_DENIED;
}
int ret = d->settings.removeNode(Settings::Controller, id);
if (ret != TELLSTICK_SUCCESS) {
return ret;
}
d->controllers.erase(it);
signalControllerEvent(id, TELLSTICK_DEVICE_REMOVED, 0, L"");
return TELLSTICK_SUCCESS;
}
int ControllerManager::setControllerValue(int id, const std::wstring &name, const std::wstring &value) {
TelldusCore::MutexLocker locker(&d->mutex);
ControllerMap::iterator it = d->controllers.find(id);
if (it == d->controllers.end()) {
return TELLSTICK_ERROR_NOT_FOUND;
}
if (name == L"name") {
it->second.name = value;
d->settings.setName(Settings::Controller, id, value);
signalControllerEvent(id, TELLSTICK_DEVICE_CHANGED, TELLSTICK_CHANGE_NAME, value);
} else {
return TELLSTICK_ERROR_SYNTAX; // TODO(micke): Is this the best error?
}
return TELLSTICK_SUCCESS;
}
void ControllerManager::signalControllerEvent(int controllerId, int changeEvent, int changeType, const std::wstring &newValue) {
EventUpdateData *eventData = new EventUpdateData();
eventData->messageType = L"TDControllerEvent";
eventData->controllerId = controllerId;
eventData->eventState = changeEvent;
eventData->eventChangeType = changeType;
eventData->eventValue = newValue;
d->updateEvent->signal(eventData);
}

View File

@@ -0,0 +1,40 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_CONTROLLERMANAGER_H_
#define TELLDUS_CORE_SERVICE_CONTROLLERMANAGER_H_
#include <string>
#include "common/Event.h"
class Controller;
class ControllerManager {
public:
ControllerManager(TelldusCore::EventRef event, TelldusCore::EventRef updateEvent);
~ControllerManager(void);
void deviceInsertedOrRemoved(int vid, int pid, const std::string &serial, bool inserted);
int count();
Controller *getBestControllerById(int id);
void loadControllers();
void loadStoredControllers();
void queryControllerStatus();
int resetController(Controller *controller);
std::wstring getControllers() const;
std::wstring getControllerValue(int id, const std::wstring &name);
int removeController(int id);
int setControllerValue(int id, const std::wstring &name, const std::wstring &value);
private:
void signalControllerEvent(int controllerId, int changeEvent, int changeType, const std::wstring &newValue);
class PrivateData;
PrivateData *d;
};
#endif // TELLDUS_CORE_SERVICE_CONTROLLERMANAGER_H_

View File

@@ -0,0 +1,95 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ControllerMessage.h"
#include <map>
#include <string>
#include "service/Device.h"
#include "common/Strings.h"
#include "common/common.h"
class ControllerMessage::PrivateData {
public:
std::map<std::string, std::string> parameters;
std::string protocol, model, msgClass;
int method;
};
ControllerMessage::ControllerMessage(const std::string &message) {
d = new PrivateData;
// Process our message into bits
size_t prevPos = 0;
size_t pos = message.find(";");
while(pos != std::string::npos) {
std::string param = message.substr(prevPos, pos-prevPos);
prevPos = pos+1;
size_t delim = param.find(":");
if (delim == std::string::npos) {
break;
}
if (param.substr(0, delim).compare("class") == 0) {
d->msgClass = param.substr(delim+1, param.length()-delim);
} else if (param.substr(0, delim).compare("protocol") == 0) {
d->protocol = param.substr(delim+1, param.length()-delim);
} else if (param.substr(0, delim).compare("model") == 0) {
d->model = param.substr(delim+1, param.length()-delim);
} else if (param.substr(0, delim).compare("method") == 0) {
d->method = Device::methodId(param.substr(delim+1, param.length()-delim));
} else {
d->parameters[param.substr(0, delim)] = param.substr(delim+1, param.length()-delim);
}
pos = message.find(";", pos+1);
}
}
ControllerMessage::~ControllerMessage() {
delete d;
}
std::string ControllerMessage::msgClass() const {
return d->msgClass;
}
int ControllerMessage::method() const {
return d->method;
}
std::wstring ControllerMessage::protocol() const {
return TelldusCore::charToWstring(d->protocol.c_str());
}
std::wstring ControllerMessage::model() const {
return TelldusCore::charToWstring(d->model.c_str());
}
uint64_t ControllerMessage::getInt64Parameter(const std::string &key) const {
std::string strValue = getParameter(key);
if (strValue.compare("") == 0) {
return -1;
}
if (strValue.substr(0, 2).compare("0x") == 0) {
return TelldusCore::hexTo64l(strValue);
}
// TODO(micke): strtol() does not return uint64_t. Create a platform independent version similar to hexTo64l()
return strtol(strValue.c_str(), NULL, 10);
}
std::string ControllerMessage::getParameter(const std::string &key) const {
std::map<std::string, std::string>::iterator it = d->parameters.find(key);
if (it == d->parameters.end()) {
return "";
}
return d->parameters[key];
}
bool ControllerMessage::hasParameter(const std::string &key) const {
std::map<std::string, std::string>::iterator it = d->parameters.find(key);
if (it == d->parameters.end()) {
return false;
}
return true;
}

View File

@@ -0,0 +1,36 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_CONTROLLERMESSAGE_H_
#define TELLDUS_CORE_SERVICE_CONTROLLERMESSAGE_H_
#ifdef _MSC_VER
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif
#include <string>
class ControllerMessage {
public:
explicit ControllerMessage(const std::string &rawMessage);
virtual ~ControllerMessage();
std::string msgClass() const;
uint64_t getInt64Parameter(const std::string &key) const;
std::string getParameter(const std::string &key) const;
int method() const;
std::wstring protocol() const;
std::wstring model() const;
bool hasParameter(const std::string &key) const;
private:
class PrivateData;
PrivateData *d;
};
#endif // TELLDUS_CORE_SERVICE_CONTROLLERMESSAGE_H_

View File

@@ -0,0 +1,272 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/Device.h"
#include <list>
#include <string>
#include "service/Settings.h"
#include "service/TellStick.h"
class Device::PrivateData {
public:
std::wstring model;
std::wstring name;
ParameterMap parameterList;
Protocol *protocol;
std::wstring protocolName;
int preferredControllerId;
int state;
std::wstring stateValue;
};
Device::Device(int id)
:Mutex() {
d = new PrivateData;
d->protocol = 0;
d->preferredControllerId = 0;
d->state = 0;
}
Device::~Device(void) {
delete d->protocol;
delete d;
}
/**
* Get-/Set-methods
*/
int Device::getLastSentCommand(int methodsSupported) {
int lastSentCommand = Device::maskUnsupportedMethods(d->state, methodsSupported);
if (lastSentCommand == TELLSTICK_BELL) {
// Bell is not a state
lastSentCommand = TELLSTICK_TURNOFF;
}
if (lastSentCommand == 0) {
lastSentCommand = TELLSTICK_TURNOFF;
}
return lastSentCommand;
}
int Device::getMethods() const {
Protocol *p = this->retrieveProtocol();
if (p) {
return p->methods();
}
return 0;
}
void Device::setLastSentCommand(int command, std::wstring value) {
d->state = command;
d->stateValue = value;
}
std::wstring Device::getModel() {
return d->model;
}
void Device::setModel(const std::wstring &model) {
if(d->protocol) {
delete(d->protocol);
d->protocol = 0;
}
d->model = model;
}
std::wstring Device::getName() {
return d->name;
}
void Device::setName(const std::wstring &name) {
d->name = name;
}
std::wstring Device::getParameter(const std::wstring &key) {
ParameterMap::iterator it = d->parameterList.find(key);
if (it == d->parameterList.end()) {
return L"";
}
return d->parameterList[key];
}
std::list<std::string> Device::getParametersForProtocol() const {
return Protocol::getParametersForProtocol(getProtocolName());
}
void Device::setParameter(const std::wstring &key, const std::wstring &value) {
d->parameterList[key] = value;
if(d->protocol) {
d->protocol->setParameters(d->parameterList);
}
}
int Device::getPreferredControllerId() {
return d->preferredControllerId;
}
void Device::setPreferredControllerId(int controllerId) {
d->preferredControllerId = controllerId;
}
std::wstring Device::getProtocolName() const {
return d->protocolName;
}
void Device::setProtocolName(const std::wstring &protocolName) {
if(d->protocol) {
delete(d->protocol);
d->protocol = 0;
}
d->protocolName = protocolName;
}
std::wstring Device::getStateValue() {
return d->stateValue;
}
int Device::getType() {
if(d->protocolName == L"group") {
return TELLSTICK_TYPE_GROUP;
} else if(d->protocolName == L"scene") {
return TELLSTICK_TYPE_SCENE;
}
return TELLSTICK_TYPE_DEVICE;
}
/**
* End Get-/Set
*/
int Device::doAction(int action, unsigned char data, Controller *controller) {
Protocol *p = this->retrieveProtocol();
if (!p) {
// Syntax error in configuration, no such protocol
return TELLSTICK_ERROR_CONFIG_SYNTAX;
}
// Try to determine if we need to call another method due to masking
int method = this->isMethodSupported(action);
if (method <= 0) {
return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED;
}
std::string code = p->getStringForMethod(method, data, controller);
if (code == "") {
return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED;
}
if (code[0] != 'S' && code[0] != 'T' && code[0] != 'P' && code[0] != 'R') {
// Try autodetect sendtype
TellStick *tellstick = reinterpret_cast<TellStick *>(controller);
if (!tellstick) {
return TELLSTICK_ERROR_UNKNOWN;
}
unsigned int maxlength = 80;
if (tellstick->pid() == 0x0c31) {
maxlength = 512;
}
if (code.length() <= maxlength) {
// S is enough
code.insert(0, 1, 'S');
code.append(1, '+');
} else {
code = TellStick::createTPacket(code);
}
}
return controller->send(code);
}
int Device::isMethodSupported(int method) const {
Protocol *p = this->retrieveProtocol();
if (!p) {
// Syntax error in configuration, no such protocol
return TELLSTICK_ERROR_CONFIG_SYNTAX;
}
// Try to determine if we need to call another method due to masking
int methods = p->methods();
if ((method & methods) == 0) {
// Loop all methods an see if any method masks to this one
for(int i = 1; i <= methods; i <<= 1) {
if ((i & methods) == 0) {
continue;
}
if (this->maskUnsupportedMethods(i, method)) {
method = i;
break;
}
}
}
if ((method & methods) == 0) {
return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED;
}
return method;
}
Protocol* Device::retrieveProtocol() const {
if (d->protocol) {
return d->protocol;
}
d->protocol = Protocol::getProtocolInstance(d->protocolName);
if(d->protocol) {
d->protocol->setModel(d->model);
d->protocol->setParameters(d->parameterList);
return d->protocol;
}
return 0;
}
int Device::maskUnsupportedMethods(int methods, int supportedMethods) {
// Bell -> On
if ((methods & TELLSTICK_BELL) && !(supportedMethods & TELLSTICK_BELL)) {
methods |= TELLSTICK_TURNON;
}
// Execute -> On
if ((methods & TELLSTICK_EXECUTE) && !(supportedMethods & TELLSTICK_EXECUTE)) {
methods |= TELLSTICK_TURNON;
}
// Up -> Off
if ((methods & TELLSTICK_UP) && !(supportedMethods & TELLSTICK_UP)) {
methods |= TELLSTICK_TURNOFF;
}
// Down -> On
if ((methods & TELLSTICK_DOWN) && !(supportedMethods & TELLSTICK_DOWN)) {
methods |= TELLSTICK_TURNON;
}
// Cut of the rest of the unsupported methods we don't have a fallback for
return methods & supportedMethods;
}
int Device::methodId( const std::string &methodName ) {
if (methodName.compare("turnon") == 0) {
return TELLSTICK_TURNON;
}
if (methodName.compare("turnoff") == 0) {
return TELLSTICK_TURNOFF;
}
if (methodName.compare("bell") == 0) {
return TELLSTICK_BELL;
}
if (methodName.compare("dim") == 0) {
return TELLSTICK_DIM;
}
if (methodName.compare("execute") == 0) {
return TELLSTICK_EXECUTE;
}
if (methodName.compare("up") == 0) {
return TELLSTICK_UP;
}
if (methodName.compare("down") == 0) {
return TELLSTICK_DOWN;
}
if (methodName.compare("stop") == 0) {
return TELLSTICK_STOP;
}
return 0;
}

View File

@@ -0,0 +1,51 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_DEVICE_H_
#define TELLDUS_CORE_SERVICE_DEVICE_H_
#include <list>
#include <string>
#include "service/Controller.h"
#include "common/Mutex.h"
#include "service/Protocol.h"
class Device : public TelldusCore::Mutex {
public:
explicit Device(int id);
~Device(void);
int doAction(int action, unsigned char data, Controller *controller);
int isMethodSupported(int method) const;
std::wstring getStateValue();
int getLastSentCommand(int methodsSupported);
int getMethods() const;
std::wstring getModel();
void setModel(const std::wstring &model);
std::wstring getName();
void setName(const std::wstring &name);
std::wstring getParameter(const std::wstring &key);
std::list<std::string> getParametersForProtocol() const;
void setParameter(const std::wstring &key, const std::wstring &value);
int getPreferredControllerId();
void setPreferredControllerId(int controllerId);
std::wstring getProtocolName() const;
void setProtocolName(const std::wstring &name);
void setStateValue(int stateValue);
void setLastSentCommand(int command, std::wstring value);
int getType();
static int maskUnsupportedMethods(int methods, int supportedMethods);
static int methodId( const std::string &methodName );
private:
Protocol *retrieveProtocol() const;
class PrivateData;
PrivateData *d;
};
#endif // TELLDUS_CORE_SERVICE_DEVICE_H_

View File

@@ -0,0 +1,790 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/DeviceManager.h"
#include <time.h>
#include <list>
#include <map>
#include <memory>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include "service/ControllerMessage.h"
#include "common/Mutex.h"
#include "service/Sensor.h"
#include "service/Settings.h"
#include "common/Strings.h"
#include "common/Message.h"
#include "service/Log.h"
typedef std::map<int, Device *> DeviceMap;
class DeviceManager::PrivateData {
public:
DeviceMap devices;
std::list<Sensor *> sensorList;
Settings set;
TelldusCore::Mutex lock;
ControllerManager *controllerManager;
TelldusCore::EventRef deviceUpdateEvent, executeActionEvent;
};
class ExecuteActionEventData : public TelldusCore::EventDataBase {
public:
int deviceId;
int method;
unsigned char data;
};
DeviceManager::DeviceManager(ControllerManager *controllerManager, TelldusCore::EventRef deviceUpdateEvent) {
d = new PrivateData;
d->controllerManager = controllerManager;
d->deviceUpdateEvent = deviceUpdateEvent;
fillDevices();
}
DeviceManager::~DeviceManager(void) {
{
TelldusCore::MutexLocker deviceListLocker(&d->lock);
for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) {
{TelldusCore::MutexLocker deviceLocker(it->second);} // aquire lock, and release it, just to see that the device it's not in use anywhere
delete(it->second);
}
for (std::list<Sensor *>::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) {
{TelldusCore::MutexLocker sensorLocker(*it);} // aquire lock, and release it, just to see that the device it's not in use anywhere
delete(*it);
}
}
delete d;
}
void DeviceManager::executeActionEvent() {
Device *device = 0;
TelldusCore::EventDataRef eventData = d->executeActionEvent->takeSignal();
ExecuteActionEventData *data = dynamic_cast<ExecuteActionEventData*>(eventData.get());
if (!data) {
Log::error("Could not cast executeAction data");
return;
}
Log::notice("Execute a TellStick Action for device %i", data->deviceId);
std::auto_ptr<TelldusCore::MutexLocker> deviceLocker(0);
{
// devicelist locked
TelldusCore::MutexLocker deviceListLocker(&d->lock);
DeviceMap::iterator it = d->devices.find(data->deviceId);
if (it == d->devices.end()) {
return;
}
// device locked
deviceLocker = std::auto_ptr<TelldusCore::MutexLocker>(new TelldusCore::MutexLocker(it->second));
device = it->second;
} // devicelist unlocked
Controller *controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId());
if(!controller) {
return;
}
int retval = device->doAction(data->method, data->data, controller);
if(retval == TELLSTICK_ERROR_BROKEN_PIPE) {
Log::warning("Error in communication with TellStick when executing action. Resetting USB");
d->controllerManager->resetController(controller);
}
if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND) {
Log::warning("Rescanning USB ports");
d->controllerManager->loadControllers();
controller = d->controllerManager->getBestControllerById(device->getPreferredControllerId());
if(!controller) {
Log::error("No contoller (TellStick) found, even after reset. Giving up.");
return;
}
retval = device->doAction(data->method, data->data, controller); // retry one more time
}
if(retval == TELLSTICK_SUCCESS && device->getMethods() & data->method) {
// if method isn't explicitly supported by device, but used anyway as a fallback (i.e. bell), don't change state
std::wstring datastring = TelldusCore::charUnsignedToWstring(data->data);
if (this->triggerDeviceStateChange(data->deviceId, data->method, datastring)) {
device->setLastSentCommand(data->method, datastring);
d->set.setDeviceState(data->deviceId, data->method, datastring);
}
}
}
void DeviceManager::setExecuteActionEvent(TelldusCore::EventRef event) {
d->executeActionEvent = event;
}
void DeviceManager::fillDevices() {
int numberOfDevices = d->set.getNumberOfNodes(Settings::Device);
TelldusCore::MutexLocker deviceListLocker(&d->lock);
for (int i = 0; i < numberOfDevices; ++i) {
int id = d->set.getNodeId(Settings::Device, i);
d->devices[id] = new Device(id);
d->devices[id]->setName(d->set.getName(Settings::Device, id));
d->devices[id]->setModel(d->set.getModel(id));
d->devices[id]->setProtocolName(d->set.getProtocol(id));
d->devices[id]->setPreferredControllerId(d->set.getPreferredControllerId(id));
d->devices[id]->setLastSentCommand(d->set.getDeviceState(id), d->set.getDeviceStateValue(id));
d->devices[id]->setParameter(L"house", d->set.getDeviceParameter(id, L"house"));
d->devices[id]->setParameter(L"unit", d->set.getDeviceParameter(id, L"unit"));
d->devices[id]->setParameter(L"code", d->set.getDeviceParameter(id, L"code"));
d->devices[id]->setParameter(L"units", d->set.getDeviceParameter(id, L"units"));
d->devices[id]->setParameter(L"fade", d->set.getDeviceParameter(id, L"fade"));
d->devices[id]->setParameter(L"system", d->set.getDeviceParameter(id, L"system"));
d->devices[id]->setParameter(L"devices", d->set.getDeviceParameter(id, L"devices"));
}
}
int DeviceManager::getDeviceLastSentCommand(int deviceId, int methodsSupported) {
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
TelldusCore::MutexLocker deviceLocker(it->second);
return it->second->getLastSentCommand(methodsSupported);
}
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
int DeviceManager::setDeviceLastSentCommand(int deviceId, int command, const std::wstring &value) {
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
TelldusCore::MutexLocker deviceLocker(it->second);
d->set.setDeviceState(deviceId, command, value);
it->second->setLastSentCommand(command, value);
} else {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
return TELLSTICK_SUCCESS;
}
std::wstring DeviceManager::getDeviceStateValue(int deviceId) {
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return L"UNKNOWN";
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
TelldusCore::MutexLocker deviceLocker(it->second);
return it->second->getStateValue();
}
return L"UNKNOWN";
}
int DeviceManager::getDeviceMethods(int deviceId, int methodsSupported) {
return Device::maskUnsupportedMethods(DeviceManager::getDeviceMethods(deviceId), methodsSupported);
}
int DeviceManager::getDeviceMethods(int deviceId) {
std::set<int> duplicateDeviceIds;
return DeviceManager::getDeviceMethods(deviceId, &duplicateDeviceIds);
}
int DeviceManager::getDeviceMethods(int deviceId, std::set<int> *duplicateDeviceIds) {
int type = 0;
int methods = 0;
std::wstring deviceIds;
std::wstring protocol;
{
// devices locked
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
{
TelldusCore::MutexLocker deviceLocker(it->second);
type = it->second->getType();
methods = it->second->getMethods();
deviceIds = it->second->getParameter(L"devices");
protocol = it->second->getProtocolName();
}
}
}
if(type == 0) {
return 0;
}
if(type == TELLSTICK_TYPE_GROUP) {
// get all methods that some device in the groups supports
std::wstring deviceIdBuffer;
std::wstringstream devicesstream(deviceIds);
methods = 0;
duplicateDeviceIds->insert(deviceId);
while(std::getline(devicesstream, deviceIdBuffer, L',')) {
int deviceIdInGroup = TelldusCore::wideToInteger(deviceIdBuffer);
if(duplicateDeviceIds->count(deviceIdInGroup) == 1) {
// action for device already executed, or will execute, do nothing to avoid infinite loop
continue;
}
duplicateDeviceIds->insert(deviceIdInGroup);
int deviceMethods = getDeviceMethods(deviceIdInGroup, duplicateDeviceIds);
if(deviceMethods > 0) {
methods |= deviceMethods;
}
}
}
return methods;
}
std::wstring DeviceManager::getDeviceModel(int deviceId) {
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return L"UNKNOWN";
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
TelldusCore::MutexLocker deviceLocker(it->second);
return it->second->getModel();
}
return L"UNKNOWN";
}
int DeviceManager::setDeviceModel(int deviceId, const std::wstring &model) {
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
TelldusCore::MutexLocker deviceLocker(it->second);
int ret = d->set.setModel(deviceId, model);
if (ret != TELLSTICK_SUCCESS) {
return ret;
}
it->second->setModel(model);
} else {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
return TELLSTICK_SUCCESS;
}
std::wstring DeviceManager::getDeviceName(int deviceId) {
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return L"UNKNOWN";
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
TelldusCore::MutexLocker deviceLocker(it->second);
return it->second->getName();
}
return L"UNKNOWN";
}
int DeviceManager::setDeviceName(int deviceId, const std::wstring &name) {
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
TelldusCore::MutexLocker deviceLocker(it->second);
int ret = d->set.setName(Settings::Device, deviceId, name);
if (ret != TELLSTICK_SUCCESS) {
return ret;
}
it->second->setName(name);
} else {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
return TELLSTICK_SUCCESS;
}
std::wstring DeviceManager::getDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &defaultValue) {
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return defaultValue;
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
TelldusCore::MutexLocker deviceLocker(it->second);
std::wstring returnString = it->second->getParameter(name);
if(returnString != L"") {
return returnString;
}
}
return defaultValue;
}
int DeviceManager::setDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &value) {
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
TelldusCore::MutexLocker deviceLocker(it->second);
int ret = d->set.setDeviceParameter(deviceId, name, value);
if (ret != TELLSTICK_SUCCESS) {
return ret;
}
it->second->setParameter(name, value);
} else {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
return TELLSTICK_SUCCESS;
}
std::wstring DeviceManager::getDeviceProtocol(int deviceId) {
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return L"UNKNOWN";
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
TelldusCore::MutexLocker deviceLocker(it->second);
return it->second->getProtocolName();
}
return L"UNKNOWN";
}
int DeviceManager::setDeviceProtocol(int deviceId, const std::wstring &protocol) {
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
TelldusCore::MutexLocker deviceLocker(it->second);
int ret = d->set.setProtocol(deviceId, protocol);
if (ret != TELLSTICK_SUCCESS) {
return ret;
}
it->second->setProtocolName(protocol);
} else {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
return TELLSTICK_SUCCESS;
}
int DeviceManager::getNumberOfDevices() {
TelldusCore::MutexLocker deviceListLocker(&d->lock);
return static_cast<int>(d->devices.size());
}
int DeviceManager::addDevice() {
int id = d->set.addNode(Settings::Device);
if(id < 0) {
return id;
}
TelldusCore::MutexLocker deviceListLocker(&d->lock);
d->devices[id] = new Device(id);
if(!d->devices[id]) {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
return id;
}
int DeviceManager::getDeviceId(int deviceIndex) {
return d->set.getNodeId(Settings::Device, deviceIndex);
}
int DeviceManager::getDeviceType(int deviceId) {
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
TelldusCore::MutexLocker deviceLocker(it->second);
return it->second->getType();
}
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
int DeviceManager::getPreferredControllerId(int deviceId) {
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
TelldusCore::MutexLocker deviceLocker(it->second);
return it->second->getPreferredControllerId();
}
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
void DeviceManager::connectTellStickController(int vid, int pid, const std::string &serial) {
d->controllerManager->deviceInsertedOrRemoved(vid, pid, serial, true);
}
void DeviceManager::disconnectTellStickController(int vid, int pid, const std::string &serial) {
d->controllerManager->deviceInsertedOrRemoved(vid, pid, serial, false);
}
int DeviceManager::doAction(int deviceId, int action, unsigned char data) {
int deviceType = 0;
{
// devicelist locked
TelldusCore::MutexLocker deviceListLocker(&d->lock);
DeviceMap::iterator it = d->devices.find(deviceId);
if (it == d->devices.end()) {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND; // not found
}
// device locked
TelldusCore::MutexLocker deviceLocker(it->second);
deviceType = it->second->getType();
if (it->second->isMethodSupported(action) <= 0) {
return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED;
}
}
if (d->controllerManager->count() == 0) {
return TELLSTICK_ERROR_NOT_FOUND;
}
// The device exists and there is at least one connected controller
if(deviceType == TELLSTICK_TYPE_GROUP || deviceType == TELLSTICK_TYPE_SCENE) {
return this->doGroupSceneAction(deviceId, action, data);
}
ExecuteActionEventData *eventData = new ExecuteActionEventData();
eventData->deviceId = deviceId;
eventData->method = action;
eventData->data = data;
d->executeActionEvent->signal(eventData);
return TELLSTICK_SUCCESS;
}
int DeviceManager::doGroupSceneAction(int deviceId, int action, unsigned char data) {
std::set<int> parsedDevices;
std::queue<int> devicesToParse;
devicesToParse.push(deviceId);
while (!devicesToParse.empty()) {
int deviceId = devicesToParse.front();
devicesToParse.pop();
if (parsedDevices.count(deviceId)) {
continue;
}
parsedDevices.insert(deviceId);
TelldusCore::MutexLocker deviceListLocker(&d->lock);
DeviceMap::iterator it = d->devices.find(deviceId);
if (it == d->devices.end()) {
// Not found
continue;
}
if (it->second->isMethodSupported(action) <= 0) {
return TELLSTICK_ERROR_METHOD_NOT_SUPPORTED;
}
TelldusCore::MutexLocker deviceLocker(it->second);
if (it->second->getType() == TELLSTICK_TYPE_DEVICE) {
ExecuteActionEventData *eventData = new ExecuteActionEventData();
eventData->deviceId = deviceId;
eventData->method = action;
eventData->data = data;
d->executeActionEvent->signal(eventData);
continue;
}
if (it->second->getType() == TELLSTICK_TYPE_GROUP) {
std::string devices = TelldusCore::wideToString(it->second->getParameter(L"devices"));
std::stringstream devicesstream(devices);
std::string singledevice;
while(std::getline(devicesstream, singledevice, ',')) {
devicesToParse.push(TelldusCore::charToInteger(singledevice.c_str()));
}
// Update state
if(it->second->getMethods() & action) {
// if method isn't explicitly supported by device, but used anyway as a fallback (i.e. bell), don't change state
std::wstring datastring = TelldusCore::charUnsignedToWstring(data);
if (this->triggerDeviceStateChange(deviceId, action, datastring)) {
it->second->setLastSentCommand(action, datastring);
d->set.setDeviceState(deviceId, action, datastring);
}
}
}
if (it->second->getType() == TELLSTICK_TYPE_SCENE) {
// TODO(micke): Not supported yet
Log::warning("Scenes are not supported yet!");
}
}
return TELLSTICK_SUCCESS;
}
int DeviceManager::executeScene(std::wstring singledevice, int groupDeviceId) {
std::wstringstream devicestream(singledevice);
const int deviceParameterLength = 3;
std::wstring deviceParts[deviceParameterLength] = {L"", L"", L""};
std::wstring devicePart = L"";
int i = 0;
while(std::getline(devicestream, devicePart, L':') && i < deviceParameterLength) {
deviceParts[i] = devicePart;
i++;
}
if(deviceParts[0] == L"" || deviceParts[1] == L"") {
return TELLSTICK_ERROR_UNKNOWN; // malformed or missing parameter
}
int deviceId = TelldusCore::wideToInteger(deviceParts[0]);
if(deviceId == groupDeviceId) {
return TELLSTICK_ERROR_UNKNOWN; // the scene itself has been added to its devices, avoid infinite loop
}
int method = Device::methodId(TelldusCore::wideToString(deviceParts[1])); // support methodparts both in the form of integers (e.g. TELLSTICK_TURNON) or text (e.g. "turnon")
if(method == 0) {
method = TelldusCore::wideToInteger(deviceParts[1]);
}
unsigned char devicedata = 0;
if(deviceParts[2] != L"") {
devicedata = TelldusCore::wideToInteger(deviceParts[2]);
}
if(deviceId > 0 && method > 0) { // check for format error in parameter "devices"
return doAction(deviceId, method, devicedata);
}
return TELLSTICK_ERROR_UNKNOWN;
}
int DeviceManager::removeDevice(int deviceId) {
Device *device = 0;
{
int ret = d->set.removeNode(Settings::Device, deviceId); // remove from register/settings
if (ret != TELLSTICK_SUCCESS) {
return ret;
}
TelldusCore::MutexLocker deviceListLocker(&d->lock);
if (!d->devices.size()) {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
DeviceMap::iterator it = d->devices.find(deviceId);
if (it != d->devices.end()) {
device = it->second;
d->devices.erase(it); // remove from list, keep reference
} else {
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
}
{TelldusCore::MutexLocker lock(device);} // waiting for device lock, if it's aquired, just unlock again. Device is removed from list, and cannot be accessed from anywhere else
delete device;
return TELLSTICK_SUCCESS;
}
std::wstring DeviceManager::getSensors() const {
TelldusCore::MutexLocker sensorListLocker(&d->lock);
TelldusCore::Message msg;
msg.addArgument(static_cast<int>(d->sensorList.size()));
for (std::list<Sensor *>::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) {
TelldusCore::MutexLocker sensorLocker(*it);
msg.addArgument((*it)->protocol());
msg.addArgument((*it)->model());
msg.addArgument((*it)->id());
msg.addArgument((*it)->dataTypes());
}
return msg;
}
std::wstring DeviceManager::getSensorValue(const std::wstring &protocol, const std::wstring &model, int id, int dataType) const {
TelldusCore::MutexLocker sensorListLocker(&d->lock);
Sensor *sensor = 0;
for (std::list<Sensor *>::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) {
TelldusCore::MutexLocker sensorLocker(*it);
if (!TelldusCore::comparei((*it)->protocol(), protocol)) {
continue;
}
if (!TelldusCore::comparei((*it)->model(), model)) {
continue;
}
if ((*it)->id() != id) {
continue;
}
sensor = *it;
break;
}
if (!sensor) {
return L"";
}
TelldusCore::MutexLocker sensorLocker(sensor);
TelldusCore::Message msg;
std::string value = sensor->value(dataType);
if (value.length() > 0) {
msg.addArgument(TelldusCore::charToWstring(value.c_str()));
msg.addArgument(static_cast<int>(sensor->timestamp()));
}
return msg;
}
void DeviceManager::handleControllerMessage(const ControllerEventData &eventData) {
// Trigger raw-event
EventUpdateData *eventUpdateData = new EventUpdateData();
eventUpdateData->messageType = L"TDRawDeviceEvent";
eventUpdateData->controllerId = eventData.controllerId;
eventUpdateData->eventValue = TelldusCore::charToWstring(eventData.msg.c_str());
d->deviceUpdateEvent->signal(eventUpdateData);
ControllerMessage msg(eventData.msg);
if (msg.msgClass().compare("sensor") == 0) {
handleSensorMessage(msg);
return;
}
TelldusCore::MutexLocker deviceListLocker(&d->lock);
for (DeviceMap::iterator it = d->devices.begin(); it != d->devices.end(); ++it) {
TelldusCore::MutexLocker deviceLocker(it->second);
if (!TelldusCore::comparei(it->second->getProtocolName(), msg.protocol())) {
continue;
}
if ( !(it->second->getMethods() & msg.method()) ) {
continue;
}
std::list<std::string> parameters = it->second->getParametersForProtocol();
bool thisDevice = true;
for (std::list<std::string>::iterator paramIt = parameters.begin(); paramIt != parameters.end(); ++paramIt) {
if(!TelldusCore::comparei(it->second->getParameter(TelldusCore::charToWstring((*paramIt).c_str())), TelldusCore::charToWstring(msg.getParameter(*paramIt).c_str()))) {
thisDevice = false;
break;
}
}
if(!thisDevice) {
continue;
}
if (this->triggerDeviceStateChange(it->first, msg.method(), L"")) {
d->set.setDeviceState(it->first, msg.method(), L"");
it->second->setLastSentCommand(msg.method(), L"");
}
}
}
void DeviceManager::handleSensorMessage(const ControllerMessage &msg) {
TelldusCore::MutexLocker sensorListLocker(&d->lock);
Sensor *sensor = 0;
for (std::list<Sensor *>::iterator it = d->sensorList.begin(); it != d->sensorList.end(); ++it) {
TelldusCore::MutexLocker sensorLocker(*it);
if (!TelldusCore::comparei((*it)->protocol(), msg.protocol())) {
continue;
}
if (!TelldusCore::comparei((*it)->model(), msg.model())) {
continue;
}
if ((*it)->id() != msg.getInt64Parameter("id")) {
continue;
}
sensor = *it;
break;
}
if (!sensor) {
sensor = new Sensor(msg.protocol(), msg.model(), msg.getInt64Parameter("id"));
d->sensorList.push_back(sensor);
}
TelldusCore::MutexLocker sensorLocker(sensor);
time_t t = time(NULL);
setSensorValueAndSignal("temp", TELLSTICK_TEMPERATURE, sensor, msg, t);
setSensorValueAndSignal("humidity", TELLSTICK_HUMIDITY, sensor, msg, t);
setSensorValueAndSignal("rainrate", TELLSTICK_RAINRATE, sensor, msg, t);
setSensorValueAndSignal("raintotal", TELLSTICK_RAINTOTAL, sensor, msg, t);
setSensorValueAndSignal("winddirection", TELLSTICK_WINDDIRECTION, sensor, msg, t);
setSensorValueAndSignal("windaverage", TELLSTICK_WINDAVERAGE, sensor, msg, t);
setSensorValueAndSignal("windgust", TELLSTICK_WINDGUST, sensor, msg, t);
}
void DeviceManager::setSensorValueAndSignal( const std::string &dataType, int dataTypeId, Sensor *sensor, const ControllerMessage &msg, time_t timestamp) const {
if (!msg.hasParameter(dataType)) {
return;
}
sensor->setValue(dataTypeId, msg.getParameter(dataType), timestamp);
EventUpdateData *eventData = new EventUpdateData();
eventData->messageType = L"TDSensorEvent";
eventData->protocol = sensor->protocol();
eventData->model = sensor->model();
eventData->sensorId = sensor->id();
eventData->dataType = dataTypeId;
eventData->value = TelldusCore::charToWstring(sensor->value(dataTypeId).c_str());
eventData->timestamp = static_cast<int>(timestamp);
d->deviceUpdateEvent->signal(eventData);
}
int DeviceManager::sendRawCommand(const std::wstring &command, int reserved) {
Controller *controller = d->controllerManager->getBestControllerById(-1);
if(!controller) {
// no controller found, scan for one, and retry once
d->controllerManager->loadControllers();
controller = d->controllerManager->getBestControllerById(-1);
}
int retval = TELLSTICK_ERROR_UNKNOWN;
if(controller) {
retval = controller->send(TelldusCore::wideToString(command));
if(retval == TELLSTICK_ERROR_BROKEN_PIPE) {
d->controllerManager->resetController(controller);
}
if(retval == TELLSTICK_ERROR_BROKEN_PIPE || retval == TELLSTICK_ERROR_NOT_FOUND) {
d->controllerManager->loadControllers();
controller = d->controllerManager->getBestControllerById(-1);
if(!controller) {
return TELLSTICK_ERROR_NOT_FOUND;
}
retval = controller->send(TelldusCore::wideToString(command)); // retry one more time
}
return retval;
} else {
return TELLSTICK_ERROR_NOT_FOUND;
}
}
bool DeviceManager::triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue ) {
if ( intDeviceState == TELLSTICK_BELL || intDeviceState == TELLSTICK_LEARN || intDeviceState == TELLSTICK_EXECUTE) {
return false;
}
EventUpdateData *eventData = new EventUpdateData();
eventData->messageType = L"TDDeviceEvent";
eventData->eventState = intDeviceState;
eventData->deviceId = deviceId;
eventData->eventValue = strDeviceStateValue;
d->deviceUpdateEvent->signal(eventData);
return true;
}

View File

@@ -0,0 +1,68 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_DEVICEMANAGER_H_
#define TELLDUS_CORE_SERVICE_DEVICEMANAGER_H_
#include <set>
#include <string>
#include "service/Device.h"
#include "service/ControllerManager.h"
#include "service/ControllerMessage.h"
#include "service/EventUpdateManager.h"
class Sensor;
class DeviceManager {
public:
DeviceManager(ControllerManager *controllerManager, TelldusCore::EventRef deviceUpdateEvent);
~DeviceManager(void);
int getNumberOfDevices(void);
int addDevice();
void connectTellStickController(int vid, int pid, const std::string &serial);
void disconnectTellStickController(int vid, int pid, const std::string &serial);
void executeActionEvent();
int getDeviceId(int deviceIndex);
int getDeviceLastSentCommand(int deviceId, int methodsSupported);
int setDeviceLastSentCommand(int deviceId, int command, const std::wstring &value);
int getDeviceMethods(int deviceId);
int getDeviceMethods(int deviceId, int methodsSupported);
std::wstring getDeviceModel(int deviceId);
int setDeviceModel(int deviceId, const std::wstring &model);
std::wstring getDeviceName(int deviceId);
int setDeviceName(int deviceId, const std::wstring &name);
std::wstring getDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &defauleValue);
int setDeviceParameter(int deviceId, const std::wstring &name, const std::wstring &value);
std::wstring getDeviceProtocol(int deviceId);
int setDeviceProtocol(int deviceId, const std::wstring &name);
std::wstring getDeviceStateValue(int deviceId);
int getDeviceType(int deviceId);
int getPreferredControllerId(int deviceId);
int doAction(int deviceId, int action, unsigned char data);
int removeDevice(int deviceId);
int sendRawCommand(const std::wstring &command, int reserved);
void setExecuteActionEvent(TelldusCore::EventRef event);
std::wstring getSensors() const;
std::wstring getSensorValue(const std::wstring &protocol, const std::wstring &model, int id, int dataType) const;
void handleControllerMessage(const ControllerEventData &event);
private:
void handleSensorMessage(const ControllerMessage &msg);
void setSensorValueAndSignal( const std::string &dataType, int dataTypeId, Sensor *sensor, const ControllerMessage &msg, time_t timestamp) const;
int getDeviceMethods(int deviceId, std::set<int> *duplicateDeviceIds);
int doGroupSceneAction(int deviceId, int action, unsigned char data);
int executeScene(std::wstring singledevice, int groupDeviceId);
bool triggerDeviceStateChange(int deviceId, int intDeviceState, const std::wstring &strDeviceStateValue );
void fillDevices(void);
class PrivateData;
PrivateData *d;
};
#endif // TELLDUS_CORE_SERVICE_DEVICEMANAGER_H_

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

View File

@@ -0,0 +1,53 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_EVENTUPDATEMANAGER_H_
#define TELLDUS_CORE_SERVICE_EVENTUPDATEMANAGER_H_
#include <string>
#include "common/Thread.h"
#include "common/Event.h"
class EventUpdateData : public TelldusCore::EventDataBase {
public:
std::wstring messageType;
int controllerId;
int deviceId;
int eventChangeType;
int eventDeviceChanges;
int eventState;
std::wstring eventValue;
// Sensor event
std::wstring protocol;
std::wstring model;
int sensorId;
int dataType;
std::wstring value;
int timestamp;
};
class EventUpdateManager : public TelldusCore::Thread {
public:
EventUpdateManager(void);
~EventUpdateManager(void);
TelldusCore::EventRef retrieveUpdateEvent();
TelldusCore::EventRef retrieveClientConnectEvent();
protected:
void run();
private:
class PrivateData;
PrivateData *d;
void loadScripts(const std::string &folder);
void sendMessageToClients(EventUpdateData *data);
void executeScripts(EventUpdateData *data);
static void executeScript(std::string script, const std::string &name, char **env);
};
#endif // TELLDUS_CORE_SERVICE_EVENTUPDATEMANAGER_H_

View File

@@ -0,0 +1,183 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/Log.h"
#include <stdarg.h>
#if defined(_LINUX)
#include <syslog.h>
#elif defined(_WINDOWS)
#include <windows.h>
#include "common/Strings.h"
#include "service/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;
Log::debug("Debug message output enabled");
}
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, reinterpret_cast<LPCWSTR*>(&pInsertStrings), NULL);
break;
case Notice:
ReportEvent(d->eventSource, EVENTLOG_INFORMATION_TYPE, NULL, LOG_NOTICE, NULL, 1, 0, reinterpret_cast<LPCWSTR*>(&pInsertStrings), NULL);
break;
case Warning:
ReportEvent(d->eventSource, EVENTLOG_WARNING_TYPE, NULL, LOG_WARNING, NULL, 1, 0, reinterpret_cast<LPCWSTR*>(&pInsertStrings), NULL);
break;
case Error:
ReportEvent(d->eventSource, EVENTLOG_ERROR_TYPE, NULL, LOG_ERR, NULL, 1, 0, reinterpret_cast<LPCWSTR*>(&pInsertStrings), NULL);
break;
}
#endif
}
}
Log *Log::instance() {
if (PrivateData::instance == 0) {
PrivateData::instance = new Log();
}
return PrivateData::instance;
}

View File

@@ -0,0 +1,40 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_LOG_H_
#define TELLDUS_CORE_SERVICE_LOG_H_
#include <stdio.h>
#include <stdarg.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 // TELLDUS_CORE_SERVICE_LOG_H_

Binary file not shown.

View File

@@ -0,0 +1,267 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/Protocol.h"
#include <list>
#include <sstream>
#include <string>
#include "client/telldus-core.h"
#include "service/ControllerMessage.h"
#include "service/ProtocolBrateck.h"
#include "service/ProtocolComen.h"
#include "service/ProtocolEverflourish.h"
#include "service/ProtocolFineoffset.h"
#include "service/ProtocolFuhaote.h"
#include "service/ProtocolGroup.h"
#include "service/ProtocolHasta.h"
#include "service/ProtocolIkea.h"
#include "service/ProtocolMandolyn.h"
#include "service/ProtocolNexa.h"
#include "service/ProtocolOregon.h"
#include "service/ProtocolRisingSun.h"
#include "service/ProtocolSartano.h"
#include "service/ProtocolScene.h"
#include "service/ProtocolSilvanChip.h"
#include "service/ProtocolUpm.h"
#include "service/ProtocolWaveman.h"
#include "service/ProtocolX10.h"
#include "service/ProtocolYidong.h"
#include "common/Strings.h"
class Protocol::PrivateData {
public:
ParameterMap parameterList;
std::wstring model;
};
Protocol::Protocol() {
d = new PrivateData;
}
Protocol::~Protocol(void) {
delete d;
}
std::wstring Protocol::model() const {
std::wstring strModel = d->model;
// Strip anything after : if it is found
size_t pos = strModel.find(L":");
if (pos != std::wstring::npos) {
strModel = strModel.substr(0, pos);
}
return strModel;
}
void Protocol::setModel(const std::wstring &model) {
d->model = model;
}
void Protocol::setParameters(const ParameterMap &parameterList) {
d->parameterList = parameterList;
}
std::wstring Protocol::getStringParameter(const std::wstring &name, const std::wstring &defaultValue) const {
ParameterMap::const_iterator it = d->parameterList.find(name);
if (it == d->parameterList.end()) {
return defaultValue;
}
return it->second;
}
int Protocol::getIntParameter(const std::wstring &name, int min, int max) const {
std::wstring value = getStringParameter(name, L"");
if (value == L"") {
return min;
}
std::wstringstream st;
st << value;
int intValue = 0;
st >> intValue;
if (intValue < min) {
return min;
}
if (intValue > max) {
return max;
}
return intValue;
}
bool Protocol::checkBit(int data, int bitno) {
return ((data >> bitno)&0x01);
}
Protocol *Protocol::getProtocolInstance(const std::wstring &protocolname) {
if(TelldusCore::comparei(protocolname, L"arctech")) {
return new ProtocolNexa();
} else if (TelldusCore::comparei(protocolname, L"brateck")) {
return new ProtocolBrateck();
} else if (TelldusCore::comparei(protocolname, L"comen")) {
return new ProtocolComen();
} else if (TelldusCore::comparei(protocolname, L"everflourish")) {
return new ProtocolEverflourish();
} else if (TelldusCore::comparei(protocolname, L"fuhaote")) {
return new ProtocolFuhaote();
} else if (TelldusCore::comparei(protocolname, L"hasta")) {
return new ProtocolHasta();
} else if (TelldusCore::comparei(protocolname, L"ikea")) {
return new ProtocolIkea();
} else if (TelldusCore::comparei(protocolname, L"risingsun")) {
return new ProtocolRisingSun();
} else if (TelldusCore::comparei(protocolname, L"sartano")) {
return new ProtocolSartano();
} else if (TelldusCore::comparei(protocolname, L"silvanchip")) {
return new ProtocolSilvanChip();
} else if (TelldusCore::comparei(protocolname, L"upm")) {
return new ProtocolUpm();
} else if (TelldusCore::comparei(protocolname, L"waveman")) {
return new ProtocolWaveman();
} else if (TelldusCore::comparei(protocolname, L"x10")) {
return new ProtocolX10();
} else if (TelldusCore::comparei(protocolname, L"yidong")) {
return new ProtocolYidong();
} else if (TelldusCore::comparei(protocolname, L"group")) {
return new ProtocolGroup();
} else if (TelldusCore::comparei(protocolname, L"scene")) {
return new ProtocolScene();
}
return 0;
}
std::list<std::string> Protocol::getParametersForProtocol(const std::wstring &protocolName) {
std::list<std::string> parameters;
if(TelldusCore::comparei(protocolName, L"arctech")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"brateck")) {
parameters.push_back("house");
} else if (TelldusCore::comparei(protocolName, L"comen")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"everflourish")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"fuhaote")) {
parameters.push_back("code");
} else if (TelldusCore::comparei(protocolName, L"hasta")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"ikea")) {
parameters.push_back("system");
parameters.push_back("units");
// parameters.push_back("fade");
} else if (TelldusCore::comparei(protocolName, L"risingsun")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"sartano")) {
parameters.push_back("code");
} else if (TelldusCore::comparei(protocolName, L"silvanchip")) {
parameters.push_back("house");
} else if (TelldusCore::comparei(protocolName, L"upm")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"waveman")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"x10")) {
parameters.push_back("house");
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"yidong")) {
parameters.push_back("unit");
} else if (TelldusCore::comparei(protocolName, L"group")) {
parameters.push_back("devices");
} else if (TelldusCore::comparei(protocolName, L"scene")) {
parameters.push_back("devices");
}
return parameters;
}
std::list<std::string> Protocol::decodeData(const std::string &fullData) {
std::list<std::string> retval;
std::string decoded = "";
ControllerMessage dataMsg(fullData);
if( TelldusCore::comparei(dataMsg.protocol(), L"arctech") ) {
decoded = ProtocolNexa::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
decoded = ProtocolWaveman::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
decoded = ProtocolSartano::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
} else if(TelldusCore::comparei(dataMsg.protocol(), L"everflourish") ) {
decoded = ProtocolEverflourish::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
} else if(TelldusCore::comparei(dataMsg.protocol(), L"fineoffset") ) {
decoded = ProtocolFineoffset::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
} else if(TelldusCore::comparei(dataMsg.protocol(), L"mandolyn") ) {
decoded = ProtocolMandolyn::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
} else if(TelldusCore::comparei(dataMsg.protocol(), L"oregon") ) {
decoded = ProtocolOregon::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
} else if(TelldusCore::comparei(dataMsg.protocol(), L"x10") ) {
decoded = ProtocolX10::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
} else if(TelldusCore::comparei(dataMsg.protocol(), L"hasta") ) {
decoded = ProtocolHasta::decodeData(dataMsg);
if (decoded != "") {
retval.push_back(decoded);
}
}
return retval;
}

View File

@@ -0,0 +1,46 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOL_H_
#define TELLDUS_CORE_SERVICE_PROTOCOL_H_
#include <string>
#include <list>
#include <map>
#include "client/telldus-core.h"
typedef std::map<std::wstring, std::wstring> ParameterMap;
class Controller;
class Protocol {
public:
Protocol();
virtual ~Protocol(void);
static Protocol *getProtocolInstance(const std::wstring &protocolname);
static std::list<std::string> getParametersForProtocol(const std::wstring &protocolName);
static std::list<std::string> decodeData(const std::string &fullData);
virtual int methods() const = 0;
std::wstring model() const;
void setModel(const std::wstring &model);
void setParameters(const ParameterMap &parameterList);
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller) = 0;
protected:
virtual std::wstring getStringParameter(const std::wstring &name, const std::wstring &defaultValue = L"") const;
virtual int getIntParameter(const std::wstring &name, int min, int max) const;
static bool checkBit(int data, int bit);
private:
class PrivateData;
PrivateData *d;
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOL_H_

View File

@@ -0,0 +1,53 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolBrateck.h"
#include <string>
int ProtocolBrateck::methods() const {
return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP;
}
std::string ProtocolBrateck::getStringForMethod(int method, unsigned char, Controller *) {
const char S = '!';
const char L = 'V';
const char B1[] = {L, S, L, S, 0};
const char BX[] = {S, L, L, S, 0};
const char B0[] = {S, L, S, L, 0};
const char BUP[] = {L, S, L, S, S, L, S, L, S, L, S, L, S, L, S, L, S, 0};
const char BSTOP[] = {S, L, S, L, L, S, L, S, S, L, S, L, S, L, S, L, S, 0};
const char BDOWN[] = {S, L, S, L, S, L, S, L, S, L, S, L, L, S, L, S, S, 0};
std::string strReturn;
std::wstring strHouse = this->getStringParameter(L"house", L"");
if (strHouse == L"") {
return "";
}
for( size_t i = 0; i < strHouse.length(); ++i ) {
if (strHouse[i] == '1') {
strReturn.insert(0, B1);
} else if (strHouse[i] == '-') {
strReturn.insert(0, BX);
} else if (strHouse[i] == '0') {
strReturn.insert(0, B0);
}
}
strReturn.insert(0, "S");
if (method == TELLSTICK_UP) {
strReturn.append(BUP);
} else if (method == TELLSTICK_DOWN) {
strReturn.append(BDOWN);
} else if (method == TELLSTICK_STOP) {
strReturn.append(BSTOP);
} else {
return "";
}
strReturn.append("+");
return strReturn;
}

View File

@@ -0,0 +1,19 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLBRATECK_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLBRATECK_H_
#include <string>
#include "service/Protocol.h"
class ProtocolBrateck : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLBRATECK_H_

View File

@@ -0,0 +1,23 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolComen.h"
#include <string>
int ProtocolComen::methods() const {
return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN);
}
int ProtocolComen::getIntParameter(const std::wstring &name, int min, int max) const {
if (name.compare(L"house") == 0) {
int intHouse = Protocol::getIntParameter(L"house", 1, 16777215);
// The last two bits must be hardcoded
intHouse <<= 2;
intHouse += 2;
return intHouse;
}
return Protocol::getIntParameter(name, min, max);
}

View File

@@ -0,0 +1,21 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_
#include <string>
#include "service/ProtocolNexa.h"
class ProtocolComen : public ProtocolNexa {
public:
virtual int methods() const;
protected:
virtual int getIntParameter(const std::wstring &name, int min, int max) const;
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLCOMEN_H_

View File

@@ -0,0 +1,133 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolEverflourish.h"
#include <stdio.h>
#include <sstream>
#include <string>
#include "service/ControllerMessage.h"
int ProtocolEverflourish::methods() const {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN;
}
std::string ProtocolEverflourish::getStringForMethod(int method, unsigned char, Controller *) {
unsigned int deviceCode = this->getIntParameter(L"house", 0, 16383);
unsigned int intCode = this->getIntParameter(L"unit", 1, 4)-1;
unsigned char action;
if (method == TELLSTICK_TURNON) {
action = 15;
} else if (method == TELLSTICK_TURNOFF) {
action = 0;
} else if (method == TELLSTICK_LEARN) {
action = 10;
} else {
return "";
}
const char ssss = 85;
const char sssl = 84; // 0
const char slss = 69; // 1
const char bits[2] = {sssl, slss};
int i, check;
std::string strCode;
deviceCode = (deviceCode << 2) | intCode;
check = calculateChecksum(deviceCode);
char preamble[] = {'R', 5, 'T', 114, 60, 1, 1, 105, ssss, ssss, 0};
strCode.append(preamble);
for(i = 15; i >= 0; i--) {
strCode.append(1, bits[(deviceCode >> i)&0x01]);
}
for(i = 3; i >= 0; i--) {
strCode.append(1, bits[(check >> i)&0x01]);
}
for(i = 3; i >= 0; i--) {
strCode.append(1, bits[(action >> i)&0x01]);
}
strCode.append(1, ssss);
strCode.append(1, '+');
return strCode;
}
// The calculation used in this function is provided by Frank Stevenson
unsigned int ProtocolEverflourish::calculateChecksum(unsigned int x) {
unsigned int bits[16] = {
0xf, 0xa, 0x7, 0xe,
0xf, 0xd, 0x9, 0x1,
0x1, 0x2, 0x4, 0x8,
0x3, 0x6, 0xc, 0xb
};
unsigned int bit = 1;
unsigned int res = 0x5;
int i;
unsigned int lo, hi;
if ((x & 0x3) == 3) {
lo = x & 0x00ff;
hi = x & 0xff00;
lo += 4;
if (lo>0x100) {
lo = 0x12;
}
x = lo | hi;
}
for(i = 0; i < 16; i++) {
if (x & bit) {
res = res ^ bits[i];
}
bit = bit << 1;
}
return res;
}
std::string ProtocolEverflourish::decodeData(const ControllerMessage &dataMsg) {
uint64_t allData;
unsigned int house = 0;
unsigned int unit = 0;
unsigned int method = 0;
allData = dataMsg.getInt64Parameter("data");
house = allData & 0xFFFC00;
house >>= 10;
unit = allData & 0x300;
unit >>= 8;
unit++; // unit from 1 to 4
method = allData & 0xF;
if(house > 16383 || unit < 1 || unit > 4) {
// not everflourish
return "";
}
std::stringstream retString;
retString << "class:command;protocol:everflourish;model:selflearning;house:" << house << ";unit:" << unit << ";method:";
if(method == 0) {
retString << "turnoff;";
} else if(method == 15) {
retString << "turnon;";
} else if(method == 10) {
retString << "learn;";
} else {
// not everflourish
return "";
}
return retString.str();
}

View File

@@ -0,0 +1,24 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLEVERFLOURISH_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLEVERFLOURISH_H_
#include <string>
#include "service/Protocol.h"
#include "service/ControllerMessage.h"
class ProtocolEverflourish : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
static std::string decodeData(const ControllerMessage &dataMsg);
private:
static unsigned int calculateChecksum(unsigned int x);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLEVERFLOURISH_H_

View File

@@ -0,0 +1,52 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolFineoffset.h"
#include <stdlib.h>
#include <iomanip>
#include <sstream>
#include <string>
#include "common/Strings.h"
std::string ProtocolFineoffset::decodeData(const ControllerMessage &dataMsg) {
std::string data = dataMsg.getParameter("data");
if (data.length() < 8) {
return "";
}
// Checksum currently not used
// uint8_t checksum = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2));
data = data.substr(0, data.length()-2);
uint8_t humidity = (uint8_t)TelldusCore::hexTo64l(data.substr(data.length()-2));
data = data.substr(0, data.length()-2);
uint16_t value = (uint16_t)TelldusCore::hexTo64l(data.substr(data.length()-3));
double temperature = (value & 0x7FF)/10.0;
value >>= 11;
if (value & 1) {
temperature = -temperature;
}
data = data.substr(0, data.length()-3);
uint16_t id = (uint16_t)TelldusCore::hexTo64l(data) & 0xFF;
std::stringstream retString;
retString << "class:sensor;protocol:fineoffset;id:" << id << ";model:";
if (humidity <= 100) {
retString << "temperaturehumidity;humidity:" << static_cast<int>(humidity) << ";";
} else if (humidity == 0xFF) {
retString << "temperature;";
} else {
return "";
}
retString << "temp:" << std::fixed << std::setprecision(1) << temperature << ";";
return retString.str();
}

View File

@@ -0,0 +1,19 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_
#include <string>
#include "service/Protocol.h"
#include "service/ControllerMessage.h"
class ProtocolFineoffset : public Protocol {
public:
static std::string decodeData(const ControllerMessage &dataMsg);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLFINEOFFSET_H_

View File

@@ -0,0 +1,60 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolFuhaote.h"
#include <string>
int ProtocolFuhaote::methods() const {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF;
}
std::string ProtocolFuhaote::getStringForMethod(int method, unsigned char, Controller *) {
const char S = 19;
const char L = 58;
const char B0[] = {S, L, L, S, 0};
const char B1[] = {L, S, L, S, 0};
const char OFF[] = {S, L, S, L, S, L, L, S, 0};
const char ON[] = {S, L, L, S, S, L, S, L, 0};
std::string strReturn = "S";
std::wstring strCode = this->getStringParameter(L"code", L"");
if (strCode == L"") {
return "";
}
// House code
for(size_t i = 0; i < 5; ++i) {
if (strCode[i] == '0') {
strReturn.append(B0);
} else if (strCode[i] == '1') {
strReturn.append(B1);
}
}
// Unit code
for(size_t i = 5; i < 10; ++i) {
if (strCode[i] == '0') {
strReturn.append(B0);
} else if (strCode[i] == '1') {
strReturn.append(1, S);
strReturn.append(1, L);
strReturn.append(1, S);
strReturn.append(1, L);
}
}
if (method == TELLSTICK_TURNON) {
strReturn.append(ON);
} else if (method == TELLSTICK_TURNOFF) {
strReturn.append(OFF);
} else {
return "";
}
strReturn.append(1, S);
strReturn.append("+");
return strReturn;
}

View File

@@ -0,0 +1,19 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLFUHAOTE_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLFUHAOTE_H_
#include <string>
#include "service/Protocol.h"
class ProtocolFuhaote : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLFUHAOTE_H_

View File

@@ -0,0 +1,16 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolGroup.h"
#include <string>
int ProtocolGroup::methods() const {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_BELL | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_TOGGLE | TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP;
}
std::string ProtocolGroup::getStringForMethod(int method, unsigned char data, Controller *) {
return "";
}

View File

@@ -0,0 +1,22 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_
#include <string>
#include "service/Protocol.h"
class ProtocolGroup : public Protocol {
public:
virtual int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLGROUP_H_

View File

@@ -0,0 +1,201 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolHasta.h"
#include <stdio.h>
#include <sstream>
#include <string>
#include "common/Strings.h"
int ProtocolHasta::methods() const {
return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN;
}
std::string ProtocolHasta::getStringForMethod(int method, unsigned char, Controller *) {
if (TelldusCore::comparei(model(), L"selflearningv2")) {
return getStringForMethodv2(method);
}
return getStringForMethodv1(method);
}
std::string ProtocolHasta::getStringForMethodv1(int method) {
int house = this->getIntParameter(L"house", 1, 65536);
int unit = this->getIntParameter(L"unit", 1, 15);
std::string strReturn;
strReturn.append(1, 164);
strReturn.append(1, 1);
strReturn.append(1, 164);
strReturn.append(1, 1);
strReturn.append(1, 164);
strReturn.append(1, 164);
strReturn.append(convertByte( (house & 0xFF) ));
strReturn.append(convertByte( (house>>8) & 0xFF ));
int byte = unit&0x0F;
if (method == TELLSTICK_UP) {
byte |= 0x00;
} else if (method == TELLSTICK_DOWN) {
byte |= 0x10;
} else if (method == TELLSTICK_STOP) {
byte |= 0x50;
} else if (method == TELLSTICK_LEARN) {
byte |= 0x40;
} else {
return "";
}
strReturn.append(convertByte(byte));
strReturn.append(convertByte(0x0));
strReturn.append(convertByte(0x0));
// Remove the last pulse
strReturn.erase(strReturn.end()-1, strReturn.end());
return strReturn;
}
std::string ProtocolHasta::convertByte(unsigned char byte) {
std::string retval;
for(int i = 0; i < 8; ++i) {
if (byte & 1) {
retval.append(1, 33);
retval.append(1, 17);
} else {
retval.append(1, 17);
retval.append(1, 33);
}
byte >>= 1;
}
return retval;
}
std::string ProtocolHasta::getStringForMethodv2(int method) {
int house = this->getIntParameter(L"house", 1, 65536);
int unit = this->getIntParameter(L"unit", 1, 15);
int sum = 0;
std::string strReturn;
strReturn.append(1, 245);
strReturn.append(1, 1);
strReturn.append(1, 245);
strReturn.append(1, 245);
strReturn.append(1, 63);
strReturn.append(1, 1);
strReturn.append(1, 63);
strReturn.append(1, 1);
strReturn.append(1, 35);
strReturn.append(1, 35);
strReturn.append(convertBytev2( (house>>8) & 0xFF ));
sum = ((house>>8)&0xFF);
strReturn.append(convertBytev2( (house & 0xFF) ));
sum += (house & 0xFF);
int byte = unit&0x0F;
if (method == TELLSTICK_UP) {
byte |= 0xC0;
} else if (method == TELLSTICK_DOWN) {
byte |= 0x10;
} else if (method == TELLSTICK_STOP) {
byte |= 0x50;
} else if (method == TELLSTICK_LEARN) {
byte |= 0x40;
} else {
return "";
}
strReturn.append(convertBytev2(byte));
sum += byte;
strReturn.append(convertBytev2(0x01));
sum += 0x01;
int checksum = ((static_cast<int>(sum/256)+1)*256+1) - sum;
strReturn.append(convertBytev2(checksum));
strReturn.append(1, 63);
strReturn.append(1, 35);
return strReturn;
}
std::string ProtocolHasta::convertBytev2(unsigned char byte) {
std::string retval;
for(int i = 0; i < 8; ++i) {
if (byte & 1) {
retval.append(1, 63);
retval.append(1, 35);
} else {
retval.append(1, 35);
retval.append(1, 63);
}
byte >>= 1;
}
return retval;
}
std::string ProtocolHasta::decodeData(const ControllerMessage& dataMsg) {
uint64_t allData = dataMsg.getInt64Parameter("data");
unsigned int house = 0;
unsigned int unit = 0;
unsigned int method = 0;
std::string model;
std::string methodstring;
allData >>= 8;
unit = allData & 0xF;
allData >>= 4;
method = allData & 0xF;
allData >>= 4;
if(TelldusCore::comparei(dataMsg.model(), L"selflearning")) {
// version1
house = allData & 0xFFFF;
house = ((house << 8) | (house >> 8)) & 0xFFFF;
model = "selflearning";
if(method == 0) {
methodstring = "up";
} else if(method == 1) {
methodstring = "down";
} else if(method == 5) {
methodstring = "stop";
} else {
return "";
}
} else {
// version2
house = allData & 0xFFFF;
model = "selflearningv2";
if(method == 12) {
methodstring = "up";
} else if(method == 1 || method == 8) { // is method 8 correct?
methodstring = "down";
} else if(method == 5) {
methodstring = "stop";
} else {
return "";
}
}
if(house < 1 || house > 65535 || unit < 1 || unit > 16) {
// not hasta
return "";
}
std::stringstream retString;
retString << "class:command;protocol:hasta;model:" << model << ";house:" << house << ";unit:" << unit << ";method:" << methodstring << ";";
return retString.str();
}

View File

@@ -0,0 +1,27 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_
#include <string>
#include "service/ControllerMessage.h"
#include "service/Protocol.h"
class ProtocolHasta : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
static std::string decodeData(const ControllerMessage &dataMsg);
protected:
static std::string convertByte(unsigned char byte);
static std::string convertBytev2(unsigned char byte);
std::string getStringForMethodv1(int method);
std::string getStringForMethodv2(int method);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLHASTA_H_

View File

@@ -0,0 +1,151 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolIkea.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include "common/Strings.h"
#ifdef _WINDOWS
#define strtok_r(s, d, p) strtok_s(s, d, p)
#endif
int ProtocolIkea::methods() const {
if (TelldusCore::comparei(model(), L"selflearning-switch")) {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF;
}
return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM;
}
std::string ProtocolIkea::getStringForMethod(int method, unsigned char level, Controller *) {
const char B1[] = {84, 84, 0};
const char B0[] = {static_cast<char>(170), 0};
int intSystem = this->getIntParameter(L"system", 1, 16)-1;
int intFadeStyle = TelldusCore::comparei(this->getStringParameter(L"fade", L"true"), L"true");
std::wstring wstrUnits = this->getStringParameter(L"units", L"");
if (method == TELLSTICK_TURNON) {
level = 255;
} else if (method == TELLSTICK_TURNOFF) {
level = 0;
} else if (method == TELLSTICK_DIM) {
} else {
return "";
}
if (wstrUnits == L"") {
return "";
}
std::string strUnits(TelldusCore::wideToString(wstrUnits));
int intUnits = 0; // Start without any units
char *tempUnits = new char[strUnits.size()+1];
#ifdef _WINDOWS
strcpy_s(tempUnits, strUnits.size()+1, strUnits.c_str());
#else
snprintf(tempUnits, strUnits.size()+1, "%s", strUnits.c_str());
#endif
char *saveptr;
char *strToken = strtok_r(tempUnits, ",", &saveptr);
do {
int intUnit = atoi(strToken);
if (intUnit == 10) {
intUnit = 0;
}
intUnits = intUnits | ( 1<<(9-intUnit) );
} while ( (strToken = strtok_r(NULL, ",", &saveptr)) != NULL );
delete[] tempUnits;
std::string strReturn;
strReturn.append(1, 'S');
strReturn.append(1, 84);
strReturn.append(1, 84);
strReturn.append(1, 84);
strReturn.append(1, 84);
strReturn.append(1, 84);
strReturn.append(1, 84);
strReturn.append(1, static_cast<char>(170));
std::string strChannels = "";
int intCode = (intSystem << 10) | intUnits;
int checksum1 = 0;
int checksum2 = 0;
for (int i = 13; i >= 0; --i) {
if ((intCode >> i) & 1) {
strChannels.append(B1);
if (i % 2 == 0)
checksum2++;
else
checksum1++;
} else {
strChannels.append(B0);
}
}
strReturn.append(strChannels); // System + Units
strReturn.append(checksum1 %2 == 0 ? B1 : B0); // 1st checksum
strReturn.append(checksum2 %2 == 0 ? B1 : B0); // 2nd checksum
int intLevel = 0;
if (level <= 12) {
intLevel = 10; // Level 10 is actually off
} else if (level <= 37) {
intLevel = 1;
} else if (level <= 62) {
intLevel = 2;
} else if (level <= 87) {
intLevel = 3;
} else if (level <= 112) {
intLevel = 4;
} else if (level <= 137) {
intLevel = 5;
} else if (level <= 162) {
intLevel = 6;
} else if (level <= 187) {
intLevel = 7;
} else if (level <= 212) {
intLevel = 8;
} else if (level <= 237) {
intLevel = 9;
} else {
intLevel = 0; // Level 0 is actually full on
}
int intFade = 0;
if (intFadeStyle == 1) {
intFade = 11 << 4; // Smooth
} else {
intFade = 1 << 4; // Instant
}
intCode = intLevel | intFade; // Concat level and fade
checksum1 = 0;
checksum2 = 0;
for (int i = 0; i < 6; ++i) {
if ((intCode >> i) & 1) {
strReturn.append(B1);
if (i % 2 == 0)
checksum1++;
else
checksum2++;
} else {
strReturn.append(B0);
}
}
strReturn.append(checksum1 %2 == 0 ? B1 : B0); // 1st checksum
strReturn.append(checksum2 %2 == 0 ? B1 : B0); // 2nd checksum
strReturn.append("+");
return strReturn;
}

View File

@@ -0,0 +1,19 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLIKEA_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLIKEA_H_
#include <string>
#include "service/Protocol.h"
class ProtocolIkea : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLIKEA_H_

View File

@@ -0,0 +1,46 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolMandolyn.h"
#include <stdlib.h>
#include <iomanip>
#include <sstream>
#include <string>
#include "common/Strings.h"
std::string ProtocolMandolyn::decodeData(const ControllerMessage &dataMsg) {
std::string data = dataMsg.getParameter("data");
uint32_t value = (uint32_t)TelldusCore::hexTo64l(data);
// parity not used
// bool parity = value & 0x1;
value >>= 1;
double temp = static_cast<double>(value & 0x7FFF) - static_cast<double>(6400);
temp = temp/128.0;
value >>= 15;
uint8_t humidity = (value & 0x7F);
value >>= 7;
// battOk not used
// bool battOk = value & 0x1;
value >>= 3;
uint8_t channel = (value & 0x3)+1;
value >>= 2;
uint8_t house = value & 0xF;
std::stringstream retString;
retString << "class:sensor;protocol:mandolyn;id:"
<< house*10+channel
<< ";model:temperaturehumidity;"
<< "temp:" << std::fixed << std::setprecision(1) << temp
<< ";humidity:" << static_cast<int>(humidity) << ";";
return retString.str();
}

View File

@@ -0,0 +1,19 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_
#include <string>
#include "service/Protocol.h"
#include "service/ControllerMessage.h"
class ProtocolMandolyn : public Protocol {
public:
static std::string decodeData(const ControllerMessage &dataMsg);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLMANDOLYN_H_

View File

@@ -0,0 +1,279 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolNexa.h"
#include <stdio.h>
#include <sstream>
#include <string>
#include "service/TellStick.h"
#include "common/Strings.h"
int ProtocolNexa::lastArctecCodeSwitchWasTurnOff = 0; // TODO(stefan): always removing first turnon now, make more flexible (waveman too)
int ProtocolNexa::methods() const {
if (TelldusCore::comparei(model(), L"codeswitch")) {
return (TELLSTICK_TURNON | TELLSTICK_TURNOFF);
} else if (TelldusCore::comparei(model(), L"selflearning-switch")) {
return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN);
} else if (TelldusCore::comparei(model(), L"selflearning-dimmer")) {
return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_DIM | TELLSTICK_LEARN);
} else if (TelldusCore::comparei(model(), L"bell")) {
return TELLSTICK_BELL;
}
return 0;
}
std::string ProtocolNexa::getStringForMethod(int method, unsigned char data, Controller *controller) {
if (TelldusCore::comparei(model(), L"codeswitch")) {
return getStringCodeSwitch(method);
} else if (TelldusCore::comparei(model(), L"bell")) {
return getStringBell();
}
if ((method == TELLSTICK_TURNON) && TelldusCore::comparei(model(), L"selflearning-dimmer")) {
// Workaround for not letting a dimmer do into "dimming mode"
return getStringSelflearning(TELLSTICK_DIM, 255);
}
if (method == TELLSTICK_LEARN) {
std::string str = getStringSelflearning(TELLSTICK_TURNON, data);
// Check to see if we are an old TellStick (fw <= 2, batch <= 8)
TellStick *ts = reinterpret_cast<TellStick *>(controller);
if (!ts) {
return str;
}
if (ts->pid() == 0x0c30 && ts->firmwareVersion() <= 2) {
// Workaround for the bug in early firmwares
// The TellStick have a fixed pause (max) between two packets.
// It is only correct between the first and second packet.
// It seems faster to send two packes at a time and some
// receivers seems picky about this when learning.
// We also return the last packet so Device::doAction() doesn't
// report TELLSTICK_ERROR_METHOD_NOT_SUPPORTED
str.insert(0, 1, 2); // Repeat two times
str.insert(0, 1, 'R');
for (int i = 0; i < 5; ++i) {
controller->send(str);
}
}
return str;
}
return getStringSelflearning(method, data);
}
std::string ProtocolNexa::getStringCodeSwitch(int method) {
std::string strReturn = "S";
std::wstring house = getStringParameter(L"house", L"A");
int intHouse = house[0] - L'A';
strReturn.append(getCodeSwitchTuple(intHouse));
strReturn.append(getCodeSwitchTuple(getIntParameter(L"unit", 1, 16)-1));
if (method == TELLSTICK_TURNON) {
strReturn.append("$k$k$kk$$kk$$kk$$k+");
} else if (method == TELLSTICK_TURNOFF) {
strReturn.append(this->getOffCode());
} else {
return "";
}
return strReturn;
}
std::string ProtocolNexa::getStringBell() {
std::string strReturn = "S";
std::wstring house = getStringParameter(L"house", L"A");
int intHouse = house[0] - L'A';
strReturn.append(getCodeSwitchTuple(intHouse));
strReturn.append("$kk$$kk$$kk$$k$k"); // Unit 7
strReturn.append("$kk$$kk$$kk$$kk$$k+"); // Bell
return strReturn;
}
std::string ProtocolNexa::getStringSelflearning(int method, unsigned char level) {
int intHouse = getIntParameter(L"house", 1, 67108863);
int intCode = getIntParameter(L"unit", 1, 16)-1;
return getStringSelflearningForCode(intHouse, intCode, method, level);
}
std::string ProtocolNexa::getStringSelflearningForCode(int intHouse, int intCode, int method, unsigned char level) {
const unsigned char START[] = {'T', 127, 255, 24, 1, 0};
// const char START[] = {'T',130,255,26,24,0};
std::string strMessage(reinterpret_cast<const char*>(START));
strMessage.append(1, (method == TELLSTICK_DIM ? 147 : 132)); // Number of pulses
std::string m;
for (int i = 25; i >= 0; --i) {
m.append( intHouse & 1 << i ? "10" : "01" );
}
m.append("01"); // Group
// On/off
if (method == TELLSTICK_DIM) {
m.append("00");
} else if (method == TELLSTICK_TURNOFF) {
m.append("01");
} else if (method == TELLSTICK_TURNON) {
m.append("10");
} else {
return "";
}
for (int i = 3; i >= 0; --i) {
m.append( intCode & 1 << i ? "10" : "01" );
}
if (method == TELLSTICK_DIM) {
unsigned char newLevel = level/16;
for (int i = 3; i >= 0; --i) {
m.append(newLevel & 1 << i ? "10" : "01");
}
}
// The number of data is odd.
// Add this to make it even, otherwise the following loop will not work
m.append("0");
unsigned char code = 9; // b1001, startcode
for (unsigned int i = 0; i < m.length(); ++i) {
code <<= 4;
if (m[i] == '1') {
code |= 8; // b1000
} else {
code |= 10; // b1010
// code |= 11; //b1011
}
if (i % 2 == 0) {
strMessage.append(1, code);
code = 0;
}
}
strMessage.append("+");
// for( int i = 0; i < strMessage.length(); ++i ) {
// printf("%i,", (unsigned char)strMessage[i]);
// }
// printf("\n");
return strMessage;
}
std::string ProtocolNexa::decodeData(const ControllerMessage& dataMsg) {
uint64_t allData = dataMsg.getInt64Parameter("data");
if(TelldusCore::comparei(dataMsg.model(), L"selflearning")) {
// selflearning
return decodeDataSelfLearning(allData);
} else {
// codeswitch
return decodeDataCodeSwitch(allData);
}
}
std::string ProtocolNexa::decodeDataSelfLearning(uint64_t allData) {
unsigned int house = 0;
unsigned int unit = 0;
unsigned int group = 0;
unsigned int method = 0;
house = allData & 0xFFFFFFC0;
house >>= 6;
group = allData & 0x20;
group >>= 5;
method = allData & 0x10;
method >>= 4;
unit = allData & 0xF;
unit++;
if(house < 1 || house > 67108863 || unit < 1 || unit > 16) {
// not arctech selflearning
return "";
}
std::stringstream retString;
retString << "class:command;protocol:arctech;model:selflearning;house:" << house << ";unit:" << unit << ";group:" << group << ";method:";
if(method == 1) {
retString << "turnon;";
} else if(method == 0) {
retString << "turnoff;";
} else {
// not arctech selflearning
return "";
}
return retString.str();
}
std::string ProtocolNexa::decodeDataCodeSwitch(uint64_t allData) {
unsigned int house = 0;
unsigned int unit = 0;
unsigned int method = 0;
method = allData & 0xF00;
method >>= 8;
unit = allData & 0xF0;
unit >>= 4;
unit++;
house = allData & 0xF;
if(house > 16 || unit < 1 || unit > 16) {
// not arctech codeswitch
return "";
}
house = house + 'A'; // house from A to P
if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1) {
lastArctecCodeSwitchWasTurnOff = 0;
return ""; // probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose
// one turnon/bell, but it's better than the alternative...
}
if(method == 6) {
lastArctecCodeSwitchWasTurnOff = 1;
}
std::stringstream retString;
retString << "class:command;protocol:arctech;model:codeswitch;house:" << static_cast<char>(house);
if(method == 6) {
retString << ";unit:" << unit << ";method:turnoff;";
} else if(method == 14) {
retString << ";unit:" << unit << ";method:turnon;";
} else if(method == 15) {
retString << ";method:bell;";
} else {
// not arctech codeswitch
return "";
}
return retString.str();
}
std::string ProtocolNexa::getCodeSwitchTuple(int intCode) {
std::string strReturn = "";
for( int i = 0; i < 4; ++i ) {
if (intCode & 1) { // Convert 1
strReturn.append("$kk$");
} else { // Convert 0
strReturn.append("$k$k");
}
intCode >>= 1;
}
return strReturn;
}
std::string ProtocolNexa::getOffCode() const {
return "$k$k$kk$$kk$$k$k$k+";
}

View File

@@ -0,0 +1,39 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_
#ifdef _MSC_VER
typedef unsigned __int64 uint64_t;
#else
#include <stdint.h>
#endif
#include <string>
#include "service/ControllerMessage.h"
#include "service/Device.h"
class ProtocolNexa : public Protocol {
public:
virtual int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
static std::string decodeData(const ControllerMessage &dataMsg);
protected:
std::string getStringSelflearning(int method, unsigned char data);
std::string getStringCodeSwitch(int method);
std::string getStringBell();
virtual std::string getOffCode() const;
static std::string getCodeSwitchTuple(int code);
static std::string getStringSelflearningForCode(int house, int unit, int method, unsigned char data);
private:
static int lastArctecCodeSwitchWasTurnOff;
static std::string decodeDataCodeSwitch(uint64_t allData);
static std::string decodeDataSelfLearning(uint64_t allData);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLNEXA_H_

View File

@@ -0,0 +1,347 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolOregon.h"
#include <stdlib.h>
#include <iomanip>
#include <sstream>
#include <string>
#include "common/Strings.h"
std::string ProtocolOregon::decodeData(const ControllerMessage &dataMsg) {
std::string data = dataMsg.getParameter("data");
std::wstring model = dataMsg.model();
if (model.compare(L"0xEA4C") == 0) {
return decodeEA4C(data);
} else if (model.compare(L"0x1A2D") == 0) {
return decode1A2D(data);
} else if (model.compare(L"0xF824") == 0) {
return decodeF824(data);
} else if (model.compare(L"0x1984") == 0 || model.compare(L"0x1994") == 0) {
return decode1984(data, model);
} else if (model.compare(L"0x2914") == 0) {
return decode2914(data);
} else if (model.compare(L"0xC844") == 0 || model.compare(L"0xEC40") == 0) {
// C844 - pool thermometer
return decodeC844(data, model);
}
return "";
}
std::string ProtocolOregon::decodeEA4C(const std::string &data) {
uint64_t value = TelldusCore::hexTo64l(data);
uint8_t checksum = 0xE + 0xA + 0x4 + 0xC;
checksum -= (value & 0xF) * 0x10;
checksum -= 0xA;
value >>= 8;
uint8_t checksumw = (value >> 4) & 0xF;
bool neg = value & (1 << 3);
int hundred = value & 3;
checksum += (value & 0xF);
value >>= 8;
uint8_t temp2 = value & 0xF;
uint8_t temp1 = (value >> 4) & 0xF;
checksum += temp2 + temp1;
value >>= 8;
uint8_t temp3 = (value >> 4) & 0xF;
checksum += (value & 0xF) + temp3;
value >>= 8;
checksum += ((value >> 4) & 0xF) + (value & 0xF);
uint8_t address = value & 0xFF;
value >>= 8;
checksum += ((value >> 4) & 0xF) + (value & 0xF);
// channel not used
// uint8_t channel = (value >> 4) & 0x7;
if (checksum != checksumw) {
return "";
}
double temperature = ((hundred * 1000) + (temp1 * 100) + (temp2 * 10) + temp3)/10.0;
if (neg) {
temperature = -temperature;
}
std::stringstream retString;
retString << "class:sensor;protocol:oregon;model:EA4C;id:" << static_cast<int>(address)
<< ";temp:" << std::fixed << std::setprecision(1) << temperature << ";";
return retString.str();
}
std::string ProtocolOregon::decode1984(const std::string &data, const std::wstring &model) {
// wind
uint64_t value = TelldusCore::hexTo64l(data);
uint8_t crcCheck = value & 0xF; // PROBABLY crc
value >>= 4;
uint8_t messageChecksum1 = value & 0xF;
value >>= 4;
uint8_t messageChecksum2 = value & 0xF;
value >>= 4;
uint8_t avg1 = value & 0xF;
value >>= 4;
uint8_t avg2 = value & 0xF;
value >>= 4;
uint8_t avg3 = value & 0xF;
value >>= 4;
uint8_t gust1 = value & 0xF;
value >>= 4;
uint8_t gust2 = value & 0xF;
value >>= 4;
uint8_t gust3 = value & 0xF;
value >>= 4;
uint8_t unknown1 = value & 0xF;
value >>= 4;
uint8_t unknown2 = value & 0xF;
value >>= 4;
uint8_t direction = value & 0xF;
value >>= 4;
uint8_t battery = value & 0xF; // PROBABLY battery
value >>= 4;
uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF);
uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF);
value >>= 8;
uint8_t channel = value & 0xF;
checksum += unknown1 + unknown2 + avg1 + avg2 + avg3 + gust1 + gust2 + gust3 + direction + battery + channel;
if (model.compare(L"0x1984") == 0) {
checksum += 0x1 + 0x9 + 0x8 + 0x4;
} else {
checksum += 0x1 + 0x9 + 0x9 + 0x4;
}
if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) {
// checksum error
return "";
}
double avg = ((avg1 * 100) + (avg2 * 10) + avg3)/10.0;
double gust = ((gust1 * 100) + (gust2 * 10) + gust3)/10.0;
float directiondegree = 22.5 * direction;
std::stringstream retString;
retString << "class:sensor;protocol:oregon;model:1984;id:" << static_cast<int>(rollingcode)
<< ";winddirection:" << directiondegree
<< ";windaverage:" << std::fixed << std::setprecision(1) << avg
<< ";windgust:" << std::fixed << std::setprecision(1) << gust << ";";
return retString.str();
}
std::string ProtocolOregon::decode1A2D(const std::string &data) {
uint64_t value = TelldusCore::hexTo64l(data);
// checksum2 not used yet
// uint8_t checksum2 = value & 0xFF;
value >>= 8;
uint8_t checksum1 = value & 0xFF;
value >>= 8;
uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF);
uint8_t hum1 = value & 0xF;
value >>= 8;
checksum += ((value >> 4) & 0xF) + (value & 0xF);
uint8_t neg = value & (1 << 3);
uint8_t hum2 = (value >> 4) & 0xF;
value >>= 8;
checksum += ((value >> 4) & 0xF) + (value & 0xF);
uint8_t temp2 = value & 0xF;
uint8_t temp1 = (value >> 4) & 0xF;
value >>= 8;
checksum += ((value >> 4) & 0xF) + (value & 0xF);
uint8_t temp3 = (value >> 4) & 0xF;
value >>= 8;
checksum += ((value >> 4) & 0xF) + (value & 0xF);
uint8_t address = value & 0xFF;
value >>= 8;
checksum += ((value >> 4) & 0xF) + (value & 0xF);
// channel not used
// uint8_t channel = (value >> 4) & 0x7;
checksum += 0x1 + 0xA + 0x2 + 0xD - 0xA;
// TODO(micke): Find out how checksum2 works
if (checksum != checksum1) {
return "";
}
double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0;
if (neg) {
temperature = -temperature;
}
int humidity = (hum1 * 10.0) + hum2;
std::stringstream retString;
retString << "class:sensor;protocol:oregon;model:1A2D;id:" << static_cast<int>(address)
<< ";temp:" << std::fixed << std::setprecision(1) << temperature
<< ";humidity:" << humidity << ";";
return retString.str();
}
std::string ProtocolOregon::decode2914(const std::string &data) {
// rain
uint64_t value = TelldusCore::hexTo64l(data);
uint8_t messageChecksum1 = value & 0xF;
value >>= 4;
uint8_t messageChecksum2 = value & 0xF;
value >>= 4;
uint8_t totRain1 = value & 0xF;
value >>= 4;
uint8_t totRain2 = value & 0xF;
value >>= 4;
uint8_t totRain3 = value & 0xF;
value >>= 4;
uint8_t totRain4 = value & 0xF;
value >>= 4;
uint8_t totRain5 = value & 0xF;
value >>= 4;
uint8_t totRain6 = value & 0xF;
value >>= 4;
uint8_t rainRate1 = value & 0xF;
value >>= 4;
uint8_t rainRate2 = value & 0xF;
value >>= 4;
uint8_t rainRate3 = value & 0xF;
value >>= 4;
uint8_t rainRate4 = value & 0xF;
value >>= 4;
uint8_t battery = value & 0xF; // PROBABLY battery
value >>= 4;
uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF);
uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF);
value >>= 8;
uint8_t channel = value & 0xF;
checksum += totRain1 + totRain2 + totRain3 + totRain4 + totRain5 + totRain6 + rainRate1 + rainRate2 + rainRate3 + rainRate4 + battery + channel + 0x2 + 0x9 + 0x1 + 0x4;
if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) {
// checksum error
return "";
}
double totRain = ((totRain1 * 100000) + (totRain2 * 10000) + (totRain3 * 1000) + (totRain4 * 100) + (totRain5 * 10) + totRain6)/1000.0*25.4;
double rainRate = ((rainRate1 * 1000) + (rainRate2 * 100) + (rainRate3 * 10) + rainRate4)/100.0*25.4;
std::stringstream retString;
retString << "class:sensor;protocol:oregon;model:2914;id:" << static_cast<int>(rollingcode)
<< ";raintotal:" << std::fixed << std::setprecision(1) << totRain
<< ";rainrate:" << std::fixed << std::setprecision(1) << rainRate << ";";
return retString.str();
}
std::string ProtocolOregon::decodeF824(const std::string &data) {
uint64_t value = TelldusCore::hexTo64l(data);
uint8_t crcCheck = value & 0xF; // PROBABLY crc
value >>= 4;
uint8_t messageChecksum1 = value & 0xF;
value >>= 4;
uint8_t messageChecksum2 = value & 0xF;
value >>= 4;
uint8_t unknown = value & 0xF;
value >>= 4;
uint8_t hum1 = value & 0xF;
value >>= 4;
uint8_t hum2 = value & 0xF;
value >>= 4;
uint8_t neg = value & 0xF;
value >>= 4;
uint8_t temp1 = value & 0xF;
value >>= 4;
uint8_t temp2 = value & 0xF;
value >>= 4;
uint8_t temp3 = value & 0xF;
value >>= 4;
uint8_t battery = value & 0xF; // PROBABLY battery
value >>= 4;
uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF);
uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF);
value >>= 8;
uint8_t channel = value & 0xF;
checksum += unknown + hum1 + hum2 + neg + temp1 + temp2 + temp3 + battery + channel + 0xF + 0x8 + 0x2 + 0x4;
if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) {
// checksum error
return "";
}
double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0;
if (neg) {
temperature = -temperature;
}
int humidity = (hum1 * 10.0) + hum2;
std::stringstream retString;
retString << "class:sensor;protocol:oregon;model:F824;id:" << static_cast<int>(rollingcode)
<< ";temp:" << std::fixed << std::setprecision(1) << temperature
<< ";humidity:" << humidity << ";";
return retString.str();
}
std::string ProtocolOregon::decodeC844(const std::string &data, const std::wstring &model) {
uint64_t value = TelldusCore::hexTo64l(data);
uint8_t messageChecksum1 = value & 0xF;
value >>= 4;
uint8_t messageChecksum2 = value & 0xF;
value >>= 4;
uint8_t neg = value & 0xF;
value >>= 4;
uint8_t temp1 = value & 0xF;
value >>= 4;
uint8_t temp2 = value & 0xF;
value >>= 4;
uint8_t temp3 = value & 0xF;
value >>= 4;
uint8_t battery = value & 0xF; // PROBABLY battery
value >>= 4;
uint8_t rollingcode = ((value >> 4) & 0xF) + (value & 0xF);
uint8_t checksum = ((value >> 4) & 0xF) + (value & 0xF);
value >>= 8;
uint8_t channel = value & 0xF;
checksum += neg + temp1 + temp2 + temp3 + battery + channel;
if (model.compare(L"0xC844") == 0) {
checksum += 0xC + 0x8 + 0x4 + 0x4;
} else {
checksum += 0xE + 0xC + 0x4 + 0x0;
}
if (((checksum >> 4) & 0xF) != messageChecksum1 || (checksum & 0xF) != messageChecksum2) {
// checksum error
return "";
}
double temperature = ((temp1 * 100) + (temp2 * 10) + temp3)/10.0;
if (neg) {
temperature = -temperature;
}
std::stringstream retString;
retString << "class:sensor;protocol:oregon;model:C844;id:" << static_cast<int>(rollingcode)
<< ";temp:" << std::fixed << std::setprecision(1) << temperature << ";";
return retString.str();
}

View File

@@ -0,0 +1,27 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_
#include <string>
#include "service/Protocol.h"
#include "service/ControllerMessage.h"
class ProtocolOregon : public Protocol {
public:
static std::string decodeData(const ControllerMessage &dataMsg);
protected:
static std::string decodeEA4C(const std::string &data);
static std::string decode1A2D(const std::string &data);
static std::string decodeF824(const std::string &data);
static std::string decode1984(const std::string &data, const std::wstring &model);
static std::string decode2914(const std::string &data);
static std::string decodeC844(const std::string &data, const std::wstring &model);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLOREGON_H_

View File

@@ -0,0 +1,115 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolRisingSun.h"
#include <string>
#include "common/Strings.h"
int ProtocolRisingSun::methods() const {
if (TelldusCore::comparei(model(), L"selflearning")) {
return (TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN);
}
return TELLSTICK_TURNON | TELLSTICK_TURNOFF;
}
std::string ProtocolRisingSun::getStringForMethod(int method, unsigned char data, Controller *controller) {
if (TelldusCore::comparei(model(), L"selflearning")) {
return getStringSelflearning(method);
}
return getStringCodeSwitch(method);
}
std::string ProtocolRisingSun::getStringSelflearning(int method) {
int intHouse = this->getIntParameter(L"house", 1, 33554432)-1;
int intCode = this->getIntParameter(L"code", 1, 16)-1;
const char code_on[][7] = {
"110110", "001110", "100110", "010110",
"111001", "000101", "101001", "011001",
"110000", "001000", "100000", "010000",
"111100", "000010", "101100", "011100"
};
const char code_off[][7] = {
"111110", "000001", "101110", "011110",
"110101", "001101", "100101", "010101",
"111000", "000100", "101000", "011000",
"110010", "001010", "100010", "010010"
};
const char l = 120;
const char s = 51;
std::string strCode = "10";
int code = intCode;
code = (code < 0 ? 0 : code);
code = (code > 15 ? 15 : code);
if (method == TELLSTICK_TURNON) {
strCode.append(code_on[code]);
} else if (method == TELLSTICK_TURNOFF) {
strCode.append(code_off[code]);
} else if (method == TELLSTICK_LEARN) {
strCode.append(code_on[code]);
} else {
return "";
}
int house = intHouse;
for(int i = 0; i < 25; ++i) {
if (house & 1) {
strCode.append(1, '1');
} else {
strCode.append(1, '0');
}
house >>= 1;
}
std::string strReturn;
for(unsigned int i = 0; i < strCode.length(); ++i) {
if (strCode[i] == '1') {
strReturn.append(1, l);
strReturn.append(1, s);
} else {
strReturn.append(1, s);
strReturn.append(1, l);
}
}
std::string prefix = "P";
prefix.append(1, 5);
if (method == TELLSTICK_LEARN) {
prefix.append("R");
prefix.append( 1, 50 );
}
prefix.append("S");
strReturn.insert(0, prefix);
strReturn.append(1, '+');
return strReturn;
}
std::string ProtocolRisingSun::getStringCodeSwitch(int method) {
std::string strReturn = "S.e";
strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"house", 1, 4)-1));
strReturn.append(getCodeSwitchTuple(this->getIntParameter(L"unit", 1, 4)-1));
if (method == TELLSTICK_TURNON) {
strReturn.append("e..ee..ee..ee..e+");
} else if (method == TELLSTICK_TURNOFF) {
strReturn.append("e..ee..ee..e.e.e+");
} else {
return "";
}
return strReturn;
}
std::string ProtocolRisingSun::getCodeSwitchTuple(int intToConvert) {
std::string strReturn = "";
for(int i = 0; i < 4; ++i) {
if (i == intToConvert) {
strReturn.append( ".e.e" );
} else {
strReturn.append( "e..e" );
}
}
return strReturn;
}

View File

@@ -0,0 +1,24 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLRISINGSUN_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLRISINGSUN_H_
#include <string>
#include "service/Protocol.h"
class ProtocolRisingSun : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
protected:
std::string getStringSelflearning(int method);
std::string getStringCodeSwitch(int method);
static std::string getCodeSwitchTuple(int code);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLRISINGSUN_H_

View File

@@ -0,0 +1,108 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolSartano.h"
#ifdef _MSC_VER
typedef unsigned __int16 uint16_t;
#else
#include <stdint.h>
#endif
#include <stdio.h>
#include <sstream>
#include <string>
int ProtocolSartano::methods() const {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF;
}
std::string ProtocolSartano::getStringForMethod(int method, unsigned char, Controller *) {
std::wstring strCode = this->getStringParameter(L"code", L"");
return getStringForCode(strCode, method);
}
std::string ProtocolSartano::getStringForCode(const std::wstring &strCode, int method) {
std::string strReturn("S");
for (size_t i = 0; i < strCode.length(); ++i) {
if (strCode[i] == L'1') {
strReturn.append("$k$k");
} else {
strReturn.append("$kk$");
}
}
if (method == TELLSTICK_TURNON) {
strReturn.append("$k$k$kk$$k+");
} else if (method == TELLSTICK_TURNOFF) {
strReturn.append("$kk$$k$k$k+");
} else {
return "";
}
return strReturn;
}
std::string ProtocolSartano::decodeData(const ControllerMessage &dataMsg) {
uint64_t allDataIn;
uint16_t allData = 0;
unsigned int code = 0;
unsigned int method1 = 0;
unsigned int method2 = 0;
unsigned int method = 0;
allDataIn = dataMsg.getInt64Parameter("data");
uint16_t mask = (1<<11);
for(int i = 0; i < 12; ++i) {
allData >>= 1;
if((allDataIn & mask) == 0) {
allData |= (1<<11);
}
mask >>= 1;
}
code = allData & 0xFFC;
code >>= 2;
method1 = allData & 0x2;
method1 >>= 1;
method2 = allData & 0x1;
if(method1 == 0 && method2 == 1) {
method = 0; // off
} else if(method1 == 1 && method2 == 0) {
method = 1; // on
} else {
return "";
}
if(code > 1023) {
// not sartano
return "";
}
std::stringstream retString;
retString << "class:command;protocol:sartano;model:codeswitch;code:";
mask = (1<<9);
for(int i = 0; i < 10; i++) {
if((code & mask) != 0) {
retString << 1;
} else {
retString << 0;
}
mask >>= 1;
}
retString << ";method:";
if(method == 0) {
retString << "turnoff;";
} else {
retString << "turnon;";
}
return retString.str();
}

View File

@@ -0,0 +1,24 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLSARTANO_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLSARTANO_H_
#include <string>
#include "service/Protocol.h"
#include "service/ControllerMessage.h"
class ProtocolSartano : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
static std::string decodeData(const ControllerMessage &dataMsg);
protected:
std::string getStringForCode(const std::wstring &code, int method);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLSARTANO_H_

View File

@@ -0,0 +1,16 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolScene.h"
#include <string>
int ProtocolScene::methods() const {
return TELLSTICK_EXECUTE;
}
std::string ProtocolScene::getStringForMethod(int method, unsigned char data, Controller *) {
return "";
}

View File

@@ -0,0 +1,22 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_
#include <string>
#include "service/Protocol.h"
class ProtocolScene : public Protocol {
public:
virtual int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLSCENE_H_

View File

@@ -0,0 +1,146 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolSilvanChip.h"
#include <string>
#include "common/Strings.h"
int ProtocolSilvanChip::methods() const {
if (TelldusCore::comparei(model(), L"kp100")) {
return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP | TELLSTICK_LEARN;
} else if (TelldusCore::comparei(model(), L"ecosavers")) {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN;
} else if (TelldusCore::comparei(model(), L"displaymatic")) {
return TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP;
}
return 0;
}
std::string ProtocolSilvanChip::getStringForMethod(int method, unsigned char data, Controller *controller) {
if (TelldusCore::comparei(model(), L"kp100")) {
std::string preamble;
preamble.append(1, 100);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 100);
const std::string one = "\xFF\x1\x2E\x2E";
const std::string zero = "\x2E\xFF\x1\x2E";
int button = 0;
if (method == TELLSTICK_UP) {
button = 2;
} else if (method == TELLSTICK_DOWN) {
button = 8;
} else if (method == TELLSTICK_STOP) {
button = 4;
} else if (method == TELLSTICK_LEARN) {
button = 1;
} else {
return "";
}
return this->getString(preamble, one, zero, button);
} else if (TelldusCore::comparei(model(), L"displaymatic")) {
std::string preamble;
preamble.append(1, 0x25);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 0x25);
const std::string one = "\x69\25";
const std::string zero = "\x25\x69";
int button = 0;
if (method == TELLSTICK_UP) {
button = 1;
} else if (method == TELLSTICK_DOWN) {
button = 4;
} else if (method == TELLSTICK_STOP) {
button = 2;
}
return this->getString(preamble, one, zero, button);
} else if (TelldusCore::comparei(model(), L"ecosavers")) {
std::string preamble;
preamble.append(1, 0x25);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 255);
preamble.append(1, 1);
preamble.append(1, 0x25);
const std::string one = "\x69\25";
const std::string zero = "\x25\x69";
int intUnit = this->getIntParameter(L"unit", 1, 4);
int button = 0;
if (intUnit == 1) {
button = 7;
} else if (intUnit == 2) {
button = 3;
} else if (intUnit == 3) {
button = 5;
} else if (intUnit == 4) {
button = 6;
}
if (method == TELLSTICK_TURNON || method == TELLSTICK_LEARN) {
button |= 8;
}
return this->getString(preamble, one, zero, button);
}
return "";
}
std::string ProtocolSilvanChip::getString(const std::string &preamble, const std::string &one, const std::string &zero, int button) {
int intHouse = this->getIntParameter(L"house", 1, 1048575);
std::string strReturn = preamble;
for( int i = 19; i >= 0; --i ) {
if (intHouse & (1 << i)) {
strReturn.append(one);
} else {
strReturn.append(zero);
}
}
for( int i = 3; i >= 0; --i) {
if (button & (1 << i)) {
strReturn.append(one);
} else {
strReturn.append(zero);
}
}
strReturn.append(zero);
return strReturn;
}

View File

@@ -0,0 +1,22 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLSILVANCHIP_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLSILVANCHIP_H_
#include <string>
#include "service/Protocol.h"
class ProtocolSilvanChip : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
protected:
virtual std::string getString(const std::string &preamble, const std::string &one, const std::string &zero, int button);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLSILVANCHIP_H_

View File

@@ -0,0 +1,78 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolUpm.h"
#include <string>
int ProtocolUpm::methods() const {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_LEARN;
}
std::string ProtocolUpm::getStringForMethod(int method, unsigned char, Controller *) {
const char S = ';';
const char L = '~';
const char START[] = {S, 0};
const char B1[] = {L, S, 0};
const char B0[] = {S, L, 0};
// const char BON[] = {S,L,L,S,0};
// const char BOFF[] = {S,L,S,L,0};
int intUnit = this->getIntParameter(L"unit", 1, 4)-1;
std::string strReturn;
int code = this->getIntParameter(L"house", 0, 4095);
for( size_t i = 0; i < 12; ++i ) {
if (code & 1) {
strReturn.insert(0, B1);
} else {
strReturn.insert(0, B0);
}
code >>= 1;
}
strReturn.insert(0, START); // Startcode, first
code = 0;
if (method == TELLSTICK_TURNON || method == TELLSTICK_LEARN) {
code += 2;
} else if (method != TELLSTICK_TURNOFF) {
return "";
}
code <<= 2;
code += intUnit;
int check1 = 0, check2 = 0;
for( size_t i = 0; i < 6; ++i ) {
if (code & 1) {
if (i % 2 == 0) {
check1++;
} else {
check2++;
}
}
if (code & 1) {
strReturn.append(B1);
} else {
strReturn.append(B0);
}
code >>= 1;
}
if (check1 % 2 == 0) {
strReturn.append(B0);
} else {
strReturn.append(B1);
}
if (check2 % 2 == 0) {
strReturn.append(B0);
} else {
strReturn.append(B1);
}
strReturn.insert(0, "S");
strReturn.append("+");
return strReturn;
}

View File

@@ -0,0 +1,19 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLUPM_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLUPM_H_
#include <string>
#include "service/Protocol.h"
class ProtocolUpm : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLUPM_H_

View File

@@ -0,0 +1,77 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolWaveman.h"
#ifdef _MSC_VER
#else
#include <stdint.h>
#endif
#include <stdio.h>
#include <sstream>
#include <string>
int ProtocolWaveman::lastArctecCodeSwitchWasTurnOff = 0;
int ProtocolWaveman::methods() const {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF;
}
std::string ProtocolWaveman::getStringForMethod(int method, unsigned char, Controller *) {
return getStringCodeSwitch(method);
}
std::string ProtocolWaveman::getOffCode() const {
return "$k$k$k$k$k$k$k$k$k+";
}
std::string ProtocolWaveman::decodeData(const ControllerMessage& dataMsg) {
uint64_t allData = 0;
unsigned int house = 0;
unsigned int unit = 0;
unsigned int method = 0;
allData = dataMsg.getInt64Parameter("data");
method = allData & 0xF00;
method >>= 8;
unit = allData & 0xF0;
unit >>= 4;
unit++;
house = allData & 0xF;
if(house > 16 || unit < 1 || unit > 16) {
// not waveman
return "";
}
house = house + 'A'; // house from A to P
if(method != 6 && lastArctecCodeSwitchWasTurnOff == 1) {
lastArctecCodeSwitchWasTurnOff = 0;
return ""; // probably a stray turnon or bell (perhaps: only certain time interval since last, check that it's the same house/unit... Will lose
// one turnon/bell, but it's better than the alternative...
}
if(method == 6) {
lastArctecCodeSwitchWasTurnOff = 1;
}
std::stringstream retString;
retString << "class:command;protocol:waveman;model:codeswitch;house:" << static_cast<char>(house);
if(method == 0) {
retString << ";unit:" << unit << ";method:turnoff;";
} else if(method == 14) {
retString << ";unit:" << unit << ";method:turnon;";
} else {
// not waveman
return "";
}
return retString.str();
}

View File

@@ -0,0 +1,26 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLWAVEMAN_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLWAVEMAN_H_
#include <string>
#include "service/ProtocolNexa.h"
class ProtocolWaveman : public ProtocolNexa {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
static std::string decodeData(const ControllerMessage &dataMsg);
protected:
virtual std::string getOffCode() const;
private:
static int lastArctecCodeSwitchWasTurnOff;
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLWAVEMAN_H_

View File

@@ -0,0 +1,185 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/ProtocolX10.h"
#ifdef _MSC_VER
#else
#include <stdint.h>
#endif
#include <stdio.h>
#include <sstream>
#include <string>
const unsigned char HOUSES[] = {6, 0xE, 2, 0xA, 1, 9, 5, 0xD, 7, 0xF, 3, 0xB, 0, 8, 4, 0xC};
int ProtocolX10::methods() const {
return TELLSTICK_TURNON | TELLSTICK_TURNOFF;
}
std::string ProtocolX10::getStringForMethod(int method, unsigned char data, Controller *controller) {
const unsigned char S = 59, L = 169;
const char B0[] = {static_cast<char>(S), static_cast<char>(S), 0};
const char B1[] = {static_cast<char>(S), static_cast<char>(L), 0};
const unsigned char START_CODE[] = {'S', 255, 1, 255, 1, 255, 1, 100, 255, 1, 180, 0};
const unsigned char STOP_CODE[] = {S, 0};
std::string strReturn = reinterpret_cast<const char*>(START_CODE);
std::string strComplement = "";
std::wstring strHouse = getStringParameter(L"house", L"A");
int intHouse = strHouse[0] - L'A';
if (intHouse < 0) {
intHouse = 0;
} else if (intHouse > 15) {
intHouse = 15;
}
// Translate it
intHouse = HOUSES[intHouse];
int intCode = getIntParameter(L"unit", 1, 16)-1;
for( int i = 0; i < 4; ++i ) {
if (intHouse & 1) {
strReturn.append(B1);
strComplement.append(B0);
} else {
strReturn.append(B0);
strComplement.append(B1);
}
intHouse >>= 1;
}
strReturn.append( B0 );
strComplement.append( B1 );
if (intCode >= 8) {
strReturn.append(B1);
strComplement.append(B0);
} else {
strReturn.append(B0);
strComplement.append(B1);
}
strReturn.append( B0 );
strComplement.append( B1 );
strReturn.append( B0 );
strComplement.append( B1 );
strReturn.append( strComplement );
strComplement = "";
strReturn.append( B0 );
strComplement.append( B1 );
if (intCode >> 2 & 1) { // Bit 2 of intCode
strReturn.append(B1);
strComplement.append(B0);
} else {
strReturn.append(B0);
strComplement.append(B1);
}
if (method == TELLSTICK_TURNON) {
strReturn.append(B0);
strComplement.append(B1);
} else if (method == TELLSTICK_TURNOFF) {
strReturn.append(B1);
strComplement.append(B0);
} else {
return "";
}
if (intCode & 1) { // Bit 0 of intCode
strReturn.append(B1);
strComplement.append(B0);
} else {
strReturn.append(B0);
strComplement.append(B1);
}
if (intCode >> 1 & 1) { // Bit 1 of intCode
strReturn.append(B1);
strComplement.append(B0);
} else {
strReturn.append(B0);
strComplement.append(B1);
}
for( int i = 0; i < 3; ++i ) {
strReturn.append( B0 );
strComplement.append( B1 );
}
strReturn.append( strComplement );
strReturn.append( reinterpret_cast<const char*>(STOP_CODE) );
strReturn.append("+");
return strReturn;
}
std::string ProtocolX10::decodeData(const ControllerMessage& dataMsg) {
uint64_t intData = 0, currentBit = 31;
bool method = 0;
intData = dataMsg.getInt64Parameter("data");
int unit = 0;
int rawHouse = 0;
for(int i = 0; i < 4; ++i) {
rawHouse >>= 1;
if (checkBit(intData, currentBit--)) {
rawHouse |= 0x8;
}
}
if (checkBit(intData, currentBit--) != 0) {
return "";
}
if (checkBit(intData, currentBit--)) {
unit |= (1<<3);
}
if (checkBit(intData, currentBit--)) {
return "";
}
if (checkBit(intData, currentBit--)) {
return "";
}
currentBit = 14;
if (checkBit(intData, currentBit--)) {
unit |= (1<<2);
}
if (checkBit(intData, currentBit--)) {
method = 1;
}
if (checkBit(intData, currentBit--)) {
unit |= (1<<0);
}
if (checkBit(intData, currentBit--)) {
unit |= (1<<1);
}
int intHouse = 0;
for(int i = 0; i < 16; ++i) {
if (HOUSES[i] == rawHouse) {
intHouse = i;
break;
}
}
std::stringstream retString;
retString << "class:command;protocol:x10;model:codeswitch;";
retString << "house:" << static_cast<char>('A' + intHouse);
retString << ";unit:" << unit+1;
retString << ";method:";
if(method == 0) {
retString << "turnon;";
} else {
retString << "turnoff;";
}
return retString.str();
}

View File

@@ -0,0 +1,22 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLX10_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLX10_H_
#include <string>
#include "service/Protocol.h"
#include "service/ControllerMessage.h"
class ProtocolX10 : public Protocol {
public:
int methods() const;
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
static std::string decodeData(const ControllerMessage &dataMsg);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLX10_H_

View File

@@ -0,0 +1,31 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include <string>
#include "service/ProtocolYidong.h"
std::string ProtocolYidong::getStringForMethod(int method, unsigned char, Controller *) {
int intCode = this->getIntParameter(L"unit", 1, 4);
std::wstring strCode = L"111";
switch(intCode) {
case 1:
strCode.append(L"0010");
break;
case 2:
strCode.append(L"0001");
break;
case 3:
strCode.append(L"0100");
break;
case 4:
strCode.append(L"1000");
break;
}
strCode.append(L"110");
return getStringForCode(strCode, method);
}

View File

@@ -0,0 +1,18 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_PROTOCOLYIDONG_H_
#define TELLDUS_CORE_SERVICE_PROTOCOLYIDONG_H_
#include <string>
#include "service/ProtocolSartano.h"
class ProtocolYidong : public ProtocolSartano {
public:
virtual std::string getStringForMethod(int method, unsigned char data, Controller *controller);
};
#endif // TELLDUS_CORE_SERVICE_PROTOCOLYIDONG_H_

View File

@@ -0,0 +1,73 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/Sensor.h"
#include <map>
#include <string>
#include "common/common.h"
#include "client/telldus-core.h"
class Sensor::PrivateData {
public:
std::wstring protocol, model;
int id;
std::map<int, std::string> values;
time_t timestamp;
};
Sensor::Sensor(const std::wstring &protocol, const std::wstring &model, int id)
:Mutex() {
d = new PrivateData;
d->protocol = protocol;
d->model = model;
d->id = id;
}
Sensor::~Sensor() {
delete d;
}
std::wstring Sensor::protocol() const {
return d->protocol;
}
std::wstring Sensor::model() const {
return d->model;
}
int Sensor::id() const {
return d->id;
}
time_t Sensor::timestamp() const {
return d->timestamp;
}
int Sensor::dataTypes() const {
int retval = 0;
for (std::map<int, std::string>::iterator it = d->values.begin(); it != d->values.end(); ++it) {
retval |= (*it).first;
}
return retval;
}
void Sensor::setValue(int type, const std::string &value, time_t timestamp) {
if (value.substr(0, 2).compare("0x") == 0) {
int intval = strtol(value.c_str(), NULL, 16);
d->values[type] = TelldusCore::intToString(intval);
} else {
d->values[type] = value;
}
d->timestamp = timestamp;
}
std::string Sensor::value(int type) const {
std::map<int, std::string>::const_iterator it = d->values.find(type);
if (it == d->values.end()) {
return "";
}
return (*it).second;
}

View File

@@ -0,0 +1,33 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_SENSOR_H_
#define TELLDUS_CORE_SERVICE_SENSOR_H_
#include <string>
#include "common/Mutex.h"
class Sensor : public TelldusCore::Mutex {
public:
Sensor(const std::wstring &protocol, const std::wstring &model, int id);
~Sensor();
std::wstring protocol() const;
std::wstring model() const;
int id() const;
time_t timestamp() const;
int dataTypes() const;
void setValue(int type, const std::string &value, time_t timestamp);
std::string value(int type) const;
private:
class PrivateData;
PrivateData *d;
};
#endif // TELLDUS_CORE_SERVICE_SENSOR_H_

View File

@@ -0,0 +1,140 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/Settings.h"
#include <string>
TelldusCore::Mutex Settings::mutex;
/*
* Get the name of the device
*/
std::wstring Settings::getName(Node type, int intNodeId) const {
TelldusCore::MutexLocker locker(&mutex);
return getStringSetting(type, intNodeId, L"name", false);
}
/*
* Set the name of the device
*/
int Settings::setName(Node type, int intDeviceId, const std::wstring &strNewName) {
TelldusCore::MutexLocker locker(&mutex);
return setStringSetting(type, intDeviceId, L"name", strNewName, false);
}
/*
* Get the device vendor
*/
std::wstring Settings::getProtocol(int intDeviceId) const {
TelldusCore::MutexLocker locker(&mutex);
return getStringSetting(Device, intDeviceId, L"protocol", false);
}
/*
* Set the device vendor
*/
int Settings::setProtocol(int intDeviceId, const std::wstring &strVendor) {
TelldusCore::MutexLocker locker(&mutex);
return setStringSetting(Device, intDeviceId, L"protocol", strVendor, false);
}
/*
* Get the device model
*/
std::wstring Settings::getModel(int intDeviceId) const {
TelldusCore::MutexLocker locker(&mutex);
return getStringSetting(Device, intDeviceId, L"model", false);
}
/*
* Set the device model
*/
int Settings::setModel(int intDeviceId, const std::wstring &strModel) {
TelldusCore::MutexLocker locker(&mutex);
return setStringSetting(Device, intDeviceId, L"model", strModel, false);
}
/*
* Set device argument
*/
int Settings::setDeviceParameter(int intDeviceId, const std::wstring &strName, const std::wstring &strValue) {
TelldusCore::MutexLocker locker(&mutex);
return setStringSetting(Device, intDeviceId, strName, strValue, true);
}
/*
* Get device argument
*/
std::wstring Settings::getDeviceParameter(int intDeviceId, const std::wstring &strName) const {
TelldusCore::MutexLocker locker(&mutex);
return getStringSetting(Device, intDeviceId, strName, true);
}
/*
* Set preferred controller id
*/
int Settings::setPreferredControllerId(int intDeviceId, int value) {
TelldusCore::MutexLocker locker(&mutex);
return setIntSetting(Device, intDeviceId, L"controller", value, false);
}
/*
* Get preferred controller id
*/
int Settings::getPreferredControllerId(int intDeviceId) {
TelldusCore::MutexLocker locker(&mutex);
return getIntSetting(Device, intDeviceId, L"controller", false);
}
std::wstring Settings::getControllerSerial(int intControllerId) const {
TelldusCore::MutexLocker locker(&mutex);
return getStringSetting(Controller, intControllerId, L"serial", false);
}
int Settings::setControllerSerial(int intControllerId, const std::wstring &serial) {
TelldusCore::MutexLocker locker(&mutex);
return setStringSetting(Controller, intControllerId, L"serial", serial, false);
}
int Settings::getControllerType(int intControllerId) const {
TelldusCore::MutexLocker locker(&mutex);
return getIntSetting(Controller, intControllerId, L"type", false);
}
int Settings::setControllerType(int intControllerId, int type) {
TelldusCore::MutexLocker locker(&mutex);
return setIntSetting(Controller, intControllerId, L"type", type, false);
}
std::string Settings::getNodeString(Settings::Node type) const {
if (type == Device) {
return "device";
} else if (type == Controller) {
return "controller";
}
return "";
}
#ifndef _CONFUSE
bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::wstring &strDeviceStateValue ) {
TelldusCore::MutexLocker locker(&mutex);
bool retval = setIntSetting( Settings::Device, intDeviceId, L"state", intDeviceState, true );
setStringSetting( Settings::Device, intDeviceId, L"stateValue", strDeviceStateValue, true );
return retval;
}
int Settings::getDeviceState( int intDeviceId ) const {
TelldusCore::MutexLocker locker(&mutex);
return getIntSetting( Settings::Device, intDeviceId, L"state", true );
}
std::wstring Settings::getDeviceStateValue( int intDeviceId ) const {
TelldusCore::MutexLocker locker(&mutex);
return getStringSetting( Settings::Device, intDeviceId, L"stateValue", true );
}
#endif

View File

@@ -0,0 +1,60 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_SETTINGS_H_
#define TELLDUS_CORE_SERVICE_SETTINGS_H_
#include <string>
#include "common/Mutex.h"
class Settings {
public:
enum Node { Device, Controller };
Settings(void);
virtual ~Settings(void);
std::wstring getSetting(const std::wstring &strName) const;
int getNumberOfNodes(Node type) const;
std::wstring getName(Node type, int intNodeId) const;
int setName(Node type, int intDeviceId, const std::wstring &strNewName);
std::wstring getProtocol(int intDeviceId) const;
int setProtocol(int intDeviceId, const std::wstring &strVendor);
std::wstring getModel(int intDeviceId) const;
int setModel(int intDeviceId, const std::wstring &strModel);
std::wstring getDeviceParameter(int intDeviceId, const std::wstring &strName) const;
int setDeviceParameter(int intDeviceId, const std::wstring &strName, const std::wstring &strValue);
bool setDeviceState( int intDeviceId, int intDeviceState, const std::wstring &strDeviceStateValue );
int getDeviceState( int intDeviceId ) const;
std::wstring getDeviceStateValue( int intDeviceId ) const;
int getPreferredControllerId(int intDeviceId);
int setPreferredControllerId(int intDeviceId, int value);
int addNode(Node type);
int getNodeId(Node type, int intDeviceIndex) const;
int removeNode(Node type, int intNodeId);
std::wstring getControllerSerial(int intControllerId) const;
int setControllerSerial(int intControllerId, const std::wstring &serial);
int getControllerType(int intControllerId) const;
int setControllerType(int intControllerId, int type);
protected:
std::wstring getStringSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const;
int setStringSetting(Node type, int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter);
int getIntSetting(Node type, int intDeviceId, const std::wstring &name, bool parameter) const;
int setIntSetting(Node type, int intDeviceId, const std::wstring &name, int value, bool parameter);
private:
int getNextNodeId(Node type) const;
std::string getNodeString(Node type) const;
class PrivateData;
PrivateData *d;
static TelldusCore::Mutex mutex;
};
#endif // TELLDUS_CORE_SERVICE_SETTINGS_H_

View File

@@ -0,0 +1,451 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include <confuse.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <string>
#include "service/Settings.h"
#include "service/config.h"
#include "client/telldus-core.h"
#include "common/Strings.h"
#include "service/Log.h"
class Settings::PrivateData {
public:
cfg_t *cfg;
cfg_t *var_cfg;
};
bool readConfig(cfg_t **cfg);
bool readVarConfig(cfg_t **cfg);
const char* CONFIG_FILE = CONFIG_PATH "/tellstick.conf";
const char* VAR_CONFIG_FILE = VAR_CONFIG_PATH "/telldus-core.conf";
/*
* Constructor
*/
Settings::Settings(void) {
TelldusCore::MutexLocker locker(&mutex);
d = new PrivateData;
readConfig(&d->cfg);
readVarConfig(&d->var_cfg);
}
/*
* Destructor
*/
Settings::~Settings(void) {
TelldusCore::MutexLocker locker(&mutex);
if (d->cfg != NULL) {
cfg_free(d->cfg);
}
if (d->var_cfg != NULL) {
cfg_free(d->var_cfg);
}
delete d;
}
/*
* Return a setting
*/
std::wstring Settings::getSetting(const std::wstring &strName) const {
TelldusCore::MutexLocker locker(&mutex);
if (d->cfg != NULL) {
std::string setting(cfg_getstr(d->cfg, TelldusCore::wideToString(strName).c_str()));
return TelldusCore::charToWstring(setting.c_str());
}
return L"";
}
/*
* Return the number of stored devices
*/
int Settings::getNumberOfNodes(Node node) const {
TelldusCore::MutexLocker locker(&mutex);
if (d->cfg != NULL) {
if (node == Device) {
return cfg_size(d->cfg, "device");
} else if (node == Controller) {
return cfg_size(d->cfg, "controller");
}
}
return 0;
}
int Settings::getNodeId(Node type, int intDeviceIndex) const {
if (intDeviceIndex >= getNumberOfNodes(type)) { // Out of bounds
return -1;
}
TelldusCore::MutexLocker locker(&mutex);
cfg_t *cfg_node;
if (type == Device) {
cfg_node = cfg_getnsec(d->cfg, "device", intDeviceIndex);
} else if (type == Controller) {
cfg_node = cfg_getnsec(d->cfg, "controller", intDeviceIndex);
}
int id = cfg_getint(cfg_node, "id");
return id;
}
/*
* Add a new node
*/
int Settings::addNode(Node type) {
TelldusCore::MutexLocker locker(&mutex);
int intNodeId = getNextNodeId(type);
FILE *fp = fopen(CONFIG_FILE, "we"); // e for setting O_CLOEXEC on the file handle
if (!fp) {
return TELLSTICK_ERROR_PERMISSION_DENIED;
}
cfg_print(d->cfg, fp); // Print the config-file
if (type == Device) {
fprintf(fp, "device {\n id=%d\n}\n", intNodeId); // Print the new device
} else if (type == Controller) {
fprintf(fp, "controller {\n id=%d\n}\n", intNodeId); // Print the new controller
}
fclose(fp);
// Re-read config-file
cfg_free(d->cfg);
readConfig(&d->cfg);
return intNodeId;
}
/*
* Get next available node id
*/
int Settings::getNextNodeId(Node type) const {
// Private, no locks needed
int intNodeId = 0;
cfg_t *cfg_node;
std::string strType;
if (type == Device) {
strType = "device";
} else if (type == Controller) {
strType = "controller";
}
for (int i = 0; i < cfg_size(d->cfg, strType.c_str()); ++i) {
cfg_node = cfg_getnsec(d->cfg, strType.c_str(), i);
if (cfg_getint(cfg_node, "id") >= intNodeId) {
intNodeId = cfg_getint(cfg_node, "id");
}
}
intNodeId++;
return intNodeId;
}
/*
* Remove a device
*/
int Settings::removeNode(Node type, int intNodeId) {
TelldusCore::MutexLocker locker(&mutex);
FILE *fp = fopen(CONFIG_FILE, "we"); // e for setting O_CLOEXEC on the file handle
if (!fp) {
return TELLSTICK_ERROR_PERMISSION_DENIED;
}
std::string strType = getNodeString(type);
// Print all opts
for(int i = 0; d->cfg->opts[i].name; i++) {
// Check if it isn't a device section
if (strcmp(d->cfg->opts[i].name, strType.c_str()) != 0) {
cfg_opt_print(&d->cfg->opts[i], fp);
} else {
// Print all sections except the one to remove
cfg_t *cfg_node;
for (int i = 0; i < cfg_size(d->cfg, strType.c_str()); ++i) {
cfg_node = cfg_getnsec(d->cfg, strType.c_str(), i);
if (cfg_getint(cfg_node, "id") != intNodeId) { // This isn't the one to skip
fprintf(fp, "%s {\n", strType.c_str());
cfg_print_indent(cfg_node, fp, 1);
fprintf(fp, "}\n");
}
}
}
}
fclose(fp);
// Re-read config-file
cfg_free(d->cfg);
readConfig(&d->cfg);
return TELLSTICK_SUCCESS;
}
bool Settings::setDeviceState( int intDeviceId, int intDeviceState, const std::wstring &strDeviceStateValue ) {
TelldusCore::MutexLocker locker(&mutex);
if (d->var_cfg == 0) {
return false;
}
cfg_t *cfg_device;
for (int i = 0; i < cfg_size(d->var_cfg, "device"); ++i) {
cfg_device = cfg_getnsec(d->var_cfg, "device", i);
int deviceId = atoi(cfg_title(cfg_device));
if (deviceId == intDeviceId) {
cfg_setint(cfg_device, "state", intDeviceState);
cfg_setstr(cfg_device, "stateValue", TelldusCore::wideToString(strDeviceStateValue).c_str());
FILE *fp = fopen(VAR_CONFIG_FILE, "we"); // e for setting O_CLOEXEC on the file handle
if(fp == 0) {
return false;
}
cfg_print(d->var_cfg, fp);
fclose(fp);
return true;
}
}
// The device is not found in the file, we must create it manualy...
FILE *fp = fopen(VAR_CONFIG_FILE, "we"); // e for setting O_CLOEXEC on the file handle
if(!fp) {
fprintf(stderr, "Failed to write state to %s: %s\n",
VAR_CONFIG_FILE, strerror(errno));
return false;
}
cfg_print(d->var_cfg, fp); // Print the config-file
fprintf(fp, "device %d {\n}\n", intDeviceId); // Print the new device
fclose(fp);
// Re-read config-file
cfg_free(d->var_cfg);
readVarConfig(&d->var_cfg);
return false;
}
int Settings::getDeviceState( int intDeviceId ) const {
TelldusCore::MutexLocker locker(&mutex);
if (d->var_cfg == 0) {
return false;
}
cfg_t *cfg_device;
for (int i = 0; i < cfg_size(d->var_cfg, "device"); ++i) {
cfg_device = cfg_getnsec(d->var_cfg, "device", i);
int deviceId = atoi(cfg_title(cfg_device));
if (deviceId == intDeviceId) {
return cfg_getint(cfg_device, "state");
}
}
return TELLSTICK_TURNOFF;
}
std::wstring Settings::getDeviceStateValue( int intDeviceId ) const {
TelldusCore::MutexLocker locker(&mutex);
if (d->var_cfg == 0) {
return L"";
}
cfg_t *cfg_device;
for (int i = 0; i < cfg_size(d->var_cfg, "device"); ++i) {
cfg_device = cfg_getnsec(d->var_cfg, "device", i);
int deviceId = atoi(cfg_title(cfg_device));
if (deviceId == intDeviceId) {
std::string value(cfg_getstr(cfg_device, "stateValue"));
return TelldusCore::charToWstring(value.c_str());
}
}
return L"";
}
std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const {
// already locked
if (d->cfg == 0) {
return L"";
}
std::string strType = getNodeString(type);
cfg_t *cfg_device;
for (int i = 0; i < cfg_size(d->cfg, strType.c_str()); ++i) {
cfg_device = cfg_getnsec(d->cfg, strType.c_str(), i);
if (cfg_getint(cfg_device, "id") == intNodeId) {
if (parameter) {
cfg_device = cfg_getsec(cfg_device, "parameters");
}
std::wstring setting;
char *cSetting = cfg_getstr(cfg_device, TelldusCore::wideToString(name).c_str());
if (cSetting) {
setting = TelldusCore::charToWstring(cSetting);
}
return setting;
}
}
return L"";
}
int Settings::setStringSetting(Node type, int intDeviceId, const std::wstring &name, const std::wstring &value, bool parameter) {
// already locked
if (d->cfg == 0) {
return TELLSTICK_ERROR_PERMISSION_DENIED;
}
std::string strType = getNodeString(type);
cfg_t *cfg_device;
for (int i = 0; i < cfg_size(d->cfg, strType.c_str()); ++i) {
cfg_device = cfg_getnsec(d->cfg, strType.c_str(), i);
if (cfg_getint(cfg_device, "id") == intDeviceId) {
std::string newValue = TelldusCore::wideToString(value);
cfg_t *p = cfg_device;
if (parameter) {
p = cfg_getsec(cfg_device, "parameters");
}
cfg_opt_t *opt = cfg_getopt(p, TelldusCore::wideToString(name).c_str());
if (!opt) {
return TELLSTICK_ERROR_CONFIG_SYNTAX;
}
cfg_setstr(p, TelldusCore::wideToString(name).c_str(), newValue.c_str());
FILE *fp = fopen(CONFIG_FILE, "we"); // e for setting O_CLOEXEC on the file handle
if (!fp) {
return TELLSTICK_ERROR_PERMISSION_DENIED;
}
cfg_print(d->cfg, fp);
fclose(fp);
return TELLSTICK_SUCCESS;
}
}
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
int Settings::getIntSetting(Node type, int intDeviceId, const std::wstring &name, bool parameter) const {
// already locked
if (d->cfg == 0) {
return 0;
}
std::string strType = getNodeString(type);
cfg_t *cfg_node;
for(int i = 0; i < cfg_size(d->cfg, strType.c_str()); ++i) {
cfg_node = cfg_getnsec(d->cfg, strType.c_str(), i);
if (cfg_getint(cfg_node, "id") == intDeviceId) {
if (parameter) {
cfg_node = cfg_getsec(cfg_node, "parameters");
}
return cfg_getint(cfg_node, TelldusCore::wideToString(name).c_str());
}
}
return 0;
}
int Settings::setIntSetting(Node type, int intDeviceId, const std::wstring &name, int value, bool parameter) {
// already locked
if (d->cfg == 0) {
return TELLSTICK_ERROR_PERMISSION_DENIED;
}
std::string strType = getNodeString(type);
cfg_t *cfg_device;
for (int i = 0; i < cfg_size(d->cfg, strType.c_str()); ++i) {
cfg_device = cfg_getnsec(d->cfg, strType.c_str(), i);
if (cfg_getint(cfg_device, "id") == intDeviceId) {
if (parameter) {
cfg_t *cfg_parameters = cfg_getsec(cfg_device, "parameters");
cfg_setint(cfg_parameters, TelldusCore::wideToString(name).c_str(), value);
} else {
cfg_setint(cfg_device, TelldusCore::wideToString(name).c_str(), value);
}
FILE *fp = fopen(CONFIG_FILE, "we"); // e for setting O_CLOEXEC on the file handle
if (!fp) {
return TELLSTICK_ERROR_PERMISSION_DENIED;
}
cfg_print(d->cfg, fp);
fclose(fp);
return TELLSTICK_SUCCESS;
}
}
return TELLSTICK_ERROR_DEVICE_NOT_FOUND;
}
bool readConfig(cfg_t **cfg) {
// All the const_cast keywords is to remove the compiler warnings generated by the C++-compiler.
cfg_opt_t controller_opts[] = {
CFG_INT(const_cast<char *>("id"), -1, CFGF_NONE),
CFG_STR(const_cast<char *>("name"), const_cast<char *>(""), CFGF_NONE),
CFG_INT(const_cast<char *>("type"), 0, CFGF_NONE),
CFG_STR(const_cast<char *>("serial"), const_cast<char *>(""), CFGF_NONE),
CFG_END()
};
cfg_opt_t device_parameter_opts[] = {
// Groups
CFG_STR(const_cast<char *>("devices"), 0, CFGF_NONE),
CFG_STR(const_cast<char *>("house"), 0, CFGF_NONE),
CFG_STR(const_cast<char *>("unit"), 0, CFGF_NONE),
CFG_STR(const_cast<char *>("code"), 0, CFGF_NONE),
CFG_STR(const_cast<char *>("system"), 0, CFGF_NONE),
CFG_STR(const_cast<char *>("units"), 0, CFGF_NONE),
CFG_STR(const_cast<char *>("fade"), 0, CFGF_NONE),
CFG_END()
};
cfg_opt_t device_opts[] = {
CFG_INT(const_cast<char *>("id"), -1, CFGF_NONE),
CFG_STR(const_cast<char *>("name"), const_cast<char *>("Unnamed"), CFGF_NONE),
CFG_INT(const_cast<char *>("controller"), 0, CFGF_NONE),
CFG_STR(const_cast<char *>("protocol"), const_cast<char *>("arctech"), CFGF_NONE),
CFG_STR(const_cast<char *>("model"), const_cast<char *>(""), CFGF_NONE),
CFG_SEC(const_cast<char *>("parameters"), device_parameter_opts, CFGF_NONE),
CFG_END()
};
cfg_opt_t opts[] = {
CFG_STR(const_cast<char *>("user"), const_cast<char *>("nobody"), CFGF_NONE),
CFG_STR(const_cast<char *>("group"), const_cast<char *>("plugdev"), CFGF_NONE),
CFG_STR(const_cast<char *>("deviceNode"), const_cast<char *>("/dev/tellstick"), CFGF_NONE),
CFG_STR(const_cast<char *>("ignoreControllerConfirmation"), const_cast<char *>("false"), CFGF_NONE),
CFG_SEC(const_cast<char *>("device"), device_opts, CFGF_MULTI),
CFG_SEC(const_cast<char *>("controller"), controller_opts, CFGF_MULTI),
CFG_END()
};
FILE *fp = fopen(CONFIG_FILE, "re"); // e for setting O_CLOEXEC on the file handle
if (!fp) {
Log::warning("Unable to open config file, %s", CONFIG_FILE);
return false;
}
(*cfg) = cfg_init(opts, CFGF_NOCASE);
if (cfg_parse_fp((*cfg), fp) == CFG_PARSE_ERROR) {
(*cfg) = 0;
fclose(fp);
Log::warning("Unable to parse config file, %s", CONFIG_FILE);
return false;
}
fclose(fp);
return true;
}
bool readVarConfig(cfg_t **cfg) {
cfg_opt_t device_opts[] = {
CFG_INT(const_cast<char *>("state"), 0, CFGF_NONE),
CFG_STR(const_cast<char *>("stateValue"), const_cast<char *>(""), CFGF_NONE),
CFG_END()
};
cfg_opt_t opts[] = {
CFG_SEC(const_cast<char *>("device"), device_opts, CFGF_MULTI | CFGF_TITLE),
CFG_END()
};
FILE *fp = fopen(VAR_CONFIG_FILE, "re"); // e for setting O_CLOEXEC on the file handle
if (!fp) {
Log::warning("Unable to open var config file, %s", VAR_CONFIG_FILE);
return false;
}
(*cfg) = cfg_init(opts, CFGF_NOCASE);
if (cfg_parse_fp((*cfg), fp) == CFG_PARSE_ERROR) {
(*cfg) = 0;
fclose(fp);
Log::warning("Unable to parse var config file, %s", VAR_CONFIG_FILE);
return false;
}
fclose(fp);
return true;
}

View File

@@ -0,0 +1,310 @@
//
// C++ Implementation: telldussettingsconfuse
//
// Description:
//
//
// Author: Micke Prag <micke.prag@telldus.se>, (C) 2008
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include <stdlib.h>
#include <string.h>
#include <CoreFoundation/CoreFoundation.h>
#include <string>
#include "common/Strings.h"
#include "service/Settings.h"
#include "client/telldus-core.h"
class privateVars {
public:
CFStringRef app_ID;
CFStringRef userName;
CFStringRef hostName;
};
class Settings::PrivateData {
public:
CFStringRef app_ID;
CFStringRef userName;
CFStringRef hostName;
};
/*
* Constructor
*/
Settings::Settings(void) {
d = new PrivateData();
d->app_ID = CFSTR( "com.telldus.core" );
d->userName = kCFPreferencesAnyUser;
d->hostName = kCFPreferencesCurrentHost;
}
/*
* Destructor
*/
Settings::~Settings(void) {
delete d;
}
/*
* Return a setting
*/
std::wstring Settings::getSetting(const std::wstring &strName) const {
return L"";
}
/*
* Return the number of stored devices
*/
int Settings::getNumberOfNodes(Node type) const {
CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName );
if (!cfarray) {
return 0;
}
CFIndex size = CFArrayGetCount( cfarray );
int nodes = 0;
for (CFIndex k = 0; k < size; ++k) {
CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k);
if (!CFStringHasSuffix( key, CFSTR(".name") )) {
continue;
}
if (type == Device && CFStringHasPrefix( key, CFSTR("devices.") )) {
++nodes;
} else if (type == Controller && CFStringHasPrefix( key, CFSTR("controllers.") )) {
++nodes;
}
}
CFRelease(cfarray);
return nodes;
}
int Settings::getNodeId(Node type, int intNodeIndex) const {
CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName );
if (!cfarray) {
return 0;
}
CFIndex size = CFArrayGetCount( cfarray );
int index = 0;
int id = 0;
for (CFIndex k = 0; k < size; ++k) {
CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k);
if (!CFStringHasSuffix( key, CFSTR(".name") )) {
continue;
}
if ( type == Device && !CFStringHasPrefix(key, CFSTR("devices.")) ) {
continue;
}
if ( type == Controller && !CFStringHasPrefix(key, CFSTR("controllers.")) ) {
continue;
}
if (index == intNodeIndex) {
CFArrayRef split = CFStringCreateArrayBySeparatingStrings( 0, key, CFSTR(".") );
if ( !split ) {
continue;
}
if (CFArrayGetCount( split ) != 3 ) {
CFRelease( split );
continue;
}
// This code crashes!
// CFNumberRef cfid = (CFNumberRef) CFArrayGetValueAtIndex( split, 1 );
// if (cfid)
// CFNumberGetValue( cfid, kCFNumberIntType, &id);
CFStringRef cfid = (CFStringRef) CFArrayGetValueAtIndex( split, 1 );
char *cp = NULL;
CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( cfid ), kCFStringEncodingUTF8) + 1;
cp = reinterpret_cast<char *>(malloc(size));
CFStringGetCString( cfid, cp, size, kCFStringEncodingUTF8 );
char *newcp = reinterpret_cast<char *>(realloc( cp, strlen(cp) + 1));
if (newcp != NULL) {
cp = newcp;
id = atoi(cp);
} else {
// Should not happen
id = 0;
}
free(cp);
CFRelease(split);
break;
}
index++;
}
CFRelease(cfarray);
return id;
}
/*
* Add a new node
*/
int Settings::addNode(Node type) {
int id = getNextNodeId(type);
setStringSetting( type, id, L"name", L"", false ); // Create a empty name so the node has an entry
if (type == Device) {
// Is there a reason we do this?
setStringSetting( type, id, L"model", L"", false );
}
return id;
}
/*
* Get next available node id
*/
int Settings::getNextNodeId(Node type) const {
int id = 0, max = 0;
int numberOfNodes = getNumberOfNodes(type);
for( int i = 0; i < numberOfNodes; i++) {
id = getNodeId( type, i );
if (id > max) {
max = id;
}
}
max++;
return max;
}
/*
* Remove a device
*/
int Settings::removeNode(Node type, int intNodeId) {
int ret = TELLSTICK_ERROR_DEVICE_NOT_FOUND;
CFStringRef filterKey = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d."), getNodeString(type).c_str(), intNodeId); // The key to search for
CFArrayRef cfarray = CFPreferencesCopyKeyList( d->app_ID, d->userName, d->hostName );
if (!cfarray) {
CFRelease(filterKey);
return TELLSTICK_ERROR_UNKNOWN;
}
CFIndex size = CFArrayGetCount( cfarray );
for (CFIndex k = 0; k < size; ++k) {
CFStringRef key = (CFStringRef) CFArrayGetValueAtIndex(cfarray, k);
if (CFStringHasPrefix( key, filterKey ) ) {
CFPreferencesSetValue( key, NULL, d->app_ID, d->userName, d->hostName ); // Remove the key
ret = TELLSTICK_SUCCESS;
}
}
CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName );
CFRelease(cfarray);
CFRelease(filterKey);
return ret;
}
std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wstring &wname, bool parameter) const {
std::string name(TelldusCore::wideToString(wname));
CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 );
CFStringRef key;
if (parameter) {
key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.parameters.%@"), getNodeString(type).c_str(), intNodeId, cfname);
} else {
key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.%@"), getNodeString(type).c_str(), intNodeId, cfname);
}
CFStringRef value;
value = (CFStringRef)CFPreferencesCopyValue(key, d->app_ID, d->userName, d->hostName);
if (!value) {
CFRelease(key);
CFRelease(cfname);
return L"";
}
std::wstring retval;
char *cp = NULL;
CFIndex size = CFStringGetMaximumSizeForEncoding( CFStringGetLength( value ), kCFStringEncodingUTF8) + 1;
cp = reinterpret_cast<char *>(malloc(size));
CFStringGetCString( value, cp, size, kCFStringEncodingUTF8 );
char *newcp = reinterpret_cast<char *>(realloc( cp, strlen(cp) + 1));
if (newcp != NULL) {
cp = newcp;
retval = TelldusCore::charToWstring(cp);
} else {
// Should not happen
retval = L"";
}
free(cp);
CFRelease(value);
CFRelease(key);
CFRelease(cfname);
return retval;
}
int Settings::setStringSetting(Node type, int intNodeId, const std::wstring &wname, const std::wstring &wvalue, bool parameter) {
std::string name(TelldusCore::wideToString(wname));
std::string value(TelldusCore::wideToString(wvalue));
CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 );
CFStringRef cfvalue = CFStringCreateWithCString( 0, value.c_str(), kCFStringEncodingUTF8 );
CFStringRef key;
if (parameter) {
key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.parameters.%@"), getNodeString(type).c_str(), intNodeId, cfname);
} else {
key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.%@"), getNodeString(type).c_str(), intNodeId, cfname);
}
CFPreferencesSetValue( key, cfvalue, d->app_ID, d->userName, d->hostName );
CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName );
CFRelease(key);
CFRelease(cfvalue);
CFRelease(cfname);
return TELLSTICK_SUCCESS;
}
int Settings::getIntSetting(Node type, int intNodeId, const std::wstring &wname, bool parameter) const {
int retval = 0;
std::string name(TelldusCore::wideToString(wname));
CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 );
CFNumberRef cfvalue;
CFStringRef key;
if (parameter) {
key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.parameters.%@"), getNodeString(type).c_str(), intNodeId, cfname);
} else {
key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.%@"), getNodeString(type).c_str(), intNodeId, cfname);
}
cfvalue = (CFNumberRef)CFPreferencesCopyValue(key, d->app_ID, d->userName, d->hostName);
// If the preference exists, use it.
if (cfvalue) {
try {
// Numbers come out of preferences as CFNumber objects.
if (!CFNumberGetValue(cfvalue, kCFNumberIntType, &retval)) {
retval = 0;
}
CFRelease(cfvalue);
} catch (std::exception e) {
retval = 0;
}
}
CFRelease(key);
CFRelease(cfname);
return retval;
}
int Settings::setIntSetting(Node type, int intNodeId, const std::wstring &wname, int value, bool parameter) {
std::string name(TelldusCore::wideToString(wname));
CFStringRef cfname = CFStringCreateWithCString( 0, name.c_str(), kCFStringEncodingUTF8 );
CFNumberRef cfvalue = CFNumberCreate(NULL, kCFNumberIntType, &value);
CFStringRef key;
if (parameter) {
key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.parameters.%@"), getNodeString(type).c_str(), intNodeId, cfname);
} else {
key = CFStringCreateWithFormat(0, NULL, CFSTR("%ss.%d.%@"), getNodeString(type).c_str(), intNodeId, cfname);
}
CFPreferencesSetValue( key, cfvalue, d->app_ID, d->userName, d->hostName );
CFPreferencesSynchronize( d->app_ID, d->userName, d->hostName );
CFRelease(key);
CFRelease(cfvalue);
CFRelease(cfname);
return TELLSTICK_SUCCESS;
}

View File

@@ -0,0 +1,270 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include <Windows.h>
#include <sstream>
#include <string>
#include <vector>
#include "../client/telldus-core.h"
#include "common/common.h"
#include "common/Strings.h"
#include "service/Settings.h"
const int intMaxRegValueLength = 1000;
class Settings::PrivateData {
public:
HKEY rootKey;
std::wstring strRegPath;
std::wstring getNodePath(Settings::Node type);
};
std::wstring Settings::PrivateData::getNodePath(Settings::Node type) {
if (type == Settings::Device) {
return L"SOFTWARE\\Telldus\\Devices\\";
} else if (type == Settings::Controller) {
return L"SOFTWARE\\Telldus\\Controllers\\";
}
return L"";
}
/*
* Constructor
*/
Settings::Settings(void) {
d = new PrivateData();
d->strRegPath = L"SOFTWARE\\Telldus\\";
d->rootKey = HKEY_LOCAL_MACHINE;
}
/*
* Destructor
*/
Settings::~Settings(void) {
delete d;
}
/*
* Return the number of stored devices
*/
int Settings::getNumberOfNodes(Node type) const {
TelldusCore::MutexLocker locker(&mutex);
int intNumberOfNodes = 0;
HKEY hk;
LONG lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_QUERY_VALUE, &hk);
if(lnExists == ERROR_SUCCESS) {
std::wstring strNumSubKeys;
DWORD dNumSubKeys;
RegQueryInfoKey(hk, NULL, NULL, NULL, &dNumSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
intNumberOfNodes = static_cast<int>(dNumSubKeys);
RegCloseKey(hk);
}
return intNumberOfNodes;
}
int Settings::getNodeId(Node type, int intNodeIndex) const {
TelldusCore::MutexLocker locker(&mutex);
int intReturn = -1;
HKEY hk;
LONG lnExists = RegOpenKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, KEY_READ, &hk);
if(lnExists == ERROR_SUCCESS) {
wchar_t* Buff = new wchar_t[intMaxRegValueLength];
DWORD size = intMaxRegValueLength;
if (RegEnumKeyEx(hk, intNodeIndex, (LPWSTR)Buff, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
intReturn = _wtoi(Buff);
}
delete[] Buff;
RegCloseKey(hk);
}
return intReturn;
}
/*
* Add a new node
*/
int Settings::addNode(Node type) {
TelldusCore::MutexLocker locker(&mutex);
int intNodeId = -1;
HKEY hk;
DWORD dwDisp;
intNodeId = getNextNodeId(type);
std::wstring strCompleteRegPath = d->getNodePath(type);
strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId));
if (RegCreateKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp)) {
// fail
intNodeId = -1;
}
RegCloseKey(hk);
return intNodeId;
}
/*
* Get next available device id
*/
int Settings::getNextNodeId(Node type) const {
// Private, no locks needed
int intReturn = -1;
HKEY hk;
DWORD dwDisp;
LONG lnExists = RegCreateKeyEx(d->rootKey, d->getNodePath(type).c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, &dwDisp); // create or open if already created
if(lnExists == ERROR_SUCCESS) {
DWORD dwLength = sizeof(DWORD);
DWORD nResult(0);
LONG lngStatus = RegQueryValueEx(hk, L"LastUsedId", NULL, NULL, reinterpret_cast<LPBYTE>(&nResult), &dwLength);
if(lngStatus == ERROR_SUCCESS) {
intReturn = nResult + 1;
} else {
intReturn = 1;
}
DWORD dwVal = intReturn;
RegSetValueEx (hk, L"LastUsedId", 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD));
}
RegCloseKey(hk);
return intReturn;
}
/*
* Remove a device
*/
int Settings::removeNode(Node type, int intNodeId) {
TelldusCore::MutexLocker locker(&mutex);
std::wstring strCompleteRegPath = d->getNodePath(type);
strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId));
LONG lngSuccess = RegDeleteKey(d->rootKey, strCompleteRegPath.c_str());
if(lngSuccess == ERROR_SUCCESS) {
// one of the deletions succeeded
return TELLSTICK_SUCCESS;
}
return TELLSTICK_ERROR_UNKNOWN;
}
std::wstring Settings::getSetting(const std::wstring &strName) const {
std::wstring strReturn;
HKEY hk;
std::wstring strCompleteRegPath = d->strRegPath;
LONG lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk);
if(lnExists == ERROR_SUCCESS) {
wchar_t* Buff = new wchar_t[intMaxRegValueLength];
DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength;
LONG lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength);
if(lngStatus == ERROR_MORE_DATA) {
// The buffer is to small, recreate it
delete[] Buff;
Buff = new wchar_t[dwLength];
lngStatus = RegQueryValueEx(hk, strName.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength);
}
if (lngStatus == ERROR_SUCCESS) {
strReturn = Buff;
}
delete[] Buff;
}
RegCloseKey(hk);
return strReturn;
}
std::wstring Settings::getStringSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const {
std::wstring strReturn;
HKEY hk;
std::wstring strCompleteRegPath = d->getNodePath(type);
strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId));
LONG lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_QUERY_VALUE, &hk);
if(lnExists == ERROR_SUCCESS) {
wchar_t* Buff = new wchar_t[intMaxRegValueLength];
DWORD dwLength = sizeof(wchar_t)*intMaxRegValueLength;
LONG lngStatus = RegQueryValueEx(hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength);
if(lngStatus == ERROR_MORE_DATA) {
// The buffer is to small, recreate it
delete[] Buff;
Buff = new wchar_t[dwLength];
lngStatus = RegQueryValueEx(hk, name.c_str(), NULL, NULL, (LPBYTE)Buff, &dwLength);
}
if (lngStatus == ERROR_SUCCESS) {
strReturn = Buff;
}
delete[] Buff;
}
RegCloseKey(hk);
return strReturn;
}
int Settings::setStringSetting(Node type, int intNodeId, const std::wstring &name, const std::wstring &value, bool parameter) {
HKEY hk;
int ret = TELLSTICK_SUCCESS;
std::wstring strNodeId = TelldusCore::intToWstring(intNodeId);
std::wstring strCompleteRegPath = d->getNodePath(type);
strCompleteRegPath.append(strNodeId);
LONG lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk);
if (lnExists == ERROR_SUCCESS) {
int length = static_cast<int>(value.length()) * sizeof(wchar_t);
RegSetValueEx(hk, name.c_str(), 0, REG_SZ, (LPBYTE)value.c_str(), length+1);
} else {
ret = TELLSTICK_ERROR_UNKNOWN;
}
RegCloseKey(hk);
return ret;
}
int Settings::getIntSetting(Node type, int intNodeId, const std::wstring &name, bool parameter) const {
int intReturn = 0;
std::wstring strSetting = getStringSetting(type, intNodeId, name, parameter);
if (strSetting.length()) {
intReturn = static_cast<int>(strSetting[0]); // TODO(micke): do real conversion instead
}
return intReturn;
}
int Settings::setIntSetting(Node type, int intNodeId, const std::wstring &name, int value, bool parameter) {
int intReturn = TELLSTICK_ERROR_UNKNOWN;
HKEY hk;
std::wstring strCompleteRegPath = d->getNodePath(type);
strCompleteRegPath.append(TelldusCore::intToWstring(intNodeId));
LONG lnExists = RegOpenKeyEx(d->rootKey, strCompleteRegPath.c_str(), 0, KEY_WRITE, &hk);
if (lnExists == ERROR_SUCCESS) {
DWORD dwVal = value;
lnExists = RegSetValueEx (hk, name.c_str(), 0L, REG_DWORD, (CONST BYTE*) &dwVal, sizeof(DWORD));
if (lnExists == ERROR_SUCCESS) {
intReturn = TELLSTICK_SUCCESS;
}
}
RegCloseKey(hk);
return intReturn;
}

View File

@@ -0,0 +1,79 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/TellStick.h"
#include <stdio.h>
#include <map>
#include <string>
std::string TellStick::createTPacket( const std::string &msg ) {
std::map<unsigned char, char> times;
std::string data;
int index = 0;
for(size_t i = 0; i < msg.length(); ++i) {
// Search to se if it already exists and get the index
if (times.find(msg.at(i)) == times.end()) {
times[msg.at(i)] = index++;
if (times.size() > 4) {
return "";
}
}
data.append(1, times[msg.at(i)]);
}
// Reorder the times
unsigned char t0 = 1, t1 = 1, t2 = 1, t3 = 1;
for(std::map<unsigned char, char>::const_iterator it = times.begin(); it != times.end(); ++it) {
if ((*it).second == 0) {
t0 = (*it).first;
} else if ((*it).second == 1) {
t1 = (*it).first;
} else if ((*it).second == 2) {
t2 = (*it).first;
} else if ((*it).second == 3) {
t3 = (*it).first;
}
}
return TellStick::convertSToT(t0, t1, t2, t3, data);
}
std::string TellStick::convertSToT( unsigned char t0, unsigned char t1, unsigned char t2, unsigned char t3, const std::string &data ) {
unsigned char dataByte = 0;
std::string retString = "T";
retString.append(1, t0);
retString.append(1, t1);
retString.append(1, t2);
retString.append(1, t3);
if (data.length() > 255) {
return "";
}
unsigned char length = (unsigned char)data.length();
retString.append(1, length);
for (size_t i = 0; i < data.length(); ++i) {
dataByte <<= 2;
if (data.at(i) == 1) {
dataByte |= 1;
} else if (data.at(i) == 2) {
dataByte |= 2;
} else if (data.at(i) == 3) {
dataByte |= 3;
}
if ( (i+1) % 4 == 0) {
retString.append(1, dataByte);
dataByte = 0;
}
}
if (data.length() % 4 != 0) {
dataByte <<= (data.length() % 4)*2;
retString.append(1, dataByte);
}
retString.append("+");
return retString;
}

View File

@@ -0,0 +1,54 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_TELLSTICK_H_
#define TELLDUS_CORE_SERVICE_TELLSTICK_H_
#include <list>
#include <string>
#include "service/Controller.h"
#include "common/Thread.h"
class TellStickDescriptor {
public:
std::string serial;
int vid, pid;
};
class TellStick : public Controller, public TelldusCore::Thread {
public:
TellStick(int controllerId, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent, const TellStickDescriptor &d);
virtual ~TellStick();
virtual int pid() const;
virtual int vid() const;
virtual std::string serial() const;
bool isOpen() const;
bool isSameAsDescriptor(const TellStickDescriptor &d) const;
virtual int reset();
virtual int send( const std::string &message );
bool stillConnected() const;
static std::list<TellStickDescriptor> findAll();
static std::string createTPacket( const std::string & );
static std::string convertSToT( unsigned char t0, unsigned char t1, unsigned char t2, unsigned char t3, const std::string &data );
protected:
void processData( const std::string &data );
void run();
void setBaud( int baud );
void stop();
private:
static std::list<TellStickDescriptor> findAllByVIDPID( int vid, int pid );
class PrivateData;
PrivateData *d;
};
#endif // TELLDUS_CORE_SERVICE_TELLSTICK_H_

View File

@@ -0,0 +1,343 @@
//
// C++ Implementation: TellStick
//
// Description:
//
//
// Author: Micke Prag <micke.prag@telldus.se>, (C) 2009
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include <string.h>
#include <stdlib.h>
#include <string>
#include <list>
#include "common/common.h"
#include "common/Mutex.h"
#include "common/Strings.h"
#include "service/Log.h"
#include "service/Settings.h"
#include "service/TellStick.h"
#include "../client/telldus-core.h"
#include "service/ftd2xx.h"
class TellStick::PrivateData {
public:
bool open, running, ignoreControllerConfirmation;
int vid, pid;
std::string serial, message;
FT_HANDLE ftHandle;
TelldusCore::Mutex mutex;
#ifdef _WINDOWS
HANDLE eh;
#else
// #include <unistd.h>
struct {
pthread_cond_t eCondVar;
pthread_mutex_t eMutex;
} eh;
#endif
};
TellStick::TellStick(int controllerId, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent, const TellStickDescriptor &td )
:Controller(controllerId, event, updateEvent) {
d = new PrivateData;
#ifdef _WINDOWS
d->eh = CreateEvent( NULL, false, false, NULL );
#else
pthread_mutex_init(&d->eh.eMutex, NULL);
pthread_cond_init(&d->eh.eCondVar, NULL);
#endif
d->open = false;
d->running = false;
d->vid = td.vid;
d->pid = td.pid;
d->serial = td.serial;
Settings set;
d->ignoreControllerConfirmation = set.getSetting(L"ignoreControllerConfirmation") == L"true";
char *tempSerial = new char[td.serial.size()+1];
#ifdef _WINDOWS
strcpy_s(tempSerial, td.serial.size()+1, td.serial.c_str());
#else
snprintf(tempSerial, td.serial.size()+1, "%s", 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) {
d->open = true;
FT_SetFlowControl(d->ftHandle, FT_FLOW_NONE, 0, 0);
FT_SetTimeouts(d->ftHandle, 5000, 0);
}
if (d->open) {
if (td.pid == 0x0C31) {
setBaud(9600);
} else {
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;
#ifdef _WINDOWS
SetEvent(d->eh);
#else
pthread_cond_broadcast(&d->eh.eCondVar);
#endif
}
this->wait();
if (d->open) {
FT_Close(d->ftHandle);
}
delete d;
}
void TellStick::setBaud( int baud ) {
FT_SetBaudRate(d->ftHandle, baud);
}
int TellStick::pid() const {
return d->pid;
}
int TellStick::vid() const {
return d->vid;
}
std::string TellStick::serial() const {
return d->serial;
}
bool TellStick::isOpen() const {
return d->open;
}
bool TellStick::isSameAsDescriptor(const TellStickDescriptor &td) const {
if (td.vid != d->vid) {
return false;
}
if (td.pid != d->pid) {
return false;
}
if (td.serial != d->serial) {
return false;
}
return true;
}
void TellStick::processData( const std::string &data ) {
for (unsigned int i = 0; i < data.length(); ++i) {
if (data[i] == 13) { // Skip \r
continue;
} else if (data[i] == 10) { // \n found
if (d->message.substr(0, 2).compare("+V") == 0) {
setFirmwareVersion(TelldusCore::charToInteger(d->message.substr(2).c_str()));
} else if (d->message.substr(0, 2).compare("+R") == 0) {
this->publishData(d->message.substr(2));
} else if(d->message.substr(0, 2).compare("+W") == 0) {
this->decodePublishData(d->message.substr(2));
}
d->message.clear();
} else { // Append the character
d->message.append( 1, data[i] );
}
}
}
int TellStick::reset() {
#ifndef _WINDOWS
return TELLSTICK_SUCCESS; // nothing to be done on other platforms
#else
int success = FT_CyclePort( d->ftHandle );
if(success == FT_OK) {
return TELLSTICK_SUCCESS;
}
return TELLSTICK_ERROR_UNKNOWN;
#endif
}
void TellStick::run() {
d->running = true;
DWORD dwBytesInQueue = 0;
DWORD dwBytesRead = 0;
char *buf = 0;
// Send a firmware version request
char msg[] = "V+";
FT_Write(d->ftHandle, msg, (DWORD)strlen(msg), &dwBytesRead);
while(1) {
#ifdef _WINDOWS
FT_SetEventNotification(d->ftHandle, FT_EVENT_RXCHAR, d->eh);
WaitForSingleObject(d->eh, INFINITE);
#else
FT_SetEventNotification(d->ftHandle, FT_EVENT_RXCHAR, (PVOID)&d->eh);
pthread_mutex_lock(&d->eh.eMutex);
pthread_cond_wait(&d->eh.eCondVar, &d->eh.eMutex);
pthread_mutex_unlock(&d->eh.eMutex);
#endif
TelldusCore::MutexLocker locker(&d->mutex);
if (!d->running) {
break;
}
FT_GetQueueStatus(d->ftHandle, &dwBytesInQueue);
if (dwBytesInQueue < 1) {
continue;
}
buf = reinterpret_cast<char*>(malloc(sizeof(buf) * (dwBytesInQueue+1)));
memset(buf, 0, dwBytesInQueue+1);
FT_Read(d->ftHandle, buf, dwBytesInQueue, &dwBytesRead);
processData( buf );
free(buf);
}
}
int TellStick::send( const std::string &strMessage ) {
if (!d->open) {
return TELLSTICK_ERROR_NOT_FOUND;
}
// This lock does two things
// 1 Prevents two calls from different threads to this function
// 2 Prevents our running thread from receiving the data we are interested in here
TelldusCore::MutexLocker locker(&d->mutex);
char *tempMessage = reinterpret_cast<char *>(malloc(sizeof(std::string::value_type) * (strMessage.size()+1)));
#ifdef _WINDOWS
strcpy_s(tempMessage, strMessage.size()+1, strMessage.c_str());
#else
snprintf(tempMessage, strMessage.size()+1, "%s", strMessage.c_str());
#endif
ULONG bytesWritten, bytesRead;
char in;
FT_STATUS ftStatus;
ftStatus = FT_Write(d->ftHandle, tempMessage, (DWORD)strMessage.length(), &bytesWritten);
free(tempMessage);
if(ftStatus != FT_OK) {
Log::debug("Broken pipe on send");
return TELLSTICK_ERROR_BROKEN_PIPE;
}
if(strMessage.compare("N+") == 0 && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))) {
// these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly
return TELLSTICK_SUCCESS;
}
if(d->ignoreControllerConfirmation) {
// wait for TellStick to finish its air-sending
msleep(1000);
return TELLSTICK_SUCCESS;
}
while(1) {
ftStatus = FT_Read(d->ftHandle, &in, 1, &bytesRead);
if (ftStatus == FT_OK) {
if (bytesRead == 1) {
if (in == '\n') {
return TELLSTICK_SUCCESS;
} else {
continue;
}
} else { // Timeout
return TELLSTICK_ERROR_COMMUNICATION;
}
} else { // Error
Log::debug("Broken pipe on read");
return TELLSTICK_ERROR_BROKEN_PIPE;
}
}
}
bool TellStick::stillConnected() const {
FT_STATUS ftStatus;
DWORD numDevs;
// create the device information list
ftStatus = FT_CreateDeviceInfoList(&numDevs);
if (ftStatus != FT_OK) {
return false;
}
if (numDevs <= 0) {
return false;
}
for (int i = 0; i < static_cast<int>(numDevs); i++) {
FT_HANDLE ftHandleTemp;
DWORD flags;
DWORD id;
DWORD type;
DWORD locId;
char serialNumber[16];
char description[64];
// get information for device i
ftStatus = FT_GetDeviceInfoDetail(i, &flags, &type, &id, &locId, serialNumber, description, &ftHandleTemp);
if (ftStatus != FT_OK) {
continue;
}
if (d->serial.compare(serialNumber) == 0) {
return true;
}
}
return false;
}
std::list<TellStickDescriptor> TellStick::findAll() {
std::list<TellStickDescriptor> tellstick = findAllByVIDPID(0x1781, 0x0C30);
std::list<TellStickDescriptor> duo = findAllByVIDPID(0x1781, 0x0C31);
for(std::list<TellStickDescriptor>::const_iterator it = duo.begin(); it != duo.end(); ++it) {
tellstick.push_back(*it);
}
return tellstick;
}
std::list<TellStickDescriptor> TellStick::findAllByVIDPID( int vid, int pid ) {
std::list<TellStickDescriptor> retval;
FT_STATUS ftStatus = FT_OK;
DWORD dwNumberOfDevices = 0;
#ifndef _WINDOWS
FT_SetVIDPID(vid, pid);
#endif
ftStatus = FT_CreateDeviceInfoList(&dwNumberOfDevices);
if (ftStatus != FT_OK) {
return retval;
}
if (dwNumberOfDevices > 0) {
FT_DEVICE_LIST_INFO_NODE *devInfo;
// allocate storage for list based on dwNumberOfDevices
devInfo = reinterpret_cast<FT_DEVICE_LIST_INFO_NODE*>(malloc(sizeof(FT_DEVICE_LIST_INFO_NODE)*dwNumberOfDevices)); // get the device information list
ftStatus = FT_GetDeviceInfoList(devInfo, &dwNumberOfDevices);
if (ftStatus == FT_OK) {
unsigned int id = (vid << 16) | pid;
for (unsigned int i = 0; i < dwNumberOfDevices; i++) {
if (devInfo[i].ID != id) {
continue;
}
TellStickDescriptor td;
td.vid = vid;
td.pid = pid;
td.serial = devInfo[i].SerialNumber;
retval.push_back(td);
}
}
free(devInfo);
}
return retval;
}

View File

@@ -0,0 +1,327 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include <ftdi.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <list>
#include <string>
#include "service/TellStick.h"
#include "service/Log.h"
#include "service/Settings.h"
#include "client/telldus-core.h"
#include "common/Thread.h"
#include "common/Mutex.h"
#include "common/Strings.h"
#include "common/common.h"
typedef struct _EVENT_HANDLE {
pthread_cond_t eCondVar;
pthread_mutex_t eMutex;
} EVENT_HANDLE;
typedef int DWORD;
class TellStick::PrivateData {
public:
bool open, ignoreControllerConfirmation;
int vid, pid;
std::string serial, message;
ftdi_context ftHandle;
EVENT_HANDLE eh;
bool running;
TelldusCore::Mutex mutex;
};
TellStick::TellStick(int controllerId, TelldusCore::EventRef event, TelldusCore::EventRef updateEvent, const TellStickDescriptor &td )
:Controller(controllerId, event, updateEvent) {
d = new PrivateData;
d->open = false;
d->vid = td.vid;
d->pid = td.pid;
d->serial = td.serial;
d->running = false;
Settings set;
d->ignoreControllerConfirmation = set.getSetting(L"ignoreControllerConfirmation") == L"true";
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);
return;
}
d->open = true;
ftdi_usb_reset( &d->ftHandle );
ftdi_disable_bitbang( &d->ftHandle );
ftdi_set_latency_timer(&d->ftHandle, 16);
if (d->open) {
if (td.pid == 0x0C31) {
this->setBaud(9600);
} else {
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();
}
if (d->open) {
ftdi_usb_close(&d->ftHandle);
ftdi_deinit(&d->ftHandle);
}
delete d;
}
int TellStick::pid() const {
return d->pid;
}
int TellStick::vid() const {
return d->vid;
}
std::string TellStick::serial() const {
return d->serial;
}
bool TellStick::isOpen() const {
return d->open;
}
bool TellStick::isSameAsDescriptor(const TellStickDescriptor &td) const {
if (td.vid != d->vid) {
return false;
}
if (td.pid != d->pid) {
return false;
}
if (td.serial != d->serial) {
return false;
}
return true;
}
void TellStick::processData( const std::string &data ) {
for (unsigned int i = 0; i < data.length(); ++i) {
if (data[i] == 13) { // Skip \r
continue;
} else if (data[i] == 10) { // \n found
if (d->message.substr(0, 2).compare("+V") == 0) {
setFirmwareVersion(TelldusCore::charToInteger(d->message.substr(2).c_str()));
} else if (d->message.substr(0, 2).compare("+R") == 0) {
this->publishData(d->message.substr(2));
} else if(d->message.substr(0, 2).compare("+W") == 0) {
this->decodePublishData(d->message.substr(2));
}
d->message.clear();
} else { // Append the character
d->message.append( 1, data[i] );
}
}
}
int TellStick::reset() {
int success = ftdi_usb_reset( &d->ftHandle );
if(success < 0) {
return TELLSTICK_ERROR_UNKNOWN; // -1 = FTDI reset failed, -2 = USB device unavailable
}
return TELLSTICK_SUCCESS;
}
void TellStick::run() {
int dwBytesRead = 0;
unsigned char buf[1024]; // = 0;
pthread_mutex_init(&d->eh.eMutex, NULL);
pthread_cond_init(&d->eh.eCondVar, NULL);
{
TelldusCore::MutexLocker locker(&d->mutex);
d->running = true;
}
// Send a firmware version request
unsigned char msg[] = "V+";
ftdi_write_data( &d->ftHandle, msg, 2 );
while(1) {
// Is there any better way then sleeping between reads?
msleep(100);
TelldusCore::MutexLocker locker(&d->mutex);
if (!d->running) {
break;
}
memset(buf, 0, sizeof(buf));
dwBytesRead = ftdi_read_data(&d->ftHandle, buf, sizeof(buf));
if (dwBytesRead < 0) {
// An error occured, avoid flooding by sleeping longer
// Hopefully if will start working again
msleep(1000); // 1s
}
if (dwBytesRead < 1) {
continue;
}
processData( reinterpret_cast<char *>(&buf) );
}
}
int TellStick::send( const std::string &strMessage ) {
if (!d->open) {
return TELLSTICK_ERROR_NOT_FOUND;
}
bool c = true;
unsigned char *tempMessage = new unsigned char[strMessage.size()];
memcpy(tempMessage, strMessage.c_str(), strMessage.size());
// This lock does two things
// 1 Prevents two calls from different threads to this function
// 2 Prevents our running thread from receiving the data we are interested in here
TelldusCore::MutexLocker locker(&d->mutex);
int ret;
ret = ftdi_write_data( &d->ftHandle, tempMessage, strMessage.length() );
if(ret < 0) {
c = false;
} else if(ret != strMessage.length()) {
Log::debug("Weird send length? retval %i instead of %d\n", ret, static_cast<int>(strMessage.length()));
}
delete[] tempMessage;
if(!c) {
Log::debug("Broken pipe on send");
return TELLSTICK_ERROR_BROKEN_PIPE;
}
if(strMessage.compare("N+") == 0 && ((pid() == 0x0C31 && firmwareVersion() < 5) || (pid() == 0x0C30 && firmwareVersion() < 6))) {
// these firmware versions doesn't implement ack to noop, just check that the noop can be sent correctly
return TELLSTICK_SUCCESS;
}
if(d->ignoreControllerConfirmation) {
// allow TellStick to finish its air-sending
msleep(1000);
return TELLSTICK_SUCCESS;
}
int retrycnt = 250;
unsigned char in;
while(--retrycnt) {
ret = ftdi_read_data( &d->ftHandle, &in, 1);
if (ret > 0) {
if (in == '\n') {
return TELLSTICK_SUCCESS;
}
} else if(ret == 0) { // No data available
usleep(100);
} else { // Error
Log::debug("Broken pipe on read");
return TELLSTICK_ERROR_BROKEN_PIPE;
}
}
return TELLSTICK_ERROR_COMMUNICATION;
}
void TellStick::setBaud(int baud) {
int ret = ftdi_set_baudrate(&d->ftHandle, baud);
if(ret != 0) {
fprintf(stderr, "set Baud failed, retval %i\n", ret);
}
}
std::list<TellStickDescriptor> TellStick::findAll() {
std::list<TellStickDescriptor> tellstick = findAllByVIDPID(0x1781, 0x0C30);
std::list<TellStickDescriptor> duo = findAllByVIDPID(0x1781, 0x0C31);
for(std::list<TellStickDescriptor>::const_iterator it = duo.begin(); it != duo.end(); ++it) {
tellstick.push_back(*it);
}
return tellstick;
}
bool TellStick::stillConnected() const {
ftdi_context ftdic;
struct ftdi_device_list *devlist, *curdev;
char serialBuffer[10];
ftdi_init(&ftdic);
bool found = false;
int ret = ftdi_usb_find_all(&ftdic, &devlist, d->vid, d->pid);
if (ret > 0) {
for (curdev = devlist; curdev != NULL; curdev = curdev->next) {
ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10);
if (ret != 0) {
continue;
}
if (d->serial.compare(serialBuffer) == 0) {
found = true;
break;
}
}
}
ftdi_list_free(&devlist);
ftdi_deinit(&ftdic);
return found;
}
std::list<TellStickDescriptor> TellStick::findAllByVIDPID( int vid, int pid ) {
std::list<TellStickDescriptor> retval;
ftdi_context ftdic;
struct ftdi_device_list *devlist, *curdev;
char serialBuffer[10];
ftdi_init(&ftdic);
int ret = ftdi_usb_find_all(&ftdic, &devlist, vid, pid);
if (ret > 0) {
for (curdev = devlist; curdev != NULL; curdev = curdev->next) {
ret = ftdi_usb_get_strings(&ftdic, curdev->dev, NULL, 0, NULL, 0, serialBuffer, 10);
if (ret != 0) {
continue;
}
TellStickDescriptor td;
td.vid = vid;
td.pid = pid;
td.serial = serialBuffer;
retval.push_back(td);
}
}
ftdi_list_free(&devlist);
ftdi_deinit(&ftdic);
return retval;
}
void TellStick::stop() {
if (d->running) {
{
TelldusCore::MutexLocker locker(&d->mutex);
d->running = false;
}
// Unlock the wait-condition
pthread_cond_broadcast(&d->eh.eCondVar);
}
this->wait();
}

View File

@@ -0,0 +1,154 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/TelldusMain.h"
#include <stdio.h>
#include <list>
#include <memory>
#include "common/EventHandler.h"
#include "service/ClientCommunicationHandler.h"
#include "service/ConnectionListener.h"
#include "service/ControllerListener.h"
#include "service/ControllerManager.h"
#include "service/DeviceManager.h"
#include "service/EventUpdateManager.h"
#include "service/Log.h"
#include "service/Timer.h"
class TelldusMain::PrivateData {
public:
TelldusCore::EventHandler eventHandler;
TelldusCore::EventRef stopEvent, controllerChangeEvent;
};
TelldusMain::TelldusMain(void) {
d = new PrivateData;
d->stopEvent = d->eventHandler.addEvent();
d->controllerChangeEvent = d->eventHandler.addEvent();
}
TelldusMain::~TelldusMain(void) {
delete d;
}
void TelldusMain::deviceInsertedOrRemoved(int vid, int pid, bool inserted) {
ControllerChangeEventData *data = new ControllerChangeEventData;
data->vid = vid;
data->pid = pid;
data->inserted = inserted;
d->controllerChangeEvent->signal(data);
}
void TelldusMain::resume() {
Log::notice("Came back from suspend");
ControllerChangeEventData *data = new ControllerChangeEventData;
data->vid = 0x0;
data->pid = 0x0;
data->inserted = true;
d->controllerChangeEvent->signal(data);
}
void TelldusMain::suspend() {
Log::notice("Preparing for suspend");
ControllerChangeEventData *data = new ControllerChangeEventData;
data->vid = 0x0;
data->pid = 0x0;
data->inserted = false;
d->controllerChangeEvent->signal(data);
}
void TelldusMain::start(void) {
TelldusCore::EventRef clientEvent = d->eventHandler.addEvent();
TelldusCore::EventRef dataEvent = d->eventHandler.addEvent();
TelldusCore::EventRef executeActionEvent = d->eventHandler.addEvent();
TelldusCore::EventRef janitor = d->eventHandler.addEvent(); // Used for regular cleanups
Timer supervisor(janitor); // Tells the janitor to go back to work
supervisor.setInterval(60); // Once every minute
supervisor.start();
EventUpdateManager eventUpdateManager;
TelldusCore::EventRef deviceUpdateEvent = eventUpdateManager.retrieveUpdateEvent();
eventUpdateManager.start();
ControllerManager controllerManager(dataEvent, deviceUpdateEvent);
DeviceManager deviceManager(&controllerManager, deviceUpdateEvent);
deviceManager.setExecuteActionEvent(executeActionEvent);
ConnectionListener clientListener(L"TelldusClient", clientEvent);
std::list<ClientCommunicationHandler *> clientCommunicationHandlerList;
TelldusCore::EventRef handlerEvent = d->eventHandler.addEvent();
#ifdef _MACOSX
// This is only needed on OS X
ControllerListener controllerListener(d->controllerChangeEvent);
#endif
while(!d->stopEvent->isSignaled()) {
if (!d->eventHandler.waitForAny()) {
continue;
}
if (clientEvent->isSignaled()) {
// New client connection
TelldusCore::EventDataRef eventDataRef = clientEvent->takeSignal();
ConnectionListenerEventData *data = dynamic_cast<ConnectionListenerEventData*>(eventDataRef.get());
if (data) {
ClientCommunicationHandler *clientCommunication = new ClientCommunicationHandler(data->socket, handlerEvent, &deviceManager, deviceUpdateEvent, &controllerManager);
clientCommunication->start();
clientCommunicationHandlerList.push_back(clientCommunication);
}
}
if (d->controllerChangeEvent->isSignaled()) {
TelldusCore::EventDataRef eventDataRef = d->controllerChangeEvent->takeSignal();
ControllerChangeEventData *data = dynamic_cast<ControllerChangeEventData*>(eventDataRef.get());
if (data) {
controllerManager.deviceInsertedOrRemoved(data->vid, data->pid, "", data->inserted);
}
}
if (dataEvent->isSignaled()) {
TelldusCore::EventDataRef eventData = dataEvent->takeSignal();
ControllerEventData *data = dynamic_cast<ControllerEventData*>(eventData.get());
if (data) {
deviceManager.handleControllerMessage(*data);
}
}
if (handlerEvent->isSignaled()) {
handlerEvent->popSignal();
for ( std::list<ClientCommunicationHandler *>::iterator it = clientCommunicationHandlerList.begin(); it != clientCommunicationHandlerList.end(); ) {
if ((*it)->isDone()) {
delete *it;
it = clientCommunicationHandlerList.erase(it);
} else {
++it;
}
}
}
if (executeActionEvent->isSignaled()) {
deviceManager.executeActionEvent();
}
if (janitor->isSignaled()) {
// Clear all of them if there is more than one
while(janitor->isSignaled()) {
janitor->popSignal();
}
#ifndef _MACOSX
controllerManager.queryControllerStatus();
#endif
}
}
supervisor.stop();
}
void TelldusMain::stop(void) {
d->stopEvent->signal();
}

View File

@@ -0,0 +1,28 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_TELLDUSMAIN_H_
#define TELLDUS_CORE_SERVICE_TELLDUSMAIN_H_
class TelldusMain {
public:
TelldusMain(void);
~TelldusMain(void);
void start();
void stop();
// Thread safe!
void deviceInsertedOrRemoved(int vid, int pid, bool inserted);
void resume();
void suspend();
private:
class PrivateData;
PrivateData *d;
};
#endif // TELLDUS_CORE_SERVICE_TELLDUSMAIN_H_

View File

@@ -0,0 +1,181 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/TelldusWinService_win.h"
#include <Dbt.h>
#include <algorithm>
#include <string>
#include "service/Log.h"
#include "service/TelldusMain.h"
int g_argc;
char **g_argv;
static const GUID GUID_DEVINTERFACE_USBRAW = { 0xA5DCBF10L, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };
TelldusWinService::TelldusWinService()
:tm(0) {
tm = new TelldusMain();
}
TelldusWinService::~TelldusWinService() {
delete tm;
}
void TelldusWinService::stop() {
tm->stop();
}
DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ) {
switch ( controlCode ) {
case SERVICE_CONTROL_INTERROGATE:
SetServiceStatus( serviceStatusHandle, &serviceStatus );
return NO_ERROR;
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
stop();
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
SetServiceStatus( serviceStatusHandle, &serviceStatus );
return NO_ERROR;
case SERVICE_CONTROL_POWEREVENT:
if (dwEventType == PBT_APMSUSPEND) {
tm->suspend();
} else if (dwEventType == PBT_APMRESUMEAUTOMATIC) {
tm->resume();
}
return NO_ERROR;
}
return ERROR_CALL_NOT_IMPLEMENTED;
}
DWORD WINAPI TelldusWinService::deviceNotificationHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData ) {
if (controlCode != SERVICE_CONTROL_DEVICEEVENT) {
return ERROR_CALL_NOT_IMPLEMENTED;
}
if (dwEventType != DBT_DEVICEARRIVAL && dwEventType != DBT_DEVICEREMOVECOMPLETE) {
return ERROR_CALL_NOT_IMPLEMENTED;
}
PDEV_BROADCAST_DEVICEINTERFACE pDevInf = reinterpret_cast<PDEV_BROADCAST_DEVICEINTERFACE>(lpEventData);
if (!pDevInf) {
return ERROR_CALL_NOT_IMPLEMENTED;
}
std::wstring name(pDevInf->dbcc_name);
transform(name.begin(), name.end(), name.begin(), toupper);
// Parse VID
size_t posStart = name.find(L"VID_");
if (posStart == std::wstring::npos) {
return ERROR_CALL_NOT_IMPLEMENTED;
}
posStart += 4;
size_t posEnd = name.find(L'&', posStart);
if (posEnd == std::wstring::npos) {
return ERROR_CALL_NOT_IMPLEMENTED;
}
std::wstring strVID = name.substr(posStart, posEnd-posStart);
// Parse PID
posStart = name.find(L"PID_");
if (posStart == std::wstring::npos) {
return ERROR_CALL_NOT_IMPLEMENTED;
}
posStart += 4;
posEnd = name.find(L'#', posStart);
if (posEnd == std::wstring::npos) {
return ERROR_CALL_NOT_IMPLEMENTED;
}
std::wstring strPID = name.substr(posStart, posEnd-posStart);
int vid = static_cast<int>(strtol(std::string(strVID.begin(), strVID.end()).c_str(), NULL, 16));
int pid = static_cast<int>(strtol(std::string(strPID.begin(), strPID.end()).c_str(), NULL, 16));
if (dwEventType == DBT_DEVICEARRIVAL) {
tm->deviceInsertedOrRemoved(vid, pid, true);
} else {
tm->deviceInsertedOrRemoved(vid, pid, false);
}
return NO_ERROR;
}
DWORD WINAPI TelldusWinService::serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext ) {
TelldusWinService *instance = reinterpret_cast<TelldusWinService *>(lpContext);
if (!instance) {
return ERROR_CALL_NOT_IMPLEMENTED;
}
if (controlCode == SERVICE_CONTROL_DEVICEEVENT) {
return instance->deviceNotificationHandler(controlCode, dwEventType, lpEventData);
}
return instance->serviceControlHandler(controlCode, dwEventType, lpEventData);
}
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;
instance.serviceStatus.dwControlsAccepted = 0;
instance.serviceStatus.dwWin32ExitCode = NO_ERROR;
instance.serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
instance.serviceStatus.dwCheckPoint = 0;
instance.serviceStatus.dwWaitHint = 0;
instance.serviceStatusHandle = RegisterServiceCtrlHandlerEx( serviceName, TelldusWinService::serviceControlHandler, &instance );
if ( instance.serviceStatusHandle ) {
// service is starting
instance.serviceStatus.dwCurrentState = SERVICE_START_PENDING;
SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus );
// running
instance.serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
// Register for power management notification
instance.serviceStatus.dwControlsAccepted |= SERVICE_ACCEPT_POWEREVENT;
instance.serviceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus );
// Register for device notification
DEV_BROADCAST_DEVICEINTERFACE devInterface;
ZeroMemory( &devInterface, sizeof(devInterface) );
devInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
devInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
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 );
// service is now stopped
instance.serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
instance.serviceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus( instance.serviceStatusHandle, &instance.serviceStatus );
}
}

View File

@@ -0,0 +1,39 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_TELLDUSWINSERVICE_WIN_H_
#define TELLDUS_CORE_SERVICE_TELLDUSWINSERVICE_WIN_H_
#include <windows.h>
extern int g_argc;
extern char **g_argv;
class TelldusMain;
#define serviceName TEXT("TelldusCore")
class TelldusWinService {
public:
TelldusWinService();
~TelldusWinService();
static void WINAPI serviceMain( DWORD /*argc*/, TCHAR* /*argv*/[] );
protected:
void stop();
DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData );
DWORD WINAPI deviceNotificationHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData );
private:
TelldusMain *tm;
SERVICE_STATUS serviceStatus;
SERVICE_STATUS_HANDLE serviceStatusHandle;
static DWORD WINAPI serviceControlHandler( DWORD controlCode, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext );
};
#endif // TELLDUS_CORE_SERVICE_TELLDUSWINSERVICE_WIN_H_

View File

@@ -0,0 +1,120 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "service/Timer.h"
#ifdef _WINDOWS
#else
#include <sys/time.h>
#include <errno.h>
#endif
#include "common/Mutex.h"
class Timer::PrivateData {
public:
PrivateData() : interval(0), running(false) {}
TelldusCore::EventRef event;
int interval;
bool running;
#ifdef _WINDOWS
HANDLE cond;
TelldusCore::Mutex mutex;
#else
pthread_mutex_t waitMutex;
pthread_cond_t cond;
#endif
};
Timer::Timer(TelldusCore::EventRef event)
:TelldusCore::Thread(), d(new PrivateData) {
d->event = event;
#ifdef _WINDOWS
d->cond = CreateEventW(NULL, false, false, NULL);
#else
pthread_cond_init(&d->cond, NULL);
pthread_mutex_init(&d->waitMutex, NULL);
#endif
}
Timer::~Timer() {
this->stop();
this->wait();
#ifdef _WINDOWS
#else
pthread_mutex_destroy(&d->waitMutex);
pthread_cond_destroy(&d->cond);
delete d;
#endif
}
void Timer::setInterval(int sec) {
d->interval = sec;
}
void Timer::stop() {
#ifdef _WINDOWS
TelldusCore::MutexLocker(&d->mutex);
d->running = false;
SetEvent(d->cond);
#else
// Signal event
pthread_mutex_lock(&d->waitMutex);
if (d->running) {
d->running = false;
pthread_cond_signal(&d->cond);
}
pthread_mutex_unlock(&d->waitMutex);
#endif
}
void Timer::run() {
#ifdef _WINDOWS
int interval = 0;
{
TelldusCore::MutexLocker(&d->mutex);
d->running = true;
interval = d->interval*1000;
}
while(1) {
DWORD retval = WaitForSingleObject(d->cond, interval);
if (retval == WAIT_TIMEOUT) {
d->event->signal();
}
TelldusCore::MutexLocker(&d->mutex);
if (!d->running) {
break;
}
}
#else
struct timespec ts;
struct timeval tp;
pthread_mutex_lock(&d->waitMutex);
d->running = true;
pthread_mutex_unlock(&d->waitMutex);
while(1) {
int rc = 0;
gettimeofday(&tp, NULL);
ts.tv_sec = tp.tv_sec;
ts.tv_nsec = tp.tv_usec * 1000;
ts.tv_sec += d->interval;
pthread_mutex_lock( &d->waitMutex );
if (d->running) {
rc = pthread_cond_timedwait(&d->cond, &d->waitMutex, &ts);
} else {
pthread_mutex_unlock( &d->waitMutex );
break;
}
pthread_mutex_unlock( &d->waitMutex );
if (rc == ETIMEDOUT) {
d->event->signal();
}
}
#endif
}

View File

@@ -0,0 +1,30 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef TELLDUS_CORE_SERVICE_TIMER_H_
#define TELLDUS_CORE_SERVICE_TIMER_H_
#include "common/Event.h"
#include "common/Thread.h"
class Timer : public TelldusCore::Thread {
public:
explicit Timer(TelldusCore::EventRef event);
virtual ~Timer();
void setInterval(int sec);
void stop();
protected:
void run();
private:
class PrivateData;
PrivateData *d;
};
#endif // TELLDUS_CORE_SERVICE_TIMER_H_

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.telldus.service</string>
<key>OnDemand</key>
<false/>
<key>ProgramArguments</key>
<array>
<string>/Library/Telldus/TelldusService</string>
</array>
</dict>
</plist>

View File

@@ -0,0 +1,11 @@
#ifndef CONFIG_H
#define CONFIG_H
#define CONFIG_PATH "@SYSCONF_INSTALL_DIR@"
#define VAR_CONFIG_PATH "@STATE_INSTALL_DIR@"
#ifdef _LINUX
#define SCRIPT_PATH "@SCRIPT_PATH@"
#endif // _LINUX
#endif // CONFIG_H

View File

@@ -0,0 +1,15 @@
#ifdef LIBFTD2XX
#ifdef _WINDOWS
#include <windows.h>
#include "win\ftd2xx.h"
#else
#include "osx/WinTypes.h"
#include "osx/ftd2xx.h"
#endif
#endif
#ifdef LIBFTDI
#include <ftdi.h>
#endif

View File

@@ -0,0 +1,34 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include <signal.h>
#include "service/TelldusMain.h"
#include "service/Log.h"
TelldusMain tm;
void shutdownHandler(int onSignal) {
Log::notice("Shutting down");
tm.stop();
}
void sigpipeHandler(int onSignal) {
Log::notice("SIGPIPE received");
}
int main(int argc, char **argv) {
/* Install signal traps for proper shutdown */
signal(SIGTERM, shutdownHandler);
signal(SIGINT, shutdownHandler);
signal(SIGPIPE, sigpipeHandler);
Log::notice("telldusd started");
tm.start();
Log::notice("telldusd stopped gracefully");
Log::destroy();
return 0;
}

View File

@@ -0,0 +1,166 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
#include <string>
#include "service/TelldusMain.h"
#include "service/Settings.h"
#include "common/Strings.h"
#include "service/Log.h"
#define DAEMON_NAME "telldusd"
#define PID_FILE "/var/run/" DAEMON_NAME ".pid"
TelldusMain tm;
void signalHandler(int sig) {
switch(sig) {
case SIGHUP:
Log::warning("Received SIGHUP signal.");
break;
case SIGTERM:
case SIGINT:
Log::warning("Received SIGTERM or SIGINT signal.");
Log::warning("Shutting down");
tm.stop();
break;
case SIGPIPE:
break;
default:
Log::warning("Unhandled signal (%d) %s", sig, strsignal(sig));
break;
}
}
int main(int argc, char **argv) {
pid_t pid, sid;
FILE *fd;
bool deamonize = true;
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "--nodaemon") == 0) {
deamonize = false;
Log::setLogOutput(Log::StdOut);
} else if (strcmp(argv[i], "--debug") == 0) {
Log::setDebug();
} 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);
} 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);
}
}
if (deamonize) {
pid = fork();
if (pid < 0) {
exit(EXIT_FAILURE);
}
if (pid > 0) {
// We are the parent
// Let the parent store the clients pid,
// This way anyone starting the daemon can read the pidfile immediately
// Record the pid
fd = fopen(PID_FILE, "w");
if (fd) {
fprintf(fd, "%d\n", pid);
fclose(fd);
} else {
Log::error("Could not open pid file %s: %s", PID_FILE, strerror(errno));
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
}
Log::notice("%s daemon starting up", DAEMON_NAME);
if (deamonize) {
/* Change the file mode mask */
umask(0);
sid = setsid();
if (sid < 0) {
// Something went wrong
printf("Could not set sid\n");
exit(EXIT_FAILURE);
}
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
}
/* Reduce our permissions (change user and group) */
if (getuid() == 0 || geteuid() == 0) {
Settings settings;
std::string user = TelldusCore::wideToString(settings.getSetting(L"user"));
std::string group = TelldusCore::wideToString(settings.getSetting(L"group"));
// We use the non threadsafe function getgrnam() here. Since this is startup code
// and no other threads have been started yet.
struct group *grp = getgrnam(group.c_str()); // NOLINT(runtime/threadsafe_fn)
if (grp) {
setgid(grp->gr_gid);
} else {
Log::warning("Group %s could not be found", group.c_str());
exit(EXIT_FAILURE);
}
// We use the non threadsafe function getpwnam() here. Since this is startup code
// and no other threads have been started yet.
struct passwd *pw = getpwnam(user.c_str()); // NOLINT(runtime/threadsafe_fn)
if (pw) {
setuid( pw->pw_uid );
} else {
Log::warning("User %s could not be found", user.c_str());
exit(EXIT_FAILURE);
}
}
/* Change the current working directory */
if ((chdir("/")) < 0) {
exit(EXIT_FAILURE);
}
/* Install signal traps for proper shutdown */
signal(SIGTERM, signalHandler);
signal(SIGINT, signalHandler);
signal(SIGPIPE, signalHandler);
// Change so we do not need to call wait() for children processes
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sa.sa_flags = SA_NOCLDWAIT;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
Log::error("Could not set the SA_NOCLDWAIT flag. We will be creating zombie processes!");
}
tm.start();
Log::notice("%s daemon exited", DAEMON_NAME);
// Cleanup
Log::destroy();
exit(EXIT_SUCCESS);
}

View File

@@ -0,0 +1,25 @@
//
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include <windows.h>
#include <Dbt.h>
#include "service/TelldusWinService_win.h"
// #include <QCoreApplication>
int main(int argc, char **argv) {
g_argc = argc;
g_argv = argv;
SERVICE_TABLE_ENTRY serviceTable[] = {
{serviceName, TelldusWinService::serviceMain },
{ 0, 0 }
};
StartServiceCtrlDispatcher( serviceTable );
return 0;
}

View File

@@ -0,0 +1,87 @@
#ifndef __WINDOWS_TYPES__
#define __WINDOWS_TYPES__
#define MAX_NUM_DEVICES 50
#include <sys/time.h>
typedef unsigned int DWORD;
typedef unsigned int ULONG;
typedef unsigned short USHORT;
typedef unsigned short SHORT;
typedef unsigned char UCHAR;
typedef unsigned short WORD;
typedef unsigned char BYTE;
typedef BYTE *LPBYTE;
typedef unsigned int BOOL;
typedef unsigned char BOOLEAN;
typedef unsigned char CHAR;
typedef BOOL *LPBOOL;
typedef UCHAR *PUCHAR;
typedef const char *LPCSTR;
typedef char *PCHAR;
typedef void *PVOID;
typedef void *HANDLE;
typedef unsigned int LONG;
typedef int INT;
typedef unsigned int UINT;
typedef char *LPSTR;
typedef char *LPTSTR;
typedef DWORD *LPDWORD;
typedef WORD *LPWORD;
typedef ULONG *PULONG;
typedef PVOID LPVOID;
typedef void VOID;
typedef unsigned long long int ULONGLONG;
typedef struct _OVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
HANDLE hEvent;
} OVERLAPPED, *LPOVERLAPPED;
typedef struct _SECURITY_ATTRIBUTES {
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
} SECURITY_ATTRIBUTES , *LPSECURITY_ATTRIBUTES;
typedef struct timeval SYSTEMTIME;
typedef struct timeval FILETIME;
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
//
// Modem Status Flags
//
#define MS_CTS_ON ((DWORD)0x0010)
#define MS_DSR_ON ((DWORD)0x0020)
#define MS_RING_ON ((DWORD)0x0040)
#define MS_RLSD_ON ((DWORD)0x0080)
//
// Error Flags
//
#define CE_RXOVER 0x0001 // Receive Queue overflow
#define CE_OVERRUN 0x0002 // Receive Overrun Error
#define CE_RXPARITY 0x0004 // Receive Parity Error
#define CE_FRAME 0x0008 // Receive Framing error
#define CE_BREAK 0x0010 // Break Detected
#define CE_TXFULL 0x0100 // TX Queue is full
#define CE_PTO 0x0200 // LPTx Timeout
#define CE_IOE 0x0400 // LPTx I/O Error
#define CE_DNS 0x0800 // LPTx Device not selected
#define CE_OOP 0x1000 // LPTx Out-Of-Paper
#define CE_MODE 0x8000 // Requested mode unsupported
#ifndef INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE 0xFFFFFFFF
#endif
#endif

1008
telldus-core/service/osx/ftd2xx.h Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,13 @@
user = "nobody"
group = "plugdev"
ignoreControllerConfirmation = "false"
device {
id = 1
name = "Example device"
protocol = "arctech"
model = "codeswitch"
parameters {
house = "A"
unit = "1"
}
}

View File

@@ -0,0 +1,963 @@
/*++
Copyright (c) 2001-2007 Future Technology Devices International Ltd.
Module Name:
ftd2xx.h
Abstract:
Native USB device driver for FTDI FT8U232/245
FTD2XX library definitions
Environment:
kernel & user mode
Revision History:
13/03/01 awm Created.
13/01/03 awm Added device information support.
19/03/03 awm Added FT_W32_CancelIo.
12/06/03 awm Added FT_StopInTask and FT_RestartInTask.
18/09/03 awm Added FT_SetResetPipeRetryCount.
10/10/03 awm Added FT_ResetPort.
23/01/04 awm Added support for open-by-location.
16/03/04 awm Added support for FT2232C.
23/09/04 awm Added support for FT232R.
20/10/04 awm Added FT_CyclePort.
18/01/05 awm Added FT_DEVICE_LIST_INFO_NODE type.
11/02/05 awm Added LocId to FT_DEVICE_LIST_INFO_NODE.
25/08/05 awm Added FT_SetDeadmanTimeout.
02/12/05 awm Removed obsolete references.
05/12/05 awm Added FT_GetVersion, FT_GetVersionEx.
08/09/06 awm Added FT_W32_GetCommMask.
11/09/06 awm Added FT_Rescan.
11/07/07 awm Added support for FT2232H and FT4232H.
10/08/07 awm Added flags definitions.
21/11/07 mja Added FT_GetComPortNumber.
05/06/08 mja Added EEPROM extensions for FT2232H.
--*/
#ifndef FTD2XX_H
#define FTD2XX_H
// The following ifdef block is the standard way of creating macros
// which make exporting from a DLL simpler. All files within this DLL
// are compiled with the FTD2XX_EXPORTS symbol defined on the command line.
// This symbol should not be defined on any project that uses this DLL.
// This way any other project whose source files include this file see
// FTD2XX_API functions as being imported from a DLL, whereas this DLL
// sees symbols defined with this macro as being exported.
#ifdef FTD2XX_EXPORTS
#define FTD2XX_API __declspec(dllexport)
#else
#define FTD2XX_API __declspec(dllimport)
#endif
typedef PVOID FT_HANDLE;
typedef ULONG FT_STATUS;
//
// Device status
//
enum {
FT_OK,
FT_INVALID_HANDLE,
FT_DEVICE_NOT_FOUND,
FT_DEVICE_NOT_OPENED,
FT_IO_ERROR,
FT_INSUFFICIENT_RESOURCES,
FT_INVALID_PARAMETER,
FT_INVALID_BAUD_RATE,
FT_DEVICE_NOT_OPENED_FOR_ERASE,
FT_DEVICE_NOT_OPENED_FOR_WRITE,
FT_FAILED_TO_WRITE_DEVICE,
FT_EEPROM_READ_FAILED,
FT_EEPROM_WRITE_FAILED,
FT_EEPROM_ERASE_FAILED,
FT_EEPROM_NOT_PRESENT,
FT_EEPROM_NOT_PROGRAMMED,
FT_INVALID_ARGS,
FT_NOT_SUPPORTED,
FT_OTHER_ERROR,
FT_DEVICE_LIST_NOT_READY,
};
#define FT_SUCCESS(status) ((status) == FT_OK)
//
// FT_OpenEx Flags
//
#define FT_OPEN_BY_SERIAL_NUMBER 1
#define FT_OPEN_BY_DESCRIPTION 2
#define FT_OPEN_BY_LOCATION 4
//
// FT_ListDevices Flags (used in conjunction with FT_OpenEx Flags
//
#define FT_LIST_NUMBER_ONLY 0x80000000
#define FT_LIST_BY_INDEX 0x40000000
#define FT_LIST_ALL 0x20000000
#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL)
//
// Baud Rates
//
#define FT_BAUD_300 300
#define FT_BAUD_600 600
#define FT_BAUD_1200 1200
#define FT_BAUD_2400 2400
#define FT_BAUD_4800 4800
#define FT_BAUD_9600 9600
#define FT_BAUD_14400 14400
#define FT_BAUD_19200 19200
#define FT_BAUD_38400 38400
#define FT_BAUD_57600 57600
#define FT_BAUD_115200 115200
#define FT_BAUD_230400 230400
#define FT_BAUD_460800 460800
#define FT_BAUD_921600 921600
//
// Word Lengths
//
#define FT_BITS_8 (UCHAR) 8
#define FT_BITS_7 (UCHAR) 7
#define FT_BITS_6 (UCHAR) 6
#define FT_BITS_5 (UCHAR) 5
//
// Stop Bits
//
#define FT_STOP_BITS_1 (UCHAR) 0
#define FT_STOP_BITS_1_5 (UCHAR) 1
#define FT_STOP_BITS_2 (UCHAR) 2
//
// Parity
//
#define FT_PARITY_NONE (UCHAR) 0
#define FT_PARITY_ODD (UCHAR) 1
#define FT_PARITY_EVEN (UCHAR) 2
#define FT_PARITY_MARK (UCHAR) 3
#define FT_PARITY_SPACE (UCHAR) 4
//
// Flow Control
//
#define FT_FLOW_NONE 0x0000
#define FT_FLOW_RTS_CTS 0x0100
#define FT_FLOW_DTR_DSR 0x0200
#define FT_FLOW_XON_XOFF 0x0400
//
// Purge rx and tx buffers
//
#define FT_PURGE_RX 1
#define FT_PURGE_TX 2
//
// Events
//
typedef void (*PFT_EVENT_HANDLER)(DWORD,DWORD);
#define FT_EVENT_RXCHAR 1
#define FT_EVENT_MODEM_STATUS 2
#define FT_EVENT_LINE_STATUS 4
//
// Timeouts
//
#define FT_DEFAULT_RX_TIMEOUT 300
#define FT_DEFAULT_TX_TIMEOUT 300
//
// Device types
//
typedef ULONG FT_DEVICE;
enum {
FT_DEVICE_BM,
FT_DEVICE_AM,
FT_DEVICE_100AX,
FT_DEVICE_UNKNOWN,
FT_DEVICE_2232C,
FT_DEVICE_232R,
FT_DEVICE_2232H,
FT_DEVICE_4232H
};
#ifdef __cplusplus
extern "C" {
#endif
FTD2XX_API
FT_STATUS WINAPI FT_Open(
int deviceNumber,
FT_HANDLE *pHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_OpenEx(
PVOID pArg1,
DWORD Flags,
FT_HANDLE *pHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_ListDevices(
PVOID pArg1,
PVOID pArg2,
DWORD Flags
);
FTD2XX_API
FT_STATUS WINAPI FT_Close(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_Read(
FT_HANDLE ftHandle,
LPVOID lpBuffer,
DWORD dwBytesToRead,
LPDWORD lpBytesReturned
);
FTD2XX_API
FT_STATUS WINAPI FT_Write(
FT_HANDLE ftHandle,
LPVOID lpBuffer,
DWORD dwBytesToWrite,
LPDWORD lpBytesWritten
);
FTD2XX_API
FT_STATUS WINAPI FT_IoCtl(
FT_HANDLE ftHandle,
DWORD dwIoControlCode,
LPVOID lpInBuf,
DWORD nInBufSize,
LPVOID lpOutBuf,
DWORD nOutBufSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped
);
FTD2XX_API
FT_STATUS WINAPI FT_SetBaudRate(
FT_HANDLE ftHandle,
ULONG BaudRate
);
FTD2XX_API
FT_STATUS WINAPI FT_SetDivisor(
FT_HANDLE ftHandle,
USHORT Divisor
);
FTD2XX_API
FT_STATUS WINAPI FT_SetDataCharacteristics(
FT_HANDLE ftHandle,
UCHAR WordLength,
UCHAR StopBits,
UCHAR Parity
);
FTD2XX_API
FT_STATUS WINAPI FT_SetFlowControl(
FT_HANDLE ftHandle,
USHORT FlowControl,
UCHAR XonChar,
UCHAR XoffChar
);
FTD2XX_API
FT_STATUS WINAPI FT_ResetDevice(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetDtr(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_ClrDtr(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetRts(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_ClrRts(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_GetModemStatus(
FT_HANDLE ftHandle,
ULONG *pModemStatus
);
FTD2XX_API
FT_STATUS WINAPI FT_SetChars(
FT_HANDLE ftHandle,
UCHAR EventChar,
UCHAR EventCharEnabled,
UCHAR ErrorChar,
UCHAR ErrorCharEnabled
);
FTD2XX_API
FT_STATUS WINAPI FT_Purge(
FT_HANDLE ftHandle,
ULONG Mask
);
FTD2XX_API
FT_STATUS WINAPI FT_SetTimeouts(
FT_HANDLE ftHandle,
ULONG ReadTimeout,
ULONG WriteTimeout
);
FTD2XX_API
FT_STATUS WINAPI FT_GetQueueStatus(
FT_HANDLE ftHandle,
DWORD *dwRxBytes
);
FTD2XX_API
FT_STATUS WINAPI FT_SetEventNotification(
FT_HANDLE ftHandle,
DWORD Mask,
PVOID Param
);
FTD2XX_API
FT_STATUS WINAPI FT_GetStatus(
FT_HANDLE ftHandle,
DWORD *dwRxBytes,
DWORD *dwTxBytes,
DWORD *dwEventDWord
);
FTD2XX_API
FT_STATUS WINAPI FT_SetBreakOn(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetBreakOff(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetWaitMask(
FT_HANDLE ftHandle,
DWORD Mask
);
FTD2XX_API
FT_STATUS WINAPI FT_WaitOnMask(
FT_HANDLE ftHandle,
DWORD *Mask
);
FTD2XX_API
FT_STATUS WINAPI FT_GetEventStatus(
FT_HANDLE ftHandle,
DWORD *dwEventDWord
);
FTD2XX_API
FT_STATUS WINAPI FT_ReadEE(
FT_HANDLE ftHandle,
DWORD dwWordOffset,
LPWORD lpwValue
);
FTD2XX_API
FT_STATUS WINAPI FT_WriteEE(
FT_HANDLE ftHandle,
DWORD dwWordOffset,
WORD wValue
);
FTD2XX_API
FT_STATUS WINAPI FT_EraseEE(
FT_HANDLE ftHandle
);
//
// structure to hold program data for FT_Program function
//
typedef struct ft_program_data {
DWORD Signature1; // Header - must be 0x00000000
DWORD Signature2; // Header - must be 0xffffffff
DWORD Version; // Header - FT_PROGRAM_DATA version
// 0 = original
// 1 = FT2232C extensions
// 2 = FT232R extensions
// 3 = FT2232H extensions
// 4 = FT4232H extensions
WORD VendorId; // 0x0403
WORD ProductId; // 0x6001
char *Manufacturer; // "FTDI"
char *ManufacturerId; // "FT"
char *Description; // "USB HS Serial Converter"
char *SerialNumber; // "FT000001" if fixed, or NULL
WORD MaxPower; // 0 < MaxPower <= 500
WORD PnP; // 0 = disabled, 1 = enabled
WORD SelfPowered; // 0 = bus powered, 1 = self powered
WORD RemoteWakeup; // 0 = not capable, 1 = capable
//
// Rev4 (FT232B) extensions
//
UCHAR Rev4; // non-zero if Rev4 chip, zero otherwise
UCHAR IsoIn; // non-zero if in endpoint is isochronous
UCHAR IsoOut; // non-zero if out endpoint is isochronous
UCHAR PullDownEnable; // non-zero if pull down enabled
UCHAR SerNumEnable; // non-zero if serial number to be used
UCHAR USBVersionEnable; // non-zero if chip uses USBVersion
WORD USBVersion; // BCD (0x0200 => USB2)
//
// Rev 5 (FT2232) extensions
//
UCHAR Rev5; // non-zero if Rev5 chip, zero otherwise
UCHAR IsoInA; // non-zero if in endpoint is isochronous
UCHAR IsoInB; // non-zero if in endpoint is isochronous
UCHAR IsoOutA; // non-zero if out endpoint is isochronous
UCHAR IsoOutB; // non-zero if out endpoint is isochronous
UCHAR PullDownEnable5; // non-zero if pull down enabled
UCHAR SerNumEnable5; // non-zero if serial number to be used
UCHAR USBVersionEnable5; // non-zero if chip uses USBVersion
WORD USBVersion5; // BCD (0x0200 => USB2)
UCHAR AIsHighCurrent; // non-zero if interface is high current
UCHAR BIsHighCurrent; // non-zero if interface is high current
UCHAR IFAIsFifo; // non-zero if interface is 245 FIFO
UCHAR IFAIsFifoTar; // non-zero if interface is 245 FIFO CPU target
UCHAR IFAIsFastSer; // non-zero if interface is Fast serial
UCHAR AIsVCP; // non-zero if interface is to use VCP drivers
UCHAR IFBIsFifo; // non-zero if interface is 245 FIFO
UCHAR IFBIsFifoTar; // non-zero if interface is 245 FIFO CPU target
UCHAR IFBIsFastSer; // non-zero if interface is Fast serial
UCHAR BIsVCP; // non-zero if interface is to use VCP drivers
//
// Rev 6 (FT232R) extensions
//
UCHAR UseExtOsc; // Use External Oscillator
UCHAR HighDriveIOs; // High Drive I/Os
UCHAR EndpointSize; // Endpoint size
UCHAR PullDownEnableR; // non-zero if pull down enabled
UCHAR SerNumEnableR; // non-zero if serial number to be used
UCHAR InvertTXD; // non-zero if invert TXD
UCHAR InvertRXD; // non-zero if invert RXD
UCHAR InvertRTS; // non-zero if invert RTS
UCHAR InvertCTS; // non-zero if invert CTS
UCHAR InvertDTR; // non-zero if invert DTR
UCHAR InvertDSR; // non-zero if invert DSR
UCHAR InvertDCD; // non-zero if invert DCD
UCHAR InvertRI; // non-zero if invert RI
UCHAR Cbus0; // Cbus Mux control
UCHAR Cbus1; // Cbus Mux control
UCHAR Cbus2; // Cbus Mux control
UCHAR Cbus3; // Cbus Mux control
UCHAR Cbus4; // Cbus Mux control
UCHAR RIsD2XX; // non-zero if using D2XX driver
//
// Rev 7 (FT2232H) Extensions
//
UCHAR PullDownEnable7; // non-zero if pull down enabled
UCHAR SerNumEnable7; // non-zero if serial number to be used
UCHAR ALSlowSlew; // non-zero if AL pins have slow slew
UCHAR ALSchmittInput; // non-zero if AL pins are Schmitt input
UCHAR ALDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA
UCHAR AHSlowSlew; // non-zero if AH pins have slow slew
UCHAR AHSchmittInput; // non-zero if AH pins are Schmitt input
UCHAR AHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA
UCHAR BLSlowSlew; // non-zero if BL pins have slow slew
UCHAR BLSchmittInput; // non-zero if BL pins are Schmitt input
UCHAR BLDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA
UCHAR BHSlowSlew; // non-zero if BH pins have slow slew
UCHAR BHSchmittInput; // non-zero if BH pins are Schmitt input
UCHAR BHDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA
UCHAR IFAIsFifo7; // non-zero if interface is 245 FIFO
UCHAR IFAIsFifoTar7; // non-zero if interface is 245 FIFO CPU target
UCHAR IFAIsFastSer7; // non-zero if interface is Fast serial
UCHAR AIsVCP7; // non-zero if interface is to use VCP drivers
UCHAR IFBIsFifo7; // non-zero if interface is 245 FIFO
UCHAR IFBIsFifoTar7; // non-zero if interface is 245 FIFO CPU target
UCHAR IFBIsFastSer7; // non-zero if interface is Fast serial
UCHAR BIsVCP7; // non-zero if interface is to use VCP drivers
UCHAR PowerSaveEnable; // non-zero if using BCBUS7 to save power for self-powered designs
//
// Rev 8 (FT4232H) Extensions
//
UCHAR PullDownEnable8; // non-zero if pull down enabled
UCHAR SerNumEnable8; // non-zero if serial number to be used
UCHAR ASlowSlew; // non-zero if AL pins have slow slew
UCHAR ASchmittInput; // non-zero if AL pins are Schmitt input
UCHAR ADriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA
UCHAR BSlowSlew; // non-zero if AH pins have slow slew
UCHAR BSchmittInput; // non-zero if AH pins are Schmitt input
UCHAR BDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA
UCHAR CSlowSlew; // non-zero if BL pins have slow slew
UCHAR CSchmittInput; // non-zero if BL pins are Schmitt input
UCHAR CDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA
UCHAR DSlowSlew; // non-zero if BH pins have slow slew
UCHAR DSchmittInput; // non-zero if BH pins are Schmitt input
UCHAR DDriveCurrent; // valid values are 4mA, 8mA, 12mA, 16mA
UCHAR ARIIsTXDEN; // non-zero if port A uses RI as RS485 TXDEN
UCHAR BRIIsTXDEN; // non-zero if port B uses RI as RS485 TXDEN
UCHAR CRIIsTXDEN; // non-zero if port C uses RI as RS485 TXDEN
UCHAR DRIIsTXDEN; // non-zero if port D uses RI as RS485 TXDEN
UCHAR AIsVCP8; // non-zero if interface is to use VCP drivers
UCHAR BIsVCP8; // non-zero if interface is to use VCP drivers
UCHAR CIsVCP8; // non-zero if interface is to use VCP drivers
UCHAR DIsVCP8; // non-zero if interface is to use VCP drivers
} FT_PROGRAM_DATA, *PFT_PROGRAM_DATA;
FTD2XX_API
FT_STATUS WINAPI FT_EE_Program(
FT_HANDLE ftHandle,
PFT_PROGRAM_DATA pData
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_ProgramEx(
FT_HANDLE ftHandle,
PFT_PROGRAM_DATA pData,
char *Manufacturer,
char *ManufacturerId,
char *Description,
char *SerialNumber
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_Read(
FT_HANDLE ftHandle,
PFT_PROGRAM_DATA pData
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_ReadEx(
FT_HANDLE ftHandle,
PFT_PROGRAM_DATA pData,
char *Manufacturer,
char *ManufacturerId,
char *Description,
char *SerialNumber
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_UASize(
FT_HANDLE ftHandle,
LPDWORD lpdwSize
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_UAWrite(
FT_HANDLE ftHandle,
PUCHAR pucData,
DWORD dwDataLen
);
FTD2XX_API
FT_STATUS WINAPI FT_EE_UARead(
FT_HANDLE ftHandle,
PUCHAR pucData,
DWORD dwDataLen,
LPDWORD lpdwBytesRead
);
FTD2XX_API
FT_STATUS WINAPI FT_SetLatencyTimer(
FT_HANDLE ftHandle,
UCHAR ucLatency
);
FTD2XX_API
FT_STATUS WINAPI FT_GetLatencyTimer(
FT_HANDLE ftHandle,
PUCHAR pucLatency
);
FTD2XX_API
FT_STATUS WINAPI FT_SetBitMode(
FT_HANDLE ftHandle,
UCHAR ucMask,
UCHAR ucEnable
);
FTD2XX_API
FT_STATUS WINAPI FT_GetBitMode(
FT_HANDLE ftHandle,
PUCHAR pucMode
);
FTD2XX_API
FT_STATUS WINAPI FT_SetUSBParameters(
FT_HANDLE ftHandle,
ULONG ulInTransferSize,
ULONG ulOutTransferSize
);
FTD2XX_API
FT_STATUS WINAPI FT_SetDeadmanTimeout(
FT_HANDLE ftHandle,
ULONG ulDeadmanTimeout
);
FTD2XX_API
FT_STATUS WINAPI FT_GetDeviceInfo(
FT_HANDLE ftHandle,
FT_DEVICE *lpftDevice,
LPDWORD lpdwID,
PCHAR SerialNumber,
PCHAR Description,
LPVOID Dummy
);
FTD2XX_API
FT_STATUS WINAPI FT_StopInTask(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_RestartInTask(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_SetResetPipeRetryCount(
FT_HANDLE ftHandle,
DWORD dwCount
);
FTD2XX_API
FT_STATUS WINAPI FT_ResetPort(
FT_HANDLE ftHandle
);
FTD2XX_API
FT_STATUS WINAPI FT_CyclePort(
FT_HANDLE ftHandle
);
//
// Win32-type functions
//
FTD2XX_API
FT_HANDLE WINAPI FT_W32_CreateFile(
LPCTSTR lpszName,
DWORD dwAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreate,
DWORD dwAttrsAndFlags,
HANDLE hTemplate
);
FTD2XX_API
BOOL WINAPI FT_W32_CloseHandle(
FT_HANDLE ftHandle
);
FTD2XX_API
BOOL WINAPI FT_W32_ReadFile(
FT_HANDLE ftHandle,
LPVOID lpBuffer,
DWORD nBufferSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped
);
FTD2XX_API
BOOL WINAPI FT_W32_WriteFile(
FT_HANDLE ftHandle,
LPVOID lpBuffer,
DWORD nBufferSize,
LPDWORD lpBytesWritten,
LPOVERLAPPED lpOverlapped
);
FTD2XX_API
DWORD WINAPI FT_W32_GetLastError(
FT_HANDLE ftHandle
);
FTD2XX_API
BOOL WINAPI FT_W32_GetOverlappedResult(
FT_HANDLE ftHandle,
LPOVERLAPPED lpOverlapped,
LPDWORD lpdwBytesTransferred,
BOOL bWait
);
FTD2XX_API
BOOL WINAPI FT_W32_CancelIo(
FT_HANDLE ftHandle
);
//
// Win32 COMM API type functions
//
typedef struct _FTCOMSTAT {
DWORD fCtsHold : 1;
DWORD fDsrHold : 1;
DWORD fRlsdHold : 1;
DWORD fXoffHold : 1;
DWORD fXoffSent : 1;
DWORD fEof : 1;
DWORD fTxim : 1;
DWORD fReserved : 25;
DWORD cbInQue;
DWORD cbOutQue;
} FTCOMSTAT, *LPFTCOMSTAT;
typedef struct _FTDCB {
DWORD DCBlength; /* sizeof(FTDCB) */
DWORD BaudRate; /* Baudrate at which running */
DWORD fBinary: 1; /* Binary Mode (skip EOF check) */
DWORD fParity: 1; /* Enable parity checking */
DWORD fOutxCtsFlow:1; /* CTS handshaking on output */
DWORD fOutxDsrFlow:1; /* DSR handshaking on output */
DWORD fDtrControl:2; /* DTR Flow control */
DWORD fDsrSensitivity:1; /* DSR Sensitivity */
DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */
DWORD fOutX: 1; /* Enable output X-ON/X-OFF */
DWORD fInX: 1; /* Enable input X-ON/X-OFF */
DWORD fErrorChar: 1; /* Enable Err Replacement */
DWORD fNull: 1; /* Enable Null stripping */
DWORD fRtsControl:2; /* Rts Flow control */
DWORD fAbortOnError:1; /* Abort all reads and writes on Error */
DWORD fDummy2:17; /* Reserved */
WORD wReserved; /* Not currently used */
WORD XonLim; /* Transmit X-ON threshold */
WORD XoffLim; /* Transmit X-OFF threshold */
BYTE ByteSize; /* Number of bits/byte, 4-8 */
BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */
BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */
char XonChar; /* Tx and Rx X-ON character */
char XoffChar; /* Tx and Rx X-OFF character */
char ErrorChar; /* Error replacement char */
char EofChar; /* End of Input character */
char EvtChar; /* Received Event character */
WORD wReserved1; /* Fill for now. */
} FTDCB, *LPFTDCB;
typedef struct _FTTIMEOUTS {
DWORD ReadIntervalTimeout; /* Maximum time between read chars. */
DWORD ReadTotalTimeoutMultiplier; /* Multiplier of characters. */
DWORD ReadTotalTimeoutConstant; /* Constant in milliseconds. */
DWORD WriteTotalTimeoutMultiplier; /* Multiplier of characters. */
DWORD WriteTotalTimeoutConstant; /* Constant in milliseconds. */
} FTTIMEOUTS,*LPFTTIMEOUTS;
FTD2XX_API
BOOL WINAPI FT_W32_ClearCommBreak(
FT_HANDLE ftHandle
);
FTD2XX_API
BOOL WINAPI FT_W32_ClearCommError(
FT_HANDLE ftHandle,
LPDWORD lpdwErrors,
LPFTCOMSTAT lpftComstat
);
FTD2XX_API
BOOL WINAPI FT_W32_EscapeCommFunction(
FT_HANDLE ftHandle,
DWORD dwFunc
);
FTD2XX_API
BOOL WINAPI FT_W32_GetCommModemStatus(
FT_HANDLE ftHandle,
LPDWORD lpdwModemStatus
);
FTD2XX_API
BOOL WINAPI FT_W32_GetCommState(
FT_HANDLE ftHandle,
LPFTDCB lpftDcb
);
FTD2XX_API
BOOL WINAPI FT_W32_GetCommTimeouts(
FT_HANDLE ftHandle,
FTTIMEOUTS *pTimeouts
);
FTD2XX_API
BOOL WINAPI FT_W32_PurgeComm(
FT_HANDLE ftHandle,
DWORD dwMask
);
FTD2XX_API
BOOL WINAPI FT_W32_SetCommBreak(
FT_HANDLE ftHandle
);
FTD2XX_API
BOOL WINAPI FT_W32_SetCommMask(
FT_HANDLE ftHandle,
ULONG ulEventMask
);
FTD2XX_API
BOOL WINAPI FT_W32_GetCommMask(
FT_HANDLE ftHandle,
LPDWORD lpdwEventMask
);
FTD2XX_API
BOOL WINAPI FT_W32_SetCommState(
FT_HANDLE ftHandle,
LPFTDCB lpftDcb
);
FTD2XX_API
BOOL WINAPI FT_W32_SetCommTimeouts(
FT_HANDLE ftHandle,
FTTIMEOUTS *pTimeouts
);
FTD2XX_API
BOOL WINAPI FT_W32_SetupComm(
FT_HANDLE ftHandle,
DWORD dwReadBufferSize,
DWORD dwWriteBufferSize
);
FTD2XX_API
BOOL WINAPI FT_W32_WaitCommEvent(
FT_HANDLE ftHandle,
PULONG pulEvent,
LPOVERLAPPED lpOverlapped
);
//
// Device information
//
typedef struct _ft_device_list_info_node {
ULONG Flags;
ULONG Type;
ULONG ID;
DWORD LocId;
char SerialNumber[16];
char Description[64];
FT_HANDLE ftHandle;
} FT_DEVICE_LIST_INFO_NODE;
// Device information flags
enum {
FT_FLAGS_OPENED = 1,
FT_FLAGS_HISPEED = 2
};
FTD2XX_API
FT_STATUS WINAPI FT_CreateDeviceInfoList(
LPDWORD lpdwNumDevs
);
FTD2XX_API
FT_STATUS WINAPI FT_GetDeviceInfoList(
FT_DEVICE_LIST_INFO_NODE *pDest,
LPDWORD lpdwNumDevs
);
FTD2XX_API
FT_STATUS WINAPI FT_GetDeviceInfoDetail(
DWORD dwIndex,
LPDWORD lpdwFlags,
LPDWORD lpdwType,
LPDWORD lpdwID,
LPDWORD lpdwLocId,
LPVOID lpSerialNumber,
LPVOID lpDescription,
FT_HANDLE *pftHandle
);
//
// Version information
//
FTD2XX_API
FT_STATUS WINAPI FT_GetDriverVersion(
FT_HANDLE ftHandle,
LPDWORD lpdwVersion
);
FTD2XX_API
FT_STATUS WINAPI FT_GetLibraryVersion(
LPDWORD lpdwVersion
);
FTD2XX_API
FT_STATUS WINAPI FT_Rescan(
void
);
FTD2XX_API
FT_STATUS WINAPI FT_Reload(
WORD wVid,
WORD wPid
);
FTD2XX_API
FT_STATUS WINAPI FT_GetComPortNumber(
FT_HANDLE ftHandle,
LPLONG lpdwComPortNumber
);
#ifdef __cplusplus
}
#endif
#endif /* FTD2XX_H */