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:
Eric F
2026-06-08 00:38:27 -04:00
parent 468cfeaa50
commit d398a6ced2
7326 changed files with 1177561 additions and 7 deletions

View File

@@ -0,0 +1,33 @@
# EVerest Boot Mode Application Logic
The `manager` process retrieves the EVerest configuration, manages module dependencies and communication, and starts EVerest modules as individual processes.
The EVerest configuration can be provided via a YAML file, an SQLite database, or both. This section explains how EVerest starts up depending on the CLI options used:
- `--config`: Full path to the EVerest YAML configuration file.
- `--db`: Full path to the EVerest SQLite configuration database.
- `--db-init`: Indicates that the specified config should be used to initialize the database if it does not exist or does not contain a valid configuration.
Based on these options, there are three possible boot modes:
- **YAML Boot Mode**: The configuration is loaded from a YAML file. This mode is used when only the `--config` argument is provided.
- **Database Boot Mode**: The configuration is loaded from an SQLite database. This mode is used when only the `--db` argument is provided.
- **DatabaseInit Boot Mode**: The configuration is preferably loaded from an SQLite database. If the database does not exist or does not contain a valid EVerest configuration, the YAML file specified by `--config` is used instead, and the configuration is then written to the database. This mode requires all three options: `--config`, `--db`, and `--db-init`. In a subsequent start of the application, the database can be used to retrieve
the configuration.
## Boot Mode Application Logic Flow Chart
```mermaid
flowchart TD
A[Start] --> B[Parse CLI arguments]
B --> C{--config provided}
C -->|yes| D{--db provided}
D -->|yes| E{--db-init provided}
E -->|yes| F[Boot Mode: DatabaseInit]
E -->|no| H[Invalid combination]
D -->|no| J[Boot Mode: YAML]
C -->|no| L{--db provided}
L -->|yes| M[Boot Mode: Database]
L -->|no| O[Invalid combination]
```

View File

@@ -0,0 +1,134 @@
# EVerest Framework MQTT Topic Structure
This document describes the MQTT topic structure used by the EVerest framework for communication between modules.
## Topic Prefix Structure
The EVerest framework uses a configurable MQTT prefixes for topics. This allows multiple instances of EVerest
to run at the same time using the same broker. The default prefix is `everest`.
## 1. Variables (Vars)
The following structure applies for variable topics:
### Topic Structure
```bash
{everest_prefix}modules/{module_id}/impl/{impl_id}/var/{var_name}
```
### Message Payload Structure
The payload contains the actual variable data in the `data` field.
```json
{
"data": <variable_value>
}
```
## 2. Commands (Cmds)
The following structure applies for command topics. Modules that provide (implement) the command subscribe to the command topic, while modules that call the command publish to it. Each command call generates a unique UUID as the call ID. The origin field identifies the calling module. Command handlers process the request and publish responses to a separate response topic.
### Topic Structure
```bash
{everest_prefix}modules/{module_id}/impl/{impl_id}/cmd/{cmd_name}
```
### Message Payload Structure
```json
{
"id": "<unique_call_id>",
"args": {
"arg1": "value1",
"arg2": "value2"
},
"origin": "<calling_module_id>"
}
```
## 3. Command Responses
The following structure applies for command response topics. These are used to send back results or errors from command handlers to the calling module. Response topics include the calling module ID for proper routing. The call ID matches the original command request.
### Topic Structure
```bash
{everest_prefix}modules/{module_id}/impl/{impl_id}/cmd/{cmd_name}/response/{calling_module_id}
```
### Message Payload Structure
#### Successful Response
```json
{
"name": "<cmd_name>",
"type": "result",
"data": {
"id": "<matching_call_id>",
"retval": <return_value>,
"origin": "<responding_module_id>"
}
}
```
#### Error Response
```json
{
"name": "<cmd_name>",
"type": "result",
"data": {
"id": "<matching_call_id>",
"error": {
"event": "<error_type>",
"msg": "<error_message>"
},
"origin": "<responding_module_id>"
}
}
```
### Error Types
Command responses can contain the following error events:
- `MessageParsingFailed`: JSON parsing error
- `SchemaValidationFailed`: Schema validation error
- `HandlerException`: Exception in command handler
- `Timeout`: Command execution timeout
- `Shutdown`: System shutdown
- `NotReady`: Module not ready
## 4. Errors
The following structure applies for error topics. Errors are raised by modules and can be subscribed to by other modules. Each error has a unique UUID and includes information about the originating module, implementation, EVSE, and connector if applicable.
### Topic Structure
```bash
{everest_prefix}modules/{module_id}/impl/{impl_id}/error/{error_type}
```
### Message Payload Structure
```json
{
"type": "<error_namespace>/<error_name>",
"message": "<error_description>",
"severity": "<error_severity>",
"origin": {
"module_id": "<originating_module>",
"implementation_id": "<originating_impl>",
"evse": <evse_number>,
"connector": <connector_number>
},
"state": "<error_state>",
"timestamp": "<iso_timestamp>",
"uuid": "<unique_error_id>"
}
```

View File

@@ -0,0 +1,120 @@
# Module configuration distributed via MQTT
Since everest-framework 0.19.0 the module configuration is parsed once
by the manager and then distributed to the modules via MQTT.
This is achieved by parsing the MQTT settings from the config,
spawning the modules and passing these MQTT settings to them.
The modules themselves then ask for their module config via MQTT,
which is in turn provided to them from the manager.
After the modules have received their config, their init() function is called.
Afterwards they signal ready to the manager.
The manager sends out the global ready signal
once it has received all Module ready signals.
The following sequence diagram illustrates this startup process
```mermaid
sequenceDiagram
create participant manager
create participant ManagerSettings
manager-)ManagerSettings: ManagerSettings(prefix, config_path)
ManagerSettings-->>manager: return ms
create participant ManagerConfig
manager-)ManagerConfig: ManagerConfig(ms)
create participant MQTTAbstraction
manager-)MQTTAbstraction: MQTTAbstraction(ms.mqtt_settings)
MQTTAbstraction-->>manager: return mqtt_abstraction
activate manager
manager->>manager: start_modules()
manager->>ManagerConfig: serialize()
ManagerConfig-->>manager: serialized_config
manager->>MQTTAbstraction: publish(interfaces, types, schemas, manifests, settings, retain=true)
loop For every module
manager->>manager: spawn_modules(Module)
create participant Module
manager->>Module: spawn Module
Module->>MQTTAbstraction: get(Config)
MQTTAbstraction->>manager: get(Config of Module)
manager-->>MQTTAbstraction: publish(module configs, mappings)
MQTTAbstraction-->>Module: publish(module configs, mappings)
Module->>Module: init
Module->>MQTTAbstraction: publish(ready)
MQTTAbstraction->>manager: publish(ready of Module)
end
manager->>MQTTAbstraction: publish global ready
```
Class diagram
```mermaid
classDiagram
ConfigBase <|-- ManagerConfig
ConfigBase <|-- Config
MQTTSettings *-- ConfigBase
ManagerSettings *-- ManagerConfig
note for ConfigBase "
Baseclass containing json config, manifests, interfaces,
types and functions to access this information which
needs to be available in all derived classes
"
class ManagerSettings{
+fs::path configs_dir
+fs::path schemas_dir
+fs::path interfaces_dir
+fs::path types_dir
+fs::path errors_dir
+fs::path config_file
+fs::path www_dir
+int controller_port
+int controller_rpc_timeout_ms
+std::string run_as_user
+std::string version_information
+nlohmann::json config
+MQTTSettings mqtt_settings
+std::unique_ptr<RuntimeSettings> runtime_settings
+ManagerSettings(const std::string& prefix, const std::string& config)
+const RuntimeSettings& get_runtime_settings()
}
class MQTTSettings{
+std::string broker_socket_path
+std::string broker_host
+int broker_port
+std::string everest_prefix
+std::string external_prefix
+bool uses_socket()
}
class ConfigBase{
#const MQTTSettings mqtt_settings
+ConfigBase(const MQTTSettings& mqtt_settings)
}
class ManagerConfig{
-const ManagerSettings& ms
+ManagerConfig(const ManagerSettings& ms)
+nlohmann::json serialize()
-load_and_validate_manifest(const std::string& module_id, const nlohmann::json& module_config)
-std::tuple~nlohmann::json, int64_t~ load_and_validate_with_schema(const fs::path& file_path, const nlohmann::json& schema)
-nlohmann::json resolve_interface(const std::string& intf_name)
-nlohmann::json load_interface_file(const std::string& intf_name)
-resolve_all_requirements()
-parse(nlohmann::json config)
}
class Config{
+Config(const MQTTSettings& mqtt_settings, nlohmann::json config)
+bool module_provides(const std::string& module_name, const std::string& impl_id);
+nlohmann::json get_module_cmds(const std::string& module_name, const std::string& impl_id)
+nlohmann::json resolve_requirement(const std::string& module_id, const std::string& requirement_id)
+std::list~Requirement~ get_requirements(const std::string& module_id)
+RequirementInitialization get_requirement_initialization(const std::string& module_id)
+ModuleConfigs get_module_configs(const std::string& module_id)
+nlohmann::json get_module_json_config(const std::string& module_id)
+ModuleInfo get_module_info(const std::string& module_id)
+std::optional~<~TelemetryConfig~ get_telemetry_config()
+nlohmann::json get_interface_definition(const std::string& interface_name) const;
}
```

View File

@@ -0,0 +1,3 @@
# Additional documentation about the inner workings of EVerest Framework
[MQTT Config distribution](MQTTConfigDistribution.md)