Skip to main content

Client Plugin Description (electricclawplugin-hmi)

Development Environment​

EnvironmentToolchain
WindowsQt 5.15.2, MSVC 2015 64-bit
linux X86GNU Compiler Collection 9.4
linux aarch64gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu

Project Structure​

The code folder contains include and lib folders that provide the plugin environment support and necessary tools. Open the .pro project in Qt Creator and you will see the following project structure.

HMI Project Structure

Description of each part:

ComponentDescription
Configuration file (.pro)Qt compilation configuration file (can be understood as the Qt version of CMake); key configuration below
UI files (.ui)Qt Designer visual layout files; ui_*.h files are generated after building for UI component binding
Code files (.cpp/.h)Declaration and implementation of UI classes, business logic classes, and the plugin entry class
Resource files (.qrc/.ts)Files related to control text translation

Key .pro Configuration​

pro Configuration File

Key configurations in the Electric Claw project .pro related to plugin development:

TEMPLATE = lib                          # Build as a shared library (.dll/.so)
DEFINES += ELECTRICCLAWPLUGIN_LIBRARY # Control export/import symbols
DEFINES += PLUGIN_NAME=\\\"OnrobotPlugin\\\" # Plugin registration name, used for plugin registration
LIBS += -L$$PWD/lib/windows -lxplugin # Link the plugin SDK (xplugin)
INCLUDEPATH += $$PWD/include # SDK header file search path

For general qmake configurations such as QT += widgets, CONFIG += c++11, FORMS, TRANSLATIONS, and RESOURCES, see Create a Simple HMI Plugin.

Code File Composition​

File/ModuleResponsibility
OnrobotPlugin.h/.cppPlugin entry class ElectricClawPlugin: plugin registration, process package UI creation, RL instruction registration
OnrobotWidget.h/.cpp/.uiProcess package main UI class ElectricClawWidget: UI generation, signal-slot binding, init/run/stop control
StatusPoller.h/.cppStatus polling class: queries the claw status at a 200 ms cycle in a child thread and notifies the UI to refresh
JsonWorker.h/.cppJSON instruction worker class: sends plugin instructions asynchronously in the thread pool to avoid blocking the UI
rl/RLStartWidget, RLStopWidget, RLStatusWidgetRL instruction UI classes: generate specific RL scripts from the data of units in the window
OnrobotPlugin_global.hExport symbol macro definition (ELECTRICCLAWPLUGIN_EXPORT)

Core Code Logic​

Plugin Registration​

Plugin registration is declared via a macro in OnrobotPlugin.cpp (PLUGIN_NAME is the OnrobotPlugin defined in the .pro file). After declaration, the plugin class is automatically initialized when the plugin is loaded, and the plugin initialization functions init() and afterInit() are executed in sequence:

XPLUGIN_REGISTER(PLUGIN_NAME, ElectricClawPlugin)

Plugin Entry and UI Registration​

Plugin Entry

In init(), the process package main UI ElectricClawWidget is created and registered as the center widget via CreateCenterWidget:

void xplugin::ElectricClawPlugin::init()
{
m_widget = new ElectricClawWidget;
xplugin::CreateCenterWidget(PLUGIN_NAME, m_widget);
}

Process Package UI (ElectricClawWidget)​

Signal-slot binding and status monitoring startup are completed in the ElectricClawWidget constructor:

  1. Creates a QThread child thread and moves the StatusPoller into it; status polling at a 200 ms cycle starts once the thread starts;
  2. The polling result signal statusUpdated is bound to the UI refresh slot via a queued connection (Qt::QueuedConnection), updating the four display fields: status, force, internal width, and external width;
  3. Sets QIntValidator range limits on each input field (device ID 0–255, force 0–140, speed 20–100, width 160–685).

Button click logic:

ButtonLogic
InitClamps input values first, then sends a stop instruction to the device as a "handshake" check; on success, records the device ID and enables the run/stop buttons and all parameter input fields; on failure, disables them and clears the status display
RunClamps input values, then packs the UI parameters (mode, width, force, speed) and sends a start instruction
StopClamps input values, then packs and sends a stop instruction

In addition, the UI overrides showEvent/hideEvent to start the polling timer when the process package page is shown and stop it when hidden, avoiding unnecessary background polling.

clampLineEdit() clamps input field values to the valid range: non-numeric input is reset to the minimum, and out-of-range values are clamped to the boundaries.

JSON Instruction Sending/Receiving (JsonWorker)​

All UI requests are issued through sendRequest(): a JsonWorker (inheriting QObject + QRunnable) is constructed and submitted to the global thread pool for asynchronous execution; when finished, the finished signal calls back to the UI via a queued connection, avoiding UI thread blocking:

void JsonWorker::run()
{
QJsonArray result = xplugin::xPluginInterface().commandCustomData(nullptr, m_json);
emit finished(result);
}

The JSON protocol sent corresponds one-to-one with the plugin instructions registered by the controller plugin (see Controller Plugin Description):

OperationJSON SentResponse
Stop / init handshake{"ElectricClawPlugin":{"stop":{"slave_id":1}}}{"return":true}
Start{"ElectricClawPlugin":{"start":{"slave_id":1,"mode":1,"width":400,"force":50,"speed":50}}}{"return":true}
Status polling{"ElectricClawPlugin":{"get_status":{"slave_id":1}}}{"status":...,"external_width":...,"internal_width":...,"force":...,"return":true}

Status Polling (StatusPoller)​

StatusPoller runs in the child thread. startPolling() creates a QTimer that triggers pollStatus() every 200 ms:

  • If the device is not initialized (m_is_init == false), it returns directly without sending a request;
  • It packs a get_status instruction and queries via commandCustomData, parses the ElectricClawPlugin → get_status node in the returned array, and emits statusUpdated to the UI thread to refresh the display.

RL Instruction Registration​

RL Instruction Registration

RL Instruction Registration

RL editor instructions (OnrobotMove, OnrobotStop, OnrobotStatus) are registered in the afterInit() function via RLManager. Five items are registered for each instruction:

m_rlManager->createTypeKey("OnrobotMove");                 // Instruction type key
m_rlManager->createSkeleton("OnrobotMove", "OnrobotMove"); // Instruction skeleton
m_rlManager->createInsDescribe("OnrobotMove", tr("...")); // Instruction description
m_rlManager->createPattern("OnrobotMove", "^\\s*...$"); // Matching regex
m_rlManager->createInsertWidget("OnrobotMove", [](){ // Editing widget for insertion
return new xplugin::RLStartWidget("OnrobotMove");
});

Finally, createTypeToGroup groups the three instructions under OnrobotPlugin, and createGroups sets the group display title.

note

What is registered here is only simplified RL writing logic for assisted programming, which does not include RL execution logic; the RL execution logic is implemented in the controller plugin, see Controller Plugin Description.

RL Instruction UI Classes​

RL instruction UI classes inherit RLContentBase and need to implement three interfaces:

InterfacePurpose
ToString()Converts UI control parameters into an instruction string (called when generating the RL script)
FillWith(str)Fills the UI in reverse from an instruction string (this example only prints a debug log; no parsing)
CheckInsert()Determines whether it can be inserted as an output value (this example always returns true)

Example of RLStartWidget::ToString() — reads each control value and concatenates them in the form instruction_name param1,param2,...:

Output forms of the three UI classes:

UI ClassCorresponding InstructionToString Output Example
RLStartWidgetOnrobotMoveOnrobotMove 1,1,400,50,50 (ID, mode, width, force, speed)
RLStopWidgetOnrobotStopOnrobotStop 1 (ID)
RLStatusWidgetOnrobotStatusOnrobotStatus 1,s,e,i,f (ID + 4 combo box texts)

Compilation and Packaging​

  1. Open Qt Creator and select the build type (Release is recommended for distribution).
  2. Compilation process: qmake parses the .pro file to generate the Makefile → jom/make executes compilation → the dynamic library (.dll) is generated.

Compilation Process

  1. After the build completes, the generated dynamic library can be found in the build directory.

Build Output

For packaging specifications and the general process, see Creating the Plugin Package. You can also use the PluginPackage packaging script directly.