random ai stuff
This commit is contained in:
278
telldus-core/service/CMakeLists.txt
Normal file
278
telldus-core/service/CMakeLists.txt
Normal 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()
|
||||
266
telldus-core/service/ClientCommunicationHandler.cpp
Normal file
266
telldus-core/service/ClientCommunicationHandler.cpp
Normal 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);
|
||||
}
|
||||
41
telldus-core/service/ClientCommunicationHandler.h
Normal file
41
telldus-core/service/ClientCommunicationHandler.h
Normal 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_
|
||||
37
telldus-core/service/ConnectionListener.h
Normal file
37
telldus-core/service/ConnectionListener.h
Normal 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_
|
||||
100
telldus-core/service/ConnectionListener_unix.cpp
Normal file
100
telldus-core/service/ConnectionListener_unix.cpp
Normal 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);
|
||||
}
|
||||
|
||||
153
telldus-core/service/ConnectionListener_win.cpp
Normal file
153
telldus-core/service/ConnectionListener_win.cpp
Normal 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);
|
||||
}
|
||||
99
telldus-core/service/Controller.cpp
Normal file
99
telldus-core/service/Controller.cpp
Normal 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);
|
||||
}
|
||||
38
telldus-core/service/Controller.h
Normal file
38
telldus-core/service/Controller.h
Normal 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_
|
||||
32
telldus-core/service/ControllerListener.h
Normal file
32
telldus-core/service/ControllerListener.h
Normal 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_
|
||||
187
telldus-core/service/ControllerListener_mac.cpp
Normal file
187
telldus-core/service/ControllerListener_mac.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
374
telldus-core/service/ControllerManager.cpp
Normal file
374
telldus-core/service/ControllerManager.cpp
Normal 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);
|
||||
}
|
||||
40
telldus-core/service/ControllerManager.h
Normal file
40
telldus-core/service/ControllerManager.h
Normal 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_
|
||||
95
telldus-core/service/ControllerMessage.cpp
Normal file
95
telldus-core/service/ControllerMessage.cpp
Normal 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;
|
||||
}
|
||||
36
telldus-core/service/ControllerMessage.h
Normal file
36
telldus-core/service/ControllerMessage.h
Normal 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_
|
||||
272
telldus-core/service/Device.cpp
Normal file
272
telldus-core/service/Device.cpp
Normal 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;
|
||||
}
|
||||
51
telldus-core/service/Device.h
Normal file
51
telldus-core/service/Device.h
Normal 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_
|
||||
790
telldus-core/service/DeviceManager.cpp
Normal file
790
telldus-core/service/DeviceManager.cpp
Normal 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;
|
||||
}
|
||||
68
telldus-core/service/DeviceManager.h
Normal file
68
telldus-core/service/DeviceManager.h
Normal 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_
|
||||
259
telldus-core/service/EventUpdateManager.cpp
Normal file
259
telldus-core/service/EventUpdateManager.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
//
|
||||
// Copyright (C) 2012 Telldus Technologies AB. All rights reserved.
|
||||
//
|
||||
// Copyright: See COPYING file that comes with this distribution
|
||||
//
|
||||
//
|
||||
#include "service/EventUpdateManager.h"
|
||||
|
||||
#ifdef _LINUX
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#endif // _LINUX
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#ifdef _LINUX
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#endif // _LINUX
|
||||
|
||||
#include "common/EventHandler.h"
|
||||
#include "common/Message.h"
|
||||
#include "common/Socket.h"
|
||||
#include "common/Strings.h"
|
||||
#include "service/config.h"
|
||||
#include "service/ConnectionListener.h"
|
||||
#include "service/Log.h"
|
||||
|
||||
typedef std::list<TelldusCore::Socket *> SocketList;
|
||||
typedef std::list<std::string> StringList;
|
||||
|
||||
class EventUpdateManager::PrivateData {
|
||||
public:
|
||||
TelldusCore::EventHandler eventHandler;
|
||||
TelldusCore::EventRef stopEvent, updateEvent, clientConnectEvent;
|
||||
SocketList clients;
|
||||
ConnectionListener *eventUpdateClientListener;
|
||||
#ifdef _LINUX
|
||||
std::map<std::string, StringList> fileList;
|
||||
#endif // _LINUX
|
||||
};
|
||||
|
||||
EventUpdateManager::EventUpdateManager()
|
||||
:Thread() {
|
||||
d = new PrivateData;
|
||||
d->stopEvent = d->eventHandler.addEvent();
|
||||
d->updateEvent = d->eventHandler.addEvent();
|
||||
d->clientConnectEvent = d->eventHandler.addEvent();
|
||||
d->eventUpdateClientListener = new ConnectionListener(L"TelldusEvents", d->clientConnectEvent);
|
||||
#ifdef _LINUX
|
||||
loadScripts("deviceevent");
|
||||
loadScripts("devicechangeevent");
|
||||
loadScripts("rawdeviceevent");
|
||||
loadScripts("sensorevent");
|
||||
loadScripts("controllerevent");
|
||||
#endif // _LINUX
|
||||
}
|
||||
|
||||
EventUpdateManager::~EventUpdateManager(void) {
|
||||
d->stopEvent->signal();
|
||||
wait();
|
||||
delete d->eventUpdateClientListener;
|
||||
|
||||
for (SocketList::iterator it = d->clients.begin(); it != d->clients.end(); ++it) {
|
||||
delete(*it);
|
||||
}
|
||||
|
||||
delete d;
|
||||
}
|
||||
|
||||
TelldusCore::EventRef EventUpdateManager::retrieveUpdateEvent() {
|
||||
return d->updateEvent;
|
||||
}
|
||||
|
||||
void EventUpdateManager::run() {
|
||||
while(!d->stopEvent->isSignaled()) {
|
||||
if (!d->eventHandler.waitForAny()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if(d->clientConnectEvent->isSignaled()) {
|
||||
// new client added
|
||||
TelldusCore::EventDataRef eventData = d->clientConnectEvent->takeSignal();
|
||||
ConnectionListenerEventData *data = dynamic_cast<ConnectionListenerEventData*>(eventData.get());
|
||||
if(data) {
|
||||
d->clients.push_back(data->socket);
|
||||
}
|
||||
} else if(d->updateEvent->isSignaled()) {
|
||||
// device event, signal all clients
|
||||
TelldusCore::EventDataRef eventData = d->updateEvent->takeSignal();
|
||||
EventUpdateData *data = reinterpret_cast<EventUpdateData*>(eventData.get());
|
||||
if(data) {
|
||||
sendMessageToClients(data);
|
||||
executeScripts(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventUpdateManager::loadScripts(const std::string &folder) {
|
||||
#ifdef _LINUX
|
||||
std::string path = TelldusCore::formatf("%s/%s", SCRIPT_PATH, folder.c_str());
|
||||
struct dirent **namelist;
|
||||
int count = scandir(path.c_str(), &namelist, NULL, alphasort);
|
||||
if (count < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = 0; i < count; ++i) {
|
||||
if (strcmp(namelist[i]->d_name, ".") != 0 && strcmp(namelist[i]->d_name, "..") != 0) {
|
||||
d->fileList[folder].push_back(namelist[i]->d_name);
|
||||
}
|
||||
free(namelist[i]);
|
||||
}
|
||||
free(namelist);
|
||||
#endif // _LINUX
|
||||
}
|
||||
|
||||
void EventUpdateManager::sendMessageToClients(EventUpdateData *data) {
|
||||
int connected = 0;
|
||||
for(SocketList::iterator it = d->clients.begin(); it != d->clients.end();) {
|
||||
if((*it)->isConnected()) {
|
||||
connected++;
|
||||
TelldusCore::Message msg;
|
||||
|
||||
if(data->messageType == L"TDDeviceEvent") {
|
||||
msg.addArgument("TDDeviceEvent");
|
||||
msg.addArgument(data->deviceId);
|
||||
msg.addArgument(data->eventState);
|
||||
msg.addArgument(data->eventValue); // string
|
||||
} else if(data->messageType == L"TDDeviceChangeEvent") {
|
||||
msg.addArgument("TDDeviceChangeEvent");
|
||||
msg.addArgument(data->deviceId);
|
||||
msg.addArgument(data->eventDeviceChanges);
|
||||
msg.addArgument(data->eventChangeType);
|
||||
} else if(data->messageType == L"TDRawDeviceEvent") {
|
||||
msg.addArgument("TDRawDeviceEvent");
|
||||
msg.addArgument(data->eventValue); // string
|
||||
msg.addArgument(data->controllerId);
|
||||
} else if(data->messageType == L"TDSensorEvent") {
|
||||
msg.addArgument("TDSensorEvent");
|
||||
msg.addArgument(data->protocol);
|
||||
msg.addArgument(data->model);
|
||||
msg.addArgument(data->sensorId);
|
||||
msg.addArgument(data->dataType);
|
||||
msg.addArgument(data->value);
|
||||
msg.addArgument(data->timestamp);
|
||||
} else if(data->messageType == L"TDControllerEvent") {
|
||||
msg.addArgument("TDControllerEvent");
|
||||
msg.addArgument(data->controllerId);
|
||||
msg.addArgument(data->eventState);
|
||||
msg.addArgument(data->eventChangeType);
|
||||
msg.addArgument(data->eventValue);
|
||||
}
|
||||
|
||||
(*it)->write(msg);
|
||||
|
||||
it++;
|
||||
} else {
|
||||
// connection is dead, remove it
|
||||
delete *it;
|
||||
it = d->clients.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EventUpdateManager::executeScripts(EventUpdateData *data) {
|
||||
#ifdef _LINUX
|
||||
std::string dir;
|
||||
std::vector<std::string> env;
|
||||
|
||||
// Create a copy of the environment
|
||||
unsigned int size = 0;
|
||||
for(; ; ++size) {
|
||||
if (environ[size] == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
env.reserve(size + 6); // 6 is the most used extra environmental variables any event uses
|
||||
for(unsigned int i = 0; i < size; ++i) {
|
||||
env.push_back(environ[i]);
|
||||
}
|
||||
|
||||
if(data->messageType == L"TDDeviceEvent") {
|
||||
dir = "deviceevent";
|
||||
env.push_back(TelldusCore::formatf("DEVICEID=%i", data->deviceId));
|
||||
env.push_back(TelldusCore::formatf("METHOD=%i", data->eventState));
|
||||
env.push_back(TelldusCore::formatf("METHODDATA=%s", TelldusCore::wideToString(data->eventValue).c_str()));
|
||||
} else if(data->messageType == L"TDDeviceChangeEvent") {
|
||||
dir = "devicechangeevent";
|
||||
env.push_back(TelldusCore::formatf("DEVICEID=%i", data->deviceId));
|
||||
env.push_back(TelldusCore::formatf("CHANGEEVENT=%i", data->eventDeviceChanges));
|
||||
env.push_back(TelldusCore::formatf("CHANGETYPE=%i", data->eventChangeType));
|
||||
} else if(data->messageType == L"TDRawDeviceEvent") {
|
||||
dir = "rawdeviceevent";
|
||||
env.push_back(TelldusCore::formatf("RAWDATA=%s", TelldusCore::wideToString(data->eventValue).c_str())); // string
|
||||
env.push_back(TelldusCore::formatf("CONTROLLERID=%i", data->controllerId));
|
||||
} else if (data->messageType == L"TDSensorEvent") {
|
||||
dir = "sensorevent";
|
||||
env.push_back(TelldusCore::formatf("PROTOCOL=%s", TelldusCore::wideToString(data->protocol).c_str()));
|
||||
env.push_back(TelldusCore::formatf("MODEL=%s", TelldusCore::wideToString(data->model).c_str()));
|
||||
env.push_back(TelldusCore::formatf("SENSORID=%i", data->sensorId));
|
||||
env.push_back(TelldusCore::formatf("DATATYPE=%i", data->dataType));
|
||||
env.push_back(TelldusCore::formatf("VALUE=%s", TelldusCore::wideToString(data->value).c_str()));
|
||||
env.push_back(TelldusCore::formatf("TIMESTAMP=%i", data->timestamp));
|
||||
} else if(data->messageType == L"TDControllerEvent") {
|
||||
dir = "controllerevent";
|
||||
env.push_back(TelldusCore::formatf("CONTROLLERID=%i", data->controllerId));
|
||||
env.push_back(TelldusCore::formatf("CHANGEEVENT=%i", data->eventState));
|
||||
env.push_back(TelldusCore::formatf("CHANGETYPE=%i", data->eventChangeType));
|
||||
env.push_back(TelldusCore::formatf("VALUE=%s", TelldusCore::wideToString(data->eventValue).c_str()));
|
||||
} else {
|
||||
// Unknown event, should not happen
|
||||
return;
|
||||
}
|
||||
|
||||
char *newEnv[env.size()+1]; // +1 for the last stop element
|
||||
for(int i = 0; i < env.size(); ++i) {
|
||||
newEnv[i] = new char[env.at(i).length()+1];
|
||||
snprintf(newEnv[i], env.at(i).length()+1, "%s", env.at(i).c_str());
|
||||
}
|
||||
newEnv[env.size()] = NULL; // Mark end of array
|
||||
|
||||
for(StringList::iterator it = d->fileList[dir].begin(); it != d->fileList[dir].end(); ++it) {
|
||||
executeScript(TelldusCore::formatf("%s/%s/%s", SCRIPT_PATH, dir.c_str(), (*it).c_str()), (*it), newEnv);
|
||||
}
|
||||
// Cleanup
|
||||
for(int i = 0; newEnv[i] != 0; ++i) {
|
||||
delete[] newEnv[i];
|
||||
}
|
||||
#endif // _LINUX
|
||||
}
|
||||
|
||||
void EventUpdateManager::executeScript(std::string script, const std::string &name, char ** env) {
|
||||
#ifdef _LINUX
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) {
|
||||
Log::error("Could not fork() to execute script %s", script.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (pid == 0) {
|
||||
char *n = new char[name.length()+1];
|
||||
snprintf(n, name.length()+1, "%s", name.c_str());
|
||||
static char * argv[] = { n, NULL };
|
||||
execve(script.c_str(), argv, env);
|
||||
delete[] n;
|
||||
Log::error("Could not execute %s (%i): %s", script.c_str(), errno, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
#endif // _LINUX
|
||||
}
|
||||
53
telldus-core/service/EventUpdateManager.h
Normal file
53
telldus-core/service/EventUpdateManager.h
Normal 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_
|
||||
183
telldus-core/service/Log.cpp
Normal file
183
telldus-core/service/Log.cpp
Normal 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;
|
||||
}
|
||||
40
telldus-core/service/Log.h
Normal file
40
telldus-core/service/Log.h
Normal 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_
|
||||
BIN
telldus-core/service/Messages.mc
Normal file
BIN
telldus-core/service/Messages.mc
Normal file
Binary file not shown.
267
telldus-core/service/Protocol.cpp
Normal file
267
telldus-core/service/Protocol.cpp
Normal 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 ¶meterList) {
|
||||
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;
|
||||
}
|
||||
46
telldus-core/service/Protocol.h
Normal file
46
telldus-core/service/Protocol.h
Normal 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 ¶meterList);
|
||||
|
||||
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_
|
||||
53
telldus-core/service/ProtocolBrateck.cpp
Normal file
53
telldus-core/service/ProtocolBrateck.cpp
Normal 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;
|
||||
}
|
||||
19
telldus-core/service/ProtocolBrateck.h
Normal file
19
telldus-core/service/ProtocolBrateck.h
Normal 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_
|
||||
23
telldus-core/service/ProtocolComen.cpp
Normal file
23
telldus-core/service/ProtocolComen.cpp
Normal 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);
|
||||
}
|
||||
21
telldus-core/service/ProtocolComen.h
Normal file
21
telldus-core/service/ProtocolComen.h
Normal 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_
|
||||
133
telldus-core/service/ProtocolEverflourish.cpp
Normal file
133
telldus-core/service/ProtocolEverflourish.cpp
Normal 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();
|
||||
}
|
||||
24
telldus-core/service/ProtocolEverflourish.h
Normal file
24
telldus-core/service/ProtocolEverflourish.h
Normal 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_
|
||||
52
telldus-core/service/ProtocolFineoffset.cpp
Normal file
52
telldus-core/service/ProtocolFineoffset.cpp
Normal 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();
|
||||
}
|
||||
19
telldus-core/service/ProtocolFineoffset.h
Normal file
19
telldus-core/service/ProtocolFineoffset.h
Normal 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_
|
||||
60
telldus-core/service/ProtocolFuhaote.cpp
Normal file
60
telldus-core/service/ProtocolFuhaote.cpp
Normal 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;
|
||||
}
|
||||
|
||||
19
telldus-core/service/ProtocolFuhaote.h
Normal file
19
telldus-core/service/ProtocolFuhaote.h
Normal 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_
|
||||
16
telldus-core/service/ProtocolGroup.cpp
Normal file
16
telldus-core/service/ProtocolGroup.cpp
Normal 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 "";
|
||||
}
|
||||
22
telldus-core/service/ProtocolGroup.h
Normal file
22
telldus-core/service/ProtocolGroup.h
Normal 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_
|
||||
|
||||
|
||||
|
||||
201
telldus-core/service/ProtocolHasta.cpp
Normal file
201
telldus-core/service/ProtocolHasta.cpp
Normal 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();
|
||||
}
|
||||
27
telldus-core/service/ProtocolHasta.h
Normal file
27
telldus-core/service/ProtocolHasta.h
Normal 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_
|
||||
151
telldus-core/service/ProtocolIkea.cpp
Normal file
151
telldus-core/service/ProtocolIkea.cpp
Normal 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;
|
||||
}
|
||||
19
telldus-core/service/ProtocolIkea.h
Normal file
19
telldus-core/service/ProtocolIkea.h
Normal 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_
|
||||
46
telldus-core/service/ProtocolMandolyn.cpp
Normal file
46
telldus-core/service/ProtocolMandolyn.cpp
Normal 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();
|
||||
}
|
||||
19
telldus-core/service/ProtocolMandolyn.h
Normal file
19
telldus-core/service/ProtocolMandolyn.h
Normal 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_
|
||||
279
telldus-core/service/ProtocolNexa.cpp
Normal file
279
telldus-core/service/ProtocolNexa.cpp
Normal 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+";
|
||||
}
|
||||
39
telldus-core/service/ProtocolNexa.h
Normal file
39
telldus-core/service/ProtocolNexa.h
Normal 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_
|
||||
347
telldus-core/service/ProtocolOregon.cpp
Normal file
347
telldus-core/service/ProtocolOregon.cpp
Normal 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();
|
||||
}
|
||||
27
telldus-core/service/ProtocolOregon.h
Normal file
27
telldus-core/service/ProtocolOregon.h
Normal 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_
|
||||
115
telldus-core/service/ProtocolRisingSun.cpp
Normal file
115
telldus-core/service/ProtocolRisingSun.cpp
Normal 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;
|
||||
}
|
||||
24
telldus-core/service/ProtocolRisingSun.h
Normal file
24
telldus-core/service/ProtocolRisingSun.h
Normal 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_
|
||||
108
telldus-core/service/ProtocolSartano.cpp
Normal file
108
telldus-core/service/ProtocolSartano.cpp
Normal 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();
|
||||
}
|
||||
24
telldus-core/service/ProtocolSartano.h
Normal file
24
telldus-core/service/ProtocolSartano.h
Normal 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_
|
||||
16
telldus-core/service/ProtocolScene.cpp
Normal file
16
telldus-core/service/ProtocolScene.cpp
Normal 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 "";
|
||||
}
|
||||
22
telldus-core/service/ProtocolScene.h
Normal file
22
telldus-core/service/ProtocolScene.h
Normal 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_
|
||||
|
||||
|
||||
|
||||
146
telldus-core/service/ProtocolSilvanChip.cpp
Normal file
146
telldus-core/service/ProtocolSilvanChip.cpp
Normal 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;
|
||||
}
|
||||
22
telldus-core/service/ProtocolSilvanChip.h
Normal file
22
telldus-core/service/ProtocolSilvanChip.h
Normal 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_
|
||||
78
telldus-core/service/ProtocolUpm.cpp
Normal file
78
telldus-core/service/ProtocolUpm.cpp
Normal 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;
|
||||
}
|
||||
|
||||
19
telldus-core/service/ProtocolUpm.h
Normal file
19
telldus-core/service/ProtocolUpm.h
Normal 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_
|
||||
77
telldus-core/service/ProtocolWaveman.cpp
Normal file
77
telldus-core/service/ProtocolWaveman.cpp
Normal 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();
|
||||
}
|
||||
26
telldus-core/service/ProtocolWaveman.h
Normal file
26
telldus-core/service/ProtocolWaveman.h
Normal 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_
|
||||
185
telldus-core/service/ProtocolX10.cpp
Normal file
185
telldus-core/service/ProtocolX10.cpp
Normal 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();
|
||||
}
|
||||
22
telldus-core/service/ProtocolX10.h
Normal file
22
telldus-core/service/ProtocolX10.h
Normal 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_
|
||||
31
telldus-core/service/ProtocolYidong.cpp
Normal file
31
telldus-core/service/ProtocolYidong.cpp
Normal 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);
|
||||
}
|
||||
18
telldus-core/service/ProtocolYidong.h
Normal file
18
telldus-core/service/ProtocolYidong.h
Normal 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_
|
||||
73
telldus-core/service/Sensor.cpp
Normal file
73
telldus-core/service/Sensor.cpp
Normal 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;
|
||||
}
|
||||
33
telldus-core/service/Sensor.h
Normal file
33
telldus-core/service/Sensor.h
Normal 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_
|
||||
140
telldus-core/service/Settings.cpp
Normal file
140
telldus-core/service/Settings.cpp
Normal 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
|
||||
60
telldus-core/service/Settings.h
Normal file
60
telldus-core/service/Settings.h
Normal 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_
|
||||
451
telldus-core/service/SettingsConfuse.cpp
Normal file
451
telldus-core/service/SettingsConfuse.cpp
Normal 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;
|
||||
}
|
||||
310
telldus-core/service/SettingsCoreFoundationPreferences.cpp
Normal file
310
telldus-core/service/SettingsCoreFoundationPreferences.cpp
Normal 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;
|
||||
}
|
||||
270
telldus-core/service/SettingsWinRegistry.cpp
Normal file
270
telldus-core/service/SettingsWinRegistry.cpp
Normal 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;
|
||||
}
|
||||
79
telldus-core/service/TellStick.cpp
Normal file
79
telldus-core/service/TellStick.cpp
Normal 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;
|
||||
}
|
||||
54
telldus-core/service/TellStick.h
Normal file
54
telldus-core/service/TellStick.h
Normal 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_
|
||||
343
telldus-core/service/TellStick_ftd2xx.cpp
Normal file
343
telldus-core/service/TellStick_ftd2xx.cpp
Normal 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;
|
||||
}
|
||||
327
telldus-core/service/TellStick_libftdi.cpp
Normal file
327
telldus-core/service/TellStick_libftdi.cpp
Normal 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();
|
||||
}
|
||||
154
telldus-core/service/TelldusMain.cpp
Normal file
154
telldus-core/service/TelldusMain.cpp
Normal 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();
|
||||
}
|
||||
28
telldus-core/service/TelldusMain.h
Normal file
28
telldus-core/service/TelldusMain.h
Normal 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_
|
||||
181
telldus-core/service/TelldusWinService_win.cpp
Normal file
181
telldus-core/service/TelldusWinService_win.cpp
Normal 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 );
|
||||
}
|
||||
}
|
||||
39
telldus-core/service/TelldusWinService_win.h
Normal file
39
telldus-core/service/TelldusWinService_win.h
Normal 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_
|
||||
120
telldus-core/service/Timer.cpp
Normal file
120
telldus-core/service/Timer.cpp
Normal 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
|
||||
}
|
||||
30
telldus-core/service/Timer.h
Normal file
30
telldus-core/service/Timer.h
Normal 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_
|
||||
14
telldus-core/service/com.telldus.service.plist
Normal file
14
telldus-core/service/com.telldus.service.plist
Normal 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>
|
||||
11
telldus-core/service/config.h.in
Normal file
11
telldus-core/service/config.h.in
Normal 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
|
||||
15
telldus-core/service/ftd2xx.h
Normal file
15
telldus-core/service/ftd2xx.h
Normal 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
|
||||
34
telldus-core/service/main_mac.cpp
Normal file
34
telldus-core/service/main_mac.cpp
Normal 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;
|
||||
}
|
||||
166
telldus-core/service/main_unix.cpp
Normal file
166
telldus-core/service/main_unix.cpp
Normal 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);
|
||||
}
|
||||
25
telldus-core/service/main_win.cpp
Normal file
25
telldus-core/service/main_win.cpp
Normal 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;
|
||||
}
|
||||
87
telldus-core/service/osx/WinTypes.h
Executable file
87
telldus-core/service/osx/WinTypes.h
Executable 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
1008
telldus-core/service/osx/ftd2xx.h
Executable file
File diff suppressed because it is too large
Load Diff
1
telldus-core/service/telldus-core.conf
Normal file
1
telldus-core/service/telldus-core.conf
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
13
telldus-core/service/tellstick.conf
Normal file
13
telldus-core/service/tellstick.conf
Normal 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"
|
||||
}
|
||||
}
|
||||
963
telldus-core/service/win/ftd2xx.h
Normal file
963
telldus-core/service/win/ftd2xx.h
Normal 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 */
|
||||
|
||||
Reference in New Issue
Block a user