Adapt BaseCamp to Specific Product Requirements
APIs
Info
We will add further information here soon.
You can find the API reference pages in the left sidebar. Click on the link "PIONIX BaseCamp API" to get there.
BaseCamp can be extended and adapted to specific needs via two sets of APIs: The internal interfaces and the BaseCamp API.
The BaseCamp API is guaranteed to not introduce breaking changes for the same major version of BaseCamp.
Since BaseCamp features a complete and maintained version of EVerest, it is possible to use EVerest’s internal interfaces. Modules that have been created for EVerest are compatible with BaseCamp. This offers an easy migration path from EVerest to BaseCamp. However, it is important to note that the internal EVerest API is subject to regular changes.
BaseCamp API
Overview
The BaseCamp API is the interface for custom extensions and adaptations. It is provided via a public MQTT interface, and the format for data exchange is plain text JSON. The API is defined in AsyncAPI 3.
Custom client software using the BaseCamp API is therefore only loosely coupled to BaseCamp. There are no obligatory binary or link time dependencies of any kind. As a result, the clients can be built individually and without reference to BaseCamp at all.
This also implies that the programming language used for implementing the client can be chosen freely. Typically a compiled language is preferable for an embedded target, but it is not strictly required at all.
The BaseCamp API is implemented in terms of EVerest modules, and every API module implements one or more EVerest interfaces. There are two distinct versions of API modules, either to implement an interface (e.g. a driver for a DC power supply) or to consume it (e.g. to check for the validation status of a token).
They can be included in the configuration file just like any other module. E.g. - in this example -, a BaseCamp API module was loaded to fulfill the power meter requirement of the EvseManager. The actual code that talks to the power meter hardware to fetch the measurements can now be implemented in a process running outside of BaseCamp (and is started e.g. by a separate systemd unit). It just needs to feed the measured values via MQTT into the powermeter_API module.
For a better understanding of how the BaseCamp API works, let us have an exemplary closer look at the “Power Supply DC” API in BASECAMP/modules/API/power_supply_DC.
The manifest can be reduced to this:
config:
cfg_communication_check_to_s:
type: integer
default: 5
cfg_heartbeat_interval_ms:
type: integer
default: 1000
provides:
if_power_supply_DC:
interface: power_supply_DC
There are two configuration variables which are common for every API module. Both are related to communication checks between BaseCamp and the client module.
Below, there is the provides section, which states that this API module is a DC power supply. This implies that it can be used in the configuration file for BaseCamp wherever a DC power supply is expected.
In a product, this would be the evse_manager requiring a DC power supply. During development or validation it could also be a BringUp module.
In contrast to an integrated driver for actual hardware, the API module creates MQTT topics according to its specification (basecamp/api_specs/{api_type}/asyncapi.yaml) and by this provides hooks for the client to do the implementation work.
Let’s take a look at an example configuration that uses the BaseCampAPI:
active_modules:
ps_dc_1:
module: power_supply_DC_API
config_module:
cfg_communication_check_to_s: 60
cfg_heartbeat_interval_ms: 1000
cli:
module: BUPowerSupplyDC
standalone: true
connections:
psu:
- module_id: ps_dc_1
implementation_id: if_power_supply_DC
It loads two modules: The power_supply_DC_API and the BringUp module for DC power supplies. Starting BaseCamp with this configuration enables the BaseCampAPI for DC power supplies and a BringUp module, that can send to and receive messages from the API. The actual topics on the MQTT will be available under basecamp/api/1.0/power_supply_DC/ps_dc_1/.
It is as simple as this.
As explained previously, the client is only loosely coupled to BaseCamp. As a consequence, BaseCamp cannot know by itself whether the client is available and in good working conditions. For this reason, a bidirectional communication check is available.
BaseCamp sends heartbeat messages periodically (cfg_heartbeat_interval_ms - with negative values disabling heartbeat messages) and on the other hand requires the clients to send communication_check messages within the timeout interval specified (cfg_communication_check_to_s - with negative values disabling the requirement for these messages).
The same timeout interval applies to the expected replies for requests.
AsyncAPI
The BaseCamp API is defined in terms of AsyncAPI 3.0.0.
For a thorough introduction and reference refer to https://www.asyncapi.com.
All BaseCamp API modules are located in BASECAMP/modules/API and each module contains the API definition in its docs/asyncapi.yaml file. These files can be used to generate the HTML-based documentation via the basecamp_api_docs compilation target.
In order to build the documentation, the asyncapi/cli (https://www.asyncapi.com/en/tools/cli) tool has to be available on the development machine.
Another possible way is to use the file in AsyncAPI studio (https://studio.asyncapi.com/).
The asyncapi.yaml is defined for the client implementing the API and reflects the client's point of view, when using the words send and receive in the context of actions and operations.
The MQTT topics of the BaseCamp API follow a fixed pattern. All topics are prefixed with basecamp/api/1.0/{api_type}/{module_id} - with 1.0 being the version and {api_type} the type of the API.
{module_id} is the module id of the API module as configured in the BaseCamp configuration file.
The prefix is followed by the direction of the message. There are two options:
- m2b for messages from the module (client) to BaseCamp and
- b2m for messages from BaseCamp to the module (client).
This is finally followed by the name of the message. Here is a complete example:
basecamp/api/1.0/power_supply_DC/ps_dc_1/m2b/voltage_current
In the example, power_supply_DC is the API type, ps_dc_1 is the module id as configured in the BaseCamp configuration file, the message (m2b) originates from the client and is directed towards BaseCamp. The message name is voltage_current.
AsyncAPI defines channels which carry messages. A channel can be addressed via the topic as defined above. Each channel can in principle carry multiple messages, but concerning BaseCamp API, there is a one-to-one mapping between a message and a channel. A message carries content in the form of payload and possibly headers.
The content type for BaseCamp API is always JSON. The content is individual for each message and defined in components:schemas within the same file or sometimes in a referenced file.
AsyncAPI finally specifies operations on channels. The operations define the action on a specific channel (for BaseCamp API always from the client's point of view), which can be send or receive.
In many situations, the sender of a message is not interested in the receive status of a message, e.g. in a situation where a meter publishes its current values. Simple send and receive operations are used in this case.
There are situations however, where this is not the case, e.g. remote procedure calls or when a reply is requested. BaseCamp API handles this situation with the request/reply pattern offered by AsyncAPI.
The operations are then augmented with a reply property holding the reply channel and a dynamic reply address.
If the client receives a request, it has to reply to the topic provided in the header’s replyTo property within cfg_communication_check_to_s seconds. If it does not, a default response is given by the API to BaseCamp and an error is raised.
If the client sends a request, it has to specify the reply topic, where it expects the answer. This information is communicated via the replyTo property of the headers object. It is the client's responsibility to ensure that the topic is unique in order to relate replies to requests.
Using BaseCamp API
In order to use the BaseCamp API, load the needed API module in the BaseCamp configuration file and connect its interfaces as presented in the Overview section.
The chosen module id becomes part of the MQTT topic. BaseCamp API modules can be loaded multiple times, e.g. if two DC power supplies are connected.
If needed, adjust the heartbeat interval and communication check timeout via the cfg_heartbeat_interval_ms and cfg_communication_check_to_s configuration variables of the module.
Although communication check and heartbeat can be disabled with values smaller or equal to zero, this is not recommended in a production environment, since they are the only way to continuously check whether the client and BaseCamp are online and responsive.
BaseCamp API clients are completely independent applications. They have to be started independently of BaseCamp, possibly by their own systemd service.
BaseCamp cannot start them, since it is agnostic of them. On BaseCamp startup, the API modules raise an initial communication check error (if communication check is enabled). This error is cleared with the first communication check message sent from the client. It is raised again when a timeout occurs or a request is not answered. Sending a communication check message clears the error again.
It is the responsibility of the user to ensure that the client is and remains available. This includes potentially a watchdog that restarts the client in case of crash or deadlock. It is also the client's responsibility to ensure proper initialization, shutdown and surveillance of managed hardware, e.g. a DC power supply.
Examples
BaseCamp comes with a set of examples demonstrating the usage of the APIs. They are located in the folder basecamp/examples/API and available for different programming languages. The intention is to demonstrate the minimal effort required to use the API.
List of BaseCamp APIs
The following APIs are available to implement functionality used by BaseCamp. They are called Providers since they provide functionality to BaseCamp.
- auth_token_provider Used to provide tokens to be validated. Example: RFID reader
- auth_token_validator Used to validate tokens. Example: Connector to authorization server.
- display_message Show messages on a display
- evse_board_support Connector lock, AC RCD, CP/PP
- isolation_monitor Driver for isolation monitor
- power_supply_DC Driver for DC power supply
- powermeter Driver for power meters
- system Firmware updates, upload logs, reboots, ...
The following APIs are available to get information from BaseCamp. They are called Consumers.
- auth_consumer Authentication related events
- error_history_consumer Error status and error status changed events
- evse_manager_consumer Status of EVSE and associated data
- ocpp_consumer Read and write variables and bidirectional data transfer