This blog post explains how to extend the Machineface 3D printer UI with a custom UI element that interacts with HAL. For this purpose, this article explains the core concepts of HAL remote.
The blog post is a continuation of Controlling TP-Link HS100/110 Smart Plugs with Machinekit.
HAL remote is a remote API for the Machinekit HAL (Hardware Abstraction Layer). HAL bases on reusable assets called components. These components can either be real-time or userland components.
HAL remote extends this concept by adding HAL remote components. HAL remote components do not have an instance handled by HAL. Instead, they are instantiated via a remote API.
This concept allows mapping HAL remote components into the UI. For example, a HAL pin is represented by a button UI element. When pressing the button in the UI the pin value automatically changes in HAL.
The API or middleware behind HAL remote is called Machinetalk. It uses following de-facto standard technologies:
For now, I will not go into more details about Machinetalk.
To extend Machineface, you need a local copy of the Git repository. I recommend you to start by forking the Machineface repository on GitHub.
Then check out your forked repository locally.
git clone https://github.com/yourusername/Machineface.git
For editing the Machineface user interface I prefer using Qt Creator. Qt Creator comes with the Qt SDK.
You do not necessarily need to install the Qt SDK and to build QtQuickVcp. However, it helps when developing QtQuickVcp UIs. For install instructions, please take a look at the README.
Additionally, I prefer working with qmllive. A live coding environment for QML. This tool automatically reloads the UI source code whenever the file system is modified.
If you plan to use any other text editor you need to edit the Machineface source code on the Machinekit target device. Furthermore, you need to use
configserver to remotely deploy the files to the Machinekit Client
Adding a remote component to HAL
Once we have a working development setup, it is time to modify the HAL configuration. For this purpose, we need to extend the
setup_smartplugs function created in the last blog post.
Remember that we used a Python HAL configuration. The code that creates the HAL remote component for controlling the smart-plugs looks as follows.
rcomp = hal.RemoteComponent('smartplug-control', timer=100)
rcomp.newpin('power-enable', hal.HAL_BIT, hal.HAL_IO)
rcomp.newpin('fan-enable', hal.HAL_BIT, hal.HAL_IO)
rcomp.newpin('power', hal.HAL_FLOAT, hal.HAL_IN)
rcomp.newpin('energy', hal.HAL_FLOAT, hal.HAL_IN)
The first line creates a new HAL remote component and assigns it the
The first argument
'smartplug-control' of the Python class initializer is the name of the component.
timer argument specifies how often the remote component values are sent to the remote clients.
In the following lines, we add new HAL pins to the component.
- power-enable - to toggle the power plug
- fan-enable - to toggle the fan plug
- power - for monitoring the power consumption
- energy - for monitoring the energy consumption
ready function call tells the haltalk HAL remote service provider, to release the remote component.
Once created, it is possible to use the HAL remote component like any other HAL component.
For more details, please take a look at the complete source code on GitHub.
Adding a HAL remote component to Machineface
Next, it is time to add new UI elements and a new HAL remote component to Machineface.
./Machineface directory inside the Machineface repository contains all UI components of the Machineface UI.
QML is organized into
.qml files. Each file contains one root component with the name of the file. For example,
LightControl.qml contains the
LightControl QML component.
DisplayPanel component contains the display panel on the right side of Machineface. An ideal place to add a new control element.
DisplayPanel already contains some HAL remote component based controls, namely:
These components are a perfect starting point for adding new control elements to Machineface. I encourage you to take a look at these components if you interested in learning how to add new controls to Machineface.
Based on these components I added a new QML file called
SmartplugControl.qml. I will now go over the most important parts of the code. I recommend you to take a look at the complete source code on GitHub.
First of all, we need a HAL remote component.
import Machinekit.HalRemote 1.0
ready: (halrcmdService.ready && halrcompService.ready) || connected
onErrorStringChanged: console.log(componentName + " " + errorString)
onConnectedChanged: root.wasConnected = true
The first line imports the HalRemote QtQuick module.
The HalRemoteComponent represents the HAL remote component in QtQuickVcp. The
halrcompUri properties specify the ZeroMQ service URIs. In this case, the component references to properties in a parent object.
When both services are ready the
ready property is set to
true. The component tried to connect to a remote Machinekit instance.
Also important is the
name property, since it has to match the name of the remote component in HAL.
create property tells QtQuickVcp to throw an error if no remote instance of the component exists.
You may wonder how the HalRemoteComponent matches pins to UI controls such as buttons. The QML item passed to the
containerItem property is searched for
HalRemote.Controls when the component becomes
container item we can find following controls:
Layout.preferredWidth: root.width * 0.4
text: energyPin.value.toFixed(2) + "kWh"
The HalPin item is a non-visible QML item representing a single HAL pin.
direction have the same meaning as for regular HAL pins. Note that direction
In means that a signal can drive this HAL pin.
value property of the
energyPin is then used as a source for the
text property of the TextField.
The HalSwitch component is a combination of the Switch UI element and a HalPin. The
checked property of the switch binds automatically to the HAL pin with the name
The resulting control element looks as follows:
I cannot go into full details of how to implement a QtQuick/QML component here. If you are interested in this topic, I recommend you starting with the QML tutorial.
Concluding, this blog article explains how to extend Machineface with a new UI control. Furthermore, it explains some concepts of HAL remote and QtQuickVcp.
I hope this blog post has been useful for you. If you have questions about HAL remote or want to give feedback, please comment on this post.