• 1. The plugin wizard
  • 1. The plugin wizard

    This tutorial shows you how to start a new plugin project using the nymea-qtcreator wizard. You can find the source code of the qt-creator wizard on our github page.

    Create the plugin project

    Once you have installed all packages required for development, you can open the Qt Creator and start a new project. If you need help with the overall Qt Creator project creation, you can find more information here.

    Choose template

    In the template view cou can find now the nymea section. In that section you can find the template for a new plugin.

    Create a new plugin

    Project location

    Choose the project name and the path where the project should be located. As in this example the name is template and will be used within the source code as refference. A good practice is to pick a general describing name like a vendor or product/project name.

    Project location

    Plugin details

    In this section the plugin details can be defined.

    In the first part you can find the c++ specific definitions:

    • Class name: Enter the name of the main class for this device plugin. The naming should be DevicePluginName in camel case.

    In the second part you can find the json specific definitions:

    • Vendor name: Enter the name of the Vendor.
    • Device name: Enter the name for the default device which will be created as template. You can change this any time in the json file.
    • Setup method: Pick the desired setup method for the default device which will be created as template. You can change this any time in the json file. You can find more information in the CreateMethods and SetupMethods section.
    • Create method: Pick the desired create method for the default device which will be created as template. You can change this any time in the json file.
    • Icon: Pick the desired icon for the default device which will be created as template. You can change this any time in the json file.

    See also the CreateMethods and SetupMethods section.

    Plugin details

    Developer information

    Enter the name and email address of the developer for this plugin. These information will be used in the copyright sections of the plugin. The copyright information are placed in the debian/copyright file and in each source code license header.

    Developer information

    Kit selection

    Pick the build kit for this project. The kit must match the version of the nymead and libnymea1 built.

    Note: : You have to make sure you are using the same kit as the nymea daemon and libraries use. If you have installed the nymea library and Qt libraries from you default system package manager, you should probably go with the default kit of your distribution.

    Kit selection

    Project Management

    Here you can select your prefered project management tool. If you choose git, the default .gitignore file will be added to the project.

    Project Management

    Project tree

    Once you finished the plugin wizard, you can start with the development of you plugin.

    Project tree

    Walk trough

    Starting with the new created project you can find following files in you project:

    template.pro

    This is the generated project files of your plugin. If you need additional qt modules or external libraries in your project you can include them normaly using i.e. QT += network or INCLUDEPATH += /path/to/includes and LIBS += -lfoo like in any other Qt project.

    include(/usr/include/nymea/plugin.pri)
    
    TARGET = $$qtLibraryTarget(nymea_deviceplugintemplate)
    
    message(============================================)
    message("Qt version: $$[QT_VERSION]")
    message("Building $$deviceplugin$${TARGET}.so")
    
    SOURCES += \
        deviceplugintemplate.cpp
    
    HEADERS += \
        deviceplugintemplate.h
    • In the first line you can see the gloabl nymea plugin include, where all the nymea plugin related configrations and setting for your plugin project get included.
      include(/usr/include/nymea/plugin.pri)
    • The next line defines the library file name of your plugin. If you change the plugin name, this line has to be updated to.
      TARGET = $$qtLibraryTarget(nymea_deviceplugintemplate)
    • The next section is just for debugging the project configuration and showing you the project name and Qt Version you are building with.
      message(============================================)
      message("Qt version: $$[QT_VERSION]")
      message("Building $$deviceplugin$${TARGET}.so")
    • The SOURCES and HEADERS section shows the included source code files for your project.
      SOURCES += \
          deviceplugintemplate.cpp
      
      HEADERS += \
          deviceplugintemplate.h

    deviceplugintemplate.json

    Here you can find the device plugin interface describing the vendors, devices and plugin information. A detailed description of each section can be found in the The plugin JSON File section.

    {
        "name": "Template",
        "displayName": "Template",
        "id": "00000000-0000-0000-0000-000000000000",
        "vendors": [
            {
                "name": "guh",
                "displayName": "nymea",
                "id": "2062d64d-3232-433c-88bc-0d33c0ba2ba6",
                "deviceClasses": [
                    {
                        "name": "template",
                        "displayName": "Example",
                        "id": "00000000-0000-0000-0000-000000000000",
                        "deviceIcon": "None",
                        "setupMethod": "JustAdd",
                        "createMethods": ["User"],
                        "interfaces": [ ],
                        "basicTags": [ ],
                        "paramTypes": [
    
                        ],
                        "stateTypes":[
    
                        ],
                        "actionTypes":[
    
                        ],
                        "eventTypes":[
    
                        ]
                    }
                ]
            }
        ]
    }

    In the first section you can find the plugin specific properties. The id will be set to zero and must be changed with an actual uuid. The zero uuid is creaed by the plugin template in order to indicate that this field has to be updated.

    {
        "name": "Template",
        "displayName": "Template",
        "id": "00000000-0000-0000-0000-000000000000",
        "vendors": [

    In the vendors section you can see the vendor specific properties. There can be multiple vendors defined in one plugin, each with its own device classes. The uuid of the vendor guh is known, and therefore already filled out. You have to update the vendor uuid, name and id with your plugin information.

            {
                "name": "guh",
                "displayName": "nymea",
                "id": "2062d64d-3232-433c-88bc-0d33c0ba2ba6",
                "deviceClasses": [

    Here you can see the default created deviceclass, showing you the basic structure of a device class.

                    {
                        "name": "template",
                        "displayName": "Example",
                        "id": "00000000-0000-0000-0000-000000000000",
                        "deviceIcon": "None",
                        "setupMethod": "JustAdd",
                        "createMethods": ["User"],
                        "interfaces": [ ],
                        "basicTags": [ ],
                        "paramTypes": [
    
                        ],
                        "stateTypes":[
    
                        ],
                        "actionTypes":[
    
                        ],
                        "eventTypes":[
    
                        ]
                    }

    deviceplugintemplate.h

    The main header file shows you the basic structure of your DevicePlugin template. The header file start with the license header containing the copyright information passed during the wizard.

    /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     *                                                                         *
     *  Copyright (C) 2018 Developer Name <developer.name@example.com>         *
     *                                                                         *
     *  This file is part of nymea.                                            *
     *                                                                         *
     *  This library is free software; you can redistribute it and/or          *
     *  modify it under the terms of the GNU Lesser General Public             *
     *  License as published by the Free Software Foundation; either           *
     *  version 2.1 of the License, or (at your option) any later version.     *
     *                                                                         *
     *  This library is distributed in the hope that it will be useful,        *
     *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
     *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      *
     *  Lesser General Public License for more details.                        *
     *                                                                         *
     *  You should have received a copy of the GNU Lesser General Public       *
     *  License along with this library; If not, see                           *
     *  <http://www.gnu.org/licenses/>.                                        *
     *                                                                         *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    

    The main class has the name DevicePluginExample. The device plugin class inherts from the DevicePlugin class and must implement the pure virtual methods in order build correctly.

    class DevicePluginExample: public DevicePlugin
    {
        Q_OBJECT
    
        Q_PLUGIN_METADATA(IID "io.nymea.DevicePlugin" FILE "deviceplugintemplate.json")
        Q_INTERFACES(DevicePlugin)
    
    public:
        explicit DevicePluginExample();
    
        void init() override;
        void startMonitoringAutoDevices() override;
        void postSetupDevice(Device *device) override;
        void deviceRemoved(Device *device) override;
    
        DeviceManager::DeviceSetupStatus setupDevice(Device *device) override;
        DeviceManager::DeviceError executeAction(Device *device, const Action &action) override;
    
    private:
    
    private slots:
    
    };

    deviceplugintemplate.cpp

    The implementation of each method can be found in the corresponding cpp file.

    As you can see, the plugin includes in the cpp file the plugininfo.h file, which will be generated during build time from the nymea-generateplugininfo tool. This tool translates the deviceplugintemplate.json into a c++ header file containing all uuid definitions, tranlations strings and the debug catergory definition.

    #include "plugininfo.h"

    The main entry point of the plugin is the init() method. This method will be called from the DeviceManager once all plugins are loaded and the initialization phase starts for you all plugins. Here you can start creating your objects in initialize whatever you need. This method can be seen like a constructor.

    void DevicePluginExample::init()
    {
        // Initialize/create objects
    }

    The startMonitoringAutoDevices method will be called from the DeviceManager once all devices are set up and the plugin can start for searching device which appear automatically if your plugin supports such device types.

    void DevicePluginExample::startMonitoringAutoDevices()
    {
        // Start seaching for devices which can be discovered and added automatically
    }

    The postSetupDevice method will be called from the DeviceManager once the setup of a device has finished successfully. Here is a good point to initialize the states of the device.

    void DevicePluginExample::postSetupDevice(Device *device)
    {
        qCDebug(dcTemplate()) << "Post setup device" << device->name() << device->params();
    
        // This method will be called once the setup for device is finished
    }

    The deviceRemoved method will be called from the DeviceManager once a device is about to be removed from the system. Here is a good place to clean up everything releated to the device which will be removed.

    void DevicePluginExample::deviceRemoved(Device *device)
    {
        qCDebug(dcTemplate()) << "Remove device" << device->name() << device->params();
    
        // Clean up all data related to this device
    }

    When the user wants to add a new device from this plugin, the setupDevice() method will be called. Here you can initialize Objects and set up everything you need for your device.

    DeviceManager::DeviceSetupStatus DevicePluginExample::setupDevice(Device *device)
    {
        qCDebug(dcTemplate()) << "Setup device" << device->name() << device->params();
    
        return DeviceManager::DeviceSetupStatusSuccess;
    }

    When the user wants to execute an Action of a Device from this DevicePlugin, the executeAction method will be called. Here you can perform the actual execution of the custom call for your Device.

    DeviceManager::DeviceError DevicePluginExample::executeAction(Device *device, const Action &action)
    {
        qCDebug(dcTemplate()) << "Executing action for device" << device->name() << action.actionTypeId().toString() << action.params();
    
        return DeviceManager::DeviceErrorNoError;
    }

    Files: