From 97488183fbfad702c590a970d3babf30a76e61ff Mon Sep 17 00:00:00 2001 From: Sathya Laufer Date: Tue, 29 May 2018 20:51:43 +0200 Subject: [PATCH] Wait for connection before returning in constructor --- .gitignore | 4 ++-- Example.py | 3 +-- IpcClient.cpp | 1 + IpcClient.h | 2 ++ README.md | 6 +++++- homegear.cpp | 17 +++++++++++++++++ setup.py | 4 ++-- 7 files changed, 30 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index c2d2334..2f9a76f 100644 --- a/.gitignore +++ b/.gitignore @@ -54,7 +54,7 @@ local.properties autom4te.cache *.in~ config.log -homegear-management +homegear.so core vgcore.* @@ -87,4 +87,4 @@ cmake-build-debug #Python setup build/ homegear.egg-info -dist/ \ No newline at end of file +dist/ diff --git a/Example.py b/Example.py index e898b4c..fd86710 100644 --- a/Example.py +++ b/Example.py @@ -9,8 +9,7 @@ def eventHandler(peerId, channel, variableName, value): hg = Homegear("/var/run/homegear/homegearIPC.sock", eventHandler); -while(not hg.connected()): - time.sleep(1); +# hg waits until the connection is established (but for a maximum of 2 seonds). print(hg.logLevel()); print(hg.listDevices()); diff --git a/IpcClient.cpp b/IpcClient.cpp index 9b20533..522302f 100644 --- a/IpcClient.cpp +++ b/IpcClient.cpp @@ -41,6 +41,7 @@ IpcClient::~IpcClient() void IpcClient::onConnect() { + if(_onConnect) _onConnect(); } // {{{ RPC methods diff --git a/IpcClient.h b/IpcClient.h index e3c798e..2a9fe5d 100644 --- a/IpcClient.h +++ b/IpcClient.h @@ -45,8 +45,10 @@ class IpcClient : public Ipc::IIpcClient IpcClient(std::string socketPath); virtual ~IpcClient(); + void setOnConnect(std::function value) { _onConnect.swap(value); } void setBroadcastEvent(std::function value) { _broadcastEvent.swap(value); } private: + std::function _onConnect; std::function _broadcastEvent; virtual void onConnect(); diff --git a/README.md b/README.md index 70676b8..0c577d4 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,13 @@ To compile and install the extension manually, execute sudo python3 setup.py install ``` +## Methods + +There is only one object available: `Homegear`. It takes two parameters in it's constructor: The path to the Homegear IPC socket (`/var/run/homegear/homegearIPC.sock` by default) and a callback method. The callback method is executed when a device variable is updated in Homegear. On instantiation the class waits until it is connected succesfully to Homegear. After 2 seconds it returns even if there is no connection. To check, if the object is still connected, you can call `connected()`. Apart from this method, you can call all RPC methods available in Homegear. + ## Usage example -Basically there is the Homegear object which takes two parameters on instantiation: The path to the Homegear IPC socket (`/var/run/homegear/homegearIPC.sock` by default) and a callback method. The callback method is executed when a device variable is updated in Homegear. A minimal example: +A minimal example: ``` from homegear import Homegear diff --git a/homegear.cpp b/homegear.cpp index f20103e..e6a2f2c 100644 --- a/homegear.cpp +++ b/homegear.cpp @@ -34,6 +34,8 @@ std::shared_ptr _ipcClient; static PyObject* _eventCallback = nullptr; +static std::mutex _onConnectWaitMutex; +static std::condition_variable _onConnectConditionVariable; typedef struct { @@ -192,6 +194,13 @@ static PyObject* HomegearRpcMethod_call(PyObject* object, PyObject* args, PyObje return PythonVariableConverter::getPythonVariable(result); } +static void Homegear_onConnect() +{ + std::unique_lock waitLock(_onConnectWaitMutex); + waitLock.unlock(); + _onConnectConditionVariable.notify_all(); +} + static void Homegear_broadcastEvent(uint64_t peerId, int32_t channel, std::string& variableName, Ipc::PVariable value) { if(!_eventCallback) return; @@ -258,7 +267,15 @@ static int Homegear_init(HomegearObject* self, PyObject* arg) { _ipcClient = std::make_shared(self->socketPath); if(_eventCallback) _ipcClient->setBroadcastEvent(std::function(std::bind(&Homegear_broadcastEvent, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4))); + _ipcClient->setOnConnect(std::function(std::bind(&Homegear_onConnect))); _ipcClient->start(); + std::unique_lock waitLock(_onConnectWaitMutex); + int64_t startTime = Ipc::HelperFunctions::getTime(); + while (!_onConnectConditionVariable.wait_for(waitLock, std::chrono::milliseconds(2000), [&] + { + if(Ipc::HelperFunctions::getTime() - startTime > 2000) return true; + else return _ipcClient->connected(); + })); } return 0; diff --git a/setup.py b/setup.py index d69baa0..642a77c 100644 --- a/setup.py +++ b/setup.py @@ -6,14 +6,14 @@ setuptools.setup( name="homegear", - version="1.0.2", + version="1.0.3", description = 'Extension to connect to a local Homegear service.', long_description=long_description, long_description_content_type="text/markdown", author="Homegear GmbH", author_email="contact@homegear.email", url="https://github.com/Homegear/libhomegear-python", - download_url = 'https://github.com/Homegear/libhomegear-python/archive/1.0.2.tar.gz', + download_url = 'https://github.com/Homegear/libhomegear-python/archive/1.0.3.tar.gz', keywords = ['homegear', 'smart home'], ext_modules=[ Extension("homegear", ["homegear.cpp", "IpcClient.cpp", "PythonVariableConverter.cpp"],