TL;DR: Click here for the Getting Started documentation!
SensESP is a Signal K sensor development toolkit for the ESP32 platform. If you are a boater (or a professional developer!) who wants to build a custom Wi-Fi connected sensor for your boat, this is the toolkit you need. SensESP runs on commonly available ESP32 boards and helps you get sensor readings from physical sensors and transform them to meaningful data for Signal K or other outputs.
SensESP is built on the Arduino software development framework, a popular open source platform for embedded development. (Note that this refers only to the software stack - Arduino hardware is not supported.) To automate the management of external libraries, it also heavily relies on PlatformIO, a cross-platform build system for embedded devices (in other words, Arduino IDE is not supported).
SensESP features include:
To use SensESP, you need an ESP32 development board and a way to power it from the boat's 12V or 24V nominal power system. This can be done with commonly available ESP32DevKit boards and external DC-DC converters, or alternatively, the Sailor Hat with ESP32 (SH-ESP32) has all these features baked into a developer-friendly board and enclosure kit.
Example use cases of SensESP include:
At heart, SensESP is a development toolkit, and not ready-made software. This means that you will need to do some simple programming to use it. Don't worry, though. The project is newbie-friendly, so you don't need to know much to get started. A lot of examples and tutorials are provided, and some related projects also provide ready-to-use firmware for specific use cases.
To get started, see the project documentation.
For reference, the old SensESP version 1 documentation is still available at the repository wiki.
Discussion about SensESP happens mostly on the Signal K Discord on the #sensesp channel. To register as a new user, follow the invite link at signalk.org.
Another place for SensESP discussions is the discussion board on the SensESP GitHub repository.
WiFiManager replaced with built-in implementation
Web server replaced with ESP-IDF standard implementation
Websockets replaced with ESP-IDF standard implementation
AsyncTCP dependencies removed
RemoteDebug replaced with ESP-IDF debugging macros
Web Frontend rewritten from scratch with Preact and Bootstrap
Remove Startable class
Rename classes:
SensorT
-> Sensor
IntegratorT
-> Integrator
DebounceTemplate
-> Debounce
WSClient
-> SKWSClient
Add a run script to help with SensESP development
Function signature changes:
ValueConsumer::set_input
to ValueConsumer::set
. The value parameter
is now passed as a const reference. The input_channel parameter is removed.Add new transforms:
ExpiringValue
: output value expires after a given time unless updatedRepeat
: repeats the input value at a given intervalRepeatStopping
: repeats the input value at a given interval, stopping after a given timeRepeatExpiring
: repeats the input value at a given interval, expiring after a given time.
RepeatExpiring
outputs an Nullable<T>
value, where the value is invalid/null
after expiration.RepeatConstantRate
: repeats the input value at a constant rate, regardless of input rate.
RepeatConstantRate
outputs an Nullable<T>
value, where the value is invalid/null
after expiration.Join
: joins multiple input values into a single output tuple that is emitted when any inputs are updatedZip
: joins multiple input values into a single output tuple that is emitted when all inputs are updatedThrottle
: limits the rate of output updatesFilter
: emits the input value only if it passes a given testImplement stream producers that emit characters or lines from a stream (e.g., a serial port)
SKEmitter::as_signalk() has been renamed to SKEmitter::as_signalk_json(). It now writes its output to a JsonDocument reference instead of returning a String.
Custom Signal K output is done differently than before. Instead of implementing
an as_signalk()
method in your SKOutput
specialization that returned a
serialized string, you should
implement an as_signalk_json()
method that writes constructs an ArduinoJson
object in the provided JsonObject
reference.
UIOutput
has been renamed to StatusPageItem
. UILambdaOutput
has been
removed. Since StatusPageItem
is now a ValueConsumer
, you can connect
a producer to it.
SemaphoreValue
is a new class that can be used to synchronize access to a
shared value between multiple threads/tasks.
Configurable
base class has been split to Saveable
, Serializable
and
ConfigItem
. Web configuration cards are now only rendered for objects that
have been wrapped in a ConfigItem
call.
Smart pointers are used internally throughout the project. This reduces the risk of memory leaks or crashes due to dangling pointers. It is also possible, but not mandatory, to use smart pointers in your own code.
Internal instrumentation has been improved. Web user interface status page now shows memory usage and event loop statistics.
Update your project's platformio.ini
file to use the new version of SensESP:
lib_deps =
SignalK/SensESP @ >=3.0.0-beta.2,<4
# https://github.com/SignalK/SensESP.git # Use this line to use the latest git version
# symlink:///Users/mairas/src/SignalK/SensESP # Use this line to use a local copy
Adjust the build flags in your project's platformio.ini
file as follows:
build_flags =
-D LED_BUILTIN=2
; Max (and default) debugging level in Arduino ESP32 Core
-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
; Arduino Core bug workaround: define the log tag for the Arduino
; logging macros.
-D TAG='"Arduino"'
; Use the ESP-IDF logging library - required by SensESP.
-D USE_ESP_IDF_LOG
If you have the following in the beginning of your setup()
function:
#ifndef SERIAL_DEBUG_DISABLED
SetupSerialDebug(115200);
#endif
replace it with:
SetupLogging();
Remove the final sensesp_app->start();
call from your setup()
function.
The reactesp
namespace is no longer imported. If you have any references to
classes in this namespace, you will need to update them to use the namespace
explicitly.
Additionally, ReactESP classes have been renamed:
ReactESP
-> reactesp::EventLoop
*Reaction
-> reactesp::*Event
For example, ReactESP
class should be referred to as
reactesp::EventLoop
. In particular, this change probably needs to be made
in your project's main.cpp
file.
ReactESP
is no longer a singleton. Earlier, you could refer to the singleton
instance of ReactESP
using ReactESP::app
. Now, the object pointer is
maintained by the SensESPBaseApp
class, and you can refer to it using
event_loop()
. For example:
event_loop()->onRepeat(
1000,
[]() { Serial.println("Hello, world!"); }
);
Objects inheriting from Configurable
and having a config_path
defined
were automatically added to the web configuration UI. This is no longer the
case. Now, you need to explicitly call ConfigItem
with the object as an
argument. For example:
auto input_calibration = new Linear(1.0, 0.0, "/input/calibration");
ConfigItem(input_calibration)
->set_title("Input Calibration")
->set_description("Analog input value adjustment.")
->set_sort_order(1100);
analog_input->connect_to(input_calibration);
The frontend project is in the frontend
directory tree. To build the frontend,
you need to have Node and pnpm
installed. Install the required dependencies:
./run install-frontend
Then build the frontend:
./run build-frontend
This will both build the project and save the deployment files in C++ source files suitable for embedding in the SensESP firmware.
To start the development server, run:
cd frontend
pnpm run dev