Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter
- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
This commit is contained in:
219
tools/EVerest-main/docs/source/tutorials/everest_api.rst
Normal file
219
tools/EVerest-main/docs/source/tutorials/everest_api.rst
Normal file
@@ -0,0 +1,219 @@
|
||||
.. _tutorial_everest_api:
|
||||
|
||||
********************
|
||||
Using the EVerestAPI
|
||||
********************
|
||||
|
||||
.. note::
|
||||
|
||||
Find in-depth explanations about the EVerestAPI :doc:`here <../explanation/adapt-everest/apis>`.
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
The EVerestAPI is designed to remain as stable as possible across different releases of EVerest.
|
||||
It provides JSON-encoded data access via MQTT. The API serves as a stable extension point for applications
|
||||
developed outside the EVerest framework that need to exchange data with it.
|
||||
|
||||
Architecture
|
||||
============
|
||||
|
||||
The EVerestAPI is specified using AsyncAPI 3.0 documents: :doc:`EVerestAPI Reference </reference/api/autogenerated_api_index>`.
|
||||
The individual APIs generally match the internal EVerest interfaces and are implemented as standard EVerest modules.
|
||||
For more details, see the :doc:`EVerestAPI modules reference documentation </reference/modules/API/EVerestAPI/autogenerated>`.
|
||||
|
||||
As a rule of thumb, each internal interface is typically provided by one module.
|
||||
Configuring the required APIs is done by adding the corresponding modules to your EVerest configuration;
|
||||
they connect to other modules using the standard EVerest logic.
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
The ``config/bringup/config-bringup-EVerestAPI-entrypoint.yaml`` configuration file demonstrates the API in action.
|
||||
It does not implement internal functionality, but provides several API and BringUp modules for manual interaction.
|
||||
|
||||
.. hint::
|
||||
|
||||
It is advisable to set the access specification in the configuration to ``allow_global_read: true`` for EVerestAPI modules.
|
||||
This allows the modules to determine if multiple EVerestAPI modules are active, preventing the initial ``ready_beacon``
|
||||
from being sent multiple times.
|
||||
|
||||
Example
|
||||
=======
|
||||
|
||||
First, start an MQTT monitoring tool and subscribe to the ``everest_api/#`` topic.
|
||||
|
||||
Start the example configuration:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
build $ ./run-scripts/run-bringup-EVerestAPI-entrypoint.sh
|
||||
|
||||
You will see the EVerest log alongside two panes showing power supply control UIs.
|
||||
|
||||
A ``everest_api/ready_beacon`` with an empty JSON payload indicates that an EVerestAPI is available.
|
||||
Following this, messages will be periodically published to topics such as:
|
||||
``everest_api/1/power_supply_DC/ps_dc_1/e2m/heartbeat``.
|
||||
|
||||
.. note::
|
||||
|
||||
To exit the tmux session, press ``Ctrl+B`` and then ``d``.
|
||||
|
||||
MQTT Topic Structure
|
||||
====================
|
||||
|
||||
Topics follow the structure: ``everest_api/{api-version}/{api-type}/{instance-id}/{direction}/{api-subtopic}``.
|
||||
|
||||
- **api-version**: Version of the API (e.g., *1*)
|
||||
- **api-type**: Type of the API (e.g., *power_supply_DC*)
|
||||
- **instance-id**: Name of the API instance, allowing multiple instances of the same type (typically the module_id, e.g., *ps_dc_1*)
|
||||
- **{e2m|m2e}**:
|
||||
|
||||
- **e2m**: everest-to-(api-client)-module — Published by EVerest, subscribed to by the client.
|
||||
- **m2e**: (api-client)-module-to-everest — Published by the client, subscribed to by the EVerestAPI.
|
||||
|
||||
- **api-subtopic**: The actual subject of the topic (e.g., *heartbeat*).
|
||||
|
||||
Communication Monitoring
|
||||
========================
|
||||
|
||||
To ensure system reliability, both ends of the communication must know if the other side is still active.
|
||||
Two distinct mechanisms serve this goal.
|
||||
|
||||
Monitoring EVerestAPI Endpoints
|
||||
-------------------------------
|
||||
|
||||
The EVerestAPI module periodically publishes to the topic:
|
||||
``everest_api/{api-version}/{api-type}/{instance-id}/e2m/heartbeat``
|
||||
|
||||
The payload is a periodically incrementing integer. An API client can use this heartbeat to detect
|
||||
if the API module (e.g., *ps_dc_1*) is still alive. The heartbeat interval is defined in the manifest
|
||||
or configuration file via ``cfg_heartbeat_interval_ms``.
|
||||
|
||||
.. tip::
|
||||
|
||||
Look for other heartbeat signals and compare the topic structure to the designators in the configuration file.
|
||||
Observe how different intervals affect the timing in the MQTT logs.
|
||||
|
||||
Monitoring API Clients
|
||||
----------------------
|
||||
|
||||
To enable the EVerestAPI module to detect if a client is still alive, set ``cfg_communication_check_to_s``
|
||||
to a value greater than 0. It is the client application's responsibility to periodically send ``true``
|
||||
(as a raw value, not enclosed in ``{}``) to the following topic:
|
||||
|
||||
``everest_api/{api-version}/{api-type}/{instance-id}/m2e/communication_check``
|
||||
|
||||
If a client fails to check in, the API modules will raise an error within EVerest
|
||||
(e.g., "Error raised, type: generic/CommunicationFault ..."), though they will continue to function on their side.
|
||||
|
||||
.. tip::
|
||||
|
||||
Try clearing errors by sending the appropriate communication check messages, and observe how they are
|
||||
raised again once the timeout expires.
|
||||
|
||||
Request-Reply-Timeout
|
||||
---------------------
|
||||
|
||||
Some modules offer a ``cfg_request_reply_to_s`` parameter. This is used when an EVerestAPI module
|
||||
implements an internal EVerest interface and provides commands to other modules.
|
||||
When another module calls a command on that interface, the following sequence occurs:
|
||||
|
||||
* The API module attempts to fulfill the call by writing to the respective API topic.
|
||||
* The API client (having subscribed to this topic) begins the actual work.
|
||||
* The API client reports completion via the reply topic.
|
||||
* The API module relays this reply back to the internal interface.
|
||||
|
||||
If no reply arrives within the specified timeout, the API module issues a default reply
|
||||
to the internal interface to unblock the calling module.
|
||||
|
||||
The Request-Reply Pattern
|
||||
=========================
|
||||
|
||||
API command calls are asynchronous. Triggering a command and receiving a result are separate events in time.
|
||||
To execute a command, the caller writes a message to the topic defined in the API specification using this JSON structure:
|
||||
|
||||
.. code:: json
|
||||
|
||||
{
|
||||
"headers": {
|
||||
"replyTo": "reply/to/address"
|
||||
},
|
||||
"payload": {}
|
||||
}
|
||||
|
||||
- ``payload``: Required only when calling commands that have non-empty arguments.
|
||||
- ``headers``: Required whenever the caller expects a result. The result is published to the replyTo topic provided by the caller.
|
||||
|
||||
.. note::
|
||||
|
||||
Callers may omit the headers key if they do not require a result and only wish to trigger the command.
|
||||
|
||||
This pattern applies to both directions (API module calling a client command and vice versa).
|
||||
|
||||
entrypoint_API
|
||||
==============
|
||||
|
||||
The **entrypoint_API** allows clients to discover available API endpoints dynamically.
|
||||
|
||||
ready_beacon
|
||||
------------
|
||||
|
||||
The ``everest_api/ready_beacon`` mentioned earlier is part of this discovery system.
|
||||
|
||||
Discovering the API
|
||||
-------------------
|
||||
|
||||
To perform a basic query, send the following JSON to ``everest_api/discover``:
|
||||
|
||||
.. code:: json
|
||||
|
||||
{
|
||||
"headers": {
|
||||
"replyTo": "reply/to/address"
|
||||
}
|
||||
}
|
||||
|
||||
In the example configuration, this results in four individual responses that the client must aggregate.
|
||||
Example response:
|
||||
|
||||
.. code:: json
|
||||
|
||||
{
|
||||
"apis": [
|
||||
{
|
||||
"communication_monitoring": {
|
||||
"communication_check_period_s": 10,
|
||||
"heartbeat_period_ms": 10000
|
||||
},
|
||||
"module_id": "ps_dc_1",
|
||||
"type": "power_supply_DC",
|
||||
"version": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
The modules reply directly from memory; therefore, a 1-second timeout is generally sufficient to gather all replies.
|
||||
Note that the "apis" key contains an array. While usually containing one entry, an API module
|
||||
could implement multiple interfaces and report them all within this array.
|
||||
|
||||
Filtered Queries
|
||||
----------------
|
||||
|
||||
Alternatively, you can restrict responders to a specific type by sending the query to:
|
||||
``everest_api/query-modules/power_supply_DC``
|
||||
|
||||
.. code:: json
|
||||
|
||||
{
|
||||
"headers": {
|
||||
"replyTo": "reply/to/address"
|
||||
}
|
||||
}
|
||||
|
||||
The results will be filtered by the selected API type. Use the returned module_id, type,
|
||||
and version to construct topics as described in the MQTT Topic Structure section.
|
||||
|
||||
.. note::
|
||||
|
||||
Even when using this discovery mechanism, a client must have prior knowledge of the subtopics available for a given API type.
|
||||
Reference in New Issue
Block a user