mirror of https://github.com/nymea/nymea.git
218 lines
9.9 KiB
Plaintext
218 lines
9.9 KiB
Plaintext
/*!
|
|
\page getting-started-plugins.html
|
|
\title Getting Started
|
|
\brief Understanding the basic concept of guh plugins
|
|
|
|
Plugins in guh are used to exand the functionalitys and capabilitys of the guh server. A plugin is basically a shared library, which will be loaded dynamically from the guh server during the start up process. Each plugin has a \e name, a \e uuid and a list of supported \e vendors which will be visible in the system once the plugin is loaded. Each of thouse \l{Vendor}{Vendors} contains a list of supported \l{DeviceClass}{DeviceClasses}. A \l{DeviceClass} describes how the supported \l{Device} looks like, how it will be created (\l{DeviceClass::CreateMethod}{CreateMethod}), how the setup (\l{DeviceClass::SetupMethod}{SetupMethod}) looks like and what you can do with the \l{Device}.
|
|
|
|
\section1 Devices
|
|
A device in guh can represent a real device, a gateway or even a service like weather. When you want to represent you own device / service in guh, you should try to abstract that device and think in terms like:
|
|
|
|
\list
|
|
\li \l{ParamType}{ParamTypes} \unicode{0x2192} A \l{Device} can have \l{Param}{Params}, which will be needed to set up the device (like IP addresses or device configurations) and give information for the user like name or location. The \l{ParamType} represents the description of an actual \l{Param}.
|
|
\li \l{StateType}{StateTypes} \unicode{0x2192} A \l{Device} can have \l{State}{States}, which basically represent a value of a \l{Device} like \e {current temperature} or \e ON/OFF. The \l{StateType} represents the description of an actual \l{State}.
|
|
\li \l{EventType}{EventTypes} \unicode{0x2192} A \l{Device} can emit \l{Event}{Events}, which basically represent a signal. An example of an \l{Event} could be: \e {Button pressed}. An \l{Event} can have \l{Param}{Params} to give the possibility to pass information with the signal. The \l{EventType} represents the description of an actual \l{Event}.
|
|
\li \l{ActionType}{ActionTypes} \unicode{0x2192} A \l{Device} can execute \l{Action}{Actions}, which represent basically a method for the \l{Device} which the user can execute. An example of an \l{Action} could be: \e {Set temperature}. An \l{Action} can have \l{Param}{Params} to give the possibility to parameterize the action. The \l{ActionType} represents the description of an actual \l{Action}.
|
|
\endlist
|
|
|
|
The \l{DeviceClass} represents the description of an actual \l{Device}.
|
|
|
|
\section1 Hardware resources
|
|
The \e libguh provides a list of \l{Hardware Resources}{HardwareResources}, which can be used in every plugin. When sou start writing a plugin, you need to know which resource you will need. Each resource provides it's own interface for a \l{DevicePlugin}. In the plugin you don't have to take care about the resource.
|
|
|
|
|
|
\section1 Getting started with a plugin
|
|
In order to show how a plugin ist structured here is an example of the most minimalistic device plugin possible for the guh system.
|
|
|
|
|
|
For an easier start we provide a set of plugin templates which can be used for your own plugin and to have a basic for the tutorials described in this documentation. You can get the templates with following command:
|
|
|
|
\code
|
|
$ git clone https://github.com/guh/plugin-templates.git
|
|
\endcode
|
|
|
|
This will create the \tt plugin-templates folder containing all templates and examples you will need to write your own plugin. Let's start with the smallest, simplest plugin.
|
|
|
|
\section2 Basic structure
|
|
|
|
The name of the plugin should be clear and inform about the content in one word. In this first minimalistic example the \b <pluginName> is \e "minimal".
|
|
|
|
The basic structure of the \e minimal plugin looks like this:
|
|
|
|
\code
|
|
$ cd plugin-templates
|
|
$ ls -l minimal/
|
|
|
|
devicepluginminimal.cpp
|
|
devicepluginminimal.h
|
|
devicepluginminimal.json
|
|
minimal.pro
|
|
plugins.pri
|
|
\endcode
|
|
|
|
\section3 minimal.pro
|
|
The \tt minimal.pro file is the project file of the plugin, which can be openend with the \tt{Qt Creator}. The name of this file should be the same as the folder name of the project. In this example the name would be \e "minimal".
|
|
|
|
\code
|
|
include(plugins.pri)
|
|
|
|
TARGET = $$qtLibraryTarget(guh_devicepluginminimal)
|
|
|
|
message("Building $$deviceplugin$${TARGET}.so")
|
|
|
|
SOURCES += \
|
|
devicepluginminimal.cpp \
|
|
|
|
HEADERS += \
|
|
devicepluginminimal.h \
|
|
\endcode
|
|
|
|
The \b TARGET parameter definens the name of the resulting plugin lib file and should should have following name structure:
|
|
|
|
\tt {guh_deviceplugin\b<pluginName>}
|
|
|
|
In this example the pluginname is \e minimal, which means the lib file name will be \e guh_devicepluginminimal.so. You can check the name of the plugin in the "Project Messages" (\tt{alt + 6} in Qt Creator).
|
|
|
|
The \b SOURCES and \b HEADERS variables define the \tt .cpp and \tt .h files of your plugin like in any other Qt project.
|
|
|
|
|
|
|
|
\section3 plugins.pri
|
|
The \tt plugins.pri file contains all relevant definitions and configuration to build a plugin. Each plugin must contain this file and \underline{should not} be changed. In this file the precompiler \b guh-generateplugininfo will be called.
|
|
\code
|
|
TEMPLATE = lib
|
|
CONFIG += plugin
|
|
|
|
QT += network
|
|
|
|
QMAKE_CXXFLAGS += -Werror
|
|
CONFIG += c++11
|
|
|
|
INCLUDEPATH += /usr/include/guh
|
|
LIBS += -lguh
|
|
|
|
infofile.output = plugininfo.h
|
|
infofile.commands = /usr/bin/guh-generateplugininfo ${QMAKE_FILE_NAME} ${QMAKE_FILE_OUT}
|
|
infofile.depends = /usr/bin/guh-generateplugininfo
|
|
infofile.CONFIG = no_link
|
|
JSONFILES = deviceplugin"$$TARGET".json
|
|
infofile.input = JSONFILES
|
|
|
|
QMAKE_EXTRA_COMPILERS += infofile
|
|
|
|
target.path = /usr/lib/guh/plugins/
|
|
INSTALLS += target
|
|
\endcode
|
|
|
|
|
|
If you need an extra Qt module i.e. \tt serialport please add it in the \tt <pluginName>.pro file an not in the \tt plugin.pri:
|
|
\code
|
|
QT += serialport
|
|
\endcode
|
|
|
|
|
|
\section3 devicepluginminimal.json
|
|
The properties of a plugin will be definend with in the \tt JSON file containing all needed information for guh to load it. The name convention fot the json file is:
|
|
|
|
\tt {deviceplugin\b{<pluginName>}.json}
|
|
|
|
This file must have a clear, definend structure and looking like this:
|
|
|
|
\note For more details about the structure, values and Objects please take a look at the \l{The Plugin JSON File} documentation.
|
|
|
|
\code
|
|
{
|
|
"name": "Minimal plugin",
|
|
"idName": "Minimal",
|
|
"id": "6878754a-f27d-4007-a4e5-b030b55853f5",
|
|
"vendors": [
|
|
{
|
|
"name": "Minimal vendor",
|
|
"idName": "minimal",
|
|
"id": "3897e82e-7c48-4591-9a2f-0f56c55a96a4",
|
|
"deviceClasses": [
|
|
{
|
|
"deviceClassId": "7014e5f1-5b04-407a-a819-bbebd11fa372",
|
|
"idName": "minimal",
|
|
"name": "Minimal device",
|
|
"createMethods": ["user"],
|
|
"paramTypes": [
|
|
{
|
|
"name": "name",
|
|
"type": "QString",
|
|
"defaultValue": "Minimal device"
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
\endcode
|
|
|
|
In this minimal example of a device plugin we have one \l{Vendor} ("Minimal vendor") with the VendorId \tt {3897e82e-7c48-4591-9a2f-0f56c55a96a4}, which contains one \l{DeviceClass} with the name "Minimal device". The \l{DeviceClass} has one QString \l{Param} called \e name.
|
|
|
|
\section3 devicepluginminimal.h
|
|
The main header file of the plugin. The naming convention is:
|
|
|
|
\tt {deviceplugin\b<pluginName>.h}
|
|
|
|
In this file you can find the main class of the plugin: \e DevicePluginMinimal. As you can see the \e DevicePluginMinimal inherits from the class \l{DevicePlugin}. You can check out the \l{DevicePlugin} class description to find how a \l{DevicePlugin} looks like.
|
|
|
|
\code
|
|
#ifndef DEVICEPLUGINMINIMAL_H
|
|
#define DEVICEPLUGINMINIMAL_H
|
|
|
|
#include "plugin/deviceplugin.h"
|
|
#include "devicemanager.h"
|
|
|
|
class DevicePluginMinimal : public DevicePlugin
|
|
{
|
|
Q_OBJECT
|
|
|
|
Q_PLUGIN_METADATA(IID "guru.guh.DevicePlugin" FILE "devicepluginminimal.json")
|
|
Q_INTERFACES(DevicePlugin)
|
|
|
|
public:
|
|
explicit DevicePluginMinimal();
|
|
|
|
DeviceManager::HardwareResources requiredHardware() const override;
|
|
DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
|
|
};
|
|
|
|
#endif // DEVICEPLUGINBOBLIGHT_H
|
|
\endcode
|
|
|
|
As you can see this class has two methods which override the corresponding method in the \l{DevicePlugin} class. These two methods are pure virtual, which meas you \underline{must} implement them.
|
|
|
|
\section3 devicepluginminimal.cpp
|
|
The implementation of the \l{DevicePlugin}. The naming convention is:
|
|
|
|
\tt {deviceplugin\b<pluginName>.cpp}
|
|
|
|
\code
|
|
#include "devicepluginminimal.h"
|
|
#include "plugininfo.h"
|
|
|
|
DevicePluginMinimal::DevicePluginMinimal()
|
|
{
|
|
}
|
|
|
|
DeviceManager::HardwareResources DevicePluginMinimal::requiredHardware() const
|
|
{
|
|
return DeviceManager::HardwareResourceNone;
|
|
}
|
|
|
|
DeviceManager::DeviceSetupStatus DevicePluginMinimal::setupDevice(Device *device)
|
|
{
|
|
Q_UNUSED(device)
|
|
qCDebug(dcMinimal) << "setup device" << device->name() << device->id();
|
|
|
|
return DeviceManager::DeviceSetupStatusSuccess;
|
|
}
|
|
\endcode
|
|
|
|
You can start with \l{Tutorial 1 - The "Minimal" plugin}.
|
|
|
|
*/
|