more work
This commit is contained in:
parent
43ed283340
commit
a90841401c
@ -5,6 +5,7 @@
|
|||||||
#include "structmember.h"
|
#include "structmember.h"
|
||||||
|
|
||||||
#include "integrations/thingdescriptor.h"
|
#include "integrations/thingdescriptor.h"
|
||||||
|
#include "loggingcategories.h"
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
|
#pragma GCC diagnostic ignored "-Winvalid-offsetof"
|
||||||
@ -31,6 +32,7 @@ static int PyThingDescriptor_init(PyThingDescriptor *self, PyObject *args, PyObj
|
|||||||
static char *kwlist[] = {"thingClassId", "name", "description", nullptr};
|
static char *kwlist[] = {"thingClassId", "name", "description", nullptr};
|
||||||
PyObject *thingClassId = nullptr, *name = nullptr, *description = nullptr;
|
PyObject *thingClassId = nullptr, *name = nullptr, *description = nullptr;
|
||||||
|
|
||||||
|
qWarning() << "++++ PyThingDescriptor";
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &thingClassId, &name, &description))
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &thingClassId, &name, &description))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -52,12 +54,18 @@ static int PyThingDescriptor_init(PyThingDescriptor *self, PyObject *args, PyObj
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void PyThingDescriptor_dealloc(PyThingDescriptor * self)
|
||||||
|
{
|
||||||
|
qWarning() << "---- PyThingDescriptor";
|
||||||
|
Py_TYPE(self)->tp_free(self);
|
||||||
|
}
|
||||||
|
|
||||||
static PyTypeObject PyThingDescriptorType = {
|
static PyTypeObject PyThingDescriptorType = {
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
PyVarObject_HEAD_INIT(NULL, 0)
|
||||||
"nymea.ThingDescriptor", /* tp_name */
|
"nymea.ThingDescriptor", /* tp_name */
|
||||||
sizeof(PyThingDescriptor), /* tp_basicsize */
|
sizeof(PyThingDescriptor), /* tp_basicsize */
|
||||||
0, /* tp_itemsize */
|
0, /* tp_itemsize */
|
||||||
0, /* tp_dealloc */
|
(destructor)PyThingDescriptor_dealloc, /* tp_dealloc */
|
||||||
0, /* tp_print */
|
0, /* tp_print */
|
||||||
0, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
0, /* tp_setattr */
|
0, /* tp_setattr */
|
||||||
|
|||||||
@ -36,8 +36,6 @@ static PyObject* PyThingDiscoveryInfo_new(PyTypeObject *type, PyObject */*args*/
|
|||||||
|
|
||||||
static void PyThingDiscoveryInfo_dealloc(PyThingDiscoveryInfo * self)
|
static void PyThingDiscoveryInfo_dealloc(PyThingDiscoveryInfo * self)
|
||||||
{
|
{
|
||||||
// FIXME: Why is this not called? Seems we're leaking...
|
|
||||||
Q_ASSERT(false);
|
|
||||||
delete self->mutex;
|
delete self->mutex;
|
||||||
Py_TYPE(self)->tp_free(self);
|
Py_TYPE(self)->tp_free(self);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,11 +25,13 @@ static PyObject* PyThingSetupInfo_new(PyTypeObject *type, PyObject */*args*/, Py
|
|||||||
if (self == NULL) {
|
if (self == NULL) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
qWarning() << "++++ PyThingSetupInfo";
|
||||||
self->mutex = new QMutex();
|
self->mutex = new QMutex();
|
||||||
return (PyObject*)self;
|
return (PyObject*)self;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void PyThingSetupInfo_dealloc(PyThingSetupInfo * self) {
|
static void PyThingSetupInfo_dealloc(PyThingSetupInfo * self) {
|
||||||
|
qWarning() << "--- PyThingSetupInfo";
|
||||||
delete self->mutex;
|
delete self->mutex;
|
||||||
Py_TYPE(self)->tp_free(self);
|
Py_TYPE(self)->tp_free(self);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,4 +58,82 @@ QVariant PyObjectToQVariant(PyObject *pyObject)
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PyDumpError()
|
||||||
|
{
|
||||||
|
if (!PyErr_Occurred()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to stdout
|
||||||
|
PyObject* pyLog_write(PyObject* /*self*/, PyObject* args)
|
||||||
|
{
|
||||||
|
const char *what;
|
||||||
|
if (!PyArg_ParseTuple(args, "s", &what))
|
||||||
|
return nullptr;
|
||||||
|
if (!QByteArray(what).trimmed().isEmpty()) {
|
||||||
|
qCDebug(dcThingManager()) << what;
|
||||||
|
}
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
PyObject* pyLog_flush(PyObject* /*self*/, PyObject* /*args*/)
|
||||||
|
{
|
||||||
|
// Not really needed... qDebug() flushes already on its own
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyMethodDef pyLog_methods[] =
|
||||||
|
{
|
||||||
|
{"write", pyLog_write, METH_VARARGS, "Writes to stdout through qDebug()"},
|
||||||
|
{"flush", pyLog_flush, METH_VARARGS, "noop"},
|
||||||
|
{nullptr, nullptr, 0, nullptr} // sentinel
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyModuleDef pyLog_module =
|
||||||
|
{
|
||||||
|
PyModuleDef_HEAD_INIT, // PyModuleDef_Base m_base;
|
||||||
|
"pyLog", // const char* m_name;
|
||||||
|
"pyLog stdout override",// const char* m_doc;
|
||||||
|
-1, // Py_ssize_t m_size;
|
||||||
|
pyLog_methods, // PyMethodDef *m_methods
|
||||||
|
// inquiry m_reload; traverseproc m_traverse; inquiry m_clear; freefunc m_free;
|
||||||
|
nullptr, nullptr, nullptr, nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
// Write to stderr
|
||||||
|
PyObject* pyWarn_write(PyObject* /*self*/, PyObject* args)
|
||||||
|
{
|
||||||
|
const char *what;
|
||||||
|
if (!PyArg_ParseTuple(args, "s", &what))
|
||||||
|
return nullptr;
|
||||||
|
if (!QByteArray(what).trimmed().isEmpty()) {
|
||||||
|
qCWarning(dcThingManager()) << what;
|
||||||
|
}
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
PyObject* pyWarn_flush(PyObject* /*self*/, PyObject* /*args*/)
|
||||||
|
{
|
||||||
|
// Not really needed... qDebug() flushes already on its own
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyMethodDef pyWarn_methods[] =
|
||||||
|
{
|
||||||
|
{"write", pyWarn_write, METH_VARARGS, "Writes to stderr through qWarnging()"},
|
||||||
|
{"flush", pyWarn_flush, METH_VARARGS, "noop"},
|
||||||
|
{nullptr, nullptr, 0, nullptr} // sentinel
|
||||||
|
};
|
||||||
|
|
||||||
|
static PyModuleDef pyWarn_module =
|
||||||
|
{
|
||||||
|
PyModuleDef_HEAD_INIT, // PyModuleDef_Base m_base;
|
||||||
|
"pyWarn", // const char* m_name;
|
||||||
|
"pyWarn stdout override",// const char* m_doc;
|
||||||
|
-1, // Py_ssize_t m_size;
|
||||||
|
pyWarn_methods, // PyMethodDef *m_methods
|
||||||
|
// inquiry m_reload; traverseproc m_traverse; inquiry m_clear; freefunc m_free;
|
||||||
|
nullptr, nullptr, nullptr, nullptr
|
||||||
|
};
|
||||||
|
|
||||||
#endif // PYUTILS_H
|
#endif // PYUTILS_H
|
||||||
|
|||||||
@ -24,24 +24,6 @@ PyObject* PythonIntegrationPlugin::s_asyncio = nullptr;
|
|||||||
|
|
||||||
QHash<PythonIntegrationPlugin*, PyObject*> PythonIntegrationPlugin::s_plugins;
|
QHash<PythonIntegrationPlugin*, PyObject*> PythonIntegrationPlugin::s_plugins;
|
||||||
|
|
||||||
// Write to stdout/stderr
|
|
||||||
PyObject* nymea_write(PyObject* /*self*/, PyObject* args)
|
|
||||||
{
|
|
||||||
const char *what;
|
|
||||||
if (!PyArg_ParseTuple(args, "s", &what))
|
|
||||||
return nullptr;
|
|
||||||
if (!QByteArray(what).trimmed().isEmpty()) {
|
|
||||||
qCDebug(dcThingManager()) << what;
|
|
||||||
}
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush stdout/stderr
|
|
||||||
PyObject* nymea_flush(PyObject* /*self*/, PyObject* /*args*/)
|
|
||||||
{
|
|
||||||
// Not really needed... qDebug() flushes already on its own
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject* PythonIntegrationPlugin::task_done(PyObject* self, PyObject* args)
|
PyObject* PythonIntegrationPlugin::task_done(PyObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
@ -75,8 +57,6 @@ PyObject* PythonIntegrationPlugin::task_done(PyObject* self, PyObject* args)
|
|||||||
|
|
||||||
static PyMethodDef nymea_methods[] =
|
static PyMethodDef nymea_methods[] =
|
||||||
{
|
{
|
||||||
{"write", nymea_write, METH_VARARGS, "write to stdout through qDebug()"},
|
|
||||||
{"flush", nymea_flush, METH_VARARGS, "flush stdout (no-op)"},
|
|
||||||
{"task_done", PythonIntegrationPlugin::task_done, METH_VARARGS, "callback to clean up after asyc coroutines"},
|
{"task_done", PythonIntegrationPlugin::task_done, METH_VARARGS, "callback to clean up after asyc coroutines"},
|
||||||
{nullptr, nullptr, 0, nullptr} // sentinel
|
{nullptr, nullptr, 0, nullptr} // sentinel
|
||||||
};
|
};
|
||||||
@ -94,12 +74,15 @@ static PyModuleDef nymea_module =
|
|||||||
|
|
||||||
PyMODINIT_FUNC PyInit_nymea(void)
|
PyMODINIT_FUNC PyInit_nymea(void)
|
||||||
{
|
{
|
||||||
PyObject* m = PyModule_Create(&nymea_module);
|
|
||||||
// Overrride stdout/stderr to use qDebug instead
|
// Overrride stdout/stderr to use qDebug instead
|
||||||
PySys_SetObject("stdout", m);
|
PyObject* pyLog = PyModule_Create(&pyLog_module);
|
||||||
PySys_SetObject("stderr", m);
|
PySys_SetObject("stdout", pyLog);
|
||||||
|
PyObject* pyWarn = PyModule_Create(&pyWarn_module);
|
||||||
|
PySys_SetObject("stderr", pyWarn);
|
||||||
|
|
||||||
|
|
||||||
|
// Register nymea types
|
||||||
|
PyObject* m = PyModule_Create(&nymea_module);
|
||||||
registerNymeaLoggingHandler(m);
|
registerNymeaLoggingHandler(m);
|
||||||
registerParamType(m);
|
registerParamType(m);
|
||||||
registerThingType(m);
|
registerThingType(m);
|
||||||
@ -244,6 +227,21 @@ PyObject *PythonIntegrationPlugin::pyAutoThingsAppeared(PyObject *self, PyObject
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyObject *PythonIntegrationPlugin::pyAutoThingDisappeared(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
char *thingIdStr = nullptr;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "s", &thingIdStr)) {
|
||||||
|
qCWarning(dcThingManager) << "Error parsing parameters";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
ThingId thingId(thingIdStr);
|
||||||
|
PythonIntegrationPlugin *plugin = s_plugins.key(self);
|
||||||
|
QMetaObject::invokeMethod(plugin, "autoThingDisappeared", Qt::QueuedConnection, Q_ARG(ThingId, thingId));
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static PyMethodDef plugin_methods[] =
|
static PyMethodDef plugin_methods[] =
|
||||||
{
|
{
|
||||||
{"configuration", PythonIntegrationPlugin::pyConfiguration, METH_VARARGS, "Get the plugin configuration."},
|
{"configuration", PythonIntegrationPlugin::pyConfiguration, METH_VARARGS, "Get the plugin configuration."},
|
||||||
@ -251,6 +249,7 @@ static PyMethodDef plugin_methods[] =
|
|||||||
{"setConfigValue", PythonIntegrationPlugin::pySetConfigValue, METH_VARARGS, "Set the plugin configuration value for a given config paramTypeId."},
|
{"setConfigValue", PythonIntegrationPlugin::pySetConfigValue, METH_VARARGS, "Set the plugin configuration value for a given config paramTypeId."},
|
||||||
{"myThings", PythonIntegrationPlugin::pyMyThings, METH_VARARGS, "Obtain a list of things owned by this plugin."},
|
{"myThings", PythonIntegrationPlugin::pyMyThings, METH_VARARGS, "Obtain a list of things owned by this plugin."},
|
||||||
{"autoThingsAppeared", PythonIntegrationPlugin::pyAutoThingsAppeared, METH_VARARGS, "Inform the system about auto setup things having appeared."},
|
{"autoThingsAppeared", PythonIntegrationPlugin::pyAutoThingsAppeared, METH_VARARGS, "Inform the system about auto setup things having appeared."},
|
||||||
|
{"autoThingDisappeared", PythonIntegrationPlugin::pyAutoThingDisappeared, METH_VARARGS, "Inform the system about auto setup things having disappeared."},
|
||||||
{nullptr, nullptr, 0, nullptr} // sentinel
|
{nullptr, nullptr, 0, nullptr} // sentinel
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -311,9 +310,9 @@ bool PythonIntegrationPlugin::loadScript(const QString &scriptFile)
|
|||||||
m_module = PyImport_ImportModule(fi.baseName().toUtf8());
|
m_module = PyImport_ImportModule(fi.baseName().toUtf8());
|
||||||
|
|
||||||
if (!m_module) {
|
if (!m_module) {
|
||||||
dumpError();
|
|
||||||
PyErr_Clear();
|
|
||||||
qCWarning(dcThingManager()) << "Error importing python plugin from:" << fi.absoluteFilePath();
|
qCWarning(dcThingManager()) << "Error importing python plugin from:" << fi.absoluteFilePath();
|
||||||
|
PyErr_Print();
|
||||||
|
PyErr_Clear();
|
||||||
PyGILState_Release(s);
|
PyGILState_Release(s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -399,7 +398,6 @@ void PythonIntegrationPlugin::setupThing(ThingSetupInfo *info)
|
|||||||
PyThingSetupInfo *pyInfo = (PyThingSetupInfo*)PyObject_CallObject((PyObject*)&PyThingSetupInfoType, NULL);
|
PyThingSetupInfo *pyInfo = (PyThingSetupInfo*)PyObject_CallObject((PyObject*)&PyThingSetupInfoType, NULL);
|
||||||
pyInfo->info = info;
|
pyInfo->info = info;
|
||||||
pyInfo->pyThing = pyThing;
|
pyInfo->pyThing = pyThing;
|
||||||
Py_INCREF(pyThing);
|
|
||||||
|
|
||||||
m_things.insert(info->thing(), pyThing);
|
m_things.insert(info->thing(), pyThing);
|
||||||
|
|
||||||
@ -417,6 +415,7 @@ void PythonIntegrationPlugin::setupThing(ThingSetupInfo *info)
|
|||||||
|
|
||||||
bool result = callPluginFunction("setupThing", reinterpret_cast<PyObject*>(pyInfo));
|
bool result = callPluginFunction("setupThing", reinterpret_cast<PyObject*>(pyInfo));
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
Py_DECREF(pyThing);
|
||||||
// The python code did not even start, so let's finish (fail) the setup right away
|
// The python code did not even start, so let's finish (fail) the setup right away
|
||||||
info->finish(Thing::ThingErrorSetupFailed);
|
info->finish(Thing::ThingErrorSetupFailed);
|
||||||
}
|
}
|
||||||
@ -425,7 +424,11 @@ void PythonIntegrationPlugin::setupThing(ThingSetupInfo *info)
|
|||||||
void PythonIntegrationPlugin::postSetupThing(Thing *thing)
|
void PythonIntegrationPlugin::postSetupThing(Thing *thing)
|
||||||
{
|
{
|
||||||
PyThing* pyThing = m_things.value(thing);
|
PyThing* pyThing = m_things.value(thing);
|
||||||
callPluginFunction("postSetupThing", reinterpret_cast<PyObject*>(pyThing));
|
Py_INCREF(pyThing);
|
||||||
|
bool success = callPluginFunction("postSetupThing", reinterpret_cast<PyObject*>(pyThing));
|
||||||
|
if (!success) {
|
||||||
|
Py_DECREF(pyThing);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PythonIntegrationPlugin::executeAction(ThingActionInfo *info)
|
void PythonIntegrationPlugin::executeAction(ThingActionInfo *info)
|
||||||
@ -456,8 +459,12 @@ void PythonIntegrationPlugin::executeAction(ThingActionInfo *info)
|
|||||||
void PythonIntegrationPlugin::thingRemoved(Thing *thing)
|
void PythonIntegrationPlugin::thingRemoved(Thing *thing)
|
||||||
{
|
{
|
||||||
PyThing *pyThing = m_things.value(thing);
|
PyThing *pyThing = m_things.value(thing);
|
||||||
|
Py_INCREF(pyThing);
|
||||||
|
|
||||||
callPluginFunction("thingRemoved", reinterpret_cast<PyObject*>(pyThing));
|
bool success = callPluginFunction("thingRemoved", reinterpret_cast<PyObject*>(pyThing));
|
||||||
|
if (!success) {
|
||||||
|
Py_DECREF(pyThing);
|
||||||
|
}
|
||||||
|
|
||||||
m_mutex.lock();
|
m_mutex.lock();
|
||||||
m_things.remove(thing);
|
m_things.remove(thing);
|
||||||
@ -577,12 +584,12 @@ bool PythonIntegrationPlugin::callPluginFunction(const QString &function, PyObje
|
|||||||
{
|
{
|
||||||
PyGILState_STATE s = PyGILState_Ensure();
|
PyGILState_STATE s = PyGILState_Ensure();
|
||||||
|
|
||||||
qCDebug(dcThingManager()) << "Calling python plugin function" << function << "on plugin" << s_plugins.key(m_module)->pluginName();
|
qCDebug(dcThingManager()) << "Calling python plugin function" << function << "on plugin" << pluginName();
|
||||||
PyObject *pFunc = PyObject_GetAttrString(m_module, function.toUtf8());
|
PyObject *pFunc = PyObject_GetAttrString(m_module, function.toUtf8());
|
||||||
if(!pFunc || !PyCallable_Check(pFunc)) {
|
if(!pFunc || !PyCallable_Check(pFunc)) {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
Py_XDECREF(pFunc);
|
Py_XDECREF(pFunc);
|
||||||
qCWarning(dcThingManager()) << "Python plugin does not implement" << function;
|
qCWarning(dcThingManager()) << "Python plugin" << pluginName() << "does not implement" << function;
|
||||||
PyGILState_Release(s);
|
PyGILState_Release(s);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -595,8 +602,8 @@ bool PythonIntegrationPlugin::callPluginFunction(const QString &function, PyObje
|
|||||||
Py_XDECREF(pFunc);
|
Py_XDECREF(pFunc);
|
||||||
|
|
||||||
if (PyErr_Occurred()) {
|
if (PyErr_Occurred()) {
|
||||||
qCWarning(dcThingManager()) << "Error calling python method:";
|
qCWarning(dcThingManager()) << "Error calling python method:" << function << "on plugin" << pluginName();
|
||||||
dumpError();
|
PyErr_Print();
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
PyGILState_Release(s);
|
PyGILState_Release(s);
|
||||||
return false;
|
return false;
|
||||||
@ -651,7 +658,6 @@ void PythonIntegrationPlugin::cleanupPyThing(PyThing *pyThing)
|
|||||||
// on the thing (e.g. PyThing_name).
|
// on the thing (e.g. PyThing_name).
|
||||||
// We'd deadlock if we wait for the mutex forever here. So let's process events
|
// We'd deadlock if we wait for the mutex forever here. So let's process events
|
||||||
// while waiting for it...
|
// while waiting for it...
|
||||||
qWarning() << "Locking cleanup";
|
|
||||||
while (!pyThing->mutex->tryLock()) {
|
while (!pyThing->mutex->tryLock()) {
|
||||||
qApp->processEvents(QEventLoop::EventLoopExec);
|
qApp->processEvents(QEventLoop::EventLoopExec);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,7 @@ public:
|
|||||||
static PyObject* pySetConfigValue(PyObject* self, PyObject* args);
|
static PyObject* pySetConfigValue(PyObject* self, PyObject* args);
|
||||||
static PyObject* pyMyThings(PyObject *self, PyObject* args);
|
static PyObject* pyMyThings(PyObject *self, PyObject* args);
|
||||||
static PyObject* pyAutoThingsAppeared(PyObject *self, PyObject* args);
|
static PyObject* pyAutoThingsAppeared(PyObject *self, PyObject* args);
|
||||||
|
static PyObject* pyAutoThingDisappeared(PyObject *self, PyObject* args);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// python callbacks
|
// python callbacks
|
||||||
|
|||||||
@ -53,15 +53,15 @@ public:
|
|||||||
|
|
||||||
Thing::ThingError status() const;
|
Thing::ThingError status() const;
|
||||||
|
|
||||||
void addThingDescriptor(const ThingDescriptor &thingDescriptor);
|
|
||||||
void addThingDescriptors(const ThingDescriptors &thingDescriptors);
|
|
||||||
|
|
||||||
ThingDescriptors thingDescriptors() const;
|
ThingDescriptors thingDescriptors() const;
|
||||||
|
|
||||||
QString displayMessage() const;
|
QString displayMessage() const;
|
||||||
QString translatedDisplayMessage(const QLocale &locale);
|
QString translatedDisplayMessage(const QLocale &locale);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void addThingDescriptor(const ThingDescriptor &thingDescriptor);
|
||||||
|
void addThingDescriptors(const ThingDescriptors &thingDescriptors);
|
||||||
|
|
||||||
void finish(Thing::ThingError status, const QString &displayMessage = QString());
|
void finish(Thing::ThingError status, const QString &displayMessage = QString());
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|||||||
@ -75,6 +75,7 @@ NYMEA_LOGGING_CATEGORY(dcBluetoothServerTraffic, "BluetoothServerTraffic")
|
|||||||
NYMEA_LOGGING_CATEGORY(dcMqtt, "Mqtt")
|
NYMEA_LOGGING_CATEGORY(dcMqtt, "Mqtt")
|
||||||
NYMEA_LOGGING_CATEGORY(dcTranslations, "Translations")
|
NYMEA_LOGGING_CATEGORY(dcTranslations, "Translations")
|
||||||
NYMEA_LOGGING_CATEGORY(dcI2C, "I2C")
|
NYMEA_LOGGING_CATEGORY(dcI2C, "I2C")
|
||||||
|
NYMEA_LOGGING_CATEGORY(dcPythonIntegrations, "PythonIntegrations")
|
||||||
|
|
||||||
|
|
||||||
static QFile s_logFile;
|
static QFile s_logFile;
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
import nymea
|
import nymea
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
|
watchingAutoThings = False
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
logger.log("Python mock plugin init")
|
logger.log("Python mock plugin init")
|
||||||
|
|
||||||
|
|
||||||
def configValueChanged(paramTypeId, value):
|
def configValueChanged(paramTypeId, value):
|
||||||
logger.log("Plugin config value changed:", paramTypeId, value)
|
logger.log("Plugin config value changed:", paramTypeId, value, watchingAutoThings)
|
||||||
if paramTypeId == pyMockPluginAutoThingCountParamTypeId:
|
if watchingAutoThings and paramTypeId == pyMockPluginAutoThingCountParamTypeId:
|
||||||
logger.log("Auto Thing Count plugin config changed:", value, "Currently there are:", len(autoThings()), "auto things")
|
logger.log("Auto Thing Count plugin config changed:", value, "Currently there are:", len(autoThings()), "auto things")
|
||||||
things = autoThings();
|
things = autoThings();
|
||||||
for i in range(len(things), value):
|
for i in range(len(things), value):
|
||||||
@ -15,20 +17,33 @@ def configValueChanged(paramTypeId, value):
|
|||||||
descriptor = nymea.ThingDescriptor(pyMockAutoThingClassId, "Python Mock auto thing")
|
descriptor = nymea.ThingDescriptor(pyMockAutoThingClassId, "Python Mock auto thing")
|
||||||
autoThingsAppeared([descriptor])
|
autoThingsAppeared([descriptor])
|
||||||
|
|
||||||
for i in range(len(value), things):
|
for i in range(value, len(things)):
|
||||||
logger.log("Removing auto thing")
|
logger.log("Removing auto thing")
|
||||||
autoThingDisappeared(things[i].id)
|
autoThingDisappeared(things[i].id)
|
||||||
|
|
||||||
|
|
||||||
def startMonitoringAutoThings():
|
def startMonitoringAutoThings():
|
||||||
|
global watchingAutoThings
|
||||||
|
watchingAutoThings = True
|
||||||
logger.log("Start monitoring auto things. Have %i auto devices. Need %i." % (len(autoThings()), configValue(pyMockPluginAutoThingCountParamTypeId)))
|
logger.log("Start monitoring auto things. Have %i auto devices. Need %i." % (len(autoThings()), configValue(pyMockPluginAutoThingCountParamTypeId)))
|
||||||
for i in range(len(autoThings()), configValue(pyMockPluginAutoThingCountParamTypeId)):
|
things = autoThings();
|
||||||
|
for i in range(len(things), configValue(pyMockPluginAutoThingCountParamTypeId)):
|
||||||
logger.log("Creating new auto thing")
|
logger.log("Creating new auto thing")
|
||||||
descriptor = nymea.ThingDescriptor(pyMockAutoThingClassId, "Python Mock auto thing")
|
descriptor = nymea.ThingDescriptor(pyMockAutoThingClassId, "Python Mock auto thing")
|
||||||
autoThingsAppeared([descriptor])
|
autoThingsAppeared([descriptor])
|
||||||
|
for i in range(configValue(pyMockPluginAutoThingCountParamTypeId), len(things)):
|
||||||
|
logger.log("Removing auto thing")
|
||||||
|
autoThingDisappeared(things[i].id)
|
||||||
|
|
||||||
logger.log("Done start monitoring auto things")
|
logger.log("Done start monitoring auto things")
|
||||||
|
|
||||||
|
|
||||||
|
async def discoverThings(info):
|
||||||
|
await asyncio.sleep(1)
|
||||||
|
descriptor = nymea.ThingDescriptor(pyMockThingClassId, "Python mock thing")
|
||||||
|
info.addDescriptor(descriptor)
|
||||||
|
info.finish(nymea.ThingErrorNoError)
|
||||||
|
|
||||||
async def setupThing(info):
|
async def setupThing(info):
|
||||||
logger.log("setupThing for", info.thing.name)
|
logger.log("setupThing for", info.thing.name)
|
||||||
info.finish(nymea.ThingErrorNoError)
|
info.finish(nymea.ThingErrorNoError)
|
||||||
|
|||||||
Reference in New Issue
Block a user