diff --git a/libnymea-core/integrations/python/pything.h b/libnymea-core/integrations/python/pything.h index 95c79876..fd504d24 100644 --- a/libnymea-core/integrations/python/pything.h +++ b/libnymea-core/integrations/python/pything.h @@ -38,7 +38,7 @@ static PyMethodDef PyThing_methods[] = { {nullptr, nullptr, 0, nullptr} // sentinel }; -static PyTypeObject PyThingDiscoveryInfoType = { +static PyTypeObject PyThingType = { PyVarObject_HEAD_INIT(NULL, 0) "nymea.Thing", /* tp_name */ sizeof(PyThing), /* tp_basicsize */ diff --git a/libnymea-core/integrations/python/pythingsetupinfo.h b/libnymea-core/integrations/python/pythingsetupinfo.h index eff6f324..bd6f2ddb 100644 --- a/libnymea-core/integrations/python/pythingsetupinfo.h +++ b/libnymea-core/integrations/python/pythingsetupinfo.h @@ -52,8 +52,8 @@ static PyObject * PyThingSetupInfo_finish(PyThingSetupInfo* self, PyObject* args } -static PyMethodDef PyThingDiscoveryInfo_methods[] = { - { "finish", (PyCFunction)PyThingDiscoveryInfo_finish, METH_VARARGS, "finish a discovery" }, +static PyMethodDef PyThingSetupInfo_methods[] = { + { "finish", (PyCFunction)PyThingSetupInfo_finish, METH_VARARGS, "finish a setup" }, {nullptr, nullptr, 0, nullptr} // sentinel }; diff --git a/libnymea-core/integrations/pythonintegrationplugin.cpp b/libnymea-core/integrations/pythonintegrationplugin.cpp index 6db011d4..b87e1a39 100644 --- a/libnymea-core/integrations/pythonintegrationplugin.cpp +++ b/libnymea-core/integrations/pythonintegrationplugin.cpp @@ -1,5 +1,6 @@ #include #include "python/pythingdiscoveryinfo.h" +#include "python/pythingsetupinfo.h" #include "pythonintegrationplugin.h" @@ -8,6 +9,7 @@ #include #include #include +#include QHash s_modules; @@ -152,6 +154,22 @@ bool PythonIntegrationPlugin::loadScript(const QString &scriptFile) s_modules.insert(m_module, m_interpreter); + QtConcurrent::run([=](){ + PyObject *loop = PyObject_GetAttrString(m_module, "loop"); + dumpError(); +// PyObject *stop = PyObject_GetAttrString(loop, "stop"); +// PyObject *call_soon = PyObject_GetAttrString(loop, "call_soon"); + PyObject *run_forever = PyObject_GetAttrString(loop, "run_forever"); +// PyObject *run_until_complete = PyObject_GetAttrString(loop, "run_until_complete"); + qCDebug(dcThingManager()) << "Starting python event loop"; + dumpError(); + PyObject_CallFunctionObjArgs(run_forever, nullptr); + qCDebug(dcThingManager()) << "stopped python event loop"; + dumpError(); + + }); + + return true; } @@ -177,8 +195,12 @@ void PythonIntegrationPlugin::init() void PythonIntegrationPlugin::discoverThings(ThingDiscoveryInfo *info) { + PyThreadState_Swap(m_interpreter); + PyGILState_STATE s = PyGILState_Ensure(); + + qCDebug(dcThingManager()) << "Python wrapper: discoverThings()" << info; PyObject *pFunc = PyObject_GetAttrString(m_module, "discoverThings"); if(!pFunc || !PyCallable_Check(pFunc)) { @@ -194,26 +216,48 @@ void PythonIntegrationPlugin::discoverThings(ThingDiscoveryInfo *info) }); -// PyObject *loop = PyObject_GetAttrString(m_module, "_loop"); -// dumpError(); -// qWarning() << "loop:" << loop; + PyObject *future = PyObject_CallFunctionObjArgs(pFunc, pyInfo, nullptr); + dumpError(); + + PyObject *asyncio = PyObject_GetAttrString(m_module, "asyncio"); + PyObject *loop = PyObject_GetAttrString(m_module, "loop"); + PyObject *run_coroutine_threadsafe = PyObject_GetAttrString(asyncio, "run_coroutine_threadsafe"); + PyObject_CallFunctionObjArgs(run_coroutine_threadsafe, future, loop, nullptr); + + PyGILState_Release(s); + +} + +void PythonIntegrationPlugin::setupThing(ThingSetupInfo *info) +{ + PyThreadState_Swap(m_interpreter); + + PyGILState_STATE s = PyGILState_Ensure(); + + qCDebug(dcThingManager()) << "Python wrapper: setupThing()" << info; + PyObject *pFunc = PyObject_GetAttrString(m_module, "setupThing"); + if(!pFunc || !PyCallable_Check(pFunc)) { + qCWarning(dcThingManager()) << "Python plugin does not implement \"setThing()\" method."; + return; + } + + PyThingSetupInfo *pyInfo = (PyThingSetupInfo*)_PyObject_New(&PyThingSetupInfoType); + pyInfo->ptrObj = info; + + connect(info, &ThingSetupInfo::finished, this, [=](){ + PyObject_Free(pyInfo); + }); PyObject *future = PyObject_CallFunctionObjArgs(pFunc, pyInfo, nullptr); dumpError(); - qWarning() << "future:" << future; - PyObject *asyncio = PyObject_GetAttrString(m_module, "asyncio"); - qWarning() << "ayncio:" << asyncio; - PyObject *loop = PyObject_GetAttrString(m_module, "loop"); - PyObject *create_task = PyObject_GetAttrString(loop, "create_task"); - PyObject *task = PyObject_CallFunctionObjArgs(create_task, future, nullptr); - - dumpError(); - qWarning() << "Create task:" << task; + PyObject *run_coroutine_threadsafe = PyObject_GetAttrString(asyncio, "run_coroutine_threadsafe"); + PyObject_CallFunctionObjArgs(run_coroutine_threadsafe, future, loop, nullptr); + PyGILState_Release(s); } void PythonIntegrationPlugin::dumpError() diff --git a/libnymea-core/integrations/pythonintegrationplugin.h b/libnymea-core/integrations/pythonintegrationplugin.h index 6034f16b..e4f8cc70 100644 --- a/libnymea-core/integrations/pythonintegrationplugin.h +++ b/libnymea-core/integrations/pythonintegrationplugin.h @@ -27,6 +27,7 @@ public: void init() override; void discoverThings(ThingDiscoveryInfo *info) override; + void setupThing(ThingSetupInfo *info) override; private: