You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
63 lines
4.5 KiB
63 lines
4.5 KiB
\subsection{Multi-Device build infrastructure}
|
|
|
|
The firmware for all \textit{ESP8266} based devices in the hackerspace are all based on the same framework.
|
|
\textit{Sming} provides the base library for this framework.
|
|
In addition, components and functionality shared by all devices has been identified and are providing a framework for the existing and possible further devices.
|
|
This framework provides a functional base for all devices and allows to reuse code providing functionality which is common in multiple devices.
|
|
The framework also includes a build system, which allows to configure some basic parameters for all devices.
|
|
Including, but not limited to, the Wi-Fi access parameters, the \textit{MQTT} connection settings and the updater URLs.
|
|
By sharing the same code, all devices ensure to have a common behavior when it comes to reporting the device status or interacting with the home-automation controller.
|
|
This eases configuration and allows to collect information about all devices at a central location.
|
|
|
|
Each device firmware exists as a separate project and includes a link to the framework.
|
|
As development on these devices happens in cycles, older projects are missing updates of the framework and therefor do not benefit from newly added features or fixed problems.
|
|
Updating the framework version and rebuilding the firmware would often result in an easy gain of these benefits, but requires manual interaction.
|
|
More problems will arise if the application programming interface (API) of the framework changes.
|
|
In this situation, the device firmware must be updated to use the changed API, which can be an unpleasant and complex task and leads to higher latency for firmware updates.
|
|
|
|
To prevent these problems the device firmware of all devices in the hackerspace is now integrated with the framework into a larger project.
|
|
By doing so, each device specific code is always linked to the latest version of the framework.
|
|
Device specific code is now organized as a folder for each device type.
|
|
The build system has been modified to scan for all device specific folders and call the original build process for each of them.
|
|
|
|
|
|
\subsubsection{Framework integration}
|
|
|
|
The framework has been changed to keep control over the application life-cycle.
|
|
It ensures that the device unspecific code is executed at the right time and provides an API for device specific functionality.
|
|
|
|
The framework specifies a simple interface, which must be implemented by each device.
|
|
A single function \texttt{Device* getDevice()} must be defined exactly once in each device specific folder.
|
|
To implement this interface, a static instance of \texttt{Device} is created and returned.
|
|
Each \texttt{Device} is populated with device specific \texttt{Feature} instances.
|
|
While the \texttt{Feature}-API leverages common runtime polymorphism to share functionality between features, the initial \texttt{Device} creation uses compile-time polymorphism which reduces the need for memory management and increases performance by avoiding virtual function tables.
|
|
Listing~\ref{lst:create_device_socket} shows the complete device specific code used for a simple power socket.
|
|
|
|
\begin{lstlisting}[caption={Device specific code for a socket driver.},
|
|
label=lst:create_device_socket]
|
|
#include "Device.h"
|
|
#include "features/Socket.h"
|
|
|
|
Device device:
|
|
|
|
constexpr const char SOCKET_NAME[] = "socket";
|
|
constexpr const uint16_t SOCKET_GPIO = 12;
|
|
OnOffFeature<SOCKET_NAME, SOCKET_GPIO, false, 1> socket(&device);
|
|
|
|
Device* getDevice() {
|
|
return &device;
|
|
}
|
|
\end{lstlisting}
|
|
|
|
|
|
\subsubsection{Build system}
|
|
|
|
The existing \textit{Makefile} has been refactored to accept a parameter for device type identifiers called \texttt{DEVICE} and to create its whole output inside a subdirectory specific to the device type.
|
|
Another \textit{Makefile} has been created which scans a project subdirectory and uses each directory in there as container for device specific code.
|
|
For each of these directories, the other \textit{Makefile} is called and the subdirectories name is used as \texttt{DEVICE} parameter.
|
|
By splitting the build and recompiling the framework each time before intermixing it with the device specific code, the device type identifier can be used inside the shared framework code.
|
|
|
|
While building a devices firmware, the version identifier file used during updates is also created and stored beside the binary firmware image.
|
|
|
|
For development, each device can be build separately by using the device type identifier as \textit{Makefile} target.
|
|
In addition the prefix \texttt{/flash} can be used to flash a specific firmware.
|