From 7dd9249726f6b0f13e70f120a25819ad24bd9d08 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Mon, 30 Sep 2024 10:47:48 -0400 Subject: [PATCH 001/134] Create OCPP-1-6.md Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- OCPP-1-6.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 OCPP-1-6.md diff --git a/OCPP-1-6.md b/OCPP-1-6.md new file mode 100644 index 000000000..5c5499e2b --- /dev/null +++ b/OCPP-1-6.md @@ -0,0 +1 @@ +place holder for now From dc8e5116a76de612922f8930169ab4af0fd23a97 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Mon, 30 Sep 2024 10:48:43 -0400 Subject: [PATCH 002/134] Create OCPP-2-0-1.md Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- OCPP-2-0-1.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 OCPP-2-0-1.md diff --git a/OCPP-2-0-1.md b/OCPP-2-0-1.md new file mode 100644 index 000000000..5c5499e2b --- /dev/null +++ b/OCPP-2-0-1.md @@ -0,0 +1 @@ +place holder for now From d2907b41cd6ac4d431eff9b46e7a9c4dd7584c30 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:19:37 -0400 Subject: [PATCH 003/134] Update OCPP-1-6.md curating OCPP 1.6 content only Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- OCPP-1-6.md | 656 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 655 insertions(+), 1 deletion(-) diff --git a/OCPP-1-6.md b/OCPP-1-6.md index 5c5499e2b..a4d896290 100644 --- a/OCPP-1-6.md +++ b/OCPP-1-6.md @@ -1 +1,655 @@ -place holder for now +# C++ implementation of OCPP 1.6 +![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) + +This is a C++ library implementation of OCPP for version 1.6 +(see [OCPP protocols at OCA website](https://openchargealliance.org/protocols/open-charge-point-protocol/)). + +It enables charging stations to communicate with cloud backends for remote +control, monitoring and billing of charging processes. + +Libocpp can be used for the communication of one charging station and multiple EVSE using a single websocket connection. + +Libocpp provides a complete implementation of OCPP 1.6. + +## Get Involved + +See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. + +## Table of contents + +- [Feature Profile Support OCPP 1.6](#feature-profile-support-ocpp-16) +- [CSMS Compatibility OCPP 1.6](#csms-compatibility-ocpp-16) +- [Integration with EVerest](#integration-with-everest) + - [Run OCPP1.6 with EVerest](#run-ocpp16-with-everest) + - [Integrate this library with your Charging Station Implementation for OCPP1.6](#integrate-this-library-with-your-charging-station-implementation-for-ocpp16) + - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) + - [ChargePoint() constructor](#chargepoint-constructor) + - [registering callbacks](#registering-callbacks) + - [Functions that need to be triggered from the outside after new information is availble (on\_... functions in the charge point API)](#functions-that-need-to-be-triggered-from-the-outside-after-new-information-is-availble-on_-functions-in-the-charge-point-api) + - [The following functions are triggered depending on different so called "Session Events" from the EvseManager](#the-following-functions-are-triggered-depending-on-different-so-called-session-events-from-the-evsemanager) + - [Authorization](#authorization) + - [Install libocpp](#install-libocpp) + - [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) + - [Building the doxygen documentation](#building-the-doxygen-documentation) + - [Unit testing](#unit-testing) + - [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) + - [Support for security profile 2 and 3 with TPM in OCPP 1.6 using libwebsockets](#support-for-security-profile-2-and-3-with-tpm-in-ocpp-16-using-libwebsockets) + +## OCPP 1.6 Support + +The following tables show the current support for the listed OCPP 1.6 feature profiles / functional blocks and application notes. + +All documentation and the issue tracking can be found in our main repository here: https://github.com/EVerest/ + +### Feature Profile Support OCPP 1.6 + +| Feature Profile | Supported | +| -------------------------- | ------------------------- | +| Core | :heavy_check_mark: yes | +| Firmware Management | :heavy_check_mark: yes | +| Local Auth List Management | :heavy_check_mark: yes | +| Reservation | :heavy_check_mark: yes | +| Smart Charging | :heavy_check_mark: yes | +| Remote Trigger | :heavy_check_mark: yes | + +| Whitepapers & Application Notes | Supported | +| ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | +| [OCPP 1.6 Security Whitepaper (3rd edition)](https://www.openchargealliance.org/uploads/files/OCPP-1.6-security-whitepaper-edition-3.zip) | :heavy_check_mark: yes | +| [Using ISO 15118 Plug & Charge with OCPP 1.6](https://www.openchargealliance.org/uploads/files/ocpp_1_6_ISO_15118_v10.pdf) | :heavy_check_mark: yes | +| [OCPP & California Pricing Requirements](https://www.openchargealliance.org/uploads/files/ocpp_and_dms_evse_regulation-v2.0.pdf) | :heavy_check_mark: yes | + +## CSMS Compatibility + +### CSMS Compatibility OCPP 1.6 + +The EVerest implementation of OCPP 1.6 has been tested against the +OCPP Compliance Test Tool (OCTT and OCTT2) during the implementation. + +The following table shows CSMS with which this library was tested. +If you provide a CSMS that is not yet listed here, feel free to +[contact us](https://lists.lfenergy.org/g/everest)! + +- chargecloud +- chargeIQ +- Chargetic +- Compleo +- Current +- Daimler Truck +- ev.energy +- eDRV +- Fastned +- [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) +- Electrip Global +- EnergyStacks +- EV-Meter +- Fraunhofer IAO (ubstack CHARGE) +- Green Motion +- gridundco +- ihomer (Infuse CPMS) +- iLumen +- JibeCompany (CharlieV CMS and Chargebroker proxy) +- MSI +- PUMP (PUMP Connect) +- Scoptvision (Scopt Powerconnect) +- Siemens +- [SteVe](https://github.com/steve-community/steve) +- Syntech +- Trialog +- ubitricity +- Weev Energy + +## Integration with EVerest + +This library is automatically integrated as the OCPP and OCPP201 module within [everest-core](https://github.com/EVerest/everest-core) - the complete software stack for your charging station. It is recommended to use EVerest together with this OCPP implementation. + +### Run OCPP1.6 with EVerest + +If you run libocpp with OCPP1.6 with EVerest, the build process of [everest-core](https://github.com/EVerest/everest-core) will take care of installing all necessary dependencies for you. + +## Integrate this library with your Charging Station Implementation for OCPP + +OCPP is a protocol that affects, controls and monitors many areas of a charging station's operation. + +If you want to integrate this library with your charging station implementation, you have to register a couple of **callbacks** and integrate **event handlers**. This is necessary for the library to interact with your charging station according to the requirements of OCPP. + +Libocpp needs registered **callbacks** in order to execute control commands defined within OCPP (e.g Reset.req or RemoteStartTransaction.req) + +The implementation must call **event handlers** of libocpp so that the library can track the state of the charging station and trigger OCPP messages accordingly (e.g. MeterValues.req , StatusNotification.req) + +Your reference within libocpp to interact is a single instance to the class [ChargePoint](include/ocpp/v16/charge_point.hpp) for OCPP 1.6. + +### Overview of the required callbacks and events and what libocpp expects to happen + +The following section will give you a high level overview of how to integrate libocpp with your application. Please use the [Doxygen Documentation](#building-the-doxygen-documentation) as an additional source for the ChargePoint API. + +In EVerest the OCPP module leverages several other modules to perform tasks that relate to authorization, reservations, charging session handling and system tasks like rebooting or firmware updates. + +- Auth orchestrates authorization, utilizing different token providers like RFID reads and token validators. Libocpp mainly acts as a token validator, but in the case of RemoteStartTransactions it acts as a token provider as well +- EvseManager manages the charging session and charging state machine by communicating with a "board support package", a driver for the charging hardware that abstracts away the control pilot, relay control, power meters, etc. The EvseManager also handles reservations. +- System handles firmware updates, log uploads and resets + +The following sections explain the steps you can follow to implement their functionality on your own and integrate the libocpp directly into your charging station software without relying on EVerest. However, in most cases it's much easier to write an EVerest driver using the *everest-core/interfaces/board_support_AC.yaml* interface. + +### Usage for OCPP 1.6 + +#### ChargePoint() constructor + +The main entrypoint for libocpp for OCPP1.6 is the ocpp::v16::ChargePoint constructor. +This is defined in libocpp/include/ocpp/v16/charge_point.hpp and takes the following parameters: + +- config: a std::string that contains the libocpp 1.6 config. There are example configs that work with a [SteVe](https://github.com/steve-community/steve) installation [running in Docker](https://github.com/EVerest/everest-utils/tree/main/docker/steve), for example: [config-docker.json](config/v16/config-docker.json) + +- share_path: a std::filesystem path containing the path to the OCPP modules folder, for example pointing to */usr/share/everest/modules/OCPP*. This path contains the following files and directories and is installed by the libocpp install target: + + ```bash + . + ├── config-docker.json + ├── config-docker-tls.json + ├── config.json + ├── init.sql + ├── logging.ini + └── profile_schemas + ├── Config.json + ├── Core.json + ├── FirmwareManagement.json + ├── Internal.json + ├── LocalAuthListManagement.json + ├── PnC.json + ├── Reservation.json + ├── Security.json + ├── SmartCharging.json + └── Custom.json + ``` + + Here you can find: + - the aforementioned config files + + - a *logging.ini* that is needed to initialize logging with Everest::Logging::init(path_to_logging_ini, "name_of_binary") + + - a *init.sql* file which contains the database schema used by libocpp for its sqlite database + + - and a *profile_schemas* directory. This contains json schema files that are used to validate the libocpp config. The schemas are split up according to the OCPP1.6 feature profiles like Core, FirmwareManagement and so on. Additionally there is a schema for "Internal" configuration options (for example the ChargePointId, or CentralSystemURI). A "PnC" schema for the ISO 15118 Plug & Charge with OCPP 1.6 Application note, a "Security" schema for the OCPP 1.6 Security Whitepaper (3rd edition) and an exemplary "Custom" schema are provided as well. The Custom.json could be modified to be able to add custom configuration keys. Finally there's a Config.json schema that ties everything together + +- user_config_path: this points to a "user config", which we call a configuration file that's merged with the config that's provided in the "config" parameter. Here you can add, remove and overwrite settings without modifying the config passed in the first parameter directly. This is also used by libocpp to persistently modify config entries that are changed by the CSMS that should persist across restarts. + +- database_path: this points to the location of the sqlite database that libocpp uses to keep track of connector availability, the authorization cache and auth list, charging profiles and transaction data + +- sql_init_path: this points to the aforementioned init.sql file which contains the database schema used by libocpp for its sqlite database + +- message_log_path: this points to the directory in which libocpp can put OCPP communication logfiles for debugging purposes. This behavior can be controlled by the "LogMessages" (set to true by default) and "LogMessagesFormat" (set to ["log", "html", "session_logging"] by default, "console" and "console_detailed" are also available) configuration keys in the "Internal" section of the config file. Please note that this is intended for debugging purposes only as it logs all communication, including authentication messages. + +- evse_security: this is a pointer to an implementation of the [evse_security](include/ocpp/common/evse_security.hpp) interface. This allows you to include your custom implementation of the security related operations according to this interface. If you set this value to nullptr, the internal implementation of the security related operations of libocpp will be used. In this case you need to specify the parameter security_configuration + +- security_configuration: this parameter should only be set in case the evse_security parameter is nullptr. It specifies the file paths that are required to set up the internal evse_security implementation. Note that you need to specify bundle files for the CA certificates and directories for the certificates and keys + + The directory layout expected is as follows + + ```bash + . + ├── ca + │ ├── csms + │ │ └── CSMS_ROOT_CA.pem + │ ├── cso + │ │ ├── CPO_CERT_CHAIN.pem + │ │ ├── CPO_SUB_CA1_LEAF.der + │ │ ├── CPO_SUB_CA1.pem + │ │ ├── CPO_SUB_CA2_LEAF.der + │ │ └── CPO_SUB_CA2.pem + │ ├── mf + │ │ └── MF_ROOT_CA.pem + │ ├── mo + │ │ ├── INTERMEDIATE_MO_CA_CERTS.pem + │ │ ├── MO_ROOT_CA.der + │ │ ├── MO_ROOT_CA.pem + │ │ ├── MO_SUB_CA1.der + │ │ ├── MO_SUB_CA1.pem + │ │ ├── MO_SUB_CA2.der + │ │ └── MO_SUB_CA2.pem + │ └── v2g + │ ├── V2G_ROOT_CA.der + │ └── V2G_ROOT_CA.pem + ├── client + │ ├── csms + │ │ ├── CPO_CERT_CHAIN.pem + │ │ ├── CPO_SUB_CA1.key + │ │ ├── CPO_SUB_CA2.key + │ │ ├── SECC_LEAF.der + │ │ ├── SECC_LEAF.key + │ │ └── SECC_LEAF.pem + │ ├── cso + │ │ ├── CPO_CERT_CHAIN.pem + │ │ ├── CPO_SUB_CA1.key + │ │ ├── CPO_SUB_CA2.key + │ │ ├── SECC_LEAF.der + │ │ ├── SECC_LEAF.key + │ │ └── SECC_LEAF.pem + │ └── v2g + │ └── V2G_ROOT_CA.key + ``` + +#### registering callbacks + +You can (and in many cases MUST) register a number of callbacks so libocpp can interact with the charger. In EVerest most of this functionality is orchestrated by the "EvseManager" module, but you can also register your own callbacks interacting directly with your chargers software. Following is a list of callbacks that you must register and a few words about their purpose. + +TODO: in a future version of libocpp the callbacks will be organised in a struct with optional members emphasizing the required and optional callbacks. + +Some general notes: the "connector" parameter of some of the callbacks refers to the connector number as understood in the OCPP 1.6 specification, "0" means the whole charging station, the connectors with EVSEs used for charging cars start at "1". + +- `register_pause_charging_callback` + + this callback is used by libocpp to request pausing of charging, the "connector" parameter tells you which connector/EVSE has to pause charging + +- `register_resume_charging_callback` + + this callback is used by libocpp the request resuming of charging, the "connector" parameter tells you which connector/EVSE can resume charging + +- `register_stop_transaction_callback` + + in EVerest this calls the EvseManagers stop_transaction command which "Stops transactions and cancels charging externally, charging can only be resumed by replugging car. EVSE will also stop transaction automatically e.g. on disconnect, so this only needs to be called if the transaction should end before." + this will then signal the following events: + - ChargingFinished + - TransactionFinished + +- `register_unlock_connector_callback` + + can be used by libocpp to force unlock a connector + +- `register_reserve_now_callback` + + libocpp can use this to reserve a connector, reservation handling is outsourced to a reservation manager in EVerest that implements the reservation interface (everest-core/interfaces/reservation.yaml) + +- `register_upload_diagnostics_callback` + + uses a function (in EVerest provided by the System module) to upload the requested diagnostics file + +- `register_upload_logs_callback` + + uses a function (in EVerest provided by the System module) to upload the requested log file + +- `register_update_firmware_callback` + + uses a function (in EVerest provided by the System module) to perform a firmware update + +- `register_signed_update_firmware_callback` + + uses a function (in EVerest provided by the System module) to perform a signed firmware update + +- `register_provide_token_callback` + + this callback is used in a remote start transaction to provide a token (prevalidated or not) to the authorization system + +- `register_set_connection_timeout_callback` + + used by libocpp to set the authorization or plug in connection timeout in the authorization system based on the "ConnectionTimeout" configuration key + +- `register_disable_evse_callback` + + used to disable the EVSE (ChangeAvailability.req) + +- `register_enable_evse_callback` + + used to enable the EVSE (ChangeAvailability.req) + +- `register_cancel_reservation_callback` + + used to cancel a reservation in the reservation manager (CancelReservation.req) + +- `register_signal_set_charging_profiles_callback` + + used to signal that new charging schedule(s) have been set, you can then use + get_all_composite_charging_schedules(duration_s) to get the new valid charging schedules + +- `register_is_reset_allowed_callback` + + used to inquire (in EVerest from the System module) if a reset is allowed + +- `register_reset_callback` + + used to perform a reset of the requested type + +- `register_connection_state_changed_callback` + + used to inform about the connection state to the CSMS (connected = true, disconnected = false) + +- `register_configuration_key_changed_callback` + + used to react on a changed configuration key. This callback is called when the specified configuration key has been changed by the CSMS + +#### Functions that need to be triggered from the outside after new information is availble (on_... functions in the charge point API) + +- `on_log_status_notification(int32_t request_id, std::string log_status)` + + can be used to notify libocpp of a log status notification + +- `on_firmware_update_status_notification(int32_t request_id, std::string firmware_update_status)` + + can be used to notify libocpp of a firmware update status notification + +- `on_meter_values(int32_t connector, const Powermeter& powermeter)` + + provides a Powermeter struct to libocpp (for sending meter values during charging sessions or periodically) + +- `on_max_current_offered(int32_t connector, int32_t max_current)` + + the maximum current offered to the EV on this connector (in ampere) + +#### The following functions are triggered depending on different so called "Session Events" from the EvseManager + +each of these functions will have a small note what the Session Event was and what it triggers in libocpp + +- `on_enabled(int32_t connector)` + + Notifies libocpp that the connector is functional and operational + +- `on_disabled(int32_t connector)` + + Notifies libocpp that the connector is disabled + +- `on_transaction_started` + + Notifies libocpp that a transaction at the given connector has started, this means that authorization is available and the car is plugged in. + + Some of its parameters: + + - `session_id` is an internal session_id originating in the EvseManager to keep track of the transaction, this is NOT to be mistaken for the transactionId from the StartTransactionResponse in OCPP! + - `id_token` is the token with which the transaction was authenticated + - `meter_start` contains the meter value in Wh for the connector at start of the transaction + - `timestamp` at the start of the transaction + +- `on_transaction_stopped` + + Notifies libocpp that the transaction on the given connector with the given reason has been stopped. + + Some of its parameters: + + - `timestamp` at the end of the transaction + - `energy_wh_import` contains the meter value in Wh for the connector at end of the transaction + +- `on_suspend_charging_ev` + + Notifies libocpp that the EV has paused charging + +- `on_suspend_charging_evse` + + Notifies libocpp that the EVSE has paused charging + +- `on_resume_charging` + + Notifies libocpp that charging has resumed + +- `on_session_started` + + this is mostly used for logging and changing the connector state + +- `on_session_stopped` + + this is mostly used for logging and changing the connector state + +- `on_error` + + Notify libocpp of an error + +- `on_reservation_start` + + Notifies libocpp that a reservation has started + +- `on_reservation_end` + + Notifies libocpp that a reservation has ended + +#### Authorization + +In EVerest authorization is handled by the Auth module and various auth token providers and validators. The OCPP module acts as both a token provider (for pre validated tokens in RemoteStartTransactions) and a token validator (using the authorize requests, or plug & charge). + +To use libocpp as a auth token validator (e.g. before starting a transaction) you can call the "authorize_id_token" function of the ChargePoint object. + +### Register event callbacks and on_handlers + +- `all_connectors_unavailable_callback` + + Notifies that all connectors are unavailable. Used to handle charge availability + requests and firmware updates. + +- `boot_notification_callback` + + Callback to notify of a system boot + +- `clear_customer_information_callback` + + Called to clear customer information based on passed in Customer Certificate, the + IdToken for this request, and the Customer Identified that the request refers to. + If IdToken is passed in will delete authorization cache entry from database. + +- `configure_network_connection_profile_callback` + + Called to configure a network connection profile when none is configured. + +- `connector_effective_operative_status_changed_callback` + + Notifies the user of liboccp that the Operative/Inoperative state of a specific EVSE + has changed. + +- `cs_effective_operative_status_changed_callback` + + Used to notify the user of libocpp that the Operative/Inoperative state of the + charging station itself has changed. Will also call + `evse_effective_operative_status_changed_callback` for each EVSE, and + `connector_effective_operative_status_changed_callback` for each connector whose + status has changed. + +- `data_transfer_callback` + + Used to handle arbitrary data transfers. + +- `evse_effective_operative_status_changed_callback` + + Notifies the user of libocpp that the Operative/Inoperative state of an EVSE has + changed. If as a result the state of connectors changed as well, libocpp will + additionally call the connector_effective_operative_status_changed_callback for + each connector. + +- `get_customer_information_callback` + + Returns human readable customer information based on the CertificateHashDataType, + IdToken and Customer Identifier passed in. + +- `get_log_request_callback` + + Callback to return logs + +- `is_reservation_for_token_callback` + + Check if the current reservation for the given evse id is made for the id + token / group id token. + +- `is_reset_allowed_callback` + + Callback if reset is allowed. If evse_id has a value, reset only applies + to the given evse id. If it has no value, applies to complete charging station. + +- `ocpp_messages_callback` + + Callback to congfigure ocpp message logging. + +- `pause_charging_callback` + + Used to request pausing of charging, the "connector" parameter instructing which + connector/EVSE to pause. + +- `remote_start_transaction_callback` + + Called when the request can be accepted. The boolean authorize_remote_start + indicates if Authorize.req needs to follow or not + +- `reset_callback` + + Performs a reset of the requested type + +- `security_event_callback` + + Used to react to a security event callback. This callback is + called only if the SecurityEvent occured internally within libocpp. + Typically this callback is used to log security events in the security log. + +- `set_charging_profiles_callback` + + Indicates when a charging profile is received and accepted. + +- `stop_transaction_callback` + + Used to stop a transaction. Called when the idTagInfo.status of a + StartTransaction.conf is not Accepted, when a RemoteStopTransaction.req is + received, or when an UnlockConnector.req is received. + +- `time_sync_callback` + + Called on boot notification if the TimeSource ControllerComponent contains + Heartbeat. + +- `transaction_event_callback` + + Called when a transaction_event was sent to the CSMS. + +- `transaction_event_response_callback` + + Called when a transaction_event_response was received from the CSMS. + +- `unlock_connector_callback` + + Used by libocpp to force unlock a connector + +- `update_firmware_request_callback` + + Initiates a firmware update request. Triggers a security event notification + if the certificate is Invalid or Revoked. + +- `validate_network_profile_callback` + + Validates the submitted Network Profile. Is Rejected if + - No callback registered to validate network profile + - CSMS attempted to set a network profile with a lower securityProfile + - CSMS attempted to set a network profile that could not be validated + - Network profile could not be written to the device model storage + +- `variable_changed_callback` + + Called when a variable has been changed by the CSMS + +### Initialize the database + +- Use provided sql database or implement your own storage drive + +## Install libocpp + +For Debian GNU/Linux 11 you will need the following dependencies: + +```bash + sudo apt install build-essential cmake python3-pip libboost-all-dev libsqlite3-dev libssl-dev +``` + +OpenSSL version 3.0 or above is required. + +Clone this repository. + +```bash + git clone https://github.com/EVerest/libocpp +``` + +In the libocpp folder create a folder named build and cd into it. +Execute cmake and then make install: + +```bash + mkdir build && cd build + cmake .. + make install +``` + +## Quickstart for OCPP 1.6 + +Libocpp provides a small standalone OCPP1.6 client that you can control using command line. + +Install the dependencies and libocpp as described in [Install libocpp](#install-libocpp). + +Make sure you modify the following config entries in the [config.json](config/v16/config.json) file according to the CSMS you want to connect to before executing make install. + +```json +{ + "Internal": { + "ChargePointId": "", + "CentralSystemURI": "" + } +} +``` + +Change into libocpp/build and execute cmake and then make install: + +```bash + cd build + cmake -DLIBOCPP16_BUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=./dist .. + make -j$(nproc) install +``` + +Use the following command to start the charge point. Replace the config with [config-docker.json](config/v16/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. + +```bash + ./dist/bin/charge_point \ + --maindir ./dist \ + --conf config.json +``` + +Type `help` to see a list of possible commands. + +## Building the doxygen documentation + +```bash + cmake -S . -B build + cmake --build build --target doxygen-ocpp +``` + +You will find the generated doxygen documentation at: +`build/dist/docs/html/index.html` + +The main reference for the integration of libocpp for OCPP1.6 is the ocpp::v16::ChargePoint class defined in libocpp/include/ocpp/v16/charge_point.hpp . + +## Unit testing + +GTest is required for building the test cases target. +To build the target and run the tests you can reference the script `.ci/build-kit/install_and_test.sh`. +The script allows the GitHub Actions runner to execute. + +Local testing: + +```bash +mkdir build +cmake -B build -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="./dist" +cd build +make -j$(nproc) install +``` + +Run any required tests from build/tests. + +## Building with FetchContent instead of EDM + +In [doc/build-with-fetchcontent](doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. + +### Support for TPM keys + +In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. + +## Support for websocket++ + +The old websocket++ implementation has been deprecated. For enabling websocket++ support use the following cmake option: + +```bash + cmake .. -DLIBOCPP_ENABLE_DEPRECATED_WEBSOCKETPP=ON +``` + +### Support for iface + +In order to connect through a custom network iface, a custom internal config variable 'IFace' can be used. + +```json +"Internal": { + "IFace" : "enp43s0" +} +``` From 8cd418340231261851cbb4b952c2eccda634a601 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:27:40 -0400 Subject: [PATCH 004/134] Update OCPP-2-0-1.md Curated OCPP 2.0.1 content only Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- OCPP-2-0-1.md | 604 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 603 insertions(+), 1 deletion(-) diff --git a/OCPP-2-0-1.md b/OCPP-2-0-1.md index 5c5499e2b..07b0b0d5f 100644 --- a/OCPP-2-0-1.md +++ b/OCPP-2-0-1.md @@ -1 +1,603 @@ -place holder for now +# C++ implementation of OCPP 2.0.1 +![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) + +This is a C++ library implementation of OCPP for version 2.0.1 +(see [OCPP protocols at OCA website](https://openchargealliance.org/protocols/open-charge-point-protocol/)). + +It enables charging stations to communicate with cloud backends for remote +control, monitoring and billing of charging processes. + +Libocpp can be used for the communication of one charging station and multiple EVSE using a single websocket connection. + +The implementation of OCPP 2.0.1 is currently under development. + +## Get Involved + +See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. + +## Table of contents + +- [Support for OCPP 2.0.1](#support-for-ocpp-201) + - [Feature Profile Support OCPP 2.0.1](#feature-profile-support-ocpp-201) +- [CSMS Compatibility OCPP 2.0.1](#csms-compatibility-ocpp-201) +- [Run OCPP2.0.1 with EVerest](#run-ocpp201-with-everest) +- [Integrate this library with your Charging Station Implementation for OCPP2.0.1](#integrate-this-library-with-your-charging-station-implementation-for-ocpp201) + - [Register event callbacks and on\_handlers](#register-event-callbacks-and-on_handlers) + - [Initialize the database](#initialize-the-database) +- [Install libocpp](#install-libocpp) +- [Quickstart for OCPP 2.0.1](#quickstart-for-ocpp-201) +- [Building the doxygen documentation](#building-the-doxygen-documentation) +- [Unit testing](#unit-testing) +- [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) + +## Support for OCPP 2.0.1 + +The development of OCPP2.0.1 is in progress. +[Current implementation status.](/doc/ocpp_201_status.md) + +### Feature Profile Support OCPP 2.0.1 + +| Feature Profile | Supported | +| -------------------------- | ------------------------- | +| Core | :heavy_check_mark: yes | +| Advanced Security | WIP | +| Local Auth List Management | | +| Smart Charging | WIP | +| Advanced Device Management | | +| Advanced User Interface | | +| Reservation | | +| ISO 15118 support | WIP | + +| Whitepapers & Application Notes | Supported | +| ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | +| [OCPP & California Pricing Requirements](https://www.openchargealliance.org/uploads/files/ocpp_and_dms_evse_regulation-v2.0.pdf) | WIP | + + +## CSMS Compatibility OCPP 2.0.1 + +The current, ongoing implementation of OCPP 2.0.1 has been tested against a +few CSMS and is continuously tested against OCTT2. + +Additionally, the implementation has been tested against those CSMS: + +- [CitrineOS](https://lfenergy.org/projects/citrineos/) +- Chargepoint +- Current +- ihomer (Infuse CPMS) +- Instituto Tecnológico de la Energía (ITE) +- [MaEVe (Thoughtworks)](https://github.com/thoughtworks/maeve-csms) +- [Monta](https://monta.com) +- [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) +- Switch EV +- SWTCH + +## Run OCPP2.0.1 with EVerest + +This library is automatically integrated as the OCPP and OCPP201 module within [everest-core](https://github.com/EVerest/everest-core) - the complete software stack for your charging station. It is recommended to use EVerest together with this OCPP implementation. + +If you run libocpp with OCPP1.6 with EVerest, the build process of [everest-core](https://github.com/EVerest/everest-core) will take care of installing all necessary dependencies for you. This includes the initialization of the device model database using the [config.json](config/v201/config.json) file. + +## Integrate this library with your Charging Station Implementation for OCPP + +OCPP is a protocol that affects, controls and monitors many areas of a charging station's operation. + +If you want to integrate this library with your charging station implementation, you have to register a couple of **callbacks** and integrate **event handlers**. This is necessary for the library to interact with your charging station according to the requirements of OCPP. + +Libocpp needs registered **callbacks** in order to execute control commands defined within OCPP (e.g Reset.req or RemoteStartTransaction.req) + +The implementation must call **event handlers** of libocpp so that the library can track the state of the charging station and trigger OCPP messages accordingly (e.g. MeterValues.req , StatusNotification.req) + +Your reference within libocpp to interact is a single instance to the class [ChargePoint](include/ocpp/v16/charge_point.hpp) for OCPP 1.6 or to the class [ChargePoint](include/ocpp/v201/charge_point.hpp) for OCPP 2.0.1. + +### Overview of the required callbacks and events and what libocpp expects to happen + +The following section will give you a high level overview of how to integrate libocpp with your application. Please use the [Doxygen Documentation](#building-the-doxygen-documentation) as an additional source for the ChargePoint API. + +In EVerest the OCPP module leverages several other modules to perform tasks that relate to authorization, reservations, charging session handling and system tasks like rebooting or firmware updates. + +- Auth orchestrates authorization, utilizing different token providers like RFID reads and token validators. Libocpp mainly acts as a token validator, but in the case of RemoteStartTransactions it acts as a token provider as well +- EvseManager manages the charging session and charging state machine by communicating with a "board support package", a driver for the charging hardware that abstracts away the control pilot, relay control, power meters, etc. The EvseManager also handles reservations. +- System handles firmware updates, log uploads and resets + +The following sections explain the steps you can follow to implement their functionality on your own and integrate the libocpp directly into your charging station software without relying on EVerest. However, in most cases it's much easier to write an EVerest driver using the *everest-core/interfaces/board_support_AC.yaml* interface. + +## Usage for OCPP 2.0.1 + +### Smart Charging + +Work to fully support OCPP 2.0.1 Smart Charging is ongoing. Most functional requirements for General Smart Charging use cases (that is, K01–K10) are now supported. For an up-to-date overview of which features are currently supported, please refer to the [OCPP 2.0.1 Status](doc/ocpp_201_status.md) document. + +#### K01 SetChargingProfile + +Allows the CSMS to influence the charging power or current drawn from a specific EVSE or the +entire Charging Station over a period of time. + +```mermaid +sequenceDiagram + CSMS->>+ChargePoint : SetChargingProfileRequest(call) + + ChargePoint->>+DeviceModel : SmartChargingCtrlrAvailable? + DeviceModel-->>-ChargePoint : Component + + rect Red + break SmartChargingCtrlrAvailable = false + ChargePoint-->>CSMS : Smart Charging NotSupported CallError + end + end + + ChargePoint->>+SmartCharging : validate_and_add_profile(call.msg.Profile, call.msg.EVSE ID) + + SmartCharging->>SmartCharging : validate_profile(Profile, EVSE ID) + + rect Red + break Invalid Profile + SmartCharging-->>ChargePoint : SetChargingProfileResponse: Rejected + ChargePoint-->>CSMS : SetChargingProfileResponse: Rejected + end + end + + SmartCharging->>+SmartCharging : add_profile(Profile, EVSE ID) + SmartCharging->>-EVerest : signal_set_charging_profiles_callback + + SmartCharging-->>-ChargePoint : SetChargingProfileResponse: Accepted + + ChargePoint-->>-CSMS : SetChargingProfileResponse: Accepted +``` + +Profile validation returns the following errors to the caller when a Profile +is `Rejected`: + +- `ChargingProfileFirstStartScheduleIsNotZero` + + The `startPeriod` of the first `chargingSchedulePeriod` needs to be 0. + [K01.FR.31] + +- `ChargingProfileNoChargingSchedulePeriods` + + Happens when the `ChargingProfile` doesn't have any Charging Schedule + Periods. + +- `ChargingScheduleChargingRateUnitUnsupported` + + Happens when a chargingRateUnit is passed in that is not configured in the + `ChargingScheduleChargingRateUnit`. [K01.FR.26] + +- `ChargingSchedulePeriodInvalidPhaseToUse` + + Happens when an invalid `phaseToUse` is passed in. + + [K01.FR.19] [K01.FR.48] + +- `ChargingSchedulePeriodPhaseToUseACPhaseSwitchingUnsupported` + + Happens when phaseToUse is passed in and the EVSE does not have + `ACPhaseSwitchingSupported` defined and set to true. + [K01.FR.20] [K01.FR.48] + +- `ChargingSchedulePeriodsOutOfOrder` + + `ChargingSchedulePeriod.startPeriod` elements need to be in increasing + values. [K01.FR.35] + +- `ChargingStationMaxProfileCannotBeRelative` + + Happens when a `ChargingStationMaxProfile.chargingProfileKind` is set to + `Relative`. [K01.FR.38] + +- `ChargingStationMaxProfileEvseIdGreaterThanZero` + + Happens when a `ChargingStationMaxProfile` is attempted to be set with an + EvseID isn't `0`. [K01.FR.03] + +- `ChargingProfileMissingRequiredStartSchedule` + + Happens when an `Absolute` or `Recurring` `ChargingProfile` doesn't have + a `startSchedule`. [K01.FR.40] + +- `ChargingProfileExtraneousStartSchedule` + + Happens when a Relative `ChargingProfile` has a `startSchedule`. + [K01.FR.41] + +- `EvseDoesNotExist` + + Happens when the `evseId`of a `SetChargingProfileRequest` does not exist. + [K01.FR.28] + +- `ExistingChargingStationExternalConstraints` + + Happens when a `SetChargingProfileRequest` Profile has a purpose of + `ChargingStationExternalConstraints` and one already exists with the same + `ChargingProfile.id` exists. [K01.FR.05] + +- `InvalidProfileType` + + Happens when a `ChargingStationMaxProfile` is attempted to be set with a + `ChargingProfile` that isn't a `ChargingStationMaxProfile`. + +- `TxProfileEvseHasNoActiveTransaction` + + Happens when a `SetChargingProfileRequest` with a `TxProfile` is submitted + and there is no transaction active on the specified EVSE. [K01.FR.09] + +- `TxProfileEvseIdNotGreaterThanZero` + + `TxProfile` needs to have an `evseId` greater than 0. [K01.FR.16] + +- `TxProfileMissingTransactionId` + + A `transactionId` is required for `SetChargingProfileRequest`s with a + `TxProfile` in order to match the profile to a specific transation. [K01.FR.03] + +- `TxProfileTransactionNotOnEvse` + + Happens when the provided `transactionId` is not known. [K01.FR.33] + +- `TxProfileConflictingStackLevel` + + Happens when a `TxProfile` has a `stackLevel` and `transactionId` + combination already exists in a `TxProfile` with a different id in + order to ensure that no two charging profiles with same stack level and + purpose can be valid at the same time. [K01.FR.39] + +#### K08 Get Composite Schedule + +The CSMS requests the Charging Station to report the Composite Charging +Schedule, as calculated by the Charging Station for a specific point of +time, and may change over time due to external causes such as local +balancing based on grid connection capacity and EVSE availablity. + +The Composite Schedule is the result of result of merging the time periods +set in the `ChargingStationMaxProfile`, `ChargingStationExternalConstraints`, +`TxDefaultProfile` and `TxProfile` type profiles. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: GetCompositeSchedule(call) + + ChargePoint->>+DeviceModel : ChargingScheduleChargingRateUnit? + DeviceModel-->>-ChargePoint : Component + + rect Red + break call.msg.chargingRateUnit is not supported + ChargePoint-->>CSMS : ChargingScheduleChargingRateUnitUnsupported CallError + end + end + + ChargePoint->>+EvseManager : does_evse_exist(call.msg.evseId) + EvseManager-->>-ChargePoint : bool + rect Red + break EVSE does not exist + ChargePoint-->>CSMS : EvseDoesNotExist CallError + end + end + + ChargePoint->>+SmartChargingHandler : get_valid_profiles(call.msg.evseId) + + SmartChargingHandler-->>-ChargePoint : vector + + ChargePoint->>+SmartChargingHandler : calculate_composite_schedule
(vector>+Profile: calculate_composite_schedule(profiles) + Profile-->>-SmartChargingHandler: composite_schedule + end + + note right of SmartChargingHandler: Create consolidated CompositeSchedule
from all 4 Profile types + + + SmartChargingHandler->>+Profile: calculate_composite_schedule(ExternalConstraints, Max, TxDefault, Tx) + Profile-->>-SmartChargingHandler: CompositeSchedule + + SmartChargingHandler-->>-ChargePoint: CompositeSchedule + + ChargePoint-->>-CSMS : GetCompositeScheduleResponse(CompositeSchedule) +``` + +#### K09 Get Charging Profiles + +Returns to the CSMS the Charging Schedules/limits installed on a Charging Station based on the +passed in criteria. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: GetChargingProfiles(criteria) + + ChargePoint->>+SmartChargingHandler : get_reported_profiles(criteria) + + loop filter ChargingProfiles + SmartChargingHandler->>SmartChargingHandler: filter on ChargingProfile criteria + end + + SmartChargingHandler-->>-ChargePoint : Vector + + ChargePoint-->>CSMS : GetChargingProfilesResponse(profiles) + + alt no Profiles + rect Red + ChargePoint-->>CSMS : GetChargingProfilesResponse(NoProfiles) + ChargePoint->>CSMS : return + end + + else Profiles + ChargePoint-->>CSMS : GetChargingProfilesResponse(Accepted) + end + + ChargePoint->>ChargePoint : determine profiles_to_report + + ChargePoint-->>-CSMS : ReportChargingProfilesRequest(profiles_to_report) +``` + +#### K10 Clear Charging Profile + +Clears Charging Profiles installed on a Charging Station based on the +passed in criteria. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: ClearChargingProfileRequest(criteria) + + alt no Profiles matching criteria + rect Red + ChargePoint-->>CSMS : ClearChargingProfileResponse(Unknown) + + end + + else found matching Profiles + ChargePoint-->>-CSMS : ClearChargingProfileResponse(Accepted) + end +``` + +### Register event callbacks and on_handlers + +- `all_connectors_unavailable_callback` + + Notifies that all connectors are unavailable. Used to handle charge availability + requests and firmware updates. + +- `boot_notification_callback` + + Callback to notify of a system boot + +- `clear_customer_information_callback` + + Called to clear customer information based on passed in Customer Certificate, the + IdToken for this request, and the Customer Identified that the request refers to. + If IdToken is passed in will delete authorization cache entry from database. + +- `configure_network_connection_profile_callback` + + Called to configure a network connection profile when none is configured. + +- `connector_effective_operative_status_changed_callback` + + Notifies the user of liboccp that the Operative/Inoperative state of a specific EVSE + has changed. + +- `cs_effective_operative_status_changed_callback` + + Used to notify the user of libocpp that the Operative/Inoperative state of the + charging station itself has changed. Will also call + `evse_effective_operative_status_changed_callback` for each EVSE, and + `connector_effective_operative_status_changed_callback` for each connector whose + status has changed. + +- `data_transfer_callback` + + Used to handle arbitrary data transfers. + +- `evse_effective_operative_status_changed_callback` + + Notifies the user of libocpp that the Operative/Inoperative state of an EVSE has + changed. If as a result the state of connectors changed as well, libocpp will + additionally call the connector_effective_operative_status_changed_callback for + each connector. + +- `get_customer_information_callback` + + Returns human readable customer information based on the CertificateHashDataType, + IdToken and Customer Identifier passed in. + +- `get_log_request_callback` + + Callback to return logs + +- `is_reservation_for_token_callback` + + Check if the current reservation for the given evse id is made for the id + token / group id token. + +- `is_reset_allowed_callback` + + Callback if reset is allowed. If evse_id has a value, reset only applies + to the given evse id. If it has no value, applies to complete charging station. + +- `ocpp_messages_callback` + + Callback to congfigure ocpp message logging. + +- `pause_charging_callback` + + Used to request pausing of charging, the "connector" parameter instructing which + connector/EVSE to pause. + +- `remote_start_transaction_callback` + + Called when the request can be accepted. The boolean authorize_remote_start + indicates if Authorize.req needs to follow or not + +- `reset_callback` + + Performs a reset of the requested type + +- `security_event_callback` + + Used to react to a security event callback. This callback is + called only if the SecurityEvent occured internally within libocpp. + Typically this callback is used to log security events in the security log. + +- `set_charging_profiles_callback` + + Indicates when a charging profile is received and accepted. + +- `stop_transaction_callback` + + Used to stop a transaction. Called when the idTagInfo.status of a + StartTransaction.conf is not Accepted, when a RemoteStopTransaction.req is + received, or when an UnlockConnector.req is received. + +- `time_sync_callback` + + Called on boot notification if the TimeSource ControllerComponent contains + Heartbeat. + +- `transaction_event_callback` + + Called when a transaction_event was sent to the CSMS. + +- `transaction_event_response_callback` + + Called when a transaction_event_response was received from the CSMS. + +- `unlock_connector_callback` + + Used by libocpp to force unlock a connector + +- `update_firmware_request_callback` + + Initiates a firmware update request. Triggers a security event notification + if the certificate is Invalid or Revoked. + +- `validate_network_profile_callback` + + Validates the submitted Network Profile. Is Rejected if + - No callback registered to validate network profile + - CSMS attempted to set a network profile with a lower securityProfile + - CSMS attempted to set a network profile that could not be validated + - Network profile could not be written to the device model storage + +- `variable_changed_callback` + + Called when a variable has been changed by the CSMS + +### Initialize the database + +- Use provided sql database or implement your own storage drive + +## Install libocpp + +For Debian GNU/Linux 11 you will need the following dependencies: + +```bash + sudo apt install build-essential cmake python3-pip libboost-all-dev libsqlite3-dev libssl-dev +``` + +OpenSSL version 3.0 or above is required. + +Clone this repository. + +```bash + git clone https://github.com/EVerest/libocpp +``` + +In the libocpp folder create a folder named build and cd into it. +Execute cmake and then make install: + +```bash + mkdir build && cd build + cmake .. + make install +``` + +## Quickstart for OCPP 2.0.1 + +Libocpp provides a small standalone OCPP2.0.1 client that you can control using command line. + +Install the dependencies and libocpp as described in [Install libocpp](#install-libocpp). + +Make sure you modify the following config entries in the [config.json](config/v201/config.json) file according to the CSMS you want to connect to before executing make install. + +```json +{ + "Internal": { + "ChargePointId": "", + "CentralSystemURI": "" + } +} +``` + +Change into libocpp/build and execute cmake and then make install: + +```bash + cd build + cmake -DLIBOCPP16_BUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=./dist .. + make -j$(nproc) install +``` + +Use the following command to start the charge point. Replace the config with [config-docker.json](config/v16/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. + +```bash + ./dist/bin/charge_point \ + --maindir ./dist \ + --conf config.json +``` + +Type `help` to see a list of possible commands. + +## Building the doxygen documentation + +```bash + cmake -S . -B build + cmake --build build --target doxygen-ocpp +``` + +You will find the generated doxygen documentation at: +`build/dist/docs/html/index.html` + +The main reference for the integration of libocpp for OCPP2.0.1 is the ocpp::v201::ChargePoint class defined in libocpp/include/ocpp/v201/charge_point.hpp . + +## Unit testing + +GTest is required for building the test cases target. +To build the target and run the tests you can reference the script `.ci/build-kit/install_and_test.sh`. +The script allows the GitHub Actions runner to execute. + +Local testing: + +```bash +mkdir build +cmake -B build -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="./dist" +cd build +make -j$(nproc) install +``` + +Run any required tests from build/tests. + +## Building with FetchContent instead of EDM + +In [doc/build-with-fetchcontent](doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. + +### Support for TPM keys + +In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. + +## Support for websocket++ + +The old websocket++ implementation has been deprecated. For enabling websocket++ support use the following cmake option: + +```bash + cmake .. -DLIBOCPP_ENABLE_DEPRECATED_WEBSOCKETPP=ON +``` + +### Support for iface + +In order to connect through a custom network iface, a custom internal config variable 'IFace' can be used. + +```json +"Internal": { + "IFace" : "enp43s0" +} +``` From af1fb71d5a1c9db59dc7eeb1785176c9cd37188b Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 04:28:40 -0400 Subject: [PATCH 005/134] Update OCPP-1-6.md removed unsupported links to white papers and applications Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- OCPP-1-6.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/OCPP-1-6.md b/OCPP-1-6.md index a4d896290..5bdcdf66b 100644 --- a/OCPP-1-6.md +++ b/OCPP-1-6.md @@ -52,12 +52,6 @@ All documentation and the issue tracking can be found in our main repository her | Smart Charging | :heavy_check_mark: yes | | Remote Trigger | :heavy_check_mark: yes | -| Whitepapers & Application Notes | Supported | -| ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | -| [OCPP 1.6 Security Whitepaper (3rd edition)](https://www.openchargealliance.org/uploads/files/OCPP-1.6-security-whitepaper-edition-3.zip) | :heavy_check_mark: yes | -| [Using ISO 15118 Plug & Charge with OCPP 1.6](https://www.openchargealliance.org/uploads/files/ocpp_1_6_ISO_15118_v10.pdf) | :heavy_check_mark: yes | -| [OCPP & California Pricing Requirements](https://www.openchargealliance.org/uploads/files/ocpp_and_dms_evse_regulation-v2.0.pdf) | :heavy_check_mark: yes | - ## CSMS Compatibility ### CSMS Compatibility OCPP 1.6 From de8b629f8cab311be1a63f9410c8f05fe2736300 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 04:37:58 -0400 Subject: [PATCH 006/134] Update OCPP-1-6.md Updated intro text Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- OCPP-1-6.md | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/OCPP-1-6.md b/OCPP-1-6.md index 5bdcdf66b..e63e44637 100644 --- a/OCPP-1-6.md +++ b/OCPP-1-6.md @@ -1,19 +1,10 @@ -# C++ implementation of OCPP 1.6 +# EVerest C++ OCPP 1.6 Implementation ![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) -This is a C++ library implementation of OCPP for version 1.6 -(see [OCPP protocols at OCA website](https://openchargealliance.org/protocols/open-charge-point-protocol/)). +This C++ library provides a complete and production-ready solution for integrating OCPP 1.6 into your electric vehicle (EV) charging stations. Our implementation enables seamless communication between charging stations and central management systems, supporting remote control, monitoring, and billing functionalities. -It enables charging stations to communicate with cloud backends for remote -control, monitoring and billing of charging processes. +NOTE: [EVerest C++ OCPP 2.0.1](OCPP-2-0-1.md) is under active development, with core functionalities available. -Libocpp can be used for the communication of one charging station and multiple EVSE using a single websocket connection. - -Libocpp provides a complete implementation of OCPP 1.6. - -## Get Involved - -See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. ## Table of contents @@ -647,3 +638,7 @@ In order to connect through a custom network iface, a custom internal config var "IFace" : "enp43s0" } ``` + +## Get Involved + +See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. From 58f8b78a74339611f3f099690347164f41fb4968 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 04:54:34 -0400 Subject: [PATCH 007/134] Update OCPP-1-6.md Update page title and intro text Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- OCPP-1-6.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OCPP-1-6.md b/OCPP-1-6.md index e63e44637..5e935e612 100644 --- a/OCPP-1-6.md +++ b/OCPP-1-6.md @@ -1,9 +1,9 @@ -# EVerest C++ OCPP 1.6 Implementation +# EVerest OCPP 1.6 C++ Implementation ![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) This C++ library provides a complete and production-ready solution for integrating OCPP 1.6 into your electric vehicle (EV) charging stations. Our implementation enables seamless communication between charging stations and central management systems, supporting remote control, monitoring, and billing functionalities. -NOTE: [EVerest C++ OCPP 2.0.1](OCPP-2-0-1.md) is under active development, with core functionalities available. +NOTE: [EVerest OCPP 2.0.1](OCPP-2-0-1.md) is under active development, with core functionalities available. ## Table of contents From 90795e207a947f2170aa723bd198a9a2516522b0 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 05:55:15 -0400 Subject: [PATCH 008/134] Update README.md Simplified content to be more of quick links to each OCPP versions Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 572 ++---------------------------------------------------- 1 file changed, 13 insertions(+), 559 deletions(-) diff --git a/README.md b/README.md index c176b3fc0..636d76675 100644 --- a/README.md +++ b/README.md @@ -1,570 +1,24 @@ -# C++ implementation of OCPP -![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) -This is a C++ library implementation of OCPP for version 1.6 and 2.0.1 -(see [OCPP protocols at OCA website](https://openchargealliance.org/protocols/open-charge-point-protocol/)). +# EVerest OCPP C++ Implementation -It enables charging stations to communicate with cloud backends for remote -control, monitoring and billing of charging processes. +This C++ implementation is a crucial module of the EVerest software stack — supports both OCPP 1.6 and OCPP 2.0.1, enabling seamless communication between electric vehicle (EV) charging stations and their management systems. -Libocpp can be used for the communication of one charging station and multiple EVSE using a single websocket connection. +### Development Status -Libocpp provides a complete implementation of OCPP 1.6. The implementation of OCPP 2.0.1 is currently under development. +- OCPP 1.6: Fully implemented and production-ready +- OCPP 2.0.1: Under active development, with core functionalities available -## Get Involved - -See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. - -## Table of contents -- [C++ implementation of OCPP](#c-implementation-of-ocpp) - - [Table of contents](#table-of-contents) - - [OCPP 1.6 Support](#feature-support) - - [Feature Profile Support OCPP 1.6](#feature-profile-support-ocpp-16) - - [Support for OCPP 2.0.1](#support-for-ocpp-201) - - [Feature Profile Support OCPP 2.0.1](#feature-profile-support-ocpp-201) - - [CSMS Compatibility](#csms-compatibility) - - [CSMS Compatibility OCPP 1.6](#csms-compatibility-ocpp-16) - - [CSMS Compatibility OCPP 2.0.1](#csms-compatibility-ocpp-201) - - [Integration with EVerest](#integration-with-everest) - - [Run OCPP1.6 with EVerest](#run-ocpp16-with-everest) - - [Run OCPP2.0.1 with EVerest](#run-ocpp201-with-everest) - - [Integrate this library with your Charging Station Implementation for OCPP1.6](#integrate-this-library-with-your-charging-station-implementation-for-ocpp16) - - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) - - [ChargePoint() constructor](#chargepoint-constructor) - - [registering callbacks](#registering-callbacks) - - [Functions that need to be triggered from the outside after new information is availble (on\_... functions in the charge point API)](#functions-that-need-to-be-triggered-from-the-outside-after-new-information-is-availble-on_-functions-in-the-charge-point-api) - - [The following functions are triggered depending on different so called "Session Events" from the EvseManager](#the-following-functions-are-triggered-depending-on-different-so-called-session-events-from-the-evsemanager) - - [Authorization](#authorization) - - [Integrate this library with your Charging Station Implementation for OCPP2.0.1](#integrate-this-library-with-your-charging-station-implementation-for-ocpp201) - - [Register event callbacks and on\_handlers](#register-event-callbacks-and-on_handlers) - - [Initialize the database](#initialize-the-database) - - [Install libocpp](#install-libocpp) - - [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) - - [Building the doxygen documentation](#building-the-doxygen-documentation) - - [Unit testing](#unit-testing) - - [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) - - [Support for security profile 2 and 3 with TPM in OCPP 1.6 using libwebsockets](#support-for-security-profile-2-and-3-with-tpm-in-ocpp-16-using-libwebsockets) - -## OCPP 1.6 Support - -The following tables show the current support for the listed OCPP 1.6 feature profiles / functional blocks and application notes. - -All documentation and the issue tracking can be found in our main repository here: https://github.com/EVerest/ - -### Feature Profile Support OCPP 1.6 - -| Feature Profile | Supported | -| -------------------------- | ------------------------- | -| Core | :heavy_check_mark: yes | -| Firmware Management | :heavy_check_mark: yes | -| Local Auth List Management | :heavy_check_mark: yes | -| Reservation | :heavy_check_mark: yes | -| Smart Charging | :heavy_check_mark: yes | -| Remote Trigger | :heavy_check_mark: yes | - -| Whitepapers & Application Notes | Supported | -| ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | -| [OCPP 1.6 Security Whitepaper (3rd edition)](https://www.openchargealliance.org/uploads/files/OCPP-1.6-security-whitepaper-edition-3.zip) | :heavy_check_mark: yes | -| [Using ISO 15118 Plug & Charge with OCPP 1.6](https://www.openchargealliance.org/uploads/files/ocpp_1_6_ISO_15118_v10.pdf) | :heavy_check_mark: yes | -| [OCPP & California Pricing Requirements](https://www.openchargealliance.org/uploads/files/ocpp_and_dms_evse_regulation-v2.0.pdf) | :heavy_check_mark: yes | - -## Support for OCPP 2.0.1 - -The development of OCPP2.0.1 is in progress. -[Current implementation status.](/doc/ocpp_201_status.md) - -### Feature Profile Support OCPP 2.0.1 - -| Feature Profile | Supported | -| -------------------------- | ------------------------- | -| Core | :heavy_check_mark: yes | -| Advanced Security | WIP | -| Local Auth List Management | | -| Smart Charging | WIP | -| Advanced Device Management | | -| Advanced User Interface | | -| Reservation | | -| ISO 15118 support | WIP | - -| Whitepapers & Application Notes | Supported | -| ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | -| [OCPP & California Pricing Requirements](https://www.openchargealliance.org/uploads/files/ocpp_and_dms_evse_regulation-v2.0.pdf) | WIP | - - - -## CSMS Compatibility - -### CSMS Compatibility OCPP 1.6 - -The EVerest implementation of OCPP 1.6 has been tested against the -OCPP Compliance Test Tool (OCTT and OCTT2) during the implementation. - -The following table shows CSMS with which this library was tested. -If you provide a CSMS that is not yet listed here, feel free to -[contact us](https://lists.lfenergy.org/g/everest)! - -- chargecloud -- chargeIQ -- Chargetic -- Compleo -- Current -- Daimler Truck -- ev.energy -- eDRV -- Fastned -- [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) -- Electrip Global -- EnergyStacks -- EV-Meter -- Fraunhofer IAO (ubstack CHARGE) -- Green Motion -- gridundco -- ihomer (Infuse CPMS) -- iLumen -- JibeCompany (CharlieV CMS and Chargebroker proxy) -- MSI -- PUMP (PUMP Connect) -- Scoptvision (Scopt Powerconnect) -- Siemens -- [SteVe](https://github.com/steve-community/steve) -- Syntech -- Trialog -- ubitricity -- Weev Energy - -### CSMS Compatibility OCPP 2.0.1 - -The current, ongoing implementation of OCPP 2.0.1 has been tested against a -few CSMS and is continuously tested against OCTT2. - -Additionally, the implementation has been tested against those CSMS: - -- [CitrineOS](https://lfenergy.org/projects/citrineos/) -- Chargepoint -- Current -- ihomer (Infuse CPMS) -- Instituto Tecnológico de la Energía (ITE) -- [MaEVe (Thoughtworks)](https://github.com/thoughtworks/maeve-csms) -- [Monta](https://monta.com) -- [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) -- Switch EV -- SWTCH - -## Integration with EVerest - -This library is automatically integrated as the OCPP and OCPP201 module within [everest-core](https://github.com/EVerest/everest-core) - the complete software stack for your charging station. It is recommended to use EVerest together with this OCPP implementation. - -### Run OCPP1.6 with EVerest -If you run libocpp with OCPP1.6 with EVerest, the build process of [everest-core](https://github.com/EVerest/everest-core) will take care of installing all necessary dependencies for you. - -### Run OCPP2.0.1 with EVerest -If you run libocpp with OCPP1.6 with EVerest, the build process of [everest-core](https://github.com/EVerest/everest-core) will take care of installing all necessary dependencies for you. This includes the initialization of the device model database using the [component config](config/v201/component_config) files. - -## Integrate this library with your Charging Station Implementation for OCPP1.6 - -OCPP is a protocol that affects, controls and monitors many areas of a charging station's operation. - -If you want to integrate this library with your charging station implementation, you have to register a couple of **callbacks** and integrate **event handlers**. This is necessary for the library to interact with your charging station according to the requirements of OCPP. - -Libocpp needs registered **callbacks** in order to execute control commands defined within OCPP (e.g Reset.req or RemoteStartTransaction.req) - -The implementation must call **event handlers** of libocpp so that the library can track the state of the charging station and trigger OCPP messages accordingly (e.g. MeterValues.req , StatusNotification.req) - -Your reference within libocpp to interact is a single instance to the class [ChargePoint](include/ocpp/v16/charge_point.hpp) for OCPP 1.6 or to the class [ChargePoint](include/ocpp/v201/charge_point.hpp) for OCPP 2.0.1. - -### Overview of the required callbacks and events and what libocpp expects to happen - -The following section will give you a high level overview of how to integrate libocpp with your application. Please use the [Doxygen Documentation](#building-the-doxygen-documentation) as an additional source for the ChargePoint API. - -In EVerest the OCPP module leverages several other modules to perform tasks that relate to authorization, reservations, charging session handling and system tasks like rebooting or firmware updates. -- Auth orchestrates authorization, utilizing different token providers like RFID reads and token validators. Libocpp mainly acts as a token validator, but in the case of RemoteStartTransactions it acts as a token provider as well -- EvseManager manages the charging session and charging state machine by communicating with a "board support package", a driver for the charging hardware that abstracts away the control pilot, relay control, power meters, etc. The EvseManager also handles reservations. -- System handles firmware updates, log uploads and resets - -The following sections explain the steps you can follow to implement their functionality on your own and integrate the libocpp directly into your charging station software without relying on EVerest. However, in most cases it's much easier to write an EVerest driver using the *everest-core/interfaces/board_support_AC.yaml* interface. - -#### ChargePoint() constructor -The main entrypoint for libocpp for OCPP1.6 is the ocpp::v16::ChargePoint constructor. -This is defined in libocpp/include/ocpp/v16/charge_point.hpp and takes the following parameters: -- config: a std::string that contains the libocpp 1.6 config. There are example configs that work with a [SteVe](https://github.com/steve-community/steve) installation [running in Docker](https://github.com/EVerest/everest-utils/tree/main/docker/steve), for example: [config-docker.json](config/v16/config-docker.json) - -- share_path: a std::filesystem path containing the path to the OCPP modules folder, for example pointing to */usr/share/everest/modules/OCPP*. This path contains the following files and directories and is installed by the libocpp install target: - ```bash - . - ├── config-docker.json - ├── config-docker-tls.json - ├── config.json - ├── init.sql - ├── logging.ini - └── profile_schemas - ├── Config.json - ├── Core.json - ├── FirmwareManagement.json - ├── Internal.json - ├── LocalAuthListManagement.json - ├── PnC.json - ├── Reservation.json - ├── Security.json - ├── SmartCharging.json - └── Custom.json - ``` - Here you can find: - - the aforementioned config files - - - a *logging.ini* that is needed to initialize logging with Everest::Logging::init(path_to_logging_ini, "name_of_binary") - - - a *init.sql* file which contains the database schema used by libocpp for its sqlite database - - - and a *profile_schemas* directory. This contains json schema files that are used to validate the libocpp config. The schemas are split up according to the OCPP1.6 feature profiles like Core, FirmwareManagement and so on. Additionally there is a schema for "Internal" configuration options (for example the ChargePointId, or CentralSystemURI). A "PnC" schema for the ISO 15118 Plug & Charge with OCPP 1.6 Application note, a "Security" schema for the OCPP 1.6 Security Whitepaper (3rd edition) and an exemplary "Custom" schema are provided as well. The Custom.json could be modified to be able to add custom configuration keys. Finally there's a Config.json schema that ties everything together - -- user_config_path: this points to a "user config", which we call a configuration file that's merged with the config that's provided in the "config" parameter. Here you can add, remove and overwrite settings without modifying the config passed in the first parameter directly. This is also used by libocpp to persistently modify config entries that are changed by the CSMS that should persist across restarts. - -- database_path: this points to the location of the sqlite database that libocpp uses to keep track of connector availability, the authorization cache and auth list, charging profiles and transaction data - -- sql_init_path: this points to the aforementioned init.sql file which contains the database schema used by libocpp for its sqlite database - -- message_log_path: this points to the directory in which libocpp can put OCPP communication logfiles for debugging purposes. This behavior can be controlled by the "LogMessages" (set to true by default) and "LogMessagesFormat" (set to ["log", "html", "session_logging"] by default, "console" and "console_detailed" are also available) configuration keys in the "Internal" section of the config file. Please note that this is intended for debugging purposes only as it logs all communication, including authentication messages. - -- evse_security: this is a pointer to an implementation of the [evse_security](include/ocpp/common/evse_security.hpp) interface. This allows you to include your custom implementation of the security related operations according to this interface. If you set this value to nullptr, the internal implementation of the security related operations of libocpp will be used. In this case you need to specify the parameter security_configuration - -- security_configuration: this parameter should only be set in case the evse_security parameter is nullptr. It specifies the file paths that are required to set up the internal evse_security implementation. Note that you need to specify bundle files for the CA certificates and directories for the certificates and keys - - The directory layout expected is as follows - ```bash - . - ├── ca - │ ├── csms - │ │ └── CSMS_ROOT_CA.pem - │ ├── cso - │ │ ├── CPO_CERT_CHAIN.pem - │ │ ├── CPO_SUB_CA1_LEAF.der - │ │ ├── CPO_SUB_CA1.pem - │ │ ├── CPO_SUB_CA2_LEAF.der - │ │ └── CPO_SUB_CA2.pem - │ ├── mf - │ │ └── MF_ROOT_CA.pem - │ ├── mo - │ │ ├── INTERMEDIATE_MO_CA_CERTS.pem - │ │ ├── MO_ROOT_CA.der - │ │ ├── MO_ROOT_CA.pem - │ │ ├── MO_SUB_CA1.der - │ │ ├── MO_SUB_CA1.pem - │ │ ├── MO_SUB_CA2.der - │ │ └── MO_SUB_CA2.pem - │ └── v2g - │ ├── V2G_ROOT_CA.der - │ └── V2G_ROOT_CA.pem - ├── client - │ ├── csms - │ │ ├── CPO_CERT_CHAIN.pem - │ │ ├── CPO_SUB_CA1.key - │ │ ├── CPO_SUB_CA2.key - │ │ ├── SECC_LEAF.der - │ │ ├── SECC_LEAF.key - │ │ └── SECC_LEAF.pem - │ ├── cso - │ │ ├── CPO_CERT_CHAIN.pem - │ │ ├── CPO_SUB_CA1.key - │ │ ├── CPO_SUB_CA2.key - │ │ ├── SECC_LEAF.der - │ │ ├── SECC_LEAF.key - │ │ └── SECC_LEAF.pem - │ └── v2g - │ └── V2G_ROOT_CA.key - ``` - -#### registering callbacks -You can (and in many cases MUST) register a number of callbacks so libocpp can interact with the charger. In EVerest most of this functionality is orchestrated by the "EvseManager" module, but you can also register your own callbacks interacting directly with your chargers software. Following is a list of callbacks that you must register and a few words about their purpose. - -TODO: in a future version of libocpp the callbacks will be organised in a struct with optional members emphasizing the required and optional callbacks. - -Some general notes: the "connector" parameter of some of the callbacks refers to the connector number as understood in the OCPP 1.6 specification, "0" means the whole charging station, the connectors with EVSEs used for charging cars start at "1". - -- register_pause_charging_callback - - this callback is used by libocpp to request pausing of charging, the "connector" parameter tells you which connector/EVSE has to pause charging - -- register_resume_charging_callback - - this callback is used by libocpp the request resuming of charging, the "connector" parameter tells you which connector/EVSE can resume charging - -- register_stop_transaction_callback - - in EVerest this calls the EvseManagers stop_transaction command which "Stops transactions and cancels charging externally, charging can only be resumed by replugging car. EVSE will also stop transaction automatically e.g. on disconnect, so this only needs to be called if the transaction should end before." - this will then signal the following events: - - ChargingFinished - - TransactionFinished - -- register_unlock_connector_callback - - can be used by libocpp to force unlock a connector - -- register_reserve_now_callback - - libocpp can use this to reserve a connector, reservation handling is outsourced to a reservation manager in EVerest that implements the reservation interface (everest-core/interfaces/reservation.yaml) - -- register_upload_diagnostics_callback - - uses a function (in EVerest provided by the System module) to upload the requested diagnostics file - -- register_upload_logs_callback - - uses a function (in EVerest provided by the System module) to upload the requested log file - -- register_update_firmware_callback - - uses a function (in EVerest provided by the System module) to perform a firmware update - -- register_signed_update_firmware_callback - - uses a function (in EVerest provided by the System module) to perform a signed firmware update - -- register_provide_token_callback - - this callback is used in a remote start transaction to provide a token (prevalidated or not) to the authorization system - -- register_set_connection_timeout_callback - - used by libocpp to set the authorization or plug in connection timeout in the authorization system based on the "ConnectionTimeout" configuration key - -- register_disable_evse_callback - - used to disable the EVSE (ChangeAvailability.req) - -- register_enable_evse_callback - - used to enable the EVSE (ChangeAvailability.req) - -- register_cancel_reservation_callback - - used to cancel a reservation in the reservation manager (CancelReservation.req) - -- register_signal_set_charging_profiles_callback - - used to signal that new charging schedule(s) have been set, you can then use - get_all_composite_charging_schedules(duration_s) to get the new valid charging schedules -- register_is_reset_allowed_callback +## Table of Contents - used to inquire (in EVerest from the System module) if a reset is allowed +| [OCPP 2.0.1](OCPP-2-0-1.md) | [OCPP 1.6](OCPP-1-6.md) | +|--|--| +|
  1. Quickstart for OCPP 2.0.1
  2. Run OCPP 2.0.1 with EVerest
  3. Integrate OCPP 2.0.1 library with charging station
  4. Certification Profile Support
  5. CSMS Compatibility
  6. Database Initialization
|
  1. Quickstart for OCPP 1.6
  2. Run OCPP 1.6 with EVerest
  3. Integrate OCPP 1.6 library with charging station
  4. Feature Profile Support
  5. CSMS Compatibility
  6. Database Initialization
| -- register_reset_callback +For detailed information on each OCPP version, please refer to their respective README files linked above. - used to perform a reset of the requested type - -- register_connection_state_changed_callback - - used to inform about the connection state to the CSMS (connected = true, disconnected = false) - -- register_configuration_key_changed_callback - used to react on a changed configuration key. This callback is called when the specified configuration key has been changed by the CSMS - - -#### Functions that need to be triggered from the outside after new information is availble (on_... functions in the charge point API) -- on_log_status_notification(int32_t request_id, std::string log_status) - - can be used to notify libocpp of a log status notification - -- on_firmware_update_status_notification(int32_t request_id, std::string firmware_update_status) - - can be used to notify libocpp of a firmware update status notification - -- on_meter_values(int32_t connector, const Powermeter& powermeter) - - provides a Powermeter struct to libocpp (for sending meter values during charging sessions or periodically) - -- on_max_current_offered(int32_t connector, int32_t max_current) - - the maximum current offered to the EV on this connector (in ampere) - -#### The following functions are triggered depending on different so called "Session Events" from the EvseManager -each of these functions will have a small note what the Session Event was and what it triggers in libocpp - -- on_enabled(int32_t connector) - - Notifies libocpp that the connector is functional and operational - -- on_disabled(int32_t connector) - - Notifies libocpp that the connector is disabled - -- on_transaction_started - - Notifies libocpp that a transaction at the given connector has started, this means that authorization is available and the car is plugged in. - - Some of its parameters: - - session_id is an internal session_id originating in the EvseManager to keep track of the transaction, this is NOT to be mistaken for the transactionId from the StartTransactionResponse in OCPP! - - id_token is the token with which the transaction was authenticated - - meter_start contains the meter value in Wh for the connector at start of the transaction - - timestamp at the start of the transaction - -- on_transaction_stopped - - Notifies libocpp that the transaction on the given connector with the given reason has been stopped. - - Some of its parameters: - - timestamp at the end of the transaction - - energy_wh_import contains the meter value in Wh for the connector at end of the transaction - -- on_suspend_charging_ev - - Notifies libocpp that the EV has paused charging - -- on_suspend_charging_evse - - Notifies libocpp that the EVSE has paused charging - -- on_resume_charging - - Notifies libocpp that charging has resumed - -- on_session_started - - this is mostly used for logging and changing the connector state - -- on_session_stopped - - this is mostly used for logging and changing the connector state - -- on_error - - Notify libocpp of an error - -- on_reservation_start - - Notifies libocpp that a reservation has started - -- on_reservation_end - - Notifies libocpp that a reservation has ended - -#### Authorization -In EVerest authorization is handled by the Auth module and various auth token providers and validators. The OCPP module acts as both a token provider (for pre validated tokens in RemoteStartTransactions) and a token validator (using the authorize requests, or plug & charge) -To use libocpp as a auth token validator (e.g. before starting a transaction) you can call the "authorize_id_token" function of the ChargePoint object - -## Integrate this library with your Charging Station Implementation for OCPP2.0.1 -TODO - -### Register event callbacks and on_handlers - -### Initialize the database -- Use provided sql database or implement your own storage drive - - - -## Install libocpp - -For Debian GNU/Linux 11 you will need the following dependencies: - -```bash - sudo apt install build-essential cmake python3-pip libboost-all-dev libsqlite3-dev libssl-dev -``` - -OpenSSL version 3.0 or above is required. - -Clone this repository. - -```bash - git clone https://github.com/EVerest/libocpp -``` - -In the libocpp folder create a folder named build and cd into it. -Execute cmake and then make install: - -```bash - mkdir build && cd build - cmake .. - make install -``` - -## Quickstart for OCPP 1.6 - -Libocpp provides a small standalone OCPP1.6 client that you can control using command line. - -Install the dependencies and libocpp as described in [Install libocpp](#install-libocpp). - -Make sure you modify the following config entries in the [config.json](config/v16/config.json) file according to the CSMS you want to connect to before executing make install. - -```json -{ - "Internal": { - "ChargePointId": "", - "CentralSystemURI": "" - } -} -``` - -Change into libocpp/build and execute cmake and then make install: - -```bash - cd build - cmake -DLIBOCPP16_BUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=./dist .. - make -j$(nproc) install -``` - -Use the following command to start the charge point. Replace the config with [config-docker.json](config/v16/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. - -```bash - ./dist/bin/charge_point \ - --maindir ./dist \ - --conf config.json -``` - -Type `help` to see a list of possible commands. - -## Building the doxygen documentation -```bash - cmake -S . -B build - cmake --build build --target doxygen-ocpp -``` -You will find the generated doxygen documentation at: -`build/dist/docs/html/index.html` - -The main reference for the integration of libocpp for OCPP1.6 is the ocpp::v16::ChargePoint class defined in libocpp/include/ocpp/v16/charge_point.hpp . - - -## Unit testing - -GTest is required for building the test cases target. -To build the target and run the tests you can reference the script `.ci/build-kit/install_and_test.sh`. -The script allows the GitHub Actions runner to execute. - -Local testing: -```bash -mkdir build -cmake -B build -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="./dist" -cd build -make -j$(nproc) install -``` -Run any required tests from build/tests. - -## Building with FetchContent instead of EDM -In [doc/build-with-fetchcontent](doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. - -### Support for TPM keys - -In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. - -## Support for websocket++ - -The old websocket++ implementation has been deprecated. For enabling websocket++ support use the following cmake option: - -```bash - cmake .. -DLIBOCPP_ENABLE_DEPRECATED_WEBSOCKETPP=ON -``` - -### Support for iface +## Get Involved -In order to connect through a custom network iface, a custom internal config variable 'IFace' can be used. +We welcome contributions and feedback! To get involved with the EVerest project and this OCPP implementation, please refer to our [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) guides. -```json -"Internal": { - "IFace" : "enp43s0" -} -``` +Your involvement helps drive the future of open-source EV charging infrastructure! From c65af3b967e3afceac765b357b2bf2983123c5d5 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 06:06:07 -0400 Subject: [PATCH 009/134] Update README.md update URL for md doc Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 636d76675..2030e151a 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ This C++ implementation is a crucial module of the EVerest software stack — su ## Table of Contents -| [OCPP 2.0.1](OCPP-2-0-1.md) | [OCPP 1.6](OCPP-1-6.md) | +| OCPP 2.0.1 | [OCPP 1.6](OCPP-1-6.md) | |--|--| |
  1. Quickstart for OCPP 2.0.1
  2. Run OCPP 2.0.1 with EVerest
  3. Integrate OCPP 2.0.1 library with charging station
  4. Certification Profile Support
  5. CSMS Compatibility
  6. Database Initialization
|
  1. Quickstart for OCPP 1.6
  2. Run OCPP 1.6 with EVerest
  3. Integrate OCPP 1.6 library with charging station
  4. Feature Profile Support
  5. CSMS Compatibility
  6. Database Initialization
| From 007d50e7431f5c410b4fa89ead4fda9d8254d06a Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 08:55:46 -0400 Subject: [PATCH 010/134] Update README.md update text Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2030e151a..941b861f7 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,8 @@ This C++ implementation is a crucial module of the EVerest software stack — su ### Development Status -- OCPP 1.6: Fully implemented and production-ready - OCPP 2.0.1: Under active development, with core functionalities available +- OCPP 1.6: Fully implemented and production-ready ## Table of Contents From 2b5d7cb23a1e992700001f9450b50686e13c1bd8 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 09:05:22 -0400 Subject: [PATCH 011/134] Update OCPP-2-0-1.md Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- OCPP-2-0-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OCPP-2-0-1.md b/OCPP-2-0-1.md index 07b0b0d5f..6112d08d9 100644 --- a/OCPP-2-0-1.md +++ b/OCPP-2-0-1.md @@ -1,4 +1,4 @@ -# C++ implementation of OCPP 2.0.1 +# EVerest OCPP 2.0.1 C++ Implementation ![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) This is a C++ library implementation of OCPP for version 2.0.1 From 814f48b4e6239683fcc66dfa4892810ec25d65d9 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 09:08:28 -0400 Subject: [PATCH 012/134] Update README.md updated intro text Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 941b861f7..0aaf4c9da 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # EVerest OCPP C++ Implementation -This C++ implementation is a crucial module of the EVerest software stack — supports both OCPP 1.6 and OCPP 2.0.1, enabling seamless communication between electric vehicle (EV) charging stations and their management systems. +Libocpp is a comprehensive C++ library implementation of the Open Charge Point Protocol (OCPP) for versions 1.6 and 2.0.1. OCPP is a standardized communication protocol for electric vehicle charging stations and central management systems, developed by the Open Charge Alliance (OCA). For more information on OCPP, visit the [OCA website](https://openchargealliance.org/protocols/open-charge-point-protocol/). ### Development Status From dffbdf405a48191ff8ba5f575f666ebfc773913e Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 09:25:11 -0400 Subject: [PATCH 013/134] Update README.md updated page title Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0aaf4c9da..274c8af50 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# EVerest OCPP C++ Implementation +# C++ implementation of OCPP Libocpp is a comprehensive C++ library implementation of the Open Charge Point Protocol (OCPP) for versions 1.6 and 2.0.1. OCPP is a standardized communication protocol for electric vehicle charging stations and central management systems, developed by the Open Charge Alliance (OCA). For more information on OCPP, visit the [OCA website](https://openchargealliance.org/protocols/open-charge-point-protocol/). From 44ddabdbdc2dab5c9e5e83329eb37f5b167b060e Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 09:25:35 -0400 Subject: [PATCH 014/134] Update OCPP-2-0-1.md updated page title Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- OCPP-2-0-1.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OCPP-2-0-1.md b/OCPP-2-0-1.md index 6112d08d9..7f1621ec3 100644 --- a/OCPP-2-0-1.md +++ b/OCPP-2-0-1.md @@ -1,4 +1,5 @@ -# EVerest OCPP 2.0.1 C++ Implementation +# C++ implementation of OCPP 2.0.1 + ![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) This is a C++ library implementation of OCPP for version 2.0.1 From c568d477231e6c4e652a6bbbf6fb6d08aa55a1e8 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 09:25:56 -0400 Subject: [PATCH 015/134] Update OCPP-1-6.md updated page title Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- OCPP-1-6.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OCPP-1-6.md b/OCPP-1-6.md index 5e935e612..153d60789 100644 --- a/OCPP-1-6.md +++ b/OCPP-1-6.md @@ -1,4 +1,4 @@ -# EVerest OCPP 1.6 C++ Implementation +# C++ implementation of OCPP 1.6 ![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) This C++ library provides a complete and production-ready solution for integrating OCPP 1.6 into your electric vehicle (EV) charging stations. Our implementation enables seamless communication between charging stations and central management systems, supporting remote control, monitoring, and billing functionalities. From 9ace145ace0b492c98254f8246555eb48ca02ed1 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:53:06 -0400 Subject: [PATCH 016/134] Update README.md updated intro text Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 274c8af50..71383a3f0 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,21 @@ - # C++ implementation of OCPP -Libocpp is a comprehensive C++ library implementation of the Open Charge Point Protocol (OCPP) for versions 1.6 and 2.0.1. OCPP is a standardized communication protocol for electric vehicle charging stations and central management systems, developed by the Open Charge Alliance (OCA). For more information on OCPP, visit the [OCA website](https://openchargealliance.org/protocols/open-charge-point-protocol/). +![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) + +Libocpp is a comprehensive C++ library implementation of the Open Charge Point Protocol (OCPP) for versions 1.6 and 2.0.1. -### Development Status +OCPP is a standardized communication protocol for electric vehicle charging stations and central management systems, developed by the Open Charge Alliance (OCA). For more information on OCPP, visit the [OCA website](https://openchargealliance.org/protocols/open-charge-point-protocol/). -- OCPP 2.0.1: Under active development, with core functionalities available -- OCPP 1.6: Fully implemented and production-ready +| Development Status | +|:--| +|OCPP 2.0.1: Under active development, with core functionalities available | +|OCPP 1.6: Fully implemented and production-ready | ## Table of Contents | OCPP 2.0.1 | [OCPP 1.6](OCPP-1-6.md) | -|--|--| +|:--|:--| |
  1. Quickstart for OCPP 2.0.1
  2. Run OCPP 2.0.1 with EVerest
  3. Integrate OCPP 2.0.1 library with charging station
  4. Certification Profile Support
  5. CSMS Compatibility
  6. Database Initialization
|
  1. Quickstart for OCPP 1.6
  2. Run OCPP 1.6 with EVerest
  3. Integrate OCPP 1.6 library with charging station
  4. Feature Profile Support
  5. CSMS Compatibility
  6. Database Initialization
| For detailed information on each OCPP version, please refer to their respective README files linked above. From 398963e387ac65a54ce71c55b04d5129b6da50ef Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:53:56 -0400 Subject: [PATCH 017/134] Create ocpp_201_readme.md Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_readme.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/ocpp_201_readme.md diff --git a/doc/ocpp_201_readme.md b/doc/ocpp_201_readme.md new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/doc/ocpp_201_readme.md @@ -0,0 +1 @@ + From 66dcb48ed632dc85a620c71c37433a4ec30e38fd Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:54:28 -0400 Subject: [PATCH 018/134] Create ocpp_16_readme.md Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_readme.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/ocpp_16_readme.md diff --git a/doc/ocpp_16_readme.md b/doc/ocpp_16_readme.md new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/doc/ocpp_16_readme.md @@ -0,0 +1 @@ + From ec916cdd98b79ffe6f24f0d3c4ed591ef0c06101 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:55:20 -0400 Subject: [PATCH 019/134] Update ocpp_201_readme.md Added content for OCPP 2.0.1 Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_readme.md | 604 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 604 insertions(+) diff --git a/doc/ocpp_201_readme.md b/doc/ocpp_201_readme.md index 8b1378917..0d77dfaf5 100644 --- a/doc/ocpp_201_readme.md +++ b/doc/ocpp_201_readme.md @@ -1 +1,605 @@ +# C++ implementation of OCPP 2.0.1 + +![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) + +This is a C++ library implementation of OCPP for version 2.0.1 +(see [OCPP protocols at OCA website](https://openchargealliance.org/protocols/open-charge-point-protocol/)). + +It enables charging stations to communicate with cloud backends for remote +control, monitoring and billing of charging processes. + +Libocpp can be used for the communication of one charging station and multiple EVSE using a single websocket connection. + +The implementation of OCPP 2.0.1 is currently under development. + +## Get Involved + +See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. + +## Table of contents + +- [Support for OCPP 2.0.1](#support-for-ocpp-201) + - [Feature Profile Support OCPP 2.0.1](#feature-profile-support-ocpp-201) +- [CSMS Compatibility OCPP 2.0.1](#csms-compatibility-ocpp-201) +- [Run OCPP2.0.1 with EVerest](#run-ocpp201-with-everest) +- [Integrate this library with your Charging Station Implementation for OCPP2.0.1](#integrate-this-library-with-your-charging-station-implementation-for-ocpp201) + - [Register event callbacks and on\_handlers](#register-event-callbacks-and-on_handlers) + - [Initialize the database](#initialize-the-database) +- [Install libocpp](#install-libocpp) +- [Quickstart for OCPP 2.0.1](#quickstart-for-ocpp-201) +- [Building the doxygen documentation](#building-the-doxygen-documentation) +- [Unit testing](#unit-testing) +- [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) + +## Support for OCPP 2.0.1 + +The development of OCPP2.0.1 is in progress. +[Current implementation status.](/doc/ocpp_201_status.md) + +### Feature Profile Support OCPP 2.0.1 + +| Feature Profile | Supported | +| -------------------------- | ------------------------- | +| Core | :heavy_check_mark: yes | +| Advanced Security | WIP | +| Local Auth List Management | | +| Smart Charging | WIP | +| Advanced Device Management | | +| Advanced User Interface | | +| Reservation | | +| ISO 15118 support | WIP | + +| Whitepapers & Application Notes | Supported | +| ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | +| [OCPP & California Pricing Requirements](https://www.openchargealliance.org/uploads/files/ocpp_and_dms_evse_regulation-v2.0.pdf) | WIP | + + +## CSMS Compatibility OCPP 2.0.1 + +The current, ongoing implementation of OCPP 2.0.1 has been tested against a +few CSMS and is continuously tested against OCTT2. + +Additionally, the implementation has been tested against those CSMS: + +- [CitrineOS](https://lfenergy.org/projects/citrineos/) +- Chargepoint +- Current +- ihomer (Infuse CPMS) +- Instituto Tecnológico de la Energía (ITE) +- [MaEVe (Thoughtworks)](https://github.com/thoughtworks/maeve-csms) +- [Monta](https://monta.com) +- [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) +- Switch EV +- SWTCH + +## Run OCPP2.0.1 with EVerest + +This library is automatically integrated as the OCPP and OCPP201 module within [everest-core](https://github.com/EVerest/everest-core) - the complete software stack for your charging station. It is recommended to use EVerest together with this OCPP implementation. + +If you run libocpp with OCPP1.6 with EVerest, the build process of [everest-core](https://github.com/EVerest/everest-core) will take care of installing all necessary dependencies for you. This includes the initialization of the device model database using the [config.json](config/v201/config.json) file. + +## Integrate this library with your Charging Station Implementation for OCPP + +OCPP is a protocol that affects, controls and monitors many areas of a charging station's operation. + +If you want to integrate this library with your charging station implementation, you have to register a couple of **callbacks** and integrate **event handlers**. This is necessary for the library to interact with your charging station according to the requirements of OCPP. + +Libocpp needs registered **callbacks** in order to execute control commands defined within OCPP (e.g Reset.req or RemoteStartTransaction.req) + +The implementation must call **event handlers** of libocpp so that the library can track the state of the charging station and trigger OCPP messages accordingly (e.g. MeterValues.req , StatusNotification.req) + +Your reference within libocpp to interact is a single instance to the class [ChargePoint](include/ocpp/v16/charge_point.hpp) for OCPP 1.6 or to the class [ChargePoint](include/ocpp/v201/charge_point.hpp) for OCPP 2.0.1. + +### Overview of the required callbacks and events and what libocpp expects to happen + +The following section will give you a high level overview of how to integrate libocpp with your application. Please use the [Doxygen Documentation](#building-the-doxygen-documentation) as an additional source for the ChargePoint API. + +In EVerest the OCPP module leverages several other modules to perform tasks that relate to authorization, reservations, charging session handling and system tasks like rebooting or firmware updates. + +- Auth orchestrates authorization, utilizing different token providers like RFID reads and token validators. Libocpp mainly acts as a token validator, but in the case of RemoteStartTransactions it acts as a token provider as well +- EvseManager manages the charging session and charging state machine by communicating with a "board support package", a driver for the charging hardware that abstracts away the control pilot, relay control, power meters, etc. The EvseManager also handles reservations. +- System handles firmware updates, log uploads and resets + +The following sections explain the steps you can follow to implement their functionality on your own and integrate the libocpp directly into your charging station software without relying on EVerest. However, in most cases it's much easier to write an EVerest driver using the *everest-core/interfaces/board_support_AC.yaml* interface. + +## Usage for OCPP 2.0.1 + +### Smart Charging + +Work to fully support OCPP 2.0.1 Smart Charging is ongoing. Most functional requirements for General Smart Charging use cases (that is, K01–K10) are now supported. For an up-to-date overview of which features are currently supported, please refer to the [OCPP 2.0.1 Status](doc/ocpp_201_status.md) document. + +#### K01 SetChargingProfile + +Allows the CSMS to influence the charging power or current drawn from a specific EVSE or the +entire Charging Station over a period of time. + +```mermaid +sequenceDiagram + CSMS->>+ChargePoint : SetChargingProfileRequest(call) + + ChargePoint->>+DeviceModel : SmartChargingCtrlrAvailable? + DeviceModel-->>-ChargePoint : Component + + rect Red + break SmartChargingCtrlrAvailable = false + ChargePoint-->>CSMS : Smart Charging NotSupported CallError + end + end + + ChargePoint->>+SmartCharging : validate_and_add_profile(call.msg.Profile, call.msg.EVSE ID) + + SmartCharging->>SmartCharging : validate_profile(Profile, EVSE ID) + + rect Red + break Invalid Profile + SmartCharging-->>ChargePoint : SetChargingProfileResponse: Rejected + ChargePoint-->>CSMS : SetChargingProfileResponse: Rejected + end + end + + SmartCharging->>+SmartCharging : add_profile(Profile, EVSE ID) + SmartCharging->>-EVerest : signal_set_charging_profiles_callback + + SmartCharging-->>-ChargePoint : SetChargingProfileResponse: Accepted + + ChargePoint-->>-CSMS : SetChargingProfileResponse: Accepted +``` + +Profile validation returns the following errors to the caller when a Profile +is `Rejected`: + +- `ChargingProfileFirstStartScheduleIsNotZero` + + The `startPeriod` of the first `chargingSchedulePeriod` needs to be 0. + [K01.FR.31] + +- `ChargingProfileNoChargingSchedulePeriods` + + Happens when the `ChargingProfile` doesn't have any Charging Schedule + Periods. + +- `ChargingScheduleChargingRateUnitUnsupported` + + Happens when a chargingRateUnit is passed in that is not configured in the + `ChargingScheduleChargingRateUnit`. [K01.FR.26] + +- `ChargingSchedulePeriodInvalidPhaseToUse` + + Happens when an invalid `phaseToUse` is passed in. + + [K01.FR.19] [K01.FR.48] + +- `ChargingSchedulePeriodPhaseToUseACPhaseSwitchingUnsupported` + + Happens when phaseToUse is passed in and the EVSE does not have + `ACPhaseSwitchingSupported` defined and set to true. + [K01.FR.20] [K01.FR.48] + +- `ChargingSchedulePeriodsOutOfOrder` + + `ChargingSchedulePeriod.startPeriod` elements need to be in increasing + values. [K01.FR.35] + +- `ChargingStationMaxProfileCannotBeRelative` + + Happens when a `ChargingStationMaxProfile.chargingProfileKind` is set to + `Relative`. [K01.FR.38] + +- `ChargingStationMaxProfileEvseIdGreaterThanZero` + + Happens when a `ChargingStationMaxProfile` is attempted to be set with an + EvseID isn't `0`. [K01.FR.03] + +- `ChargingProfileMissingRequiredStartSchedule` + + Happens when an `Absolute` or `Recurring` `ChargingProfile` doesn't have + a `startSchedule`. [K01.FR.40] + +- `ChargingProfileExtraneousStartSchedule` + + Happens when a Relative `ChargingProfile` has a `startSchedule`. + [K01.FR.41] + +- `EvseDoesNotExist` + + Happens when the `evseId`of a `SetChargingProfileRequest` does not exist. + [K01.FR.28] + +- `ExistingChargingStationExternalConstraints` + + Happens when a `SetChargingProfileRequest` Profile has a purpose of + `ChargingStationExternalConstraints` and one already exists with the same + `ChargingProfile.id` exists. [K01.FR.05] + +- `InvalidProfileType` + + Happens when a `ChargingStationMaxProfile` is attempted to be set with a + `ChargingProfile` that isn't a `ChargingStationMaxProfile`. + +- `TxProfileEvseHasNoActiveTransaction` + + Happens when a `SetChargingProfileRequest` with a `TxProfile` is submitted + and there is no transaction active on the specified EVSE. [K01.FR.09] + +- `TxProfileEvseIdNotGreaterThanZero` + + `TxProfile` needs to have an `evseId` greater than 0. [K01.FR.16] + +- `TxProfileMissingTransactionId` + + A `transactionId` is required for `SetChargingProfileRequest`s with a + `TxProfile` in order to match the profile to a specific transation. [K01.FR.03] + +- `TxProfileTransactionNotOnEvse` + + Happens when the provided `transactionId` is not known. [K01.FR.33] + +- `TxProfileConflictingStackLevel` + + Happens when a `TxProfile` has a `stackLevel` and `transactionId` + combination already exists in a `TxProfile` with a different id in + order to ensure that no two charging profiles with same stack level and + purpose can be valid at the same time. [K01.FR.39] + +#### K08 Get Composite Schedule + +The CSMS requests the Charging Station to report the Composite Charging +Schedule, as calculated by the Charging Station for a specific point of +time, and may change over time due to external causes such as local +balancing based on grid connection capacity and EVSE availablity. + +The Composite Schedule is the result of result of merging the time periods +set in the `ChargingStationMaxProfile`, `ChargingStationExternalConstraints`, +`TxDefaultProfile` and `TxProfile` type profiles. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: GetCompositeSchedule(call) + + ChargePoint->>+DeviceModel : ChargingScheduleChargingRateUnit? + DeviceModel-->>-ChargePoint : Component + + rect Red + break call.msg.chargingRateUnit is not supported + ChargePoint-->>CSMS : ChargingScheduleChargingRateUnitUnsupported CallError + end + end + + ChargePoint->>+EvseManager : does_evse_exist(call.msg.evseId) + EvseManager-->>-ChargePoint : bool + rect Red + break EVSE does not exist + ChargePoint-->>CSMS : EvseDoesNotExist CallError + end + end + + ChargePoint->>+SmartChargingHandler : get_valid_profiles(call.msg.evseId) + + SmartChargingHandler-->>-ChargePoint : vector + + ChargePoint->>+SmartChargingHandler : calculate_composite_schedule
(vector>+Profile: calculate_composite_schedule(profiles) + Profile-->>-SmartChargingHandler: composite_schedule + end + + note right of SmartChargingHandler: Create consolidated CompositeSchedule
from all 4 Profile types + + + SmartChargingHandler->>+Profile: calculate_composite_schedule(ExternalConstraints, Max, TxDefault, Tx) + Profile-->>-SmartChargingHandler: CompositeSchedule + + SmartChargingHandler-->>-ChargePoint: CompositeSchedule + + ChargePoint-->>-CSMS : GetCompositeScheduleResponse(CompositeSchedule) +``` + +#### K09 Get Charging Profiles + +Returns to the CSMS the Charging Schedules/limits installed on a Charging Station based on the +passed in criteria. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: GetChargingProfiles(criteria) + + ChargePoint->>+SmartChargingHandler : get_reported_profiles(criteria) + + loop filter ChargingProfiles + SmartChargingHandler->>SmartChargingHandler: filter on ChargingProfile criteria + end + + SmartChargingHandler-->>-ChargePoint : Vector + + ChargePoint-->>CSMS : GetChargingProfilesResponse(profiles) + + alt no Profiles + rect Red + ChargePoint-->>CSMS : GetChargingProfilesResponse(NoProfiles) + ChargePoint->>CSMS : return + end + + else Profiles + ChargePoint-->>CSMS : GetChargingProfilesResponse(Accepted) + end + + ChargePoint->>ChargePoint : determine profiles_to_report + + ChargePoint-->>-CSMS : ReportChargingProfilesRequest(profiles_to_report) +``` + +#### K10 Clear Charging Profile + +Clears Charging Profiles installed on a Charging Station based on the +passed in criteria. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: ClearChargingProfileRequest(criteria) + + alt no Profiles matching criteria + rect Red + ChargePoint-->>CSMS : ClearChargingProfileResponse(Unknown) + + end + + else found matching Profiles + ChargePoint-->>-CSMS : ClearChargingProfileResponse(Accepted) + end +``` + +### Register event callbacks and on_handlers + +- `all_connectors_unavailable_callback` + + Notifies that all connectors are unavailable. Used to handle charge availability + requests and firmware updates. + +- `boot_notification_callback` + + Callback to notify of a system boot + +- `clear_customer_information_callback` + + Called to clear customer information based on passed in Customer Certificate, the + IdToken for this request, and the Customer Identified that the request refers to. + If IdToken is passed in will delete authorization cache entry from database. + +- `configure_network_connection_profile_callback` + + Called to configure a network connection profile when none is configured. + +- `connector_effective_operative_status_changed_callback` + + Notifies the user of liboccp that the Operative/Inoperative state of a specific EVSE + has changed. + +- `cs_effective_operative_status_changed_callback` + + Used to notify the user of libocpp that the Operative/Inoperative state of the + charging station itself has changed. Will also call + `evse_effective_operative_status_changed_callback` for each EVSE, and + `connector_effective_operative_status_changed_callback` for each connector whose + status has changed. + +- `data_transfer_callback` + + Used to handle arbitrary data transfers. + +- `evse_effective_operative_status_changed_callback` + + Notifies the user of libocpp that the Operative/Inoperative state of an EVSE has + changed. If as a result the state of connectors changed as well, libocpp will + additionally call the connector_effective_operative_status_changed_callback for + each connector. + +- `get_customer_information_callback` + + Returns human readable customer information based on the CertificateHashDataType, + IdToken and Customer Identifier passed in. + +- `get_log_request_callback` + + Callback to return logs + +- `is_reservation_for_token_callback` + + Check if the current reservation for the given evse id is made for the id + token / group id token. + +- `is_reset_allowed_callback` + + Callback if reset is allowed. If evse_id has a value, reset only applies + to the given evse id. If it has no value, applies to complete charging station. + +- `ocpp_messages_callback` + + Callback to congfigure ocpp message logging. + +- `pause_charging_callback` + + Used to request pausing of charging, the "connector" parameter instructing which + connector/EVSE to pause. + +- `remote_start_transaction_callback` + + Called when the request can be accepted. The boolean authorize_remote_start + indicates if Authorize.req needs to follow or not + +- `reset_callback` + + Performs a reset of the requested type + +- `security_event_callback` + + Used to react to a security event callback. This callback is + called only if the SecurityEvent occured internally within libocpp. + Typically this callback is used to log security events in the security log. + +- `set_charging_profiles_callback` + + Indicates when a charging profile is received and accepted. + +- `stop_transaction_callback` + + Used to stop a transaction. Called when the idTagInfo.status of a + StartTransaction.conf is not Accepted, when a RemoteStopTransaction.req is + received, or when an UnlockConnector.req is received. + +- `time_sync_callback` + + Called on boot notification if the TimeSource ControllerComponent contains + Heartbeat. + +- `transaction_event_callback` + + Called when a transaction_event was sent to the CSMS. + +- `transaction_event_response_callback` + + Called when a transaction_event_response was received from the CSMS. + +- `unlock_connector_callback` + + Used by libocpp to force unlock a connector + +- `update_firmware_request_callback` + + Initiates a firmware update request. Triggers a security event notification + if the certificate is Invalid or Revoked. + +- `validate_network_profile_callback` + + Validates the submitted Network Profile. Is Rejected if + - No callback registered to validate network profile + - CSMS attempted to set a network profile with a lower securityProfile + - CSMS attempted to set a network profile that could not be validated + - Network profile could not be written to the device model storage + +- `variable_changed_callback` + + Called when a variable has been changed by the CSMS + +### Initialize the database + +- Use provided sql database or implement your own storage drive + +## Install libocpp + +For Debian GNU/Linux 11 you will need the following dependencies: + +```bash + sudo apt install build-essential cmake python3-pip libboost-all-dev libsqlite3-dev libssl-dev +``` + +OpenSSL version 3.0 or above is required. + +Clone this repository. + +```bash + git clone https://github.com/EVerest/libocpp +``` + +In the libocpp folder create a folder named build and cd into it. +Execute cmake and then make install: + +```bash + mkdir build && cd build + cmake .. + make install +``` + +## Quickstart for OCPP 2.0.1 + +Libocpp provides a small standalone OCPP2.0.1 client that you can control using command line. + +Install the dependencies and libocpp as described in [Install libocpp](#install-libocpp). + +Make sure you modify the following config entries in the [config.json](config/v201/config.json) file according to the CSMS you want to connect to before executing make install. + +```json +{ + "Internal": { + "ChargePointId": "", + "CentralSystemURI": "" + } +} +``` + +Change into libocpp/build and execute cmake and then make install: + +```bash + cd build + cmake -DLIBOCPP16_BUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=./dist .. + make -j$(nproc) install +``` + +Use the following command to start the charge point. Replace the config with [config-docker.json](config/v16/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. + +```bash + ./dist/bin/charge_point \ + --maindir ./dist \ + --conf config.json +``` + +Type `help` to see a list of possible commands. + +## Building the doxygen documentation + +```bash + cmake -S . -B build + cmake --build build --target doxygen-ocpp +``` + +You will find the generated doxygen documentation at: +`build/dist/docs/html/index.html` + +The main reference for the integration of libocpp for OCPP2.0.1 is the ocpp::v201::ChargePoint class defined in libocpp/include/ocpp/v201/charge_point.hpp . + +## Unit testing + +GTest is required for building the test cases target. +To build the target and run the tests you can reference the script `.ci/build-kit/install_and_test.sh`. +The script allows the GitHub Actions runner to execute. + +Local testing: + +```bash +mkdir build +cmake -B build -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="./dist" +cd build +make -j$(nproc) install +``` + +Run any required tests from build/tests. + +## Building with FetchContent instead of EDM + +In [doc/build-with-fetchcontent](doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. + +### Support for TPM keys + +In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. + +## Support for websocket++ + +The old websocket++ implementation has been deprecated. For enabling websocket++ support use the following cmake option: + +```bash + cmake .. -DLIBOCPP_ENABLE_DEPRECATED_WEBSOCKETPP=ON +``` + +### Support for iface + +In order to connect through a custom network iface, a custom internal config variable 'IFace' can be used. + +```json +"Internal": { + "IFace" : "enp43s0" +} +``` From d6b4097b5c8eacd3a73b1d4881828fcfb1cd6a54 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:55:57 -0400 Subject: [PATCH 020/134] Update ocpp_16_readme.md added content for OCPP 1.6 Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_readme.md | 644 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 644 insertions(+) diff --git a/doc/ocpp_16_readme.md b/doc/ocpp_16_readme.md index 8b1378917..d76208d67 100644 --- a/doc/ocpp_16_readme.md +++ b/doc/ocpp_16_readme.md @@ -1 +1,645 @@ +# C++ implementation of OCPP 1.6 +![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) + +This C++ library provides a complete and production-ready solution for integrating OCPP 1.6 into your electric vehicle (EV) charging stations. Our implementation enables seamless communication between charging stations and central management systems, supporting remote control, monitoring, and billing functionalities. + +NOTE: [EVerest OCPP 2.0.1](OCPP-2-0-1.md) is under active development, with core functionalities available. + + +## Table of contents + +- [Feature Profile Support OCPP 1.6](#feature-profile-support-ocpp-16) +- [CSMS Compatibility OCPP 1.6](#csms-compatibility-ocpp-16) +- [Integration with EVerest](#integration-with-everest) + - [Run OCPP1.6 with EVerest](#run-ocpp16-with-everest) + - [Integrate this library with your Charging Station Implementation for OCPP1.6](#integrate-this-library-with-your-charging-station-implementation-for-ocpp16) + - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) + - [ChargePoint() constructor](#chargepoint-constructor) + - [registering callbacks](#registering-callbacks) + - [Functions that need to be triggered from the outside after new information is availble (on\_... functions in the charge point API)](#functions-that-need-to-be-triggered-from-the-outside-after-new-information-is-availble-on_-functions-in-the-charge-point-api) + - [The following functions are triggered depending on different so called "Session Events" from the EvseManager](#the-following-functions-are-triggered-depending-on-different-so-called-session-events-from-the-evsemanager) + - [Authorization](#authorization) + - [Install libocpp](#install-libocpp) + - [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) + - [Building the doxygen documentation](#building-the-doxygen-documentation) + - [Unit testing](#unit-testing) + - [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) + - [Support for security profile 2 and 3 with TPM in OCPP 1.6 using libwebsockets](#support-for-security-profile-2-and-3-with-tpm-in-ocpp-16-using-libwebsockets) + +## OCPP 1.6 Support + +The following tables show the current support for the listed OCPP 1.6 feature profiles / functional blocks and application notes. + +All documentation and the issue tracking can be found in our main repository here: https://github.com/EVerest/ + +### Feature Profile Support OCPP 1.6 + +| Feature Profile | Supported | +| -------------------------- | ------------------------- | +| Core | :heavy_check_mark: yes | +| Firmware Management | :heavy_check_mark: yes | +| Local Auth List Management | :heavy_check_mark: yes | +| Reservation | :heavy_check_mark: yes | +| Smart Charging | :heavy_check_mark: yes | +| Remote Trigger | :heavy_check_mark: yes | + +## CSMS Compatibility + +### CSMS Compatibility OCPP 1.6 + +The EVerest implementation of OCPP 1.6 has been tested against the +OCPP Compliance Test Tool (OCTT and OCTT2) during the implementation. + +The following table shows CSMS with which this library was tested. +If you provide a CSMS that is not yet listed here, feel free to +[contact us](https://lists.lfenergy.org/g/everest)! + +- chargecloud +- chargeIQ +- Chargetic +- Compleo +- Current +- Daimler Truck +- ev.energy +- eDRV +- Fastned +- [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) +- Electrip Global +- EnergyStacks +- EV-Meter +- Fraunhofer IAO (ubstack CHARGE) +- Green Motion +- gridundco +- ihomer (Infuse CPMS) +- iLumen +- JibeCompany (CharlieV CMS and Chargebroker proxy) +- MSI +- PUMP (PUMP Connect) +- Scoptvision (Scopt Powerconnect) +- Siemens +- [SteVe](https://github.com/steve-community/steve) +- Syntech +- Trialog +- ubitricity +- Weev Energy + +## Integration with EVerest + +This library is automatically integrated as the OCPP and OCPP201 module within [everest-core](https://github.com/EVerest/everest-core) - the complete software stack for your charging station. It is recommended to use EVerest together with this OCPP implementation. + +### Run OCPP1.6 with EVerest + +If you run libocpp with OCPP1.6 with EVerest, the build process of [everest-core](https://github.com/EVerest/everest-core) will take care of installing all necessary dependencies for you. + +## Integrate this library with your Charging Station Implementation for OCPP + +OCPP is a protocol that affects, controls and monitors many areas of a charging station's operation. + +If you want to integrate this library with your charging station implementation, you have to register a couple of **callbacks** and integrate **event handlers**. This is necessary for the library to interact with your charging station according to the requirements of OCPP. + +Libocpp needs registered **callbacks** in order to execute control commands defined within OCPP (e.g Reset.req or RemoteStartTransaction.req) + +The implementation must call **event handlers** of libocpp so that the library can track the state of the charging station and trigger OCPP messages accordingly (e.g. MeterValues.req , StatusNotification.req) + +Your reference within libocpp to interact is a single instance to the class [ChargePoint](include/ocpp/v16/charge_point.hpp) for OCPP 1.6. + +### Overview of the required callbacks and events and what libocpp expects to happen + +The following section will give you a high level overview of how to integrate libocpp with your application. Please use the [Doxygen Documentation](#building-the-doxygen-documentation) as an additional source for the ChargePoint API. + +In EVerest the OCPP module leverages several other modules to perform tasks that relate to authorization, reservations, charging session handling and system tasks like rebooting or firmware updates. + +- Auth orchestrates authorization, utilizing different token providers like RFID reads and token validators. Libocpp mainly acts as a token validator, but in the case of RemoteStartTransactions it acts as a token provider as well +- EvseManager manages the charging session and charging state machine by communicating with a "board support package", a driver for the charging hardware that abstracts away the control pilot, relay control, power meters, etc. The EvseManager also handles reservations. +- System handles firmware updates, log uploads and resets + +The following sections explain the steps you can follow to implement their functionality on your own and integrate the libocpp directly into your charging station software without relying on EVerest. However, in most cases it's much easier to write an EVerest driver using the *everest-core/interfaces/board_support_AC.yaml* interface. + +### Usage for OCPP 1.6 + +#### ChargePoint() constructor + +The main entrypoint for libocpp for OCPP1.6 is the ocpp::v16::ChargePoint constructor. +This is defined in libocpp/include/ocpp/v16/charge_point.hpp and takes the following parameters: + +- config: a std::string that contains the libocpp 1.6 config. There are example configs that work with a [SteVe](https://github.com/steve-community/steve) installation [running in Docker](https://github.com/EVerest/everest-utils/tree/main/docker/steve), for example: [config-docker.json](config/v16/config-docker.json) + +- share_path: a std::filesystem path containing the path to the OCPP modules folder, for example pointing to */usr/share/everest/modules/OCPP*. This path contains the following files and directories and is installed by the libocpp install target: + + ```bash + . + ├── config-docker.json + ├── config-docker-tls.json + ├── config.json + ├── init.sql + ├── logging.ini + └── profile_schemas + ├── Config.json + ├── Core.json + ├── FirmwareManagement.json + ├── Internal.json + ├── LocalAuthListManagement.json + ├── PnC.json + ├── Reservation.json + ├── Security.json + ├── SmartCharging.json + └── Custom.json + ``` + + Here you can find: + - the aforementioned config files + + - a *logging.ini* that is needed to initialize logging with Everest::Logging::init(path_to_logging_ini, "name_of_binary") + + - a *init.sql* file which contains the database schema used by libocpp for its sqlite database + + - and a *profile_schemas* directory. This contains json schema files that are used to validate the libocpp config. The schemas are split up according to the OCPP1.6 feature profiles like Core, FirmwareManagement and so on. Additionally there is a schema for "Internal" configuration options (for example the ChargePointId, or CentralSystemURI). A "PnC" schema for the ISO 15118 Plug & Charge with OCPP 1.6 Application note, a "Security" schema for the OCPP 1.6 Security Whitepaper (3rd edition) and an exemplary "Custom" schema are provided as well. The Custom.json could be modified to be able to add custom configuration keys. Finally there's a Config.json schema that ties everything together + +- user_config_path: this points to a "user config", which we call a configuration file that's merged with the config that's provided in the "config" parameter. Here you can add, remove and overwrite settings without modifying the config passed in the first parameter directly. This is also used by libocpp to persistently modify config entries that are changed by the CSMS that should persist across restarts. + +- database_path: this points to the location of the sqlite database that libocpp uses to keep track of connector availability, the authorization cache and auth list, charging profiles and transaction data + +- sql_init_path: this points to the aforementioned init.sql file which contains the database schema used by libocpp for its sqlite database + +- message_log_path: this points to the directory in which libocpp can put OCPP communication logfiles for debugging purposes. This behavior can be controlled by the "LogMessages" (set to true by default) and "LogMessagesFormat" (set to ["log", "html", "session_logging"] by default, "console" and "console_detailed" are also available) configuration keys in the "Internal" section of the config file. Please note that this is intended for debugging purposes only as it logs all communication, including authentication messages. + +- evse_security: this is a pointer to an implementation of the [evse_security](include/ocpp/common/evse_security.hpp) interface. This allows you to include your custom implementation of the security related operations according to this interface. If you set this value to nullptr, the internal implementation of the security related operations of libocpp will be used. In this case you need to specify the parameter security_configuration + +- security_configuration: this parameter should only be set in case the evse_security parameter is nullptr. It specifies the file paths that are required to set up the internal evse_security implementation. Note that you need to specify bundle files for the CA certificates and directories for the certificates and keys + + The directory layout expected is as follows + + ```bash + . + ├── ca + │ ├── csms + │ │ └── CSMS_ROOT_CA.pem + │ ├── cso + │ │ ├── CPO_CERT_CHAIN.pem + │ │ ├── CPO_SUB_CA1_LEAF.der + │ │ ├── CPO_SUB_CA1.pem + │ │ ├── CPO_SUB_CA2_LEAF.der + │ │ └── CPO_SUB_CA2.pem + │ ├── mf + │ │ └── MF_ROOT_CA.pem + │ ├── mo + │ │ ├── INTERMEDIATE_MO_CA_CERTS.pem + │ │ ├── MO_ROOT_CA.der + │ │ ├── MO_ROOT_CA.pem + │ │ ├── MO_SUB_CA1.der + │ │ ├── MO_SUB_CA1.pem + │ │ ├── MO_SUB_CA2.der + │ │ └── MO_SUB_CA2.pem + │ └── v2g + │ ├── V2G_ROOT_CA.der + │ └── V2G_ROOT_CA.pem + ├── client + │ ├── csms + │ │ ├── CPO_CERT_CHAIN.pem + │ │ ├── CPO_SUB_CA1.key + │ │ ├── CPO_SUB_CA2.key + │ │ ├── SECC_LEAF.der + │ │ ├── SECC_LEAF.key + │ │ └── SECC_LEAF.pem + │ ├── cso + │ │ ├── CPO_CERT_CHAIN.pem + │ │ ├── CPO_SUB_CA1.key + │ │ ├── CPO_SUB_CA2.key + │ │ ├── SECC_LEAF.der + │ │ ├── SECC_LEAF.key + │ │ └── SECC_LEAF.pem + │ └── v2g + │ └── V2G_ROOT_CA.key + ``` + +#### registering callbacks + +You can (and in many cases MUST) register a number of callbacks so libocpp can interact with the charger. In EVerest most of this functionality is orchestrated by the "EvseManager" module, but you can also register your own callbacks interacting directly with your chargers software. Following is a list of callbacks that you must register and a few words about their purpose. + +TODO: in a future version of libocpp the callbacks will be organised in a struct with optional members emphasizing the required and optional callbacks. + +Some general notes: the "connector" parameter of some of the callbacks refers to the connector number as understood in the OCPP 1.6 specification, "0" means the whole charging station, the connectors with EVSEs used for charging cars start at "1". + +- `register_pause_charging_callback` + + this callback is used by libocpp to request pausing of charging, the "connector" parameter tells you which connector/EVSE has to pause charging + +- `register_resume_charging_callback` + + this callback is used by libocpp the request resuming of charging, the "connector" parameter tells you which connector/EVSE can resume charging + +- `register_stop_transaction_callback` + + in EVerest this calls the EvseManagers stop_transaction command which "Stops transactions and cancels charging externally, charging can only be resumed by replugging car. EVSE will also stop transaction automatically e.g. on disconnect, so this only needs to be called if the transaction should end before." + this will then signal the following events: + - ChargingFinished + - TransactionFinished + +- `register_unlock_connector_callback` + + can be used by libocpp to force unlock a connector + +- `register_reserve_now_callback` + + libocpp can use this to reserve a connector, reservation handling is outsourced to a reservation manager in EVerest that implements the reservation interface (everest-core/interfaces/reservation.yaml) + +- `register_upload_diagnostics_callback` + + uses a function (in EVerest provided by the System module) to upload the requested diagnostics file + +- `register_upload_logs_callback` + + uses a function (in EVerest provided by the System module) to upload the requested log file + +- `register_update_firmware_callback` + + uses a function (in EVerest provided by the System module) to perform a firmware update + +- `register_signed_update_firmware_callback` + + uses a function (in EVerest provided by the System module) to perform a signed firmware update + +- `register_provide_token_callback` + + this callback is used in a remote start transaction to provide a token (prevalidated or not) to the authorization system + +- `register_set_connection_timeout_callback` + + used by libocpp to set the authorization or plug in connection timeout in the authorization system based on the "ConnectionTimeout" configuration key + +- `register_disable_evse_callback` + + used to disable the EVSE (ChangeAvailability.req) + +- `register_enable_evse_callback` + + used to enable the EVSE (ChangeAvailability.req) + +- `register_cancel_reservation_callback` + + used to cancel a reservation in the reservation manager (CancelReservation.req) + +- `register_signal_set_charging_profiles_callback` + + used to signal that new charging schedule(s) have been set, you can then use + get_all_composite_charging_schedules(duration_s) to get the new valid charging schedules + +- `register_is_reset_allowed_callback` + + used to inquire (in EVerest from the System module) if a reset is allowed + +- `register_reset_callback` + + used to perform a reset of the requested type + +- `register_connection_state_changed_callback` + + used to inform about the connection state to the CSMS (connected = true, disconnected = false) + +- `register_configuration_key_changed_callback` + + used to react on a changed configuration key. This callback is called when the specified configuration key has been changed by the CSMS + +#### Functions that need to be triggered from the outside after new information is availble (on_... functions in the charge point API) + +- `on_log_status_notification(int32_t request_id, std::string log_status)` + + can be used to notify libocpp of a log status notification + +- `on_firmware_update_status_notification(int32_t request_id, std::string firmware_update_status)` + + can be used to notify libocpp of a firmware update status notification + +- `on_meter_values(int32_t connector, const Powermeter& powermeter)` + + provides a Powermeter struct to libocpp (for sending meter values during charging sessions or periodically) + +- `on_max_current_offered(int32_t connector, int32_t max_current)` + + the maximum current offered to the EV on this connector (in ampere) + +#### The following functions are triggered depending on different so called "Session Events" from the EvseManager + +each of these functions will have a small note what the Session Event was and what it triggers in libocpp + +- `on_enabled(int32_t connector)` + + Notifies libocpp that the connector is functional and operational + +- `on_disabled(int32_t connector)` + + Notifies libocpp that the connector is disabled + +- `on_transaction_started` + + Notifies libocpp that a transaction at the given connector has started, this means that authorization is available and the car is plugged in. + + Some of its parameters: + + - `session_id` is an internal session_id originating in the EvseManager to keep track of the transaction, this is NOT to be mistaken for the transactionId from the StartTransactionResponse in OCPP! + - `id_token` is the token with which the transaction was authenticated + - `meter_start` contains the meter value in Wh for the connector at start of the transaction + - `timestamp` at the start of the transaction + +- `on_transaction_stopped` + + Notifies libocpp that the transaction on the given connector with the given reason has been stopped. + + Some of its parameters: + + - `timestamp` at the end of the transaction + - `energy_wh_import` contains the meter value in Wh for the connector at end of the transaction + +- `on_suspend_charging_ev` + + Notifies libocpp that the EV has paused charging + +- `on_suspend_charging_evse` + + Notifies libocpp that the EVSE has paused charging + +- `on_resume_charging` + + Notifies libocpp that charging has resumed + +- `on_session_started` + + this is mostly used for logging and changing the connector state + +- `on_session_stopped` + + this is mostly used for logging and changing the connector state + +- `on_error` + + Notify libocpp of an error + +- `on_reservation_start` + + Notifies libocpp that a reservation has started + +- `on_reservation_end` + + Notifies libocpp that a reservation has ended + +#### Authorization + +In EVerest authorization is handled by the Auth module and various auth token providers and validators. The OCPP module acts as both a token provider (for pre validated tokens in RemoteStartTransactions) and a token validator (using the authorize requests, or plug & charge). + +To use libocpp as a auth token validator (e.g. before starting a transaction) you can call the "authorize_id_token" function of the ChargePoint object. + +### Register event callbacks and on_handlers + +- `all_connectors_unavailable_callback` + + Notifies that all connectors are unavailable. Used to handle charge availability + requests and firmware updates. + +- `boot_notification_callback` + + Callback to notify of a system boot + +- `clear_customer_information_callback` + + Called to clear customer information based on passed in Customer Certificate, the + IdToken for this request, and the Customer Identified that the request refers to. + If IdToken is passed in will delete authorization cache entry from database. + +- `configure_network_connection_profile_callback` + + Called to configure a network connection profile when none is configured. + +- `connector_effective_operative_status_changed_callback` + + Notifies the user of liboccp that the Operative/Inoperative state of a specific EVSE + has changed. + +- `cs_effective_operative_status_changed_callback` + + Used to notify the user of libocpp that the Operative/Inoperative state of the + charging station itself has changed. Will also call + `evse_effective_operative_status_changed_callback` for each EVSE, and + `connector_effective_operative_status_changed_callback` for each connector whose + status has changed. + +- `data_transfer_callback` + + Used to handle arbitrary data transfers. + +- `evse_effective_operative_status_changed_callback` + + Notifies the user of libocpp that the Operative/Inoperative state of an EVSE has + changed. If as a result the state of connectors changed as well, libocpp will + additionally call the connector_effective_operative_status_changed_callback for + each connector. + +- `get_customer_information_callback` + + Returns human readable customer information based on the CertificateHashDataType, + IdToken and Customer Identifier passed in. + +- `get_log_request_callback` + + Callback to return logs + +- `is_reservation_for_token_callback` + + Check if the current reservation for the given evse id is made for the id + token / group id token. + +- `is_reset_allowed_callback` + + Callback if reset is allowed. If evse_id has a value, reset only applies + to the given evse id. If it has no value, applies to complete charging station. + +- `ocpp_messages_callback` + + Callback to congfigure ocpp message logging. + +- `pause_charging_callback` + + Used to request pausing of charging, the "connector" parameter instructing which + connector/EVSE to pause. + +- `remote_start_transaction_callback` + + Called when the request can be accepted. The boolean authorize_remote_start + indicates if Authorize.req needs to follow or not + +- `reset_callback` + + Performs a reset of the requested type + +- `security_event_callback` + + Used to react to a security event callback. This callback is + called only if the SecurityEvent occured internally within libocpp. + Typically this callback is used to log security events in the security log. + +- `set_charging_profiles_callback` + + Indicates when a charging profile is received and accepted. + +- `stop_transaction_callback` + + Used to stop a transaction. Called when the idTagInfo.status of a + StartTransaction.conf is not Accepted, when a RemoteStopTransaction.req is + received, or when an UnlockConnector.req is received. + +- `time_sync_callback` + + Called on boot notification if the TimeSource ControllerComponent contains + Heartbeat. + +- `transaction_event_callback` + + Called when a transaction_event was sent to the CSMS. + +- `transaction_event_response_callback` + + Called when a transaction_event_response was received from the CSMS. + +- `unlock_connector_callback` + + Used by libocpp to force unlock a connector + +- `update_firmware_request_callback` + + Initiates a firmware update request. Triggers a security event notification + if the certificate is Invalid or Revoked. + +- `validate_network_profile_callback` + + Validates the submitted Network Profile. Is Rejected if + - No callback registered to validate network profile + - CSMS attempted to set a network profile with a lower securityProfile + - CSMS attempted to set a network profile that could not be validated + - Network profile could not be written to the device model storage + +- `variable_changed_callback` + + Called when a variable has been changed by the CSMS + +### Initialize the database + +- Use provided sql database or implement your own storage drive + +## Install libocpp + +For Debian GNU/Linux 11 you will need the following dependencies: + +```bash + sudo apt install build-essential cmake python3-pip libboost-all-dev libsqlite3-dev libssl-dev +``` + +OpenSSL version 3.0 or above is required. + +Clone this repository. + +```bash + git clone https://github.com/EVerest/libocpp +``` + +In the libocpp folder create a folder named build and cd into it. +Execute cmake and then make install: + +```bash + mkdir build && cd build + cmake .. + make install +``` + +## Quickstart for OCPP 1.6 + +Libocpp provides a small standalone OCPP1.6 client that you can control using command line. + +Install the dependencies and libocpp as described in [Install libocpp](#install-libocpp). + +Make sure you modify the following config entries in the [config.json](config/v16/config.json) file according to the CSMS you want to connect to before executing make install. + +```json +{ + "Internal": { + "ChargePointId": "", + "CentralSystemURI": "" + } +} +``` + +Change into libocpp/build and execute cmake and then make install: + +```bash + cd build + cmake -DLIBOCPP16_BUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=./dist .. + make -j$(nproc) install +``` + +Use the following command to start the charge point. Replace the config with [config-docker.json](config/v16/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. + +```bash + ./dist/bin/charge_point \ + --maindir ./dist \ + --conf config.json +``` + +Type `help` to see a list of possible commands. + +## Building the doxygen documentation + +```bash + cmake -S . -B build + cmake --build build --target doxygen-ocpp +``` + +You will find the generated doxygen documentation at: +`build/dist/docs/html/index.html` + +The main reference for the integration of libocpp for OCPP1.6 is the ocpp::v16::ChargePoint class defined in libocpp/include/ocpp/v16/charge_point.hpp . + +## Unit testing + +GTest is required for building the test cases target. +To build the target and run the tests you can reference the script `.ci/build-kit/install_and_test.sh`. +The script allows the GitHub Actions runner to execute. + +Local testing: + +```bash +mkdir build +cmake -B build -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="./dist" +cd build +make -j$(nproc) install +``` + +Run any required tests from build/tests. + +## Building with FetchContent instead of EDM + +In [doc/build-with-fetchcontent](doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. + +### Support for TPM keys + +In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. + +## Support for websocket++ + +The old websocket++ implementation has been deprecated. For enabling websocket++ support use the following cmake option: + +```bash + cmake .. -DLIBOCPP_ENABLE_DEPRECATED_WEBSOCKETPP=ON +``` + +### Support for iface + +In order to connect through a custom network iface, a custom internal config variable 'IFace' can be used. + +```json +"Internal": { + "IFace" : "enp43s0" +} +``` + +## Get Involved + +See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. From 26b82942752f4124a6f5163828a497e055841b37 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:57:14 -0400 Subject: [PATCH 021/134] Delete OCPP-2-0-1.md moved content to new folder Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- OCPP-2-0-1.md | 604 -------------------------------------------------- 1 file changed, 604 deletions(-) delete mode 100644 OCPP-2-0-1.md diff --git a/OCPP-2-0-1.md b/OCPP-2-0-1.md deleted file mode 100644 index 7f1621ec3..000000000 --- a/OCPP-2-0-1.md +++ /dev/null @@ -1,604 +0,0 @@ -# C++ implementation of OCPP 2.0.1 - -![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) - -This is a C++ library implementation of OCPP for version 2.0.1 -(see [OCPP protocols at OCA website](https://openchargealliance.org/protocols/open-charge-point-protocol/)). - -It enables charging stations to communicate with cloud backends for remote -control, monitoring and billing of charging processes. - -Libocpp can be used for the communication of one charging station and multiple EVSE using a single websocket connection. - -The implementation of OCPP 2.0.1 is currently under development. - -## Get Involved - -See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. - -## Table of contents - -- [Support for OCPP 2.0.1](#support-for-ocpp-201) - - [Feature Profile Support OCPP 2.0.1](#feature-profile-support-ocpp-201) -- [CSMS Compatibility OCPP 2.0.1](#csms-compatibility-ocpp-201) -- [Run OCPP2.0.1 with EVerest](#run-ocpp201-with-everest) -- [Integrate this library with your Charging Station Implementation for OCPP2.0.1](#integrate-this-library-with-your-charging-station-implementation-for-ocpp201) - - [Register event callbacks and on\_handlers](#register-event-callbacks-and-on_handlers) - - [Initialize the database](#initialize-the-database) -- [Install libocpp](#install-libocpp) -- [Quickstart for OCPP 2.0.1](#quickstart-for-ocpp-201) -- [Building the doxygen documentation](#building-the-doxygen-documentation) -- [Unit testing](#unit-testing) -- [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) - -## Support for OCPP 2.0.1 - -The development of OCPP2.0.1 is in progress. -[Current implementation status.](/doc/ocpp_201_status.md) - -### Feature Profile Support OCPP 2.0.1 - -| Feature Profile | Supported | -| -------------------------- | ------------------------- | -| Core | :heavy_check_mark: yes | -| Advanced Security | WIP | -| Local Auth List Management | | -| Smart Charging | WIP | -| Advanced Device Management | | -| Advanced User Interface | | -| Reservation | | -| ISO 15118 support | WIP | - -| Whitepapers & Application Notes | Supported | -| ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | -| [OCPP & California Pricing Requirements](https://www.openchargealliance.org/uploads/files/ocpp_and_dms_evse_regulation-v2.0.pdf) | WIP | - - -## CSMS Compatibility OCPP 2.0.1 - -The current, ongoing implementation of OCPP 2.0.1 has been tested against a -few CSMS and is continuously tested against OCTT2. - -Additionally, the implementation has been tested against those CSMS: - -- [CitrineOS](https://lfenergy.org/projects/citrineos/) -- Chargepoint -- Current -- ihomer (Infuse CPMS) -- Instituto Tecnológico de la Energía (ITE) -- [MaEVe (Thoughtworks)](https://github.com/thoughtworks/maeve-csms) -- [Monta](https://monta.com) -- [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) -- Switch EV -- SWTCH - -## Run OCPP2.0.1 with EVerest - -This library is automatically integrated as the OCPP and OCPP201 module within [everest-core](https://github.com/EVerest/everest-core) - the complete software stack for your charging station. It is recommended to use EVerest together with this OCPP implementation. - -If you run libocpp with OCPP1.6 with EVerest, the build process of [everest-core](https://github.com/EVerest/everest-core) will take care of installing all necessary dependencies for you. This includes the initialization of the device model database using the [config.json](config/v201/config.json) file. - -## Integrate this library with your Charging Station Implementation for OCPP - -OCPP is a protocol that affects, controls and monitors many areas of a charging station's operation. - -If you want to integrate this library with your charging station implementation, you have to register a couple of **callbacks** and integrate **event handlers**. This is necessary for the library to interact with your charging station according to the requirements of OCPP. - -Libocpp needs registered **callbacks** in order to execute control commands defined within OCPP (e.g Reset.req or RemoteStartTransaction.req) - -The implementation must call **event handlers** of libocpp so that the library can track the state of the charging station and trigger OCPP messages accordingly (e.g. MeterValues.req , StatusNotification.req) - -Your reference within libocpp to interact is a single instance to the class [ChargePoint](include/ocpp/v16/charge_point.hpp) for OCPP 1.6 or to the class [ChargePoint](include/ocpp/v201/charge_point.hpp) for OCPP 2.0.1. - -### Overview of the required callbacks and events and what libocpp expects to happen - -The following section will give you a high level overview of how to integrate libocpp with your application. Please use the [Doxygen Documentation](#building-the-doxygen-documentation) as an additional source for the ChargePoint API. - -In EVerest the OCPP module leverages several other modules to perform tasks that relate to authorization, reservations, charging session handling and system tasks like rebooting or firmware updates. - -- Auth orchestrates authorization, utilizing different token providers like RFID reads and token validators. Libocpp mainly acts as a token validator, but in the case of RemoteStartTransactions it acts as a token provider as well -- EvseManager manages the charging session and charging state machine by communicating with a "board support package", a driver for the charging hardware that abstracts away the control pilot, relay control, power meters, etc. The EvseManager also handles reservations. -- System handles firmware updates, log uploads and resets - -The following sections explain the steps you can follow to implement their functionality on your own and integrate the libocpp directly into your charging station software without relying on EVerest. However, in most cases it's much easier to write an EVerest driver using the *everest-core/interfaces/board_support_AC.yaml* interface. - -## Usage for OCPP 2.0.1 - -### Smart Charging - -Work to fully support OCPP 2.0.1 Smart Charging is ongoing. Most functional requirements for General Smart Charging use cases (that is, K01–K10) are now supported. For an up-to-date overview of which features are currently supported, please refer to the [OCPP 2.0.1 Status](doc/ocpp_201_status.md) document. - -#### K01 SetChargingProfile - -Allows the CSMS to influence the charging power or current drawn from a specific EVSE or the -entire Charging Station over a period of time. - -```mermaid -sequenceDiagram - CSMS->>+ChargePoint : SetChargingProfileRequest(call) - - ChargePoint->>+DeviceModel : SmartChargingCtrlrAvailable? - DeviceModel-->>-ChargePoint : Component - - rect Red - break SmartChargingCtrlrAvailable = false - ChargePoint-->>CSMS : Smart Charging NotSupported CallError - end - end - - ChargePoint->>+SmartCharging : validate_and_add_profile(call.msg.Profile, call.msg.EVSE ID) - - SmartCharging->>SmartCharging : validate_profile(Profile, EVSE ID) - - rect Red - break Invalid Profile - SmartCharging-->>ChargePoint : SetChargingProfileResponse: Rejected - ChargePoint-->>CSMS : SetChargingProfileResponse: Rejected - end - end - - SmartCharging->>+SmartCharging : add_profile(Profile, EVSE ID) - SmartCharging->>-EVerest : signal_set_charging_profiles_callback - - SmartCharging-->>-ChargePoint : SetChargingProfileResponse: Accepted - - ChargePoint-->>-CSMS : SetChargingProfileResponse: Accepted -``` - -Profile validation returns the following errors to the caller when a Profile -is `Rejected`: - -- `ChargingProfileFirstStartScheduleIsNotZero` - - The `startPeriod` of the first `chargingSchedulePeriod` needs to be 0. - [K01.FR.31] - -- `ChargingProfileNoChargingSchedulePeriods` - - Happens when the `ChargingProfile` doesn't have any Charging Schedule - Periods. - -- `ChargingScheduleChargingRateUnitUnsupported` - - Happens when a chargingRateUnit is passed in that is not configured in the - `ChargingScheduleChargingRateUnit`. [K01.FR.26] - -- `ChargingSchedulePeriodInvalidPhaseToUse` - - Happens when an invalid `phaseToUse` is passed in. - - [K01.FR.19] [K01.FR.48] - -- `ChargingSchedulePeriodPhaseToUseACPhaseSwitchingUnsupported` - - Happens when phaseToUse is passed in and the EVSE does not have - `ACPhaseSwitchingSupported` defined and set to true. - [K01.FR.20] [K01.FR.48] - -- `ChargingSchedulePeriodsOutOfOrder` - - `ChargingSchedulePeriod.startPeriod` elements need to be in increasing - values. [K01.FR.35] - -- `ChargingStationMaxProfileCannotBeRelative` - - Happens when a `ChargingStationMaxProfile.chargingProfileKind` is set to - `Relative`. [K01.FR.38] - -- `ChargingStationMaxProfileEvseIdGreaterThanZero` - - Happens when a `ChargingStationMaxProfile` is attempted to be set with an - EvseID isn't `0`. [K01.FR.03] - -- `ChargingProfileMissingRequiredStartSchedule` - - Happens when an `Absolute` or `Recurring` `ChargingProfile` doesn't have - a `startSchedule`. [K01.FR.40] - -- `ChargingProfileExtraneousStartSchedule` - - Happens when a Relative `ChargingProfile` has a `startSchedule`. - [K01.FR.41] - -- `EvseDoesNotExist` - - Happens when the `evseId`of a `SetChargingProfileRequest` does not exist. - [K01.FR.28] - -- `ExistingChargingStationExternalConstraints` - - Happens when a `SetChargingProfileRequest` Profile has a purpose of - `ChargingStationExternalConstraints` and one already exists with the same - `ChargingProfile.id` exists. [K01.FR.05] - -- `InvalidProfileType` - - Happens when a `ChargingStationMaxProfile` is attempted to be set with a - `ChargingProfile` that isn't a `ChargingStationMaxProfile`. - -- `TxProfileEvseHasNoActiveTransaction` - - Happens when a `SetChargingProfileRequest` with a `TxProfile` is submitted - and there is no transaction active on the specified EVSE. [K01.FR.09] - -- `TxProfileEvseIdNotGreaterThanZero` - - `TxProfile` needs to have an `evseId` greater than 0. [K01.FR.16] - -- `TxProfileMissingTransactionId` - - A `transactionId` is required for `SetChargingProfileRequest`s with a - `TxProfile` in order to match the profile to a specific transation. [K01.FR.03] - -- `TxProfileTransactionNotOnEvse` - - Happens when the provided `transactionId` is not known. [K01.FR.33] - -- `TxProfileConflictingStackLevel` - - Happens when a `TxProfile` has a `stackLevel` and `transactionId` - combination already exists in a `TxProfile` with a different id in - order to ensure that no two charging profiles with same stack level and - purpose can be valid at the same time. [K01.FR.39] - -#### K08 Get Composite Schedule - -The CSMS requests the Charging Station to report the Composite Charging -Schedule, as calculated by the Charging Station for a specific point of -time, and may change over time due to external causes such as local -balancing based on grid connection capacity and EVSE availablity. - -The Composite Schedule is the result of result of merging the time periods -set in the `ChargingStationMaxProfile`, `ChargingStationExternalConstraints`, -`TxDefaultProfile` and `TxProfile` type profiles. - -```mermaid -sequenceDiagram - - CSMS->>+ChargePoint: GetCompositeSchedule(call) - - ChargePoint->>+DeviceModel : ChargingScheduleChargingRateUnit? - DeviceModel-->>-ChargePoint : Component - - rect Red - break call.msg.chargingRateUnit is not supported - ChargePoint-->>CSMS : ChargingScheduleChargingRateUnitUnsupported CallError - end - end - - ChargePoint->>+EvseManager : does_evse_exist(call.msg.evseId) - EvseManager-->>-ChargePoint : bool - rect Red - break EVSE does not exist - ChargePoint-->>CSMS : EvseDoesNotExist CallError - end - end - - ChargePoint->>+SmartChargingHandler : get_valid_profiles(call.msg.evseId) - - SmartChargingHandler-->>-ChargePoint : vector - - ChargePoint->>+SmartChargingHandler : calculate_composite_schedule
(vector>+Profile: calculate_composite_schedule(profiles) - Profile-->>-SmartChargingHandler: composite_schedule - end - - note right of SmartChargingHandler: Create consolidated CompositeSchedule
from all 4 Profile types - - - SmartChargingHandler->>+Profile: calculate_composite_schedule(ExternalConstraints, Max, TxDefault, Tx) - Profile-->>-SmartChargingHandler: CompositeSchedule - - SmartChargingHandler-->>-ChargePoint: CompositeSchedule - - ChargePoint-->>-CSMS : GetCompositeScheduleResponse(CompositeSchedule) -``` - -#### K09 Get Charging Profiles - -Returns to the CSMS the Charging Schedules/limits installed on a Charging Station based on the -passed in criteria. - -```mermaid -sequenceDiagram - - CSMS->>+ChargePoint: GetChargingProfiles(criteria) - - ChargePoint->>+SmartChargingHandler : get_reported_profiles(criteria) - - loop filter ChargingProfiles - SmartChargingHandler->>SmartChargingHandler: filter on ChargingProfile criteria - end - - SmartChargingHandler-->>-ChargePoint : Vector - - ChargePoint-->>CSMS : GetChargingProfilesResponse(profiles) - - alt no Profiles - rect Red - ChargePoint-->>CSMS : GetChargingProfilesResponse(NoProfiles) - ChargePoint->>CSMS : return - end - - else Profiles - ChargePoint-->>CSMS : GetChargingProfilesResponse(Accepted) - end - - ChargePoint->>ChargePoint : determine profiles_to_report - - ChargePoint-->>-CSMS : ReportChargingProfilesRequest(profiles_to_report) -``` - -#### K10 Clear Charging Profile - -Clears Charging Profiles installed on a Charging Station based on the -passed in criteria. - -```mermaid -sequenceDiagram - - CSMS->>+ChargePoint: ClearChargingProfileRequest(criteria) - - alt no Profiles matching criteria - rect Red - ChargePoint-->>CSMS : ClearChargingProfileResponse(Unknown) - - end - - else found matching Profiles - ChargePoint-->>-CSMS : ClearChargingProfileResponse(Accepted) - end -``` - -### Register event callbacks and on_handlers - -- `all_connectors_unavailable_callback` - - Notifies that all connectors are unavailable. Used to handle charge availability - requests and firmware updates. - -- `boot_notification_callback` - - Callback to notify of a system boot - -- `clear_customer_information_callback` - - Called to clear customer information based on passed in Customer Certificate, the - IdToken for this request, and the Customer Identified that the request refers to. - If IdToken is passed in will delete authorization cache entry from database. - -- `configure_network_connection_profile_callback` - - Called to configure a network connection profile when none is configured. - -- `connector_effective_operative_status_changed_callback` - - Notifies the user of liboccp that the Operative/Inoperative state of a specific EVSE - has changed. - -- `cs_effective_operative_status_changed_callback` - - Used to notify the user of libocpp that the Operative/Inoperative state of the - charging station itself has changed. Will also call - `evse_effective_operative_status_changed_callback` for each EVSE, and - `connector_effective_operative_status_changed_callback` for each connector whose - status has changed. - -- `data_transfer_callback` - - Used to handle arbitrary data transfers. - -- `evse_effective_operative_status_changed_callback` - - Notifies the user of libocpp that the Operative/Inoperative state of an EVSE has - changed. If as a result the state of connectors changed as well, libocpp will - additionally call the connector_effective_operative_status_changed_callback for - each connector. - -- `get_customer_information_callback` - - Returns human readable customer information based on the CertificateHashDataType, - IdToken and Customer Identifier passed in. - -- `get_log_request_callback` - - Callback to return logs - -- `is_reservation_for_token_callback` - - Check if the current reservation for the given evse id is made for the id - token / group id token. - -- `is_reset_allowed_callback` - - Callback if reset is allowed. If evse_id has a value, reset only applies - to the given evse id. If it has no value, applies to complete charging station. - -- `ocpp_messages_callback` - - Callback to congfigure ocpp message logging. - -- `pause_charging_callback` - - Used to request pausing of charging, the "connector" parameter instructing which - connector/EVSE to pause. - -- `remote_start_transaction_callback` - - Called when the request can be accepted. The boolean authorize_remote_start - indicates if Authorize.req needs to follow or not - -- `reset_callback` - - Performs a reset of the requested type - -- `security_event_callback` - - Used to react to a security event callback. This callback is - called only if the SecurityEvent occured internally within libocpp. - Typically this callback is used to log security events in the security log. - -- `set_charging_profiles_callback` - - Indicates when a charging profile is received and accepted. - -- `stop_transaction_callback` - - Used to stop a transaction. Called when the idTagInfo.status of a - StartTransaction.conf is not Accepted, when a RemoteStopTransaction.req is - received, or when an UnlockConnector.req is received. - -- `time_sync_callback` - - Called on boot notification if the TimeSource ControllerComponent contains - Heartbeat. - -- `transaction_event_callback` - - Called when a transaction_event was sent to the CSMS. - -- `transaction_event_response_callback` - - Called when a transaction_event_response was received from the CSMS. - -- `unlock_connector_callback` - - Used by libocpp to force unlock a connector - -- `update_firmware_request_callback` - - Initiates a firmware update request. Triggers a security event notification - if the certificate is Invalid or Revoked. - -- `validate_network_profile_callback` - - Validates the submitted Network Profile. Is Rejected if - - No callback registered to validate network profile - - CSMS attempted to set a network profile with a lower securityProfile - - CSMS attempted to set a network profile that could not be validated - - Network profile could not be written to the device model storage - -- `variable_changed_callback` - - Called when a variable has been changed by the CSMS - -### Initialize the database - -- Use provided sql database or implement your own storage drive - -## Install libocpp - -For Debian GNU/Linux 11 you will need the following dependencies: - -```bash - sudo apt install build-essential cmake python3-pip libboost-all-dev libsqlite3-dev libssl-dev -``` - -OpenSSL version 3.0 or above is required. - -Clone this repository. - -```bash - git clone https://github.com/EVerest/libocpp -``` - -In the libocpp folder create a folder named build and cd into it. -Execute cmake and then make install: - -```bash - mkdir build && cd build - cmake .. - make install -``` - -## Quickstart for OCPP 2.0.1 - -Libocpp provides a small standalone OCPP2.0.1 client that you can control using command line. - -Install the dependencies and libocpp as described in [Install libocpp](#install-libocpp). - -Make sure you modify the following config entries in the [config.json](config/v201/config.json) file according to the CSMS you want to connect to before executing make install. - -```json -{ - "Internal": { - "ChargePointId": "", - "CentralSystemURI": "" - } -} -``` - -Change into libocpp/build and execute cmake and then make install: - -```bash - cd build - cmake -DLIBOCPP16_BUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=./dist .. - make -j$(nproc) install -``` - -Use the following command to start the charge point. Replace the config with [config-docker.json](config/v16/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. - -```bash - ./dist/bin/charge_point \ - --maindir ./dist \ - --conf config.json -``` - -Type `help` to see a list of possible commands. - -## Building the doxygen documentation - -```bash - cmake -S . -B build - cmake --build build --target doxygen-ocpp -``` - -You will find the generated doxygen documentation at: -`build/dist/docs/html/index.html` - -The main reference for the integration of libocpp for OCPP2.0.1 is the ocpp::v201::ChargePoint class defined in libocpp/include/ocpp/v201/charge_point.hpp . - -## Unit testing - -GTest is required for building the test cases target. -To build the target and run the tests you can reference the script `.ci/build-kit/install_and_test.sh`. -The script allows the GitHub Actions runner to execute. - -Local testing: - -```bash -mkdir build -cmake -B build -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="./dist" -cd build -make -j$(nproc) install -``` - -Run any required tests from build/tests. - -## Building with FetchContent instead of EDM - -In [doc/build-with-fetchcontent](doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. - -### Support for TPM keys - -In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. - -## Support for websocket++ - -The old websocket++ implementation has been deprecated. For enabling websocket++ support use the following cmake option: - -```bash - cmake .. -DLIBOCPP_ENABLE_DEPRECATED_WEBSOCKETPP=ON -``` - -### Support for iface - -In order to connect through a custom network iface, a custom internal config variable 'IFace' can be used. - -```json -"Internal": { - "IFace" : "enp43s0" -} -``` From a436cdf7b4ff9b7996e4ce0a773d3a96704b4b35 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:57:30 -0400 Subject: [PATCH 022/134] Delete doc/ocpp_16_readme.md moved content to new folder Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_readme.md | 645 ------------------------------------------ 1 file changed, 645 deletions(-) delete mode 100644 doc/ocpp_16_readme.md diff --git a/doc/ocpp_16_readme.md b/doc/ocpp_16_readme.md deleted file mode 100644 index d76208d67..000000000 --- a/doc/ocpp_16_readme.md +++ /dev/null @@ -1,645 +0,0 @@ - -# C++ implementation of OCPP 1.6 -![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) - -This C++ library provides a complete and production-ready solution for integrating OCPP 1.6 into your electric vehicle (EV) charging stations. Our implementation enables seamless communication between charging stations and central management systems, supporting remote control, monitoring, and billing functionalities. - -NOTE: [EVerest OCPP 2.0.1](OCPP-2-0-1.md) is under active development, with core functionalities available. - - -## Table of contents - -- [Feature Profile Support OCPP 1.6](#feature-profile-support-ocpp-16) -- [CSMS Compatibility OCPP 1.6](#csms-compatibility-ocpp-16) -- [Integration with EVerest](#integration-with-everest) - - [Run OCPP1.6 with EVerest](#run-ocpp16-with-everest) - - [Integrate this library with your Charging Station Implementation for OCPP1.6](#integrate-this-library-with-your-charging-station-implementation-for-ocpp16) - - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) - - [ChargePoint() constructor](#chargepoint-constructor) - - [registering callbacks](#registering-callbacks) - - [Functions that need to be triggered from the outside after new information is availble (on\_... functions in the charge point API)](#functions-that-need-to-be-triggered-from-the-outside-after-new-information-is-availble-on_-functions-in-the-charge-point-api) - - [The following functions are triggered depending on different so called "Session Events" from the EvseManager](#the-following-functions-are-triggered-depending-on-different-so-called-session-events-from-the-evsemanager) - - [Authorization](#authorization) - - [Install libocpp](#install-libocpp) - - [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) - - [Building the doxygen documentation](#building-the-doxygen-documentation) - - [Unit testing](#unit-testing) - - [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) - - [Support for security profile 2 and 3 with TPM in OCPP 1.6 using libwebsockets](#support-for-security-profile-2-and-3-with-tpm-in-ocpp-16-using-libwebsockets) - -## OCPP 1.6 Support - -The following tables show the current support for the listed OCPP 1.6 feature profiles / functional blocks and application notes. - -All documentation and the issue tracking can be found in our main repository here: https://github.com/EVerest/ - -### Feature Profile Support OCPP 1.6 - -| Feature Profile | Supported | -| -------------------------- | ------------------------- | -| Core | :heavy_check_mark: yes | -| Firmware Management | :heavy_check_mark: yes | -| Local Auth List Management | :heavy_check_mark: yes | -| Reservation | :heavy_check_mark: yes | -| Smart Charging | :heavy_check_mark: yes | -| Remote Trigger | :heavy_check_mark: yes | - -## CSMS Compatibility - -### CSMS Compatibility OCPP 1.6 - -The EVerest implementation of OCPP 1.6 has been tested against the -OCPP Compliance Test Tool (OCTT and OCTT2) during the implementation. - -The following table shows CSMS with which this library was tested. -If you provide a CSMS that is not yet listed here, feel free to -[contact us](https://lists.lfenergy.org/g/everest)! - -- chargecloud -- chargeIQ -- Chargetic -- Compleo -- Current -- Daimler Truck -- ev.energy -- eDRV -- Fastned -- [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) -- Electrip Global -- EnergyStacks -- EV-Meter -- Fraunhofer IAO (ubstack CHARGE) -- Green Motion -- gridundco -- ihomer (Infuse CPMS) -- iLumen -- JibeCompany (CharlieV CMS and Chargebroker proxy) -- MSI -- PUMP (PUMP Connect) -- Scoptvision (Scopt Powerconnect) -- Siemens -- [SteVe](https://github.com/steve-community/steve) -- Syntech -- Trialog -- ubitricity -- Weev Energy - -## Integration with EVerest - -This library is automatically integrated as the OCPP and OCPP201 module within [everest-core](https://github.com/EVerest/everest-core) - the complete software stack for your charging station. It is recommended to use EVerest together with this OCPP implementation. - -### Run OCPP1.6 with EVerest - -If you run libocpp with OCPP1.6 with EVerest, the build process of [everest-core](https://github.com/EVerest/everest-core) will take care of installing all necessary dependencies for you. - -## Integrate this library with your Charging Station Implementation for OCPP - -OCPP is a protocol that affects, controls and monitors many areas of a charging station's operation. - -If you want to integrate this library with your charging station implementation, you have to register a couple of **callbacks** and integrate **event handlers**. This is necessary for the library to interact with your charging station according to the requirements of OCPP. - -Libocpp needs registered **callbacks** in order to execute control commands defined within OCPP (e.g Reset.req or RemoteStartTransaction.req) - -The implementation must call **event handlers** of libocpp so that the library can track the state of the charging station and trigger OCPP messages accordingly (e.g. MeterValues.req , StatusNotification.req) - -Your reference within libocpp to interact is a single instance to the class [ChargePoint](include/ocpp/v16/charge_point.hpp) for OCPP 1.6. - -### Overview of the required callbacks and events and what libocpp expects to happen - -The following section will give you a high level overview of how to integrate libocpp with your application. Please use the [Doxygen Documentation](#building-the-doxygen-documentation) as an additional source for the ChargePoint API. - -In EVerest the OCPP module leverages several other modules to perform tasks that relate to authorization, reservations, charging session handling and system tasks like rebooting or firmware updates. - -- Auth orchestrates authorization, utilizing different token providers like RFID reads and token validators. Libocpp mainly acts as a token validator, but in the case of RemoteStartTransactions it acts as a token provider as well -- EvseManager manages the charging session and charging state machine by communicating with a "board support package", a driver for the charging hardware that abstracts away the control pilot, relay control, power meters, etc. The EvseManager also handles reservations. -- System handles firmware updates, log uploads and resets - -The following sections explain the steps you can follow to implement their functionality on your own and integrate the libocpp directly into your charging station software without relying on EVerest. However, in most cases it's much easier to write an EVerest driver using the *everest-core/interfaces/board_support_AC.yaml* interface. - -### Usage for OCPP 1.6 - -#### ChargePoint() constructor - -The main entrypoint for libocpp for OCPP1.6 is the ocpp::v16::ChargePoint constructor. -This is defined in libocpp/include/ocpp/v16/charge_point.hpp and takes the following parameters: - -- config: a std::string that contains the libocpp 1.6 config. There are example configs that work with a [SteVe](https://github.com/steve-community/steve) installation [running in Docker](https://github.com/EVerest/everest-utils/tree/main/docker/steve), for example: [config-docker.json](config/v16/config-docker.json) - -- share_path: a std::filesystem path containing the path to the OCPP modules folder, for example pointing to */usr/share/everest/modules/OCPP*. This path contains the following files and directories and is installed by the libocpp install target: - - ```bash - . - ├── config-docker.json - ├── config-docker-tls.json - ├── config.json - ├── init.sql - ├── logging.ini - └── profile_schemas - ├── Config.json - ├── Core.json - ├── FirmwareManagement.json - ├── Internal.json - ├── LocalAuthListManagement.json - ├── PnC.json - ├── Reservation.json - ├── Security.json - ├── SmartCharging.json - └── Custom.json - ``` - - Here you can find: - - the aforementioned config files - - - a *logging.ini* that is needed to initialize logging with Everest::Logging::init(path_to_logging_ini, "name_of_binary") - - - a *init.sql* file which contains the database schema used by libocpp for its sqlite database - - - and a *profile_schemas* directory. This contains json schema files that are used to validate the libocpp config. The schemas are split up according to the OCPP1.6 feature profiles like Core, FirmwareManagement and so on. Additionally there is a schema for "Internal" configuration options (for example the ChargePointId, or CentralSystemURI). A "PnC" schema for the ISO 15118 Plug & Charge with OCPP 1.6 Application note, a "Security" schema for the OCPP 1.6 Security Whitepaper (3rd edition) and an exemplary "Custom" schema are provided as well. The Custom.json could be modified to be able to add custom configuration keys. Finally there's a Config.json schema that ties everything together - -- user_config_path: this points to a "user config", which we call a configuration file that's merged with the config that's provided in the "config" parameter. Here you can add, remove and overwrite settings without modifying the config passed in the first parameter directly. This is also used by libocpp to persistently modify config entries that are changed by the CSMS that should persist across restarts. - -- database_path: this points to the location of the sqlite database that libocpp uses to keep track of connector availability, the authorization cache and auth list, charging profiles and transaction data - -- sql_init_path: this points to the aforementioned init.sql file which contains the database schema used by libocpp for its sqlite database - -- message_log_path: this points to the directory in which libocpp can put OCPP communication logfiles for debugging purposes. This behavior can be controlled by the "LogMessages" (set to true by default) and "LogMessagesFormat" (set to ["log", "html", "session_logging"] by default, "console" and "console_detailed" are also available) configuration keys in the "Internal" section of the config file. Please note that this is intended for debugging purposes only as it logs all communication, including authentication messages. - -- evse_security: this is a pointer to an implementation of the [evse_security](include/ocpp/common/evse_security.hpp) interface. This allows you to include your custom implementation of the security related operations according to this interface. If you set this value to nullptr, the internal implementation of the security related operations of libocpp will be used. In this case you need to specify the parameter security_configuration - -- security_configuration: this parameter should only be set in case the evse_security parameter is nullptr. It specifies the file paths that are required to set up the internal evse_security implementation. Note that you need to specify bundle files for the CA certificates and directories for the certificates and keys - - The directory layout expected is as follows - - ```bash - . - ├── ca - │ ├── csms - │ │ └── CSMS_ROOT_CA.pem - │ ├── cso - │ │ ├── CPO_CERT_CHAIN.pem - │ │ ├── CPO_SUB_CA1_LEAF.der - │ │ ├── CPO_SUB_CA1.pem - │ │ ├── CPO_SUB_CA2_LEAF.der - │ │ └── CPO_SUB_CA2.pem - │ ├── mf - │ │ └── MF_ROOT_CA.pem - │ ├── mo - │ │ ├── INTERMEDIATE_MO_CA_CERTS.pem - │ │ ├── MO_ROOT_CA.der - │ │ ├── MO_ROOT_CA.pem - │ │ ├── MO_SUB_CA1.der - │ │ ├── MO_SUB_CA1.pem - │ │ ├── MO_SUB_CA2.der - │ │ └── MO_SUB_CA2.pem - │ └── v2g - │ ├── V2G_ROOT_CA.der - │ └── V2G_ROOT_CA.pem - ├── client - │ ├── csms - │ │ ├── CPO_CERT_CHAIN.pem - │ │ ├── CPO_SUB_CA1.key - │ │ ├── CPO_SUB_CA2.key - │ │ ├── SECC_LEAF.der - │ │ ├── SECC_LEAF.key - │ │ └── SECC_LEAF.pem - │ ├── cso - │ │ ├── CPO_CERT_CHAIN.pem - │ │ ├── CPO_SUB_CA1.key - │ │ ├── CPO_SUB_CA2.key - │ │ ├── SECC_LEAF.der - │ │ ├── SECC_LEAF.key - │ │ └── SECC_LEAF.pem - │ └── v2g - │ └── V2G_ROOT_CA.key - ``` - -#### registering callbacks - -You can (and in many cases MUST) register a number of callbacks so libocpp can interact with the charger. In EVerest most of this functionality is orchestrated by the "EvseManager" module, but you can also register your own callbacks interacting directly with your chargers software. Following is a list of callbacks that you must register and a few words about their purpose. - -TODO: in a future version of libocpp the callbacks will be organised in a struct with optional members emphasizing the required and optional callbacks. - -Some general notes: the "connector" parameter of some of the callbacks refers to the connector number as understood in the OCPP 1.6 specification, "0" means the whole charging station, the connectors with EVSEs used for charging cars start at "1". - -- `register_pause_charging_callback` - - this callback is used by libocpp to request pausing of charging, the "connector" parameter tells you which connector/EVSE has to pause charging - -- `register_resume_charging_callback` - - this callback is used by libocpp the request resuming of charging, the "connector" parameter tells you which connector/EVSE can resume charging - -- `register_stop_transaction_callback` - - in EVerest this calls the EvseManagers stop_transaction command which "Stops transactions and cancels charging externally, charging can only be resumed by replugging car. EVSE will also stop transaction automatically e.g. on disconnect, so this only needs to be called if the transaction should end before." - this will then signal the following events: - - ChargingFinished - - TransactionFinished - -- `register_unlock_connector_callback` - - can be used by libocpp to force unlock a connector - -- `register_reserve_now_callback` - - libocpp can use this to reserve a connector, reservation handling is outsourced to a reservation manager in EVerest that implements the reservation interface (everest-core/interfaces/reservation.yaml) - -- `register_upload_diagnostics_callback` - - uses a function (in EVerest provided by the System module) to upload the requested diagnostics file - -- `register_upload_logs_callback` - - uses a function (in EVerest provided by the System module) to upload the requested log file - -- `register_update_firmware_callback` - - uses a function (in EVerest provided by the System module) to perform a firmware update - -- `register_signed_update_firmware_callback` - - uses a function (in EVerest provided by the System module) to perform a signed firmware update - -- `register_provide_token_callback` - - this callback is used in a remote start transaction to provide a token (prevalidated or not) to the authorization system - -- `register_set_connection_timeout_callback` - - used by libocpp to set the authorization or plug in connection timeout in the authorization system based on the "ConnectionTimeout" configuration key - -- `register_disable_evse_callback` - - used to disable the EVSE (ChangeAvailability.req) - -- `register_enable_evse_callback` - - used to enable the EVSE (ChangeAvailability.req) - -- `register_cancel_reservation_callback` - - used to cancel a reservation in the reservation manager (CancelReservation.req) - -- `register_signal_set_charging_profiles_callback` - - used to signal that new charging schedule(s) have been set, you can then use - get_all_composite_charging_schedules(duration_s) to get the new valid charging schedules - -- `register_is_reset_allowed_callback` - - used to inquire (in EVerest from the System module) if a reset is allowed - -- `register_reset_callback` - - used to perform a reset of the requested type - -- `register_connection_state_changed_callback` - - used to inform about the connection state to the CSMS (connected = true, disconnected = false) - -- `register_configuration_key_changed_callback` - - used to react on a changed configuration key. This callback is called when the specified configuration key has been changed by the CSMS - -#### Functions that need to be triggered from the outside after new information is availble (on_... functions in the charge point API) - -- `on_log_status_notification(int32_t request_id, std::string log_status)` - - can be used to notify libocpp of a log status notification - -- `on_firmware_update_status_notification(int32_t request_id, std::string firmware_update_status)` - - can be used to notify libocpp of a firmware update status notification - -- `on_meter_values(int32_t connector, const Powermeter& powermeter)` - - provides a Powermeter struct to libocpp (for sending meter values during charging sessions or periodically) - -- `on_max_current_offered(int32_t connector, int32_t max_current)` - - the maximum current offered to the EV on this connector (in ampere) - -#### The following functions are triggered depending on different so called "Session Events" from the EvseManager - -each of these functions will have a small note what the Session Event was and what it triggers in libocpp - -- `on_enabled(int32_t connector)` - - Notifies libocpp that the connector is functional and operational - -- `on_disabled(int32_t connector)` - - Notifies libocpp that the connector is disabled - -- `on_transaction_started` - - Notifies libocpp that a transaction at the given connector has started, this means that authorization is available and the car is plugged in. - - Some of its parameters: - - - `session_id` is an internal session_id originating in the EvseManager to keep track of the transaction, this is NOT to be mistaken for the transactionId from the StartTransactionResponse in OCPP! - - `id_token` is the token with which the transaction was authenticated - - `meter_start` contains the meter value in Wh for the connector at start of the transaction - - `timestamp` at the start of the transaction - -- `on_transaction_stopped` - - Notifies libocpp that the transaction on the given connector with the given reason has been stopped. - - Some of its parameters: - - - `timestamp` at the end of the transaction - - `energy_wh_import` contains the meter value in Wh for the connector at end of the transaction - -- `on_suspend_charging_ev` - - Notifies libocpp that the EV has paused charging - -- `on_suspend_charging_evse` - - Notifies libocpp that the EVSE has paused charging - -- `on_resume_charging` - - Notifies libocpp that charging has resumed - -- `on_session_started` - - this is mostly used for logging and changing the connector state - -- `on_session_stopped` - - this is mostly used for logging and changing the connector state - -- `on_error` - - Notify libocpp of an error - -- `on_reservation_start` - - Notifies libocpp that a reservation has started - -- `on_reservation_end` - - Notifies libocpp that a reservation has ended - -#### Authorization - -In EVerest authorization is handled by the Auth module and various auth token providers and validators. The OCPP module acts as both a token provider (for pre validated tokens in RemoteStartTransactions) and a token validator (using the authorize requests, or plug & charge). - -To use libocpp as a auth token validator (e.g. before starting a transaction) you can call the "authorize_id_token" function of the ChargePoint object. - -### Register event callbacks and on_handlers - -- `all_connectors_unavailable_callback` - - Notifies that all connectors are unavailable. Used to handle charge availability - requests and firmware updates. - -- `boot_notification_callback` - - Callback to notify of a system boot - -- `clear_customer_information_callback` - - Called to clear customer information based on passed in Customer Certificate, the - IdToken for this request, and the Customer Identified that the request refers to. - If IdToken is passed in will delete authorization cache entry from database. - -- `configure_network_connection_profile_callback` - - Called to configure a network connection profile when none is configured. - -- `connector_effective_operative_status_changed_callback` - - Notifies the user of liboccp that the Operative/Inoperative state of a specific EVSE - has changed. - -- `cs_effective_operative_status_changed_callback` - - Used to notify the user of libocpp that the Operative/Inoperative state of the - charging station itself has changed. Will also call - `evse_effective_operative_status_changed_callback` for each EVSE, and - `connector_effective_operative_status_changed_callback` for each connector whose - status has changed. - -- `data_transfer_callback` - - Used to handle arbitrary data transfers. - -- `evse_effective_operative_status_changed_callback` - - Notifies the user of libocpp that the Operative/Inoperative state of an EVSE has - changed. If as a result the state of connectors changed as well, libocpp will - additionally call the connector_effective_operative_status_changed_callback for - each connector. - -- `get_customer_information_callback` - - Returns human readable customer information based on the CertificateHashDataType, - IdToken and Customer Identifier passed in. - -- `get_log_request_callback` - - Callback to return logs - -- `is_reservation_for_token_callback` - - Check if the current reservation for the given evse id is made for the id - token / group id token. - -- `is_reset_allowed_callback` - - Callback if reset is allowed. If evse_id has a value, reset only applies - to the given evse id. If it has no value, applies to complete charging station. - -- `ocpp_messages_callback` - - Callback to congfigure ocpp message logging. - -- `pause_charging_callback` - - Used to request pausing of charging, the "connector" parameter instructing which - connector/EVSE to pause. - -- `remote_start_transaction_callback` - - Called when the request can be accepted. The boolean authorize_remote_start - indicates if Authorize.req needs to follow or not - -- `reset_callback` - - Performs a reset of the requested type - -- `security_event_callback` - - Used to react to a security event callback. This callback is - called only if the SecurityEvent occured internally within libocpp. - Typically this callback is used to log security events in the security log. - -- `set_charging_profiles_callback` - - Indicates when a charging profile is received and accepted. - -- `stop_transaction_callback` - - Used to stop a transaction. Called when the idTagInfo.status of a - StartTransaction.conf is not Accepted, when a RemoteStopTransaction.req is - received, or when an UnlockConnector.req is received. - -- `time_sync_callback` - - Called on boot notification if the TimeSource ControllerComponent contains - Heartbeat. - -- `transaction_event_callback` - - Called when a transaction_event was sent to the CSMS. - -- `transaction_event_response_callback` - - Called when a transaction_event_response was received from the CSMS. - -- `unlock_connector_callback` - - Used by libocpp to force unlock a connector - -- `update_firmware_request_callback` - - Initiates a firmware update request. Triggers a security event notification - if the certificate is Invalid or Revoked. - -- `validate_network_profile_callback` - - Validates the submitted Network Profile. Is Rejected if - - No callback registered to validate network profile - - CSMS attempted to set a network profile with a lower securityProfile - - CSMS attempted to set a network profile that could not be validated - - Network profile could not be written to the device model storage - -- `variable_changed_callback` - - Called when a variable has been changed by the CSMS - -### Initialize the database - -- Use provided sql database or implement your own storage drive - -## Install libocpp - -For Debian GNU/Linux 11 you will need the following dependencies: - -```bash - sudo apt install build-essential cmake python3-pip libboost-all-dev libsqlite3-dev libssl-dev -``` - -OpenSSL version 3.0 or above is required. - -Clone this repository. - -```bash - git clone https://github.com/EVerest/libocpp -``` - -In the libocpp folder create a folder named build and cd into it. -Execute cmake and then make install: - -```bash - mkdir build && cd build - cmake .. - make install -``` - -## Quickstart for OCPP 1.6 - -Libocpp provides a small standalone OCPP1.6 client that you can control using command line. - -Install the dependencies and libocpp as described in [Install libocpp](#install-libocpp). - -Make sure you modify the following config entries in the [config.json](config/v16/config.json) file according to the CSMS you want to connect to before executing make install. - -```json -{ - "Internal": { - "ChargePointId": "", - "CentralSystemURI": "" - } -} -``` - -Change into libocpp/build and execute cmake and then make install: - -```bash - cd build - cmake -DLIBOCPP16_BUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=./dist .. - make -j$(nproc) install -``` - -Use the following command to start the charge point. Replace the config with [config-docker.json](config/v16/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. - -```bash - ./dist/bin/charge_point \ - --maindir ./dist \ - --conf config.json -``` - -Type `help` to see a list of possible commands. - -## Building the doxygen documentation - -```bash - cmake -S . -B build - cmake --build build --target doxygen-ocpp -``` - -You will find the generated doxygen documentation at: -`build/dist/docs/html/index.html` - -The main reference for the integration of libocpp for OCPP1.6 is the ocpp::v16::ChargePoint class defined in libocpp/include/ocpp/v16/charge_point.hpp . - -## Unit testing - -GTest is required for building the test cases target. -To build the target and run the tests you can reference the script `.ci/build-kit/install_and_test.sh`. -The script allows the GitHub Actions runner to execute. - -Local testing: - -```bash -mkdir build -cmake -B build -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="./dist" -cd build -make -j$(nproc) install -``` - -Run any required tests from build/tests. - -## Building with FetchContent instead of EDM - -In [doc/build-with-fetchcontent](doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. - -### Support for TPM keys - -In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. - -## Support for websocket++ - -The old websocket++ implementation has been deprecated. For enabling websocket++ support use the following cmake option: - -```bash - cmake .. -DLIBOCPP_ENABLE_DEPRECATED_WEBSOCKETPP=ON -``` - -### Support for iface - -In order to connect through a custom network iface, a custom internal config variable 'IFace' can be used. - -```json -"Internal": { - "IFace" : "enp43s0" -} -``` - -## Get Involved - -See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. From 341185a609a9c0396a3276897bef028ee7aee0d1 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:58:26 -0400 Subject: [PATCH 023/134] Create ocpp_16_README.md Added OCPP 1.6 content Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 644 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 644 insertions(+) create mode 100644 doc/ocpp_16_README.md diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md new file mode 100644 index 000000000..153d60789 --- /dev/null +++ b/doc/ocpp_16_README.md @@ -0,0 +1,644 @@ +# C++ implementation of OCPP 1.6 +![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) + +This C++ library provides a complete and production-ready solution for integrating OCPP 1.6 into your electric vehicle (EV) charging stations. Our implementation enables seamless communication between charging stations and central management systems, supporting remote control, monitoring, and billing functionalities. + +NOTE: [EVerest OCPP 2.0.1](OCPP-2-0-1.md) is under active development, with core functionalities available. + + +## Table of contents + +- [Feature Profile Support OCPP 1.6](#feature-profile-support-ocpp-16) +- [CSMS Compatibility OCPP 1.6](#csms-compatibility-ocpp-16) +- [Integration with EVerest](#integration-with-everest) + - [Run OCPP1.6 with EVerest](#run-ocpp16-with-everest) + - [Integrate this library with your Charging Station Implementation for OCPP1.6](#integrate-this-library-with-your-charging-station-implementation-for-ocpp16) + - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) + - [ChargePoint() constructor](#chargepoint-constructor) + - [registering callbacks](#registering-callbacks) + - [Functions that need to be triggered from the outside after new information is availble (on\_... functions in the charge point API)](#functions-that-need-to-be-triggered-from-the-outside-after-new-information-is-availble-on_-functions-in-the-charge-point-api) + - [The following functions are triggered depending on different so called "Session Events" from the EvseManager](#the-following-functions-are-triggered-depending-on-different-so-called-session-events-from-the-evsemanager) + - [Authorization](#authorization) + - [Install libocpp](#install-libocpp) + - [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) + - [Building the doxygen documentation](#building-the-doxygen-documentation) + - [Unit testing](#unit-testing) + - [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) + - [Support for security profile 2 and 3 with TPM in OCPP 1.6 using libwebsockets](#support-for-security-profile-2-and-3-with-tpm-in-ocpp-16-using-libwebsockets) + +## OCPP 1.6 Support + +The following tables show the current support for the listed OCPP 1.6 feature profiles / functional blocks and application notes. + +All documentation and the issue tracking can be found in our main repository here: https://github.com/EVerest/ + +### Feature Profile Support OCPP 1.6 + +| Feature Profile | Supported | +| -------------------------- | ------------------------- | +| Core | :heavy_check_mark: yes | +| Firmware Management | :heavy_check_mark: yes | +| Local Auth List Management | :heavy_check_mark: yes | +| Reservation | :heavy_check_mark: yes | +| Smart Charging | :heavy_check_mark: yes | +| Remote Trigger | :heavy_check_mark: yes | + +## CSMS Compatibility + +### CSMS Compatibility OCPP 1.6 + +The EVerest implementation of OCPP 1.6 has been tested against the +OCPP Compliance Test Tool (OCTT and OCTT2) during the implementation. + +The following table shows CSMS with which this library was tested. +If you provide a CSMS that is not yet listed here, feel free to +[contact us](https://lists.lfenergy.org/g/everest)! + +- chargecloud +- chargeIQ +- Chargetic +- Compleo +- Current +- Daimler Truck +- ev.energy +- eDRV +- Fastned +- [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) +- Electrip Global +- EnergyStacks +- EV-Meter +- Fraunhofer IAO (ubstack CHARGE) +- Green Motion +- gridundco +- ihomer (Infuse CPMS) +- iLumen +- JibeCompany (CharlieV CMS and Chargebroker proxy) +- MSI +- PUMP (PUMP Connect) +- Scoptvision (Scopt Powerconnect) +- Siemens +- [SteVe](https://github.com/steve-community/steve) +- Syntech +- Trialog +- ubitricity +- Weev Energy + +## Integration with EVerest + +This library is automatically integrated as the OCPP and OCPP201 module within [everest-core](https://github.com/EVerest/everest-core) - the complete software stack for your charging station. It is recommended to use EVerest together with this OCPP implementation. + +### Run OCPP1.6 with EVerest + +If you run libocpp with OCPP1.6 with EVerest, the build process of [everest-core](https://github.com/EVerest/everest-core) will take care of installing all necessary dependencies for you. + +## Integrate this library with your Charging Station Implementation for OCPP + +OCPP is a protocol that affects, controls and monitors many areas of a charging station's operation. + +If you want to integrate this library with your charging station implementation, you have to register a couple of **callbacks** and integrate **event handlers**. This is necessary for the library to interact with your charging station according to the requirements of OCPP. + +Libocpp needs registered **callbacks** in order to execute control commands defined within OCPP (e.g Reset.req or RemoteStartTransaction.req) + +The implementation must call **event handlers** of libocpp so that the library can track the state of the charging station and trigger OCPP messages accordingly (e.g. MeterValues.req , StatusNotification.req) + +Your reference within libocpp to interact is a single instance to the class [ChargePoint](include/ocpp/v16/charge_point.hpp) for OCPP 1.6. + +### Overview of the required callbacks and events and what libocpp expects to happen + +The following section will give you a high level overview of how to integrate libocpp with your application. Please use the [Doxygen Documentation](#building-the-doxygen-documentation) as an additional source for the ChargePoint API. + +In EVerest the OCPP module leverages several other modules to perform tasks that relate to authorization, reservations, charging session handling and system tasks like rebooting or firmware updates. + +- Auth orchestrates authorization, utilizing different token providers like RFID reads and token validators. Libocpp mainly acts as a token validator, but in the case of RemoteStartTransactions it acts as a token provider as well +- EvseManager manages the charging session and charging state machine by communicating with a "board support package", a driver for the charging hardware that abstracts away the control pilot, relay control, power meters, etc. The EvseManager also handles reservations. +- System handles firmware updates, log uploads and resets + +The following sections explain the steps you can follow to implement their functionality on your own and integrate the libocpp directly into your charging station software without relying on EVerest. However, in most cases it's much easier to write an EVerest driver using the *everest-core/interfaces/board_support_AC.yaml* interface. + +### Usage for OCPP 1.6 + +#### ChargePoint() constructor + +The main entrypoint for libocpp for OCPP1.6 is the ocpp::v16::ChargePoint constructor. +This is defined in libocpp/include/ocpp/v16/charge_point.hpp and takes the following parameters: + +- config: a std::string that contains the libocpp 1.6 config. There are example configs that work with a [SteVe](https://github.com/steve-community/steve) installation [running in Docker](https://github.com/EVerest/everest-utils/tree/main/docker/steve), for example: [config-docker.json](config/v16/config-docker.json) + +- share_path: a std::filesystem path containing the path to the OCPP modules folder, for example pointing to */usr/share/everest/modules/OCPP*. This path contains the following files and directories and is installed by the libocpp install target: + + ```bash + . + ├── config-docker.json + ├── config-docker-tls.json + ├── config.json + ├── init.sql + ├── logging.ini + └── profile_schemas + ├── Config.json + ├── Core.json + ├── FirmwareManagement.json + ├── Internal.json + ├── LocalAuthListManagement.json + ├── PnC.json + ├── Reservation.json + ├── Security.json + ├── SmartCharging.json + └── Custom.json + ``` + + Here you can find: + - the aforementioned config files + + - a *logging.ini* that is needed to initialize logging with Everest::Logging::init(path_to_logging_ini, "name_of_binary") + + - a *init.sql* file which contains the database schema used by libocpp for its sqlite database + + - and a *profile_schemas* directory. This contains json schema files that are used to validate the libocpp config. The schemas are split up according to the OCPP1.6 feature profiles like Core, FirmwareManagement and so on. Additionally there is a schema for "Internal" configuration options (for example the ChargePointId, or CentralSystemURI). A "PnC" schema for the ISO 15118 Plug & Charge with OCPP 1.6 Application note, a "Security" schema for the OCPP 1.6 Security Whitepaper (3rd edition) and an exemplary "Custom" schema are provided as well. The Custom.json could be modified to be able to add custom configuration keys. Finally there's a Config.json schema that ties everything together + +- user_config_path: this points to a "user config", which we call a configuration file that's merged with the config that's provided in the "config" parameter. Here you can add, remove and overwrite settings without modifying the config passed in the first parameter directly. This is also used by libocpp to persistently modify config entries that are changed by the CSMS that should persist across restarts. + +- database_path: this points to the location of the sqlite database that libocpp uses to keep track of connector availability, the authorization cache and auth list, charging profiles and transaction data + +- sql_init_path: this points to the aforementioned init.sql file which contains the database schema used by libocpp for its sqlite database + +- message_log_path: this points to the directory in which libocpp can put OCPP communication logfiles for debugging purposes. This behavior can be controlled by the "LogMessages" (set to true by default) and "LogMessagesFormat" (set to ["log", "html", "session_logging"] by default, "console" and "console_detailed" are also available) configuration keys in the "Internal" section of the config file. Please note that this is intended for debugging purposes only as it logs all communication, including authentication messages. + +- evse_security: this is a pointer to an implementation of the [evse_security](include/ocpp/common/evse_security.hpp) interface. This allows you to include your custom implementation of the security related operations according to this interface. If you set this value to nullptr, the internal implementation of the security related operations of libocpp will be used. In this case you need to specify the parameter security_configuration + +- security_configuration: this parameter should only be set in case the evse_security parameter is nullptr. It specifies the file paths that are required to set up the internal evse_security implementation. Note that you need to specify bundle files for the CA certificates and directories for the certificates and keys + + The directory layout expected is as follows + + ```bash + . + ├── ca + │ ├── csms + │ │ └── CSMS_ROOT_CA.pem + │ ├── cso + │ │ ├── CPO_CERT_CHAIN.pem + │ │ ├── CPO_SUB_CA1_LEAF.der + │ │ ├── CPO_SUB_CA1.pem + │ │ ├── CPO_SUB_CA2_LEAF.der + │ │ └── CPO_SUB_CA2.pem + │ ├── mf + │ │ └── MF_ROOT_CA.pem + │ ├── mo + │ │ ├── INTERMEDIATE_MO_CA_CERTS.pem + │ │ ├── MO_ROOT_CA.der + │ │ ├── MO_ROOT_CA.pem + │ │ ├── MO_SUB_CA1.der + │ │ ├── MO_SUB_CA1.pem + │ │ ├── MO_SUB_CA2.der + │ │ └── MO_SUB_CA2.pem + │ └── v2g + │ ├── V2G_ROOT_CA.der + │ └── V2G_ROOT_CA.pem + ├── client + │ ├── csms + │ │ ├── CPO_CERT_CHAIN.pem + │ │ ├── CPO_SUB_CA1.key + │ │ ├── CPO_SUB_CA2.key + │ │ ├── SECC_LEAF.der + │ │ ├── SECC_LEAF.key + │ │ └── SECC_LEAF.pem + │ ├── cso + │ │ ├── CPO_CERT_CHAIN.pem + │ │ ├── CPO_SUB_CA1.key + │ │ ├── CPO_SUB_CA2.key + │ │ ├── SECC_LEAF.der + │ │ ├── SECC_LEAF.key + │ │ └── SECC_LEAF.pem + │ └── v2g + │ └── V2G_ROOT_CA.key + ``` + +#### registering callbacks + +You can (and in many cases MUST) register a number of callbacks so libocpp can interact with the charger. In EVerest most of this functionality is orchestrated by the "EvseManager" module, but you can also register your own callbacks interacting directly with your chargers software. Following is a list of callbacks that you must register and a few words about their purpose. + +TODO: in a future version of libocpp the callbacks will be organised in a struct with optional members emphasizing the required and optional callbacks. + +Some general notes: the "connector" parameter of some of the callbacks refers to the connector number as understood in the OCPP 1.6 specification, "0" means the whole charging station, the connectors with EVSEs used for charging cars start at "1". + +- `register_pause_charging_callback` + + this callback is used by libocpp to request pausing of charging, the "connector" parameter tells you which connector/EVSE has to pause charging + +- `register_resume_charging_callback` + + this callback is used by libocpp the request resuming of charging, the "connector" parameter tells you which connector/EVSE can resume charging + +- `register_stop_transaction_callback` + + in EVerest this calls the EvseManagers stop_transaction command which "Stops transactions and cancels charging externally, charging can only be resumed by replugging car. EVSE will also stop transaction automatically e.g. on disconnect, so this only needs to be called if the transaction should end before." + this will then signal the following events: + - ChargingFinished + - TransactionFinished + +- `register_unlock_connector_callback` + + can be used by libocpp to force unlock a connector + +- `register_reserve_now_callback` + + libocpp can use this to reserve a connector, reservation handling is outsourced to a reservation manager in EVerest that implements the reservation interface (everest-core/interfaces/reservation.yaml) + +- `register_upload_diagnostics_callback` + + uses a function (in EVerest provided by the System module) to upload the requested diagnostics file + +- `register_upload_logs_callback` + + uses a function (in EVerest provided by the System module) to upload the requested log file + +- `register_update_firmware_callback` + + uses a function (in EVerest provided by the System module) to perform a firmware update + +- `register_signed_update_firmware_callback` + + uses a function (in EVerest provided by the System module) to perform a signed firmware update + +- `register_provide_token_callback` + + this callback is used in a remote start transaction to provide a token (prevalidated or not) to the authorization system + +- `register_set_connection_timeout_callback` + + used by libocpp to set the authorization or plug in connection timeout in the authorization system based on the "ConnectionTimeout" configuration key + +- `register_disable_evse_callback` + + used to disable the EVSE (ChangeAvailability.req) + +- `register_enable_evse_callback` + + used to enable the EVSE (ChangeAvailability.req) + +- `register_cancel_reservation_callback` + + used to cancel a reservation in the reservation manager (CancelReservation.req) + +- `register_signal_set_charging_profiles_callback` + + used to signal that new charging schedule(s) have been set, you can then use + get_all_composite_charging_schedules(duration_s) to get the new valid charging schedules + +- `register_is_reset_allowed_callback` + + used to inquire (in EVerest from the System module) if a reset is allowed + +- `register_reset_callback` + + used to perform a reset of the requested type + +- `register_connection_state_changed_callback` + + used to inform about the connection state to the CSMS (connected = true, disconnected = false) + +- `register_configuration_key_changed_callback` + + used to react on a changed configuration key. This callback is called when the specified configuration key has been changed by the CSMS + +#### Functions that need to be triggered from the outside after new information is availble (on_... functions in the charge point API) + +- `on_log_status_notification(int32_t request_id, std::string log_status)` + + can be used to notify libocpp of a log status notification + +- `on_firmware_update_status_notification(int32_t request_id, std::string firmware_update_status)` + + can be used to notify libocpp of a firmware update status notification + +- `on_meter_values(int32_t connector, const Powermeter& powermeter)` + + provides a Powermeter struct to libocpp (for sending meter values during charging sessions or periodically) + +- `on_max_current_offered(int32_t connector, int32_t max_current)` + + the maximum current offered to the EV on this connector (in ampere) + +#### The following functions are triggered depending on different so called "Session Events" from the EvseManager + +each of these functions will have a small note what the Session Event was and what it triggers in libocpp + +- `on_enabled(int32_t connector)` + + Notifies libocpp that the connector is functional and operational + +- `on_disabled(int32_t connector)` + + Notifies libocpp that the connector is disabled + +- `on_transaction_started` + + Notifies libocpp that a transaction at the given connector has started, this means that authorization is available and the car is plugged in. + + Some of its parameters: + + - `session_id` is an internal session_id originating in the EvseManager to keep track of the transaction, this is NOT to be mistaken for the transactionId from the StartTransactionResponse in OCPP! + - `id_token` is the token with which the transaction was authenticated + - `meter_start` contains the meter value in Wh for the connector at start of the transaction + - `timestamp` at the start of the transaction + +- `on_transaction_stopped` + + Notifies libocpp that the transaction on the given connector with the given reason has been stopped. + + Some of its parameters: + + - `timestamp` at the end of the transaction + - `energy_wh_import` contains the meter value in Wh for the connector at end of the transaction + +- `on_suspend_charging_ev` + + Notifies libocpp that the EV has paused charging + +- `on_suspend_charging_evse` + + Notifies libocpp that the EVSE has paused charging + +- `on_resume_charging` + + Notifies libocpp that charging has resumed + +- `on_session_started` + + this is mostly used for logging and changing the connector state + +- `on_session_stopped` + + this is mostly used for logging and changing the connector state + +- `on_error` + + Notify libocpp of an error + +- `on_reservation_start` + + Notifies libocpp that a reservation has started + +- `on_reservation_end` + + Notifies libocpp that a reservation has ended + +#### Authorization + +In EVerest authorization is handled by the Auth module and various auth token providers and validators. The OCPP module acts as both a token provider (for pre validated tokens in RemoteStartTransactions) and a token validator (using the authorize requests, or plug & charge). + +To use libocpp as a auth token validator (e.g. before starting a transaction) you can call the "authorize_id_token" function of the ChargePoint object. + +### Register event callbacks and on_handlers + +- `all_connectors_unavailable_callback` + + Notifies that all connectors are unavailable. Used to handle charge availability + requests and firmware updates. + +- `boot_notification_callback` + + Callback to notify of a system boot + +- `clear_customer_information_callback` + + Called to clear customer information based on passed in Customer Certificate, the + IdToken for this request, and the Customer Identified that the request refers to. + If IdToken is passed in will delete authorization cache entry from database. + +- `configure_network_connection_profile_callback` + + Called to configure a network connection profile when none is configured. + +- `connector_effective_operative_status_changed_callback` + + Notifies the user of liboccp that the Operative/Inoperative state of a specific EVSE + has changed. + +- `cs_effective_operative_status_changed_callback` + + Used to notify the user of libocpp that the Operative/Inoperative state of the + charging station itself has changed. Will also call + `evse_effective_operative_status_changed_callback` for each EVSE, and + `connector_effective_operative_status_changed_callback` for each connector whose + status has changed. + +- `data_transfer_callback` + + Used to handle arbitrary data transfers. + +- `evse_effective_operative_status_changed_callback` + + Notifies the user of libocpp that the Operative/Inoperative state of an EVSE has + changed. If as a result the state of connectors changed as well, libocpp will + additionally call the connector_effective_operative_status_changed_callback for + each connector. + +- `get_customer_information_callback` + + Returns human readable customer information based on the CertificateHashDataType, + IdToken and Customer Identifier passed in. + +- `get_log_request_callback` + + Callback to return logs + +- `is_reservation_for_token_callback` + + Check if the current reservation for the given evse id is made for the id + token / group id token. + +- `is_reset_allowed_callback` + + Callback if reset is allowed. If evse_id has a value, reset only applies + to the given evse id. If it has no value, applies to complete charging station. + +- `ocpp_messages_callback` + + Callback to congfigure ocpp message logging. + +- `pause_charging_callback` + + Used to request pausing of charging, the "connector" parameter instructing which + connector/EVSE to pause. + +- `remote_start_transaction_callback` + + Called when the request can be accepted. The boolean authorize_remote_start + indicates if Authorize.req needs to follow or not + +- `reset_callback` + + Performs a reset of the requested type + +- `security_event_callback` + + Used to react to a security event callback. This callback is + called only if the SecurityEvent occured internally within libocpp. + Typically this callback is used to log security events in the security log. + +- `set_charging_profiles_callback` + + Indicates when a charging profile is received and accepted. + +- `stop_transaction_callback` + + Used to stop a transaction. Called when the idTagInfo.status of a + StartTransaction.conf is not Accepted, when a RemoteStopTransaction.req is + received, or when an UnlockConnector.req is received. + +- `time_sync_callback` + + Called on boot notification if the TimeSource ControllerComponent contains + Heartbeat. + +- `transaction_event_callback` + + Called when a transaction_event was sent to the CSMS. + +- `transaction_event_response_callback` + + Called when a transaction_event_response was received from the CSMS. + +- `unlock_connector_callback` + + Used by libocpp to force unlock a connector + +- `update_firmware_request_callback` + + Initiates a firmware update request. Triggers a security event notification + if the certificate is Invalid or Revoked. + +- `validate_network_profile_callback` + + Validates the submitted Network Profile. Is Rejected if + - No callback registered to validate network profile + - CSMS attempted to set a network profile with a lower securityProfile + - CSMS attempted to set a network profile that could not be validated + - Network profile could not be written to the device model storage + +- `variable_changed_callback` + + Called when a variable has been changed by the CSMS + +### Initialize the database + +- Use provided sql database or implement your own storage drive + +## Install libocpp + +For Debian GNU/Linux 11 you will need the following dependencies: + +```bash + sudo apt install build-essential cmake python3-pip libboost-all-dev libsqlite3-dev libssl-dev +``` + +OpenSSL version 3.0 or above is required. + +Clone this repository. + +```bash + git clone https://github.com/EVerest/libocpp +``` + +In the libocpp folder create a folder named build and cd into it. +Execute cmake and then make install: + +```bash + mkdir build && cd build + cmake .. + make install +``` + +## Quickstart for OCPP 1.6 + +Libocpp provides a small standalone OCPP1.6 client that you can control using command line. + +Install the dependencies and libocpp as described in [Install libocpp](#install-libocpp). + +Make sure you modify the following config entries in the [config.json](config/v16/config.json) file according to the CSMS you want to connect to before executing make install. + +```json +{ + "Internal": { + "ChargePointId": "", + "CentralSystemURI": "" + } +} +``` + +Change into libocpp/build and execute cmake and then make install: + +```bash + cd build + cmake -DLIBOCPP16_BUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=./dist .. + make -j$(nproc) install +``` + +Use the following command to start the charge point. Replace the config with [config-docker.json](config/v16/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. + +```bash + ./dist/bin/charge_point \ + --maindir ./dist \ + --conf config.json +``` + +Type `help` to see a list of possible commands. + +## Building the doxygen documentation + +```bash + cmake -S . -B build + cmake --build build --target doxygen-ocpp +``` + +You will find the generated doxygen documentation at: +`build/dist/docs/html/index.html` + +The main reference for the integration of libocpp for OCPP1.6 is the ocpp::v16::ChargePoint class defined in libocpp/include/ocpp/v16/charge_point.hpp . + +## Unit testing + +GTest is required for building the test cases target. +To build the target and run the tests you can reference the script `.ci/build-kit/install_and_test.sh`. +The script allows the GitHub Actions runner to execute. + +Local testing: + +```bash +mkdir build +cmake -B build -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="./dist" +cd build +make -j$(nproc) install +``` + +Run any required tests from build/tests. + +## Building with FetchContent instead of EDM + +In [doc/build-with-fetchcontent](doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. + +### Support for TPM keys + +In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. + +## Support for websocket++ + +The old websocket++ implementation has been deprecated. For enabling websocket++ support use the following cmake option: + +```bash + cmake .. -DLIBOCPP_ENABLE_DEPRECATED_WEBSOCKETPP=ON +``` + +### Support for iface + +In order to connect through a custom network iface, a custom internal config variable 'IFace' can be used. + +```json +"Internal": { + "IFace" : "enp43s0" +} +``` + +## Get Involved + +See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. From f473fb7b6465b554238cc9f0bd58df80676e3845 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:58:52 -0400 Subject: [PATCH 024/134] Rename ocpp_201_readme.md to ocpp_201_README.md CHANGE PAGE NAME Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/{ocpp_201_readme.md => ocpp_201_README.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename doc/{ocpp_201_readme.md => ocpp_201_README.md} (100%) diff --git a/doc/ocpp_201_readme.md b/doc/ocpp_201_README.md similarity index 100% rename from doc/ocpp_201_readme.md rename to doc/ocpp_201_README.md From fa2a005658f07e171fd7517bdca1fa6776850415 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:59:33 -0400 Subject: [PATCH 025/134] Delete OCPP-1-6.md moved content to new folder Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- OCPP-1-6.md | 644 ---------------------------------------------------- 1 file changed, 644 deletions(-) delete mode 100644 OCPP-1-6.md diff --git a/OCPP-1-6.md b/OCPP-1-6.md deleted file mode 100644 index 153d60789..000000000 --- a/OCPP-1-6.md +++ /dev/null @@ -1,644 +0,0 @@ -# C++ implementation of OCPP 1.6 -![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) - -This C++ library provides a complete and production-ready solution for integrating OCPP 1.6 into your electric vehicle (EV) charging stations. Our implementation enables seamless communication between charging stations and central management systems, supporting remote control, monitoring, and billing functionalities. - -NOTE: [EVerest OCPP 2.0.1](OCPP-2-0-1.md) is under active development, with core functionalities available. - - -## Table of contents - -- [Feature Profile Support OCPP 1.6](#feature-profile-support-ocpp-16) -- [CSMS Compatibility OCPP 1.6](#csms-compatibility-ocpp-16) -- [Integration with EVerest](#integration-with-everest) - - [Run OCPP1.6 with EVerest](#run-ocpp16-with-everest) - - [Integrate this library with your Charging Station Implementation for OCPP1.6](#integrate-this-library-with-your-charging-station-implementation-for-ocpp16) - - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) - - [ChargePoint() constructor](#chargepoint-constructor) - - [registering callbacks](#registering-callbacks) - - [Functions that need to be triggered from the outside after new information is availble (on\_... functions in the charge point API)](#functions-that-need-to-be-triggered-from-the-outside-after-new-information-is-availble-on_-functions-in-the-charge-point-api) - - [The following functions are triggered depending on different so called "Session Events" from the EvseManager](#the-following-functions-are-triggered-depending-on-different-so-called-session-events-from-the-evsemanager) - - [Authorization](#authorization) - - [Install libocpp](#install-libocpp) - - [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) - - [Building the doxygen documentation](#building-the-doxygen-documentation) - - [Unit testing](#unit-testing) - - [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) - - [Support for security profile 2 and 3 with TPM in OCPP 1.6 using libwebsockets](#support-for-security-profile-2-and-3-with-tpm-in-ocpp-16-using-libwebsockets) - -## OCPP 1.6 Support - -The following tables show the current support for the listed OCPP 1.6 feature profiles / functional blocks and application notes. - -All documentation and the issue tracking can be found in our main repository here: https://github.com/EVerest/ - -### Feature Profile Support OCPP 1.6 - -| Feature Profile | Supported | -| -------------------------- | ------------------------- | -| Core | :heavy_check_mark: yes | -| Firmware Management | :heavy_check_mark: yes | -| Local Auth List Management | :heavy_check_mark: yes | -| Reservation | :heavy_check_mark: yes | -| Smart Charging | :heavy_check_mark: yes | -| Remote Trigger | :heavy_check_mark: yes | - -## CSMS Compatibility - -### CSMS Compatibility OCPP 1.6 - -The EVerest implementation of OCPP 1.6 has been tested against the -OCPP Compliance Test Tool (OCTT and OCTT2) during the implementation. - -The following table shows CSMS with which this library was tested. -If you provide a CSMS that is not yet listed here, feel free to -[contact us](https://lists.lfenergy.org/g/everest)! - -- chargecloud -- chargeIQ -- Chargetic -- Compleo -- Current -- Daimler Truck -- ev.energy -- eDRV -- Fastned -- [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) -- Electrip Global -- EnergyStacks -- EV-Meter -- Fraunhofer IAO (ubstack CHARGE) -- Green Motion -- gridundco -- ihomer (Infuse CPMS) -- iLumen -- JibeCompany (CharlieV CMS and Chargebroker proxy) -- MSI -- PUMP (PUMP Connect) -- Scoptvision (Scopt Powerconnect) -- Siemens -- [SteVe](https://github.com/steve-community/steve) -- Syntech -- Trialog -- ubitricity -- Weev Energy - -## Integration with EVerest - -This library is automatically integrated as the OCPP and OCPP201 module within [everest-core](https://github.com/EVerest/everest-core) - the complete software stack for your charging station. It is recommended to use EVerest together with this OCPP implementation. - -### Run OCPP1.6 with EVerest - -If you run libocpp with OCPP1.6 with EVerest, the build process of [everest-core](https://github.com/EVerest/everest-core) will take care of installing all necessary dependencies for you. - -## Integrate this library with your Charging Station Implementation for OCPP - -OCPP is a protocol that affects, controls and monitors many areas of a charging station's operation. - -If you want to integrate this library with your charging station implementation, you have to register a couple of **callbacks** and integrate **event handlers**. This is necessary for the library to interact with your charging station according to the requirements of OCPP. - -Libocpp needs registered **callbacks** in order to execute control commands defined within OCPP (e.g Reset.req or RemoteStartTransaction.req) - -The implementation must call **event handlers** of libocpp so that the library can track the state of the charging station and trigger OCPP messages accordingly (e.g. MeterValues.req , StatusNotification.req) - -Your reference within libocpp to interact is a single instance to the class [ChargePoint](include/ocpp/v16/charge_point.hpp) for OCPP 1.6. - -### Overview of the required callbacks and events and what libocpp expects to happen - -The following section will give you a high level overview of how to integrate libocpp with your application. Please use the [Doxygen Documentation](#building-the-doxygen-documentation) as an additional source for the ChargePoint API. - -In EVerest the OCPP module leverages several other modules to perform tasks that relate to authorization, reservations, charging session handling and system tasks like rebooting or firmware updates. - -- Auth orchestrates authorization, utilizing different token providers like RFID reads and token validators. Libocpp mainly acts as a token validator, but in the case of RemoteStartTransactions it acts as a token provider as well -- EvseManager manages the charging session and charging state machine by communicating with a "board support package", a driver for the charging hardware that abstracts away the control pilot, relay control, power meters, etc. The EvseManager also handles reservations. -- System handles firmware updates, log uploads and resets - -The following sections explain the steps you can follow to implement their functionality on your own and integrate the libocpp directly into your charging station software without relying on EVerest. However, in most cases it's much easier to write an EVerest driver using the *everest-core/interfaces/board_support_AC.yaml* interface. - -### Usage for OCPP 1.6 - -#### ChargePoint() constructor - -The main entrypoint for libocpp for OCPP1.6 is the ocpp::v16::ChargePoint constructor. -This is defined in libocpp/include/ocpp/v16/charge_point.hpp and takes the following parameters: - -- config: a std::string that contains the libocpp 1.6 config. There are example configs that work with a [SteVe](https://github.com/steve-community/steve) installation [running in Docker](https://github.com/EVerest/everest-utils/tree/main/docker/steve), for example: [config-docker.json](config/v16/config-docker.json) - -- share_path: a std::filesystem path containing the path to the OCPP modules folder, for example pointing to */usr/share/everest/modules/OCPP*. This path contains the following files and directories and is installed by the libocpp install target: - - ```bash - . - ├── config-docker.json - ├── config-docker-tls.json - ├── config.json - ├── init.sql - ├── logging.ini - └── profile_schemas - ├── Config.json - ├── Core.json - ├── FirmwareManagement.json - ├── Internal.json - ├── LocalAuthListManagement.json - ├── PnC.json - ├── Reservation.json - ├── Security.json - ├── SmartCharging.json - └── Custom.json - ``` - - Here you can find: - - the aforementioned config files - - - a *logging.ini* that is needed to initialize logging with Everest::Logging::init(path_to_logging_ini, "name_of_binary") - - - a *init.sql* file which contains the database schema used by libocpp for its sqlite database - - - and a *profile_schemas* directory. This contains json schema files that are used to validate the libocpp config. The schemas are split up according to the OCPP1.6 feature profiles like Core, FirmwareManagement and so on. Additionally there is a schema for "Internal" configuration options (for example the ChargePointId, or CentralSystemURI). A "PnC" schema for the ISO 15118 Plug & Charge with OCPP 1.6 Application note, a "Security" schema for the OCPP 1.6 Security Whitepaper (3rd edition) and an exemplary "Custom" schema are provided as well. The Custom.json could be modified to be able to add custom configuration keys. Finally there's a Config.json schema that ties everything together - -- user_config_path: this points to a "user config", which we call a configuration file that's merged with the config that's provided in the "config" parameter. Here you can add, remove and overwrite settings without modifying the config passed in the first parameter directly. This is also used by libocpp to persistently modify config entries that are changed by the CSMS that should persist across restarts. - -- database_path: this points to the location of the sqlite database that libocpp uses to keep track of connector availability, the authorization cache and auth list, charging profiles and transaction data - -- sql_init_path: this points to the aforementioned init.sql file which contains the database schema used by libocpp for its sqlite database - -- message_log_path: this points to the directory in which libocpp can put OCPP communication logfiles for debugging purposes. This behavior can be controlled by the "LogMessages" (set to true by default) and "LogMessagesFormat" (set to ["log", "html", "session_logging"] by default, "console" and "console_detailed" are also available) configuration keys in the "Internal" section of the config file. Please note that this is intended for debugging purposes only as it logs all communication, including authentication messages. - -- evse_security: this is a pointer to an implementation of the [evse_security](include/ocpp/common/evse_security.hpp) interface. This allows you to include your custom implementation of the security related operations according to this interface. If you set this value to nullptr, the internal implementation of the security related operations of libocpp will be used. In this case you need to specify the parameter security_configuration - -- security_configuration: this parameter should only be set in case the evse_security parameter is nullptr. It specifies the file paths that are required to set up the internal evse_security implementation. Note that you need to specify bundle files for the CA certificates and directories for the certificates and keys - - The directory layout expected is as follows - - ```bash - . - ├── ca - │ ├── csms - │ │ └── CSMS_ROOT_CA.pem - │ ├── cso - │ │ ├── CPO_CERT_CHAIN.pem - │ │ ├── CPO_SUB_CA1_LEAF.der - │ │ ├── CPO_SUB_CA1.pem - │ │ ├── CPO_SUB_CA2_LEAF.der - │ │ └── CPO_SUB_CA2.pem - │ ├── mf - │ │ └── MF_ROOT_CA.pem - │ ├── mo - │ │ ├── INTERMEDIATE_MO_CA_CERTS.pem - │ │ ├── MO_ROOT_CA.der - │ │ ├── MO_ROOT_CA.pem - │ │ ├── MO_SUB_CA1.der - │ │ ├── MO_SUB_CA1.pem - │ │ ├── MO_SUB_CA2.der - │ │ └── MO_SUB_CA2.pem - │ └── v2g - │ ├── V2G_ROOT_CA.der - │ └── V2G_ROOT_CA.pem - ├── client - │ ├── csms - │ │ ├── CPO_CERT_CHAIN.pem - │ │ ├── CPO_SUB_CA1.key - │ │ ├── CPO_SUB_CA2.key - │ │ ├── SECC_LEAF.der - │ │ ├── SECC_LEAF.key - │ │ └── SECC_LEAF.pem - │ ├── cso - │ │ ├── CPO_CERT_CHAIN.pem - │ │ ├── CPO_SUB_CA1.key - │ │ ├── CPO_SUB_CA2.key - │ │ ├── SECC_LEAF.der - │ │ ├── SECC_LEAF.key - │ │ └── SECC_LEAF.pem - │ └── v2g - │ └── V2G_ROOT_CA.key - ``` - -#### registering callbacks - -You can (and in many cases MUST) register a number of callbacks so libocpp can interact with the charger. In EVerest most of this functionality is orchestrated by the "EvseManager" module, but you can also register your own callbacks interacting directly with your chargers software. Following is a list of callbacks that you must register and a few words about their purpose. - -TODO: in a future version of libocpp the callbacks will be organised in a struct with optional members emphasizing the required and optional callbacks. - -Some general notes: the "connector" parameter of some of the callbacks refers to the connector number as understood in the OCPP 1.6 specification, "0" means the whole charging station, the connectors with EVSEs used for charging cars start at "1". - -- `register_pause_charging_callback` - - this callback is used by libocpp to request pausing of charging, the "connector" parameter tells you which connector/EVSE has to pause charging - -- `register_resume_charging_callback` - - this callback is used by libocpp the request resuming of charging, the "connector" parameter tells you which connector/EVSE can resume charging - -- `register_stop_transaction_callback` - - in EVerest this calls the EvseManagers stop_transaction command which "Stops transactions and cancels charging externally, charging can only be resumed by replugging car. EVSE will also stop transaction automatically e.g. on disconnect, so this only needs to be called if the transaction should end before." - this will then signal the following events: - - ChargingFinished - - TransactionFinished - -- `register_unlock_connector_callback` - - can be used by libocpp to force unlock a connector - -- `register_reserve_now_callback` - - libocpp can use this to reserve a connector, reservation handling is outsourced to a reservation manager in EVerest that implements the reservation interface (everest-core/interfaces/reservation.yaml) - -- `register_upload_diagnostics_callback` - - uses a function (in EVerest provided by the System module) to upload the requested diagnostics file - -- `register_upload_logs_callback` - - uses a function (in EVerest provided by the System module) to upload the requested log file - -- `register_update_firmware_callback` - - uses a function (in EVerest provided by the System module) to perform a firmware update - -- `register_signed_update_firmware_callback` - - uses a function (in EVerest provided by the System module) to perform a signed firmware update - -- `register_provide_token_callback` - - this callback is used in a remote start transaction to provide a token (prevalidated or not) to the authorization system - -- `register_set_connection_timeout_callback` - - used by libocpp to set the authorization or plug in connection timeout in the authorization system based on the "ConnectionTimeout" configuration key - -- `register_disable_evse_callback` - - used to disable the EVSE (ChangeAvailability.req) - -- `register_enable_evse_callback` - - used to enable the EVSE (ChangeAvailability.req) - -- `register_cancel_reservation_callback` - - used to cancel a reservation in the reservation manager (CancelReservation.req) - -- `register_signal_set_charging_profiles_callback` - - used to signal that new charging schedule(s) have been set, you can then use - get_all_composite_charging_schedules(duration_s) to get the new valid charging schedules - -- `register_is_reset_allowed_callback` - - used to inquire (in EVerest from the System module) if a reset is allowed - -- `register_reset_callback` - - used to perform a reset of the requested type - -- `register_connection_state_changed_callback` - - used to inform about the connection state to the CSMS (connected = true, disconnected = false) - -- `register_configuration_key_changed_callback` - - used to react on a changed configuration key. This callback is called when the specified configuration key has been changed by the CSMS - -#### Functions that need to be triggered from the outside after new information is availble (on_... functions in the charge point API) - -- `on_log_status_notification(int32_t request_id, std::string log_status)` - - can be used to notify libocpp of a log status notification - -- `on_firmware_update_status_notification(int32_t request_id, std::string firmware_update_status)` - - can be used to notify libocpp of a firmware update status notification - -- `on_meter_values(int32_t connector, const Powermeter& powermeter)` - - provides a Powermeter struct to libocpp (for sending meter values during charging sessions or periodically) - -- `on_max_current_offered(int32_t connector, int32_t max_current)` - - the maximum current offered to the EV on this connector (in ampere) - -#### The following functions are triggered depending on different so called "Session Events" from the EvseManager - -each of these functions will have a small note what the Session Event was and what it triggers in libocpp - -- `on_enabled(int32_t connector)` - - Notifies libocpp that the connector is functional and operational - -- `on_disabled(int32_t connector)` - - Notifies libocpp that the connector is disabled - -- `on_transaction_started` - - Notifies libocpp that a transaction at the given connector has started, this means that authorization is available and the car is plugged in. - - Some of its parameters: - - - `session_id` is an internal session_id originating in the EvseManager to keep track of the transaction, this is NOT to be mistaken for the transactionId from the StartTransactionResponse in OCPP! - - `id_token` is the token with which the transaction was authenticated - - `meter_start` contains the meter value in Wh for the connector at start of the transaction - - `timestamp` at the start of the transaction - -- `on_transaction_stopped` - - Notifies libocpp that the transaction on the given connector with the given reason has been stopped. - - Some of its parameters: - - - `timestamp` at the end of the transaction - - `energy_wh_import` contains the meter value in Wh for the connector at end of the transaction - -- `on_suspend_charging_ev` - - Notifies libocpp that the EV has paused charging - -- `on_suspend_charging_evse` - - Notifies libocpp that the EVSE has paused charging - -- `on_resume_charging` - - Notifies libocpp that charging has resumed - -- `on_session_started` - - this is mostly used for logging and changing the connector state - -- `on_session_stopped` - - this is mostly used for logging and changing the connector state - -- `on_error` - - Notify libocpp of an error - -- `on_reservation_start` - - Notifies libocpp that a reservation has started - -- `on_reservation_end` - - Notifies libocpp that a reservation has ended - -#### Authorization - -In EVerest authorization is handled by the Auth module and various auth token providers and validators. The OCPP module acts as both a token provider (for pre validated tokens in RemoteStartTransactions) and a token validator (using the authorize requests, or plug & charge). - -To use libocpp as a auth token validator (e.g. before starting a transaction) you can call the "authorize_id_token" function of the ChargePoint object. - -### Register event callbacks and on_handlers - -- `all_connectors_unavailable_callback` - - Notifies that all connectors are unavailable. Used to handle charge availability - requests and firmware updates. - -- `boot_notification_callback` - - Callback to notify of a system boot - -- `clear_customer_information_callback` - - Called to clear customer information based on passed in Customer Certificate, the - IdToken for this request, and the Customer Identified that the request refers to. - If IdToken is passed in will delete authorization cache entry from database. - -- `configure_network_connection_profile_callback` - - Called to configure a network connection profile when none is configured. - -- `connector_effective_operative_status_changed_callback` - - Notifies the user of liboccp that the Operative/Inoperative state of a specific EVSE - has changed. - -- `cs_effective_operative_status_changed_callback` - - Used to notify the user of libocpp that the Operative/Inoperative state of the - charging station itself has changed. Will also call - `evse_effective_operative_status_changed_callback` for each EVSE, and - `connector_effective_operative_status_changed_callback` for each connector whose - status has changed. - -- `data_transfer_callback` - - Used to handle arbitrary data transfers. - -- `evse_effective_operative_status_changed_callback` - - Notifies the user of libocpp that the Operative/Inoperative state of an EVSE has - changed. If as a result the state of connectors changed as well, libocpp will - additionally call the connector_effective_operative_status_changed_callback for - each connector. - -- `get_customer_information_callback` - - Returns human readable customer information based on the CertificateHashDataType, - IdToken and Customer Identifier passed in. - -- `get_log_request_callback` - - Callback to return logs - -- `is_reservation_for_token_callback` - - Check if the current reservation for the given evse id is made for the id - token / group id token. - -- `is_reset_allowed_callback` - - Callback if reset is allowed. If evse_id has a value, reset only applies - to the given evse id. If it has no value, applies to complete charging station. - -- `ocpp_messages_callback` - - Callback to congfigure ocpp message logging. - -- `pause_charging_callback` - - Used to request pausing of charging, the "connector" parameter instructing which - connector/EVSE to pause. - -- `remote_start_transaction_callback` - - Called when the request can be accepted. The boolean authorize_remote_start - indicates if Authorize.req needs to follow or not - -- `reset_callback` - - Performs a reset of the requested type - -- `security_event_callback` - - Used to react to a security event callback. This callback is - called only if the SecurityEvent occured internally within libocpp. - Typically this callback is used to log security events in the security log. - -- `set_charging_profiles_callback` - - Indicates when a charging profile is received and accepted. - -- `stop_transaction_callback` - - Used to stop a transaction. Called when the idTagInfo.status of a - StartTransaction.conf is not Accepted, when a RemoteStopTransaction.req is - received, or when an UnlockConnector.req is received. - -- `time_sync_callback` - - Called on boot notification if the TimeSource ControllerComponent contains - Heartbeat. - -- `transaction_event_callback` - - Called when a transaction_event was sent to the CSMS. - -- `transaction_event_response_callback` - - Called when a transaction_event_response was received from the CSMS. - -- `unlock_connector_callback` - - Used by libocpp to force unlock a connector - -- `update_firmware_request_callback` - - Initiates a firmware update request. Triggers a security event notification - if the certificate is Invalid or Revoked. - -- `validate_network_profile_callback` - - Validates the submitted Network Profile. Is Rejected if - - No callback registered to validate network profile - - CSMS attempted to set a network profile with a lower securityProfile - - CSMS attempted to set a network profile that could not be validated - - Network profile could not be written to the device model storage - -- `variable_changed_callback` - - Called when a variable has been changed by the CSMS - -### Initialize the database - -- Use provided sql database or implement your own storage drive - -## Install libocpp - -For Debian GNU/Linux 11 you will need the following dependencies: - -```bash - sudo apt install build-essential cmake python3-pip libboost-all-dev libsqlite3-dev libssl-dev -``` - -OpenSSL version 3.0 or above is required. - -Clone this repository. - -```bash - git clone https://github.com/EVerest/libocpp -``` - -In the libocpp folder create a folder named build and cd into it. -Execute cmake and then make install: - -```bash - mkdir build && cd build - cmake .. - make install -``` - -## Quickstart for OCPP 1.6 - -Libocpp provides a small standalone OCPP1.6 client that you can control using command line. - -Install the dependencies and libocpp as described in [Install libocpp](#install-libocpp). - -Make sure you modify the following config entries in the [config.json](config/v16/config.json) file according to the CSMS you want to connect to before executing make install. - -```json -{ - "Internal": { - "ChargePointId": "", - "CentralSystemURI": "" - } -} -``` - -Change into libocpp/build and execute cmake and then make install: - -```bash - cd build - cmake -DLIBOCPP16_BUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=./dist .. - make -j$(nproc) install -``` - -Use the following command to start the charge point. Replace the config with [config-docker.json](config/v16/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. - -```bash - ./dist/bin/charge_point \ - --maindir ./dist \ - --conf config.json -``` - -Type `help` to see a list of possible commands. - -## Building the doxygen documentation - -```bash - cmake -S . -B build - cmake --build build --target doxygen-ocpp -``` - -You will find the generated doxygen documentation at: -`build/dist/docs/html/index.html` - -The main reference for the integration of libocpp for OCPP1.6 is the ocpp::v16::ChargePoint class defined in libocpp/include/ocpp/v16/charge_point.hpp . - -## Unit testing - -GTest is required for building the test cases target. -To build the target and run the tests you can reference the script `.ci/build-kit/install_and_test.sh`. -The script allows the GitHub Actions runner to execute. - -Local testing: - -```bash -mkdir build -cmake -B build -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX="./dist" -cd build -make -j$(nproc) install -``` - -Run any required tests from build/tests. - -## Building with FetchContent instead of EDM - -In [doc/build-with-fetchcontent](doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. - -### Support for TPM keys - -In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. - -## Support for websocket++ - -The old websocket++ implementation has been deprecated. For enabling websocket++ support use the following cmake option: - -```bash - cmake .. -DLIBOCPP_ENABLE_DEPRECATED_WEBSOCKETPP=ON -``` - -### Support for iface - -In order to connect through a custom network iface, a custom internal config variable 'IFace' can be used. - -```json -"Internal": { - "IFace" : "enp43s0" -} -``` - -## Get Involved - -See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. From 01ff08ddd9068d9009fe12160fcb0ad0160e5d6f Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Thu, 3 Oct 2024 11:38:12 -0400 Subject: [PATCH 026/134] Create banner-ocpp.jpg Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/img/banner-ocpp.jpg | 1 + 1 file changed, 1 insertion(+) create mode 100644 doc/img/banner-ocpp.jpg diff --git a/doc/img/banner-ocpp.jpg b/doc/img/banner-ocpp.jpg new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/doc/img/banner-ocpp.jpg @@ -0,0 +1 @@ + From 44e038c4f6aa0bfa19c2859e5b4e6d77000ecdcf Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Thu, 3 Oct 2024 12:10:57 -0400 Subject: [PATCH 027/134] Add files via upload Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/img/banner-ocpp.jpg | Bin 1 -> 60432 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/img/banner-ocpp.jpg b/doc/img/banner-ocpp.jpg index 8b137891791fe96927ad78e64b0aad7bded08bdc..f1262f31074845ff6a6ec1f5976d92bfb316d9ac 100644 GIT binary patch literal 60432 zcmeFZcU)83wl5wFB25IOx2^OJ(lL@FY(Rnp3B7Nmh9Vt8ktj-UTdGn;2q8e|p+lrg zm#!csK|qR<077WtmwnE?@80|FtLOgyd@G-|)?l_Z$CzWSIp%ka$;Ic36~IlfuD&kd z(&bBlhtwb7f^b<}Ut8PZG1N#`|B(*h(j@@kGMA&Tuh&%o0O0*J&>yO&^_!)Y^>4K6 zfJ@Zh-w#Kp0N)3XA3yr*kAJ=YBj;bQhqM1EJ0Cr+Mq%?@a{pTD ze{!dHb_sBz=ABVbc_&~0Kmg#9G?jiF66pIE9YLjU`BOVZrT_ekcKZii@)!N&A9VBI z%a}s7sbxl}^lwh?j?Pqihe}I7`FH7V|Bm+d3i|80e;t2u%INac%!GQsMLqcdzXM=^ z0Dv#R3*ZO{1^fnh3{d=^lvnzDd2N6XwR9-JpIXli;0_3+)_Fip`KtvNDyRw_i+~&7j6HR2F3vZwWd?>q1(!UF^^aqOjr<|0p_o4o)s^9uZM7aS2H! zWffI5bq(#`b#(O}>Vr*8&CD&Rf_HLuadmTtc?1Lo1&6>x!(P6Mj){$nPe@D8$jr)q z^ET&waS5^%RfaCFt8c(IHZ`}jcK7u5^$&a;9GaY(o|&Ed{AC_bSpBxPzVUr?i?p|Y z@ayo1e0=g3UzY$^{+r1D!P$Su7gY$CE?>QR$kLC7u9yr2`NH}>`(kB=sARy@FJwYSo=F?|7VOv{ZpL%H^%;ruXzCDl}psY zyTSqh0VsOgbHL~CEUD`%Q!%$HYN|gI zs#{=Ju=b|B4yOCcFR&;sJ)|y0pt8uWLty#>pcMLM{G_0AQ?78%+HRZK_oJht0_mK0yFR+&IbDtk^R zOWrCsuMl&eLeiO{#pdOs{Cy?_pTXrQbo^AI3X^`7aJDk<#FES>8D6x?ksrw%$i)U^ z9{Y~NNLQ?heP18EM4L!o=X&b$(Ol@8g8dz$?hS}?bE;gr&AHWVe|1JpU`5}LiTdy2 zz6iD_caTP6eIasANJiTz&^X2t3z7)W6GgL%^}t;cx|FfDz3km&0~>pyQ@+Cnf?3$8&_>J0BhjcuyXPJY%e*cD{;nM{}L%TDD5|6~v&UcNRqfeSjIofRQ)dT*t z8Lb~5aQ$L#xmh`^IJ|dcWjJBE^OX1cR(VAG&zx##VZ-B%Sdh$dXmNOe)Gx;xt{sou zu9aFi)+o~y?xpOpm794SdY&ORJUT3E@9B`a;2IWkCVv6=fw}+aV`?irEmm79&_N(ek zFJGbx;g;uAz(>k0GvoA`xLb3#h`l++1YmSiomHp(!hr#cA29JAcvox``g8Bh+Tp~R zD91`R>eFPLUYh_q;;V1MO{`vOM!qK4@fv@^s`-KoReDStv8}0$^!X&ln|j9feT=$- z?1pAN7R7NThiI)z$*IV6l!VUtMxlAK2V3Aa6s_wCH+zL14eN)2K5T3|$-iTEA%~o* zQ$7`PHrQ0No{5oJNZABLtXGi!!M#NUez}L4mprFaKa0UgSN{wQ$5`}O3!t2Q%56Sx zg?aCsMARd{n&(7kj{I4v>I*EeSG_k_H(y)yX8qXpa{Fd^ZE^Ad-WTfvhUN*GD{ar9 zR1L@S2&L(X8Dh6~IkKPf%8dB^8RQFRd@7mex;a$J%V6Iwq*N?Mt6{pvuFS0qky(_` znIGlf_#cm-|9>98)c+sG&#dD-5#i;nv1HJpeQ0=&+>yCMgKX`fiUvHpBm$^~i57OF zc>wRyte#UBB|K$*dQ7HiNot9A@(Lzme6oj(CZx5!-a3a)oA?hYK18-? zIo6{-S;G`D$$x{_O$~^%T*Cb6})!xu4MX;TFQdlN5;vXj{y<`BWr*`yhfi@If>1j!PXW&yUTU zB-q<{Iw_;oZzW6=N!ku_;V(=SvN7~RD3EYTYCF%sUqa}o(b+3^)*zwpZQq=^7`VKw!pR&IX*~#wFK^6nI0f3R z4%>iZ4~pNx5f6x^iKTF#?i111cpS5P`_O8Z0sG`~-|)z9>BMHkla`&M!;el9uII z?bD!#*-IoG?w{J2Hj{wnp6?eUbGtPqHqKO`S%SRgRRI}Nx|Wa3ETkatDI6hg+T*-Sm|;$?HaXDc#Omzp-cb{eh&iOGm95yt&(UehH%qE{ATU zmuCx6*bwf5Urq@FJ2;Y4p94*&64`ve+x{Lg6CbrV=Ic^3BP}95?-LhsA1#UL#NtOi z7Il`=E37$U);Yupyk$?lizs!2`$;&>Vd8PAMO=yyU0m|2NXh1CM4+cO0coAlF`uzk zXD3DWo4l_iW)2hLfuwS89+L&tM0Znipc@Vr%pUMIJaHAucbHnwQA z-S@M*|EHe*K~c0xs>+^!x;JGz>)Y{DW1YvtHG#epbtZX2VKd(K7;B3Pv%?@UDQ{jW zq1kpj5-)zYhx{&gpx_?SC(5z)#_S}yt&c}6hR|$TyRO9QsXA*QpDGlZRP!kLbM-x@ zsD3A2%SWPOw^pCJ#1xsgB_FmT>69b0zwTh-d+?L+Bpn{Qoo%yd;U66>YrLOBUQuqt zX$L;(2dy~p!9o35pPo;Cg&Xy@%Ehh3TmCRl^A{FzY-O;krA&-)#cdK72to#-|D_ zFjzEBVz+Z2IIbEoDsl^_taf)QP8n9mE79F4FwcKiGwoE<@r1Z#9x|IY?k$IUO%e_1 zc@rH!xKB^k50Ee|<_^Gn?&SG#S?xcr%rS3Y+2F^E>r2S;O^FUG=E$Zvy+X#BH%O}O z%^}+$$?$oMN^VE72)DQRkPPZf@dD6gidcDFcoVl$IKN{LB6=U9Nn(dCB+as%$mrGZ zM0dS7AVcL6w{tx)wpUF$QzpyvRq~WJ$u5thRkwWt+c4XzS^fz&2byWWL{MQ)k^l-w zDiPIx&_50GtxZ2vYc;OR61%##Yo(HJ3(PAw#@)>XhvXq>31c^Ui9dAWiX;eit@Udt zJLC`f{mf%`f@vVt{L2nXdyMu}rkj@|)!`m#N>e&PE3<{i0LlXBkn_9{age$ygHVGX zpFQQc091z#P%^UwYsn^O!2Pq(5K4M7sABtEtH+=r>jGfXSwB_z$Cr(z<*z+%Fy`Dl z+MKz5zN8+(w@R;jbHDn$p5T-oV&4CHTO;i;iVpJhFzL>knDasd)ccF*VphCLWQ&9@ z-4N6`VF?No32_NNST-`rzW_wPSOJ~zw+m4z(c}xjAQm@GLL4x}Qw7S7IA)Wpq*}Ly z2MD4w=vYYa5lJs52%WQ_N8*UCu)V`Au>5G|;Pg04p({9HmSAB@8`YL;uj(ZzT${@k98r26CjsX$kSU4$fYhq)rcfUFSehlanjB3?_YdwA3- zOEj+yKFX=8UBO6R;p_ZuGH4-p(X&UzmwK_D2{dYafZyE|ywPrs&LxOD10QY<$XCt) zZ@6)FCri5+i14XM=7qv0`%FVjJ)lW2i}Ykc7f7`fhCIjR%jbWh9ANv_5HC>`VNTaF zT_C_2F;ix^4+;FOa!ac?V^c>XZ$I`f>a1t(=f)c9h^p?_h7p6Y5!M%g`exDw1&w>2 zd4^m?on^L!oTtArI=5Qi*cISJe0<4$0dPvvqZGMp94Mka=FO9z$|)xs8BJms6R)>U zSIbm-kBo7r-M&BlnmT3bN#-`m>;85VC77(053XB7(M@Mo4__bhuUnj#X!F2=bTd|I zLWksS>Y3;OdjEZ;p z9q1b=hSklcLj)RA1C85uL^8`ek-_eOVXe zMYzem5NwEz{u#kbTEK%|P{hfR1iC*`m^s|dLyk_|^3rtY>;>m8>r|0Fp~N8=%6n|uAnMY3-z_(tj0ZARM|Lu zd0yy)E#!NiRi0BN^Wf! zq-Rb!#QDWu9TrX;@!y0rT7D}w&s$dZx>Y*uI4XA>t_Af_D4Wa^Ugh4mGrRzR%uZR3 zSN;x${0k=XpKi1ph6q66%xx-O@-KPeu{#UIBQ0_@X`H&`PGwUjxZ5ktrNoyFqaZTX zKL{-~9bban6oqS%qm`TNy?5MQn?mBD1iE*yJBYHC%0jwcK9jU>%^Sv!0n!dLp5UYw z$!$jft?khCUg@ZsbNZD_9yWyJ>Ua-P0mNY~}*c9;)4>Q~(gV6T* zmMCtGpx@T$sLLR*VYgon)Qgiqh(cu%)&eAQCtxTD_#!Fi}xN5(7Ly93#DyCT5E9aJF6+Qqs_c3Sq^V>X1mP;&{^xIE32^s zc*1Oj#ZK+5YA%BBWO_b#!xUNJP)~D5Qt5|%h8iM6QVQKsdY@M)37@|Xuo%&1lZ)^_L7ZlWlie$%Uw)Pe33(#WVw6@?zEzpYE0m^X zr=>15IKeyOr_jJ771pF$u1-3_h|G2W{kdL8^hEKEP;tE+B*aoL$3Mv_RB8w;W&V1d zihFd@ZeIXcB6JAjH(=JCsV;tai6w^NWbGdnOcOTSxi@FK=V$Rm`eH`N^v7KxlIrYd+ilzOxZSHT%Mf+`;$S zkcU7kg1K3@x~@*{Y7KXcXx1}`viw0!p?Q!v+Odp)v6{tzRgE!RrzsX`SwnMs&pZus zwP%C8IS3Ee3m;DJ9<;2*hNMf+Kbvk$)93hQvA0NYHQd59BoE!ti8RSu%dC5}sytZB zE-_P`;cB^4hqVSS^<%uQNmg+n!M3EN^Sli(G#2P2Yu@rcf8r=KSf#)vdqt7walVFC z3S2ypNV7X6DO@$@(Ng3ZK1zQ=O!5=R1)!=sv+ z-x8cELMOBlp6p-!hU+1L`z#`6&yt3l`73qlD20QaaqZsu-;N;xu>^Y#q_*m?uX;Yc z88SEA!_<##ZCM_;wdYbF+we-VU-4T;@kpU`PCX*tRTD&9vU%gQx78vW3az@rozP{P zul)Ql03BVe!Ir09`#M_~Y1q84V~|-#Q>1zr3l|8j&1iMC7nw5O6flaLWAqkBoN zLJ4l-c+a&9fL$iz-5ALj_I9ma$C_V)I6LrkF(_Eh=8NEiEO<-$`d5j*cB|;2eKkB> z?^4_Vp(e9{l`F~CmkiWZp6mg$Z$XogjKCsJbKiu#%pbh<`E#9o5&TmP-ViEmcmBRX zkj0}h*n*QMGMc#u5wGDq-!W~R9cz^McskIsQuzf&9{A!kKAkrE}T|Y=ZHeLC40L?WvBEUSJanQ!W+gOr%9{0nar3@3X zo+hZc0i(F)5H>~;34MvVOh(PSX4|?sM@UGL3shhE`j9y!HBplmUeS%a9?2Qu5spzb zqnfFogGv}sz+E(4&vdfgW|f)2a<0)&FN!$twsxsKd>=|=-7IoF^>=`E3Qo3b9gUo7j(LkT%{aZd1k}><<-V>ng8_Rxxw; zezvyExuJkDba{)^p=<7kXinbZ6MO31@_zmqbNmqeD1Ltg$CT@0&$n)w*T%~|-Tg$Y zH$pWw(?bER;Za;ul zWRJ`A=ey)yE%hSN*;Oi%IpJ8wt{LwOY3ImtNu4W7lJF zU^Y*>Cu6e`8y&$E?uQ>wz;U(TU)klidLrY{l_M9^Zm^m-PVYf;MKgJo$w5DA?m^9L z<(F4sjc?z1Xo|N^xUp`|ms@WKXSW(Qxp*bgJHCjNzk?69$}C=e9~kH+mBR8TP;Y#3*H`x=(y(i<#uVPB*riR3%5OH* zzSU)8*J$1%YYeJ8`l+31S{ZQPc%;id(`8nifF8kh-+uP)3`(MX8R3J+34Do=%I!Xy zFZv|iZv4jy?q$2a;%2s{(xg|r**kKG6^})9yM6$5a$|xQFr15yZB0EUiROm>q0GJVlpfccLj@c`k=2Z5sx~z7=}2jBt|vsY$I>uEe3l?nLNZuBPx1+D ztPuMSX%^;37|`bLQDa;d8S$6=YQ#8}!tJ!}lDYb7bnm;gAuyNSMry#73xshE4FX0w zWsSv1Vl|p0+E~DCJ*)gc=@yI}{;&u^-0cIg{@leVVXpjbR>^@81`FYzvL#pdg|+dv zG~DMLihd{a9v-%Ino8PmbtzH@8%mk zY-^rdjk4? z*JN}2)ARWn?>by{3JW5EPgKQ5wbD-|mGcXgcqpkLPoMb;yv2?iQL%5CpCY>zHT8hF z!vuTp9=!jzoZXZN#}LmD%@->OhJ~@Arm({{k^F%SUXJ9vepi~1%I#0R3hW5 z$re3J{CE!~7d<)y-nabs^d1=j}q&X z_K-RzEGA4*{@L{(@auT6e3!YvbiOS85**i_ZT9 z>bnsHpCdTWELIlWW&37}RyJ_i7UWQZ2u#Q`7r_GOH1#ZG+H&wrQG7c8q9)P0PG2}z ze@1D0G+Sc-c$dK$sIO%j5YfaOpPnkMAW2`Kl9HM^(KoeLeZ!(!>>g4j4Gr;Ycfe$B zysa`cSH64Z;z4(BC{?k5r?h;lR3HQ?g?#$dObPqy{V!054_Rd6>{ic*WumdstCOsf zdGFL06t#%^r%Z)?4zV0_&~cZW(^o5yLA+A^W_!WE9 zEo#lHG*u&n{C2NAA0`UY7_3go9|i9MoUEtHR?CcIm~$p*@R(d4%7U}MeVRk@fnE>-2#t;U;%m2fC+6v6$> z2K8lgHqFu+o@iZQWYGOnp^$N-fe0_hIDhE?!@X>s=jwZ&2p`LTUPHuw87+s$Q(;hZk zD>73UtHkZn*paeeF)JhYQ(8{C@+Tf7*57Vu@QRG!%)!#X$(2@d&<$C`q+qzi*_C-! z!8u74vtVO?6y$Nzs)SC#5tDQJ_`a7Wjk<0usWwQ+bE?P0bKbux5OuFSZ~-!vlb%$} zk$O-~1id&DB2INJagm>`$T4pg+#*`MR5HBR6Uj+jN_{F5ILi6^q<3-s)Q&X%>TAB6 zzb81qE-7$ZRN5N`rafHl`P^wDrc)_JGHVibz8PV>+EcG`GouJ4|v zFLV+dO|NFHME$Dz6>CMSO(MbcpQ6=7xca5)3}${VgcW`~I%AKeFm$ZCk+S1KZVsP) z`igrr`G_+!OR=lV^H+2^=6H_cu@!DvbI=J*j^&}Io9>;wQ%GhX)f8_bo^@lB+8%cGmmWmBNK}NLsJo zJxtS4dZeGSt6P-$Qky?#4^7ePCcUmV^`|S8gCybl_sXD&twEEA>1iF@S}Z0NXLaQ4 zJ^@iuK~ot#w_o7ST!aO|(AuZLqu@7^Y;~Du>k`thL9DRMqZQdVbN+3C-D0%4`SoF$ z-DiNsZiD=Rd_$2olWvwkw6aH_yGgX^lbgy@&_tQ{7YeHSM_++=!n){5ILmMPTqC)a@*$?_4%nx?mj`}jx zxY0=|8AELPu*@4t_2uK`dPlF#^)6i@zr_F0?$H#RkR2EdDczEPv$*mW5$;xIHN55k z3rnuo3oZ39pUp|ms9Buvk&L{Qy-EtTzsK-q#S`6?3+Wo`G+ zg1$;m%0W~Th#3l>J;*>aWeeswl%&}oC;j00`>Wz@U{?DB=ZyDL`i1Lkr#6(a0?~7- z84MFlT&^ET6jrq^>;Z9n-BhtI(n<1M;>I;K&H;G|I`RHB%q(OB(}^Hly)(Ah0b3b6 z68(Yl6aRH9mc{w)(|}mpngPdEsOc`k$(}V++K}PbAy+~WEZ|uc#HCnoZ_F=iW=Ij} zYGY&N=&7a~9u9_rkvxr?KitRInjoG}Q#YF^Ot1^UpUgk%F942+FGm-Ehm^Z>_()9z zZ!~Uu$?pPybcx;4yhVjQfENG(y9+?cs?juvEN5}{e)%xw0#JkN@;Rp_GfSO=uDQ&5hn`@PjW^~WCzX1CUd2)x5mZ-2=CDAC9K#JHv{ z5tiJ?zGZO}oU>J=5VP51VtoL}=rabtxAB!&>5wg{nPwUG21YNw6(O>oa&ea+3CaRCt33P7oiv1W+T z>H1R9QZEvB%h5$YyDNPMC5rXr!J( zZ+NP-5IG2H93NPY3e#y_fa~dz!r|%o1LMk09bC@^fdBJ6dA!@&_U_2I$P_$4p9*Mo ztWEeVZ)u3E;sdaVRy84DHj8hgagJ%WifAeCXD43lk|LeDV=X(6x$)tQga#?~p;-bb z8=fm=r5XC>k3TTF>>XA7o-VPyIu^xOmncK*?4l<_d8u1d6egxsEVR2*;#jfq^0Z5d!$B?qhydHeZx9NGDwKK z+aMf#7joC)`;;VGzPiLzUXfZ`zi)cd`%|<|X<;!4wM)J;e#RlUO4HOYcRBLo1pq6U zj77vpUL|LjEx5>W|(QV07o%61HPwS|!B$~D1I z;I>WtWkYVOcj?Z=Rzn_*3xMh$BzV#_DW>FZvrIm7RxD6gppqX6!APLH4XE)d_jy`j zr4y&JLd<&XT8+Fc*Jq02P#VgxVKa@OJFDV2)1@|4`HbKi_7r@^F#~b~&C{;ReZV{k z-Ib->I@2RLL={h0dH0pHj^)1JI#QXJ?Ku2nq-LPneb}+`L)_0OhVO^>N@qb!#{w`T zjlsQ<`5faE$EY4co{+2yI0)8n=Dr^k=&?WPqX)lNGQI|!x&mxc=wA{2ihR{O`>tdr zZv+jQ6=(LO(WZ2-ta#cN5um_m z=UHt2@8^Y&X0X?JuWp)q{Xlm)pF+?~#iO!H7XTS$=I;<*V$-=TaaV;DkW8cuF!4!? z`>H%hcxk3sxuFo*BQsii;NrSh$%m32W{xV98WqQjS!3#`uM1<(p6x~os8Ox$(g!|8 zn|X`OP%}cr?5k?VCfRN|&!i8I9{q;{Pi~pts1jARpi8VCs;`+KD^yb&(wKViUVZf(u_{OlCP z=b;ks=II*cInH?9cNvA0c=PG9vD})GHs`1?`eK0$adV^V8q2gaEruf15d~*beOBYN zZfah;!o96r<;+P ze1qt~=d0=c;Y&l^S+{H>YkmHsrn@LwK1~oa2i6+r5{HBju*GELeIG5&2P;dMp(*jc zw1VH3esi9nda@+BhUjnYKdLI3u2qi|)&G8wSP@gcD&gp7oDl6Up=*q?&-YO3^r=qN z{7zl>Gf%~9ULvznmsewNNrX8g68m^>3+0{xUN=XMg`D#2ru(4gyVzl3nuBWWBvBZQ zDXYpoY*$QIvCTPuYJ~v3Jn*Yv%Yh)ag;0E)hgq6d&Ozn*?rZjoD?)K=t?=mB!`Y0E z3qWY$sPU@TlA!*G5zRC@%jDzj4-+HR()BVie~=(tq2j}8@SrzCu}Zm?Zt;hz#z#te zLk{)q$i=4q3jiIa57XDiV081Nxw~_Glxl2Hpv4^>C`&$ADo~pK<)1pw^d_S6ACl*~ zvr)>!u>?-3euGR+zR~x&trP0u=nmcqk7skqW@uC5-2K3M({XsV_I<+eE zpVQCQn+)ty!_Koo-^wC9sAj|~+{vF?zfLzM5EKX^=>l*lXhDrN<@2%+HN?9She^kXZ92XbKG&-9`5tH^{SeAz-Ug=l+(1jvNAN z4o;`Ll^O}Db>|x(QPj@}k=`>^liT>bt7@@A1sYbGM$suZxEn89wmgYM#v*?O#ahN% z%^eoD9ZCvJ6@Fb?|8!16dWs?*fyq)t$_Bx%0R0SqG}SK1cym*gCm;K9hPMZLzdcnn z6AcRyWp7F$S@GbDWGAws-x^Py0|+C-Jv$X$k$_%!=F1V%m#cd}Zx(B%n8c0Le9p`< zh$$auh6dfO9G2>BRp^=OLu*;a8wX^nNM;@YKFQxGEJJcdhLs(SS1* z4t&kZ+F8dOc_xzlJ_Ehkjb{q@(UQhx?@Nn~b%yR9@2(V}SNKg1XU_9vH3jB98ap|R z5*_G2&3jmcCCwqc1mtQ|`_-|Yi}vtYv%N+^Wr8{HD?WK2eB_-GGN%&BB&Jq?A0Ge| zWYS}Qt)=EQ#rB4vpfDiq2_Mugg{6)vutfjDGoSdW z-}-Kv!X`OVLypO=!`NsP#Urnk(QGSy z>!3?=h{je&Ytm1j$*nS7hNVf!1~RjKZ{o=5%)B?iS33VqJKz?l@7D($R*iNxlK7b@ zjJT;ULF1SB95O_YGrBrsr5x|~CR8b}hFs1X?E!^pTKQ95=@}Ll3~pqI=<4PM*F&>+ z74T;-dI&_zO!lOqeW2j24K=TEiGgm`4A^SjR~L=uN2Wp&dh;e5D2d5@_2H89vNIi` zBy$Ra4HHxy?ZEO2#G+T;$9{-Kow3ID( z)H~waapqK?T3(F$PZ<3%#KnTO90~0JZbkDz(L1nHQqQmmMqKx#{Av4QLy*8mK0eE# ze}AQbr{X0cMWDxJuY1T;K8OtBP3)cOIrncf^>8ZcBR@2+7!KSXpwX4-ba@~$m24e6iabY4TcOhty$X?cHA!XP$r~TKrn&9k5ggr>Kv<5p_FdL zzJM+wbNE}gV@CC@kct2Df;d(mszB;a_tbajm2y&v7g{sIKk8>nsa`t?V z$Yrr2UhS;q+u%*&tQf6UwpFqe+v?7Y7X(C33f7KykJ5^* z^uHtt_7t+8(U3TMLxQu#22PgyPE#*i4X-X*3{CAER5QbJWUE&M>B&YG#L`74%FPa& zE=`fCp!@*aj;KT9UB@M6If6aoP|XEkPo!tv(re+;+b3>x2zQGyk>@W*BkG{4dMnDW- zBEzVCqm*ELzoX*UDdle0>~4gYV?bUT%ge4m%Epq6UIh+=Zoo7ZNGiFcs&T?)2iQ>< zCZ+=R&UW)LJZrhHG3VV&lSG^BUSE45B}Kimfe2*e=Q%w0+J_9)E@%u-iXywgy_i4B zP4caS9Ah)Z3B^g#_SWTXz5Ot(h_UHu*f#YlWooIdbtG{_>(`F2Tr0wwB;*ek{?zF`$of&YJJt| z-Fo~4u`5oFZ_bTm#(lpWv8~9f?OgRV?Q!{X0k}fS@=JH&USd^?l{~BM|7IES>=AJN zoEj}cG!v0j7DYN7BJHHQI@JU(0fl4^I%&w9p;crb!;b0qQPi$mBr1D;u8#0tU3@Y* zYlV@)$^@@3fIn5fYkJ)|xUzeltPN>NBb;>q+}l#C`0@u8ncbo=O~V;uf{4>7GhJmr zcx%1MfYY`XQ@66`m{OTZlFhd+NBO{#HE7<({fN8p%4OjTfPKCDr<9QX17G!&J1IN? z=$N6sN*V5n!8#znb#1iu8!vW^H4d|UPS4yY68-t~2W6AT37xj*!v9xJ6(&2{ z-=`xCs@#|OCVq_0R#$J$2gf7lt3qtIG%(*(R8+Q~LtI-5#QQI)KaHu!nBS5xt2W!4 zDux7k7#ur7WCIZ5rPP=rGY_o{_6?{Xie||qEy-fE0Z|@8wLysCJ%#nVUChyfS0luH zynWuC$r3qZ+PU4mpWH+q%*$r`P#qv_fU?PD&zzhkPmRp!ij5@?)gy}#8dQ!h=mU4Z zi-X!|0OK5s1h^5z>A)`Q7O7)ioFRevL2r5t(~^4F&5|%7bTS~<1s$$Yd&G1r6DTT> zdHsvc+inT4PkT9dKRs*+>b*5i*r42yKQI5~kWh&2FFaLsKfw$VId?Yj=eL6l?@E|% zp2YSE^1?U@glB_X_dY#)?=99nkBSA}yP2a8$q&DVyLyLCwwl9ebD5?&vcRFIer(Gm zb#}je=6=3zAyA&nI;{v?P)+r9KswxcH;+qebi-5x|LXZY2>AuxTXLA?_tH7NPiIC>CB5aCwP&wB>=_6f2_b@fHGP2l zul9gLm5bnCzQ)Dzxnxv)*BBhAqwjIPmFW&H-W?B2g9#4j8D$Shjqg8VS1W^};)BHd zym{2(23Wu>6EON9Cz^$1xNK|2hW%Ift}h~i7|PuNyx)l?)MSqfU$;u(G};K2TQ zYrZf6J8Z(58&^_G)O|s?XLIj+!SX4{dO9$a@~NKdw`TG#13a?urr%Rmt~kjzz`Bh6 zN2VgY-Q_)F`M~=U4!WoWj284I?!LIGZDX5*&VYKuUV&gQI4Mto>r2lSE#u$}e)qAU zQcSsD5u`jR-L^i1f7kf}FxH7{U|uIu_fiY;rRm%;U~7l=ZVUVCj-=_`k#`OZy8U|M zxr@u~%;&#FNhsyON~X+VTRGvSt)+AgKN~zvXEzJK>~hjQ+CS#VH28gR;vL_n@DuwzyRAebP)fZkwMN_2$U3W)@+V^Sfu7JJ z?#b+?qF7k@^p+`D0d{JovRib#%eet(yZ|U7Q$I}fesVBFX|?+)Ah{t(jZ8idy)S0v z`I}?%5u?f=oMe}#>nD0!H04~w|)wPTPf1uo3%QH6rHM{skYDTw+YTm5DMdF zS-iiNE1ai0l|Jj;hxo?!bKm5WC`3ES|fMi=k%Fs@5eqr zepUXpEIblK3ioN=Kg3+G-jy0nAWV?;s{;hwOTwu7gs_B23oUXO#ke$tex|cZRjr1XSr(M zcj>ADH*HB=q~mZ(v_`YEi^g&nI=WY@`aC>eqW_uT7oXw-SF#m^D-THREi3!?p+fR1 zRF=PU($1Jti=~7K&WRmUhpEf&hqM=U7cm-#HPr~~&f0xOO#AtOHoIoo;f#iC^$cAf z`iETJNoL=|SGS`=cUZ)v%aYMycJ$r6X4=@VyFrZol1DgU#fWaDqwnwDXB$}03y!u2 z7Yj&@W_UmK;+;B1X5&RDTG%cFT-N^10qev%bj_e=Gh?2Pk2zn zFRrAph#OQ_`>?^HhU4G%et9{sGJqaIlr6uW-dW+}*ZJl3lCeH%GEbV?#W$0OaC)|c z;3T4zn{rrig8jG(b`isQ5Q=Y#8QOn$o3i1PncNqzehK>Cy$HB=nxp43NaT_Br$3_ntX-&dfXS zjN?og|H)bl*Z224pXd2b*9}%HXY`!Nh#Dd7EC(xm)#ssU^GGsF+Wr~jJD}@~E*n#m z)H=@}g}{fycu@Uac;gFx;5T$4(0IHJ$Ooi&_kvC(05~1(2Aa8oDsVX~2{!IcdQ1DA ze6lQSfj_{>N(QprehSwdIRwec+Wa~7De+P5On~%s;sfV0D?ZR*%JcWOT_UGMBFL6&%|9@>IFz9`4s_O3ZsV4$Y|(@LFy9aA(EGO+aj zkLso|{eQ!{A!BlME0k;;bCyP;o#+F;d-wC)(k8Rg#pQARcZEL$`b^n6%g9M7KCQeW zF`%+DQK^$Ld_rhX?aRxS+BJWb+KDP=*F}R=%dI`{}1CspeN= z?w)!_gL4hy^(Ork3uj0Ix34N|IZSnWyjF}vBj zDIPO^)b<8eE_cU}r1~>&ug01Rwt8ccPOJB!f2bcs9aX#v%^3SfG;v6&joZY|(T`$i z&BXAgXT>+wPSdwGw2b zACoE92_@{3>|i+>rh&Y<%MFskY6eh~Q{6Rd14Yoh*o~ws$mgV_zXChicFyTfpLUX- z46BvM%UG|o>;?J04jTr|-Bu{cT7UBU!J#Kqk53zPh1}CCcqP}D8}+`eN_}6vTxvF} z_nC8S!KjQK(&M}x;%zvt-*~GyC5Jj<**MpFv45NRGx`f!c0j3O$|;XWF%~cGO~6pEnm7JDQBRK6Uay?eSPs=H9OQ>w%395-PyCwmg-wo2oVGG~v^S4+jKWqaB(a$#;FjckYQu45eNWst+pzwqiusTM zGKNkW#<_JER;azHrv!14`+IGjyZIoOH* zMfU<@IyaXSyzSTTS3E$AyGcBVMg+wuUl$!r*LY!-<6DEfKtju-fs>OlAAENF)WnB+ zB5`Q%w-&ilx$h6T-sWF{R3sgQhutE-mS#9vxMYA_`g?Kdk&HRe2r-%69&8K5OsrcBpzgr+nF0#W%nSrj#ZQi+nu!wv=~( zJyq~ibE*sX^g9FpO>($Mx3AcvY$8oN5dUVRcK3xvTpqU%IyO;2;6CE@cmcFna}sZE zS}Lb!l=iq6=EZI;RMkL&cb_+=lx(GU(rGgz!U*T%9Mq!$JBw}7j?WVT*AsVN?bQtW({e$PLM+Pae9 z26Y|3Y{OOCq{#DTBYPC*B<)zTEMc~~I#`|3g+Ftg%;j6DX^v>S@4B7FtvCD=RIE(sA=~! zFdq+Sc5*u&$aYR!^^nJy zB~nhBgAWjpiRuy~g2%QSo5CX0!k0*=$|Z7k52_BB=Y~UY)^$DFl@$x(y;>f*`rGQa zn(mm+Z=rZAR5pu~)t~;;_zKo|QR@_?@G9v62QHPAw(aPPy!)P@sG61LK4CTF40D$P zA127G=c>%TYl*liJf<6-fe3+1bUhvP>j1C3ybh0yFNo|KN8W_y38$i^@&>pR!MEXT z5;~?C(v{Yg21wJCNm4&DutINHPg_WaKR{am#SckLyA`#(*i)gF7;y7)kg1)%QLfON z?guh{KluLqu%G`P>5^1IWR*2R3o7@vz1COSFwX@!418YyMfa+7k2?obo~_-YA;zw; ziijL#1NS`N5%DtpTrzsC24&};CIOACVaJr`IP)Wu(pAzEEGM;ZA;Muq`Y3H7_xl4! zx}ZeZSpgsnOHG@{q?^BJC1W z-n#9*=)e-fQ9L&jeU<}W%Hv8xy6tu!eG=y0xPNehpsL$5dofj~z3Qh}{7!d;Pp0mJ zi35n6{0(ws2`CzbO%tzMQLOPURds|^j&bKC3HQ}R4iJxLV;Lc~_ z9H&ppGe14Xs0ze%nQj}$`tnBe16X$Ii_FZTygLHnSwIZzon_f~eX>P-NwVH_uhhwE zvT3Pk!I2qK>#Os2v0ylaP{lup7MEC^)%Mg|Q#bNxejwYmjsW*N^9D)k8_=g2UkOKR z=$lm^ukHs!lG=g^pjdnHW|B+n>cqTR{uAP2G_$5r8hZ1!eSQHMg09Y zR+kZFG%M9nh}7h@y~}??51yXo=a-$DKe=ip499--1eePs1V%-PEB1~cDqyz-VsTFX z$UdIzb;OX4G#9keeTvkauEi5qDQS>q24Gx~nkJFzeJe`>9&k2_3jr=fj-L|>>3Q8S z-B2#T&qd_Fy|^(yvWcMwrW@bk9Rd#X^Ql|DEDSvbBa^`N`y}$NQ7} z|8KDel^b)ga%TBIP5l=fG=?qwAcUK?uv9bsrbJ55A^5@o$&-H0aEW)n;`kRGXwy1v zID60eSw{72d!bToZAH(U%NE1FX~7O;gIJII+rIxCsa|c0M~7El>ksbfHyG)w!=@J6 zK>FPVE!!q8ujUQwvKbl459q6%ULxNm?Cj(#zPNa_5vwhX2(oI1sA8akaX0Rp${cAIKh+cQr^h1xAhdPTs=QrU?p*E!v;nGMe)aLlcBWC(Ou+ z?D~uIvfYzmo@O|c&ILWWR%Fsv3hkOFzSWxrIBd$JUYJLS=U3Sv4N0Pu()=ac?O$}f z;7}RS+OnW7v}i)MkM8*$<`rfX3(2~zoU|SiGM8G-`A7cai9sK?`TpS%_$lc;`nPej zFBZ~`C)`pM`9a_pH!&^XnlsRcPGUe(oELQdRGBEk!RF!%0nB&qZ68O&THDz^B3Ad? zI{mF%4(~2-5?`Y~JlqLquVd(ZMC4%QkrV4_IC$i2`P$p?ws=yxdC*jM+-CjG#0mvg zv6t*H@zbUcmb_1>uKs-CT5Ni-HFL&;*~F5T|DO&))}59AEBkj8os{2;_dfrbgW9rk zxBx{$u%nQ^4AhqT#0h|YPW_^jXrdN$?#dHwe$iQ=umfbswO@3r9sK|<2%v;z6>cZ? zf1vs$Gk?(~UHU~=`rU~_lD?3k`2jr~03h?$E9@(foiu#HM50hbfaTN1g2d<``%)c5H& zNuD#o-h<|(T$rRe!%ULLdiBaH;m1J9%zw}8lf4u34`FLdr$!Et6PN7#5(FS5-C}m3 zCMtr?BQvr9iP5i$emUQ5TH0kNz-uZOH{)_eUcVUZx=#M@L4*K zOMpb2(`q4CfJY(&cqHUeU63~K3tQTx_GNNPCE5RJ12wOMo?K@@8cn2Fg}4M>PaqiI zAVarDt%)00L+-uGxf$40L+&#-4n)>~bPTGNB0wz-x;xxXosRY>4Ra<0@j4*`%bBCy>ifvzSv9kcS4vR=yM)_CzA7lR7*v-oV!qi$7a)`sOoAxzGTFGzEJ zsMV|A>!oKZB^rPT<(H8>?(5Sz8``=s$tr#DUW51*`Quw{ZS@nCat$o^x957hd*?z1 z=jZzgjrDc)jj^AbTUwewCJTgkAWYWsg6(d-6LAx9ek6ht>{ZGsyryHCvs!rVk%m4r zrQV6RyjkC{DA}-aH)*p}UokE;>=rozHy(4afA!{}BoQ-|_nY`Y9}6hR8sL{>KkNFT+Oi>k4LAl9G@ijusD1g=V5D zkU&0q%Ri!{O(*fbABw`G>+5}UpAg)lPha6CA@#JxUv#=bd0-x4-*tvQ(KvwHqJer$ z-8NWMH8s+mb=-F(jV8Js#4sOQVHKTq%{McF3X*05VUSxq@{0|7-t)6%^`4a60|%0n%Bc1B}*Ta{LzpOcj^wVMn{ zt+oUkxg>TkD^#Z;UqFDgU-ajyH4C=ba(=UwP`fp#`+?p5C=SI#PX5^|EHTq&T*7f$ z>22E586fWSR-*{w((qtW+Q5OU!fN#qvZa>vc(=opjH+B&nuNGNRrDVvB!qRf+1?=1;Jfn|DPGHg=|C4Frn#A98uF0~ zwB7h%^1~Lq4u!L0!i)DoqVn01hF8)4e5(aP%9U&=+})Zl9l=s~@K|RW~9AYpQV;QT#Vb?afvgddh$%&Qww9emAN2 zunu%upOvt3EJ7FZPwm+^bo>yJ1M9HyE@unB0yT|DDc20xF;c9zuPMG0;u^M#!v27~ zfSmJa0}?#o#2M4PcFr+0F&+RA-(-q~5X0qv(QVXFfRF4`eZT0Ag}Q&yk$s0yXCoSr z<;tZx>Do^Sj}__G>W2@Bm`JPK%)iRYzySuz>~wVOdUVX+I^MV4m@~M9t87d*`0X#x zrcZh@GqCfUkU}^}WWJABtEVsp-`h2l}tQf zcM)X4u?;JM1I1&zEJ~wGHI;I0JC(b8F|yXG4x;*&@z*8q8C^F)!yv5~KX)A(8{80Zw zwX8si$zmA#obRh3Dh2T-MOSgKsKiM^!gN@vB?XFGBYzYx9G9!&FOM&d?9q|p`n&kw zFCGXO@Esj87ll8KPcKs=I$gYzfV!8FY!U~-BKm}?i~Ff9Mbb`@9myr+!u1-}UfWHw zS^ZsC`|%Hphp$-wup0?>^o4tTSj}X9^}BlfBhBQJ?a4Uba`o~@MfFB~%)f>`1x%X&aHnZ`d*_vC)hx~2P+qA8-yPIB5O70<(~;n(FRG#Z+6 z`UmiWae8#SM?MiO$yuWXT#~SFYI-7mx48lWyl+J5>Rhq1yb8N~<66}cP_${Sd7J`2 z0fA_iVM4}RX%{-%-CS-yE*z6+C|jvfG30krO5|fh$@@Mzems2lP25dVZJ>rKb1uUG z=8f5Hzqm?Kq2{**ub?7?#fXcoB-Z=cUE{8rkMet6!G^vluAfO@#m^o-VsRdoKWrCD zi6{GI<86v6>AuoS(mI}PxTB*dO}DYj9@E|CXz)WJxyLe&C9B2uIWL+y=TWVG?dfrg zo2YxCJle?+!%jAEz;Yf7$tD^RExIhTox%M;YgjRiZ3aKbE0w9uKmhlNRf1PIQh<}| z^SWJOD}J9!bJL!wR0U|lqnJ~_gHE?3vUuO_?BBEjdnNKP(dJK*Xj9BfFyG(6JdK^n zph->#dRP#To2=C^T$auUa zRhN9~+3nwE<3Tnu?%zg2#^$%?k0VEDDLJBeP~6!DD?v#nh{q*|CEq~-teU!p$aI+m z(#;lW_oMEx>ZiHdypvcvMqfU#jz=4$4Y+~+QYH3XWQI}02H`~Gq}f&=+ELpS9;QU` z{6={s*ItHzl<*ujci~Nn9)AIEno$8yKqh`&>u<_orHE)^6M|E1B0;50H znyu4oy5*Y;u2mkh3iuKTH>g%PejI^fX{Vf6Nc zo~mmI`X^IwMv&s4BYzXEE=Q&cGtdc3j}0i8 z4As5F$mOi*^HTb*05Gq}nvr^ip%iDT~cVY0E#xbcG&1>7M0UwuxuxilPn5IIjA z#3o&&I9<$j4Bb<6Ud~O47aTA38P9I$0E(Ne7VdRWOv7FKkR`S`*96ZH50A@wTq7UL zmsGZi?CXz0Rc|wf0RRB_4SYgaoeEO&W*{5O6J$DL{K0dLcVenP%2a>M}{|p>YF>!8%O88MCBX3>Dh2*tc5^1o&n$ zOBJn{`<1A#h>A@&MZkvhC1(z6E;9e4KPW8D;wOnx@n5Hx|N1Gk_!r$}{8VMV@%+zI zrOwvp1}L&yez=;vNTO4s+EiQcCpVLUgPQIlzs16uXEl+g>w3%~#l{&c?tbOng2vZ? zV_|ij#;kPHE-}qrC2e|JHfT3{3=qaujbr@u47~TAa0ZV5Aiwi5UR|SkdZEyfCdxo1$k;x z&0lFJc+D}KPv>=5c$@q4VAF}B^s8@k;5lN&JnJ7R<@pn7GDqrYQ5V4p;dav=bKm5{ zRO{qJ*E3khUx)u8bX=l7K{>&%kK$Qp=}*mwxs!em{PC#S)@AQ#uUnbFshDo&GlS(n z4+|F9o3o3g4^?sN(LM9o*LI>X;il5XW7WgixN|%dbw~v7hU$Rb^G|qffjH z^Z-~ZOIBseIg`=w?gTorm^<%$A;^VP`iqWU+~eC0i1^f)af|dgk;X;M3KQJCBh~qu zuL|r*GQjN!=CJ0>lM@$Ba%lTz8@!j!ow^w1^64GLCJfl}oIG@gb(#Ju2wWS!hcO%N zK^m5zab}Vr2g%6zJzGqX`* ztkb+do}dgUqrIbKO=IkgM+vQGQTlOF2;a*NEyU|}hat6}KE}jCXl*Q@eyZsOv-Di_ zT+AGC_j)h%ta)W0kJ9bvroCH*VuB{UWqxhfRE9y{_lP(&`clYU(fUp(7X!`n3C!aXdfufmoZ7LH;NFILQF>Ma`> z0$AL!IL!wgh4@NSo#~qw!ZpR;?aSuf6)GydYHS%i7a!*nE6{2~z}zA@Durtk(|lW2 zGGn$mf~ZC!+OQQDqMU;y&UFS_dwfLAmiCXAJC0#l!V#~swsAO>JcV@ms$j-LWvPd78* z31=GT{h~8Ln9?GFyW3q6^ovfFU(=Yv2B$HE7sBVaVW`@m$j@IILP>q)hh~m^E`CJ#ka&|f>snlwpQjlf8QbCuXG=rqB zMA6)=QHNYnm``a;s^}(Rbj+9zsZI_hqOoe)jAVyp?`sq-VpMjD10Ho55%ieY_{MeU zL+|0eqRsSln50TMr=weh@XLA5f&D*KNr)jYWd)2348jxJO8`uY9*feLO4&K1Vk;w0 z=~n4k_`^^!5KB}yG=W)`QQcjU?Dn*n(QJBP`-VxvLfS&rdH(1Dh3hAc=>ZWS9(3O# z-7eI_2J;kaNzr?31Ob~)W<-9UHg9X=B=Qas+Kn%+oq4-+LuEQE1J~u%#P5||v~~En z<3@Y#Nv_xayxDlAijcu6>vgbV?~CshazXhH#ZmpP1FD-2(!EbHSw?DUpam^`USSWT zK(UPJXYFYc1G#$U(Hl9=z29G6VLW?bZmn7;6+2#Tp8_p@6W8V*vQ5g9nu%}_xZu+c zZcvx!{^f?=yviIQVIhFpwRcx%K>P?htA~WBam(Gr)-5DwzYJORi;zsRtPJ5;t5B6zJ6moRcsqoOrE`{Zm zbt^}>4C@4J6uBGPWG$YSZP^gy$$lUT`w}g|SQnU*a!EjUW}aQB1?7BRh zhEuu`@NIcU)VI$dvN>?ZT`xpoQA8aSSxh%lRlOlp{#2j%Xlhb@mM0cq_IP@&9lBU9 z7C3rn$}<6OXM$&^?9ZKz%-;KA2;M@Dk}ZMiaa_FZ3yi!nvc_q)YTRk&hgmAcUAD41 z?mqpSYAxoau^84|&8h8s6yR}%u#jE4@>wX-KyUgrG72mFJ5e|C`0VC51%huE*C#eb zBDIQb&YF~Z9E#o2Pc?Nups_6;vFwXXA+A3Sq^}G%Anjh0bG&W^l2pqHB=hxL{i$s; zoTIeat9SmTCP2?}JG-Bk@xxG2DKnqRLj43y%h#NRuBOG;pv6XvdnMgc3K1~O!{n*_ zL3#>zK8;CZ+2i06V)PVDO$OU|5EhJk8k;(}$y1~_Y)~F5>NtsIl$KOUxl5G8cxM~4 zZwrgoD{pDbkc6{UN5avrckZ-^WdxS&XeO-nMWMooSgee#BEnvjAfr-!Ogv1yEj{Sb zJGE_LJ>KiMWw2Pl$lmbeEDA`D&erCsrA{^V#jkxn zAD2d9huvW2=6LH08#KR{+47o(-Z<^go%25_KL3;SFY$jY2T?<6l=uAYaW2=a{h^rr zR_Hd+5?TE12H-zoQa!AMIhTe_*H%}l|zvSFcqoyS`WvBa!dt={r6><&X> zp)o70ij_^5!zfRl*F#;vVsSK16N{r%_ncG*Yzx?2tQAp0hM4wNyazvk2Cp8qnc*1FD zlyi3HEadbvIfOnA30gj$P~B6Mt)RFq$K`X8KO5R~Ti1W6VN|ccr{w0150hSreW4-dB%>oAq29;RMFAO06XL6KALd&6`$38q%)yCtQ%|9UPCh9 z)xA$F&N3)*H}xcm$2wGh$uMhenmA6n{W5;~&g<~MJ}VeU_tNAL#ke0@3HV*3Pz#|q z!>I~qk&GIzbl;{u5pm(4_)Oxp?PQ9Hmm0|hg1$!e=I%L z`P7>fhp($h0c;_Qp<^Z4@Tvw+FF1M4>8EbYtk_b-}sS{(4C_UG$$gPs8SWMPt;Vb_n_ zghta`U-=tOxBu!tEaTJV_*S0SYs8V`YFZip4^YkI=Yzg8Y~8LN(lT(`IS{xGnsC|X zp|JftebPX!0s?jbW+}`GROgA65-0FO7APKVG2DYVgM>@n9M&i&*9_8+nXo=+Q%kMlOd>Q*V0w4oCV{9TNPCXiURsbr;ZtU_X^#KkvB>%2+)s-Yp zjc!Pys@qzupFm*rk}CUt>WW9ry{U`uAVXgrf27&EQ> z@zRE`Ht9MQqdod+@32GQ%aOZRsKT8R9Bs1$rJ}reQ1N$w0 zh}z7;yc)Q!HB+xR5yem4W*XeuK%dAfz^Vcj;Q)JcOiaMp{%YP7Ulq6P`Mn8@XpD6G z5Vym}%YKxaU??XQ=zv;w8LPWH?BNq-*vI$zcC71#we}zrj+c>KmPV{jtzj!3O$E2| z!II-QVhh8esa%?+QuZTWpj1bs5h+FH>jZ(hFUrTP);(_oeHV%5GGJviUriI&wtd}$ z$7{RxCOmmyl9H>{eAHvGmK2|Vt-(0L{#N*t<`&w-*omcc>$ekM*4g37r<$Tul{l?c zOH75e<)iMt+W?J6tGPr&6w4*!l zw&YWcK3YbQ_&tp=ZvYzM!Z%*2uWvtWR=VFIK+OzbWux2sBQWF~T|I zpL5;#-dZOVw?3)xr6p5_nd=Ft=~O+(kYB|a`Ow8Zaq8Kg=vlh&ijhaE@18v$=C1+C zRWkA?Lx!V2V>#bRmO5htk%%J{;bTti#}oL|q@+!J+qm$urkkpxvo_s}tYixU2s4^{_<8B3$uakh%x z!rZ<*H(adp+&=ogGR1!RF>TsKaK#_mYHP7X*EF*Oi+#WS|=kj~0 z*fxuUb>+crP0Og={jl3xDdf%`>!Ne|@Mj@0d#ep7iYcz9_hxYP8jT@TI6r3AGfa+@rGC4__~(+5+6!-Xij6HOzWDufgp?KL##DmjRAitv!j>H;(WWXn zh8@U7!sOZbbbPQA<+{l^TZSWEMQ)vryFJNO0D>XF|EW8bOc5Koeb5%Bdh`v zC7muO`DKLKIS++y)6&7c;y0Do=6v8*#e0&EDL(}WNpU}vnbn+dIm+S1=>(}>(4NMt z+brC38>iZfQA)-PF*)+PEAP;f_DW&B$dp*p0q!8$x(Sdmxa|=(urxW!7ed=agM=gE z*_6uQTf*X@dTwrkCuz{zpZ=r7+ieDd9{QnP5$zsH89OwO6_)As>F|K@cDeweXt|-1 z@mzk5JewGQOQf@=Y3iDe?eR9A#Cf;a`~lbfb_p29=tiaKIn!Hm>uN>dL2YvzR-dF7#g)1w}L9`As9A6PE6(g#v`qA1)fNEK<$!@t^n>&2i1zci3!riC+K# z*8*!^cn_MD&g~n?r>XvN#H1=azI3*DP$hJRl=L-^n;eOc6XNMv`~$_Z)!1@UReI&n z-fddPW;1{a9oKpwhZcOVkjymyv8~=jQQ@j-jR^fkcCXx3y!Q=tmrE(W-ZzY+4u7bH zL=9~^6~qr#8&zp0!aw5O@OP_R7*j>i4+LT>cbC&#b~!(t-86x$%d;Z#wea8_uFO?F zGyiz!msO37pZP73_M#71OnKg7G%1;q_se|CqY91ljAt<(FPe*)!i)g-=04ymt;pZl zaJ>4g%z zbvneal};CxnENIBnC&!KbL(lDd0FQ~B4ZCC={SEomxV9&9ajGjMgG4{ki~nlFn<9+ z3`oe;kl!PZiKP98FwD2k{H>}SKMb3&oX9fQ(RH2PA7RG}@s`}QGP<_W&-3Fc4ZPzSE3&>3mYi8<8c?+H|PTwK&Fg|Ae@(OcwBotl= zRQ_f%-(SN$t1&00t;|&kS8PsN?>MV#0jaM{+ect~0oHe)&Pp9!p*U#h)^vpXJwUZn z(j}$<()ZP{q4TCL_&mm%T;uV%P55_eae(ZdzSlw&6G9Kz3BRWdXfwFG0%23)CU*BH z^htq-DYwqTR2rVYrx3fS&dd8D#wvJCs{l08UKfVYul8O-xKBwrDg=6>!jsJv#^!Bh zsv5nC5H_XeW&g7kPS5C}tv)s*1N`YEp3yQB75DLeedo^M%qNNzX4?2IK=fVOHvW!2 z^_zxxK<2WS(O+f7=GH^Jg%L{z;XM}Iy{=38MDElLYtnk%2A1>l!tp4B+j;wN`4_X~ zGf&wzT=2JMUoYY6O*jy_Q2XfgUx@1)i`FmRr~t?2FT?dE-@vf{?P_51^__J)Qw zJ(l+NHi;VSK2yPo}PmdXl7-P0smqR^i0-{0cb*( zB49u&o9TtuvI17-+on6QV(ml=!rDlw_Y1Xh8-zF^G3{#Qr^i^|px`#UzmfOkF798$ zT~q2RCw2<@H9LGs`7KLFtuV`Z?DHDsd&L!9qq5y(EUatRJEZOe#OyoJVfgNAv$*M{ zct4Z92Rv6ay*I4$Zm&5lbS^K0X7gd>vx{r)9V*1Ctn-X_KtTzFYnEbn=vjCqUj=5m z{;|{*a$|2tIe znbY4W$Nvcpjmvi@k<~^|!^s)MPW&j&;~*)Y1S=YlSfu3T0${bLctGcqZiI6tp*r*BlR9Qu`WWn3)#gZoi>Cc_j(dnk zgY)QhFROW@=X-&rXHLKwgP9tBazGYu>RDo<2#_p*o5zTJLgI;O`^|}Tbsfd9)smO( zUEp^9xgE1<9U4_2jJ`d1x|2cNTig7T!!xI`Hcir3;LZ}!n|o|Urj_j@p2!=|!mr-H zOsL_ASg@KX)T!8@Hx%vXvR3TqI85FgO(AH5O0k&(mQr8J)XUO*NVq#XO7GBoX24lD zImP?qg@(ZxdXn}R>c6dN3WKa{kiOW^+BZPwFw3xLyfN`;l(e>VZlpqO2Ohc-+Bk>< z^&Im(h_KO@A3kG!Hvah|!0%r)qncpI9}nC^e6 zQ|@_w#;vT-r4G#2md^B0#v)k@E}hf^?(wkIHP3)oE{C!J5PAdE^%#(3T*!c^9#yUn z5T)C+c)$Zv?t&bx0MrmR(wO!qC4_bh!hst70iv-3|1Md20o8>CviTt~))Gi(Vr|cS z@i3+v#oE?CvtPNJk-jmr@#g&c?67WE)wQ@*>_$lZ+qV@?(BHnM!*p zf}Cd01!OoEQ8I`Z837^RMRv5P8}t)CvRHI3fH+pnhar`Mu2{@~v^jsH4grc` z?b4yc5_jkBJ~$YlYrU66QIh{H%X`rmxpeqPFY5aW8!&KM1)m&HxcyIYKznDN6VX%sWI>hfVhVdgA0^g^`?8q>E12T)H^DzU+u(ld%3on`gP(@!dqVk(ya< z6J5T)($uH(v=fDmDpg_HBLRx4BB?gkN6^T8k1F)xzk5^uFE^UHL;GX&GSHM953pa? zxgckk4m-&)6hmMEkPnKi2ckVLC;_fScRmr?y7MY(zAvBoIG9&~=XFpwoXNl^GU}4l zHfg&tqTnnew7e7&Y8Phx1##yqF>NiP&m2Ao?z>S4s8@X zAu-^#haqV6-H>{E3a9SrEVbmNw~BYdQhg8(&P{fC`gIb_=Y(=u9{qiru`2mtOVS$( zi!;8H(cS*Rr-oMe=1-+R=kxAZ1oL$?i7$_E|Kq~n4AXmyor&%OcFnx&!4|IeIBvk% zn3nAIKNz}BC4-s!VwH!cm7=tianr@}?;@P}d4mIOCna>!ByG?tLP_z`TcbDrNACfs zj~mIN{RS!fPZxhi`x?@l9Dboqxi_wTo1#87Z!{gSe(3%3^O5K{_(73@hB~Bwkpsvxyw_wEowce_scx3Y3jT+bj5b-W19OyW>m3?J ziAC%z`%WraGQ*^qY|h81K)I*8ar9DyE_M@Xhv&;MnmJx;tS4dKR_!}wSP=6tGB1(M z3N_h#{Nz5B7O^Hy#rbVDQorDbId@oAVy^Rfy4A;TLz`0d`Ld5^VV@Q@^u2%4=|?p9 zWWkd6{&gAx&hQi_L1P)AW@O;KcgqQwIdS`mMOH4_SeW?p zZ;R`TkI{`}C*t9T$(YIm_8*S~YfxT@G8Ff=pB{sUoq>KdHpq4S+KL14q{ADSdir{3 ziqC1h&fha9``hFPIP0#Bm-0=N_W*_8Oqot+3z7pIw9)>p)h~~AKABg48TeSqC(*12 z36Ux8e>52~^%@m*$KW6+%)Jlj7VdHeCeKK$ePS9C+*NNjX1<)_>JeSRR#34Jr-P7{^#AN^^mB<(&<*;=S&qAG>yj zxDAKqk>Y4x2cHM+Iul|=lHG)@?AFpP+(eRfT$1&K;CY_Z~OW=oTA3LcZz<{z}f(ZX>Qd=6;bu*cEqADc6+%?I*zvdm^c@=3R z@|pC)*U#B^8OAD}0}6?HHk`~b;*n=r#kr0g>-M)>q9!)}oT1qUX>VM@C+(T#G0}ss zIui(A2brSN8K5Np$O1hFQ5{y+-DUE)+>KK?!4JN1@h`JrH6-J`u@%hsOE}aOS-|z4 z&FaGscjBB$9g+UvJT7t&24P{U&7X+1F*GzPE=4%$Hiei5$z?e=@EFQe-2UJY7&!|@ zZg)H~y;_*wcfCeS+@>s<6)ffZE0WfWZeZ71YMzOd_nax8)Xn-bbcu1FNdUd}tZ$x6O8 zgJZ2n*sNG|55}e$eZU}4eRJlmYWB}bSM%>gpKRT>^%W{acw@VbeC*E@l)vQBZeU(p z4k@Fq=m!#7FCMq}U$o~!DAy?RryV}>Q{;?pR`yMk)O3$zmp0aqGbZ(t2Dkd4qkj7S zp)T)|Zn%u_!!xdEwfYsVOT*tV{@YMe3jY1&bN(kFelc?6w~9Zl`--YE!xZOx-qhYi z3q*(OU1PY{{<8Xzws}^5DNOQ|`zK6!$HuLH@T4`swy9qG)r`}*7RQQh;f0(esk^sp zJ&kg+5bs_tl|XQRkvwD(F|`d}DkE)2NWbv%n)oTKL_%Nm9J^4sGYIk-#S|{Gfv0xZ z42r-S(=ye#8;qJg-NIv-Myp*=xl}ZP{8Irg|4+B~5oqvO9m}@AOe{T+%8bPjF)n(P zvoh);dKps7`d9FgJTKS;XVNs~qrpSBN=~#nqK37R<6i(1-;vn{QZvO6==Vyd99rzIjamS{;);V3kN_>iPk83x*PIYMHeV>f)59=Q0iN~@0 zHeZE4m?j-tVC@Bms!=*^YF6Eo>;%D!@S_SZhTcj+RsFLLlrf(vixolI46T!E9k7Eh zHL0{Nx@pAwn$a)b0e$+DZ-W=C8{bgVyaqdr$He&kP!m-*t7NnaGY5mEC(PV>14S7| z(%jP|CnAb9%*zNl#hCsMc4|(?9amvV;$kCMm8Lj1(R^e z$g)mCi>if^oT-!794ZxIyt%XT;z5s~Ms5{rZe2c_-y%~xQ?|X`Y>MIP3 zN){WjuYWFtxCvmB^=&afkrzD&EdEbY)PW^VnoICO#qW>D(@nBVMiB9;)=!gEsuknm z;6k@%-4AoNV+}LkK#ge;Py}mtOM&gE3t_D~fjrPt>N=N;8=QbBZ$0H0(Z2T{(RZ-) zWcP|x4pVn?_Pf*X+On36e&gHePATh_@5TBHD1{WDa=#3C%|l!=J;8cM*w>{qLc8TUl7moBvSRwW((riF@ven zu){LZEnWR#BVP~f#K=vGQkP-aa6s;Lk|sI}vp~_tTiSn>#*{Pm`JTDw-jPvTm}>ap zB?U8-FHgFiK9cmH-1^Sn*<0b^O;MGj^Yooy_Q>PrC9#MmFR93@vG|v_UfYYMO%Ul+ zDWx;kU_tpC;J)d2-H#@3+jU*#{9YisETF88H_3slUD54fU#XtP`DNJ?x|1Dj_>s+S`w#doW^CU-O4g61sX%9szI-$JITrbnR3cCX!U`L6PjxpToORqWG%PbsT(=b@3xvw8 zJ`X&@rxT?Z)n)Dt-qB@ElewxM<-LlZa>s@?ie*+?!D`Dhf`pD~P`R%SZ>m6L3UW|_G7xzP zxnZf@j^UO-f#LLLwOl(%Bh6EoJWq@4t0bDA*BiR5mbP_>u=s z(oWGQhG2QA(0a1|QF}dVsgXDYIwQ^vK9lhg3`?CNy2E(k zIgvzUfDlte_eQ8$s)G+tC|_~aL@D%EL|iL2)v1#%YO&wbe`p-5Zz9eT;YHY%jtq?h zcR87J89D5QbJHKRmuHUm=yQLUJXRXhmQb}+{}D*b$pj8FS=g*51I|RAY$uft+J0gTQXd72$x{j$2kx^DBk&m z^Inp5Rgb~@(5Y!w-LmZFG9%~-3)3Nm=xx|1%MRFkcZwV1{M1|tBGN8Tl$Okclft%u z0l85$Xbmljwb5Al0;@v5(*T--*$oSdHqk0ZfrWRIy^n~9SW~s_ z6{1AAe#QsugHk|mGQTGu`-8M#4qX}7gkpR*SGMXQZTw~7T^5Z`TJ%N7ri_cSBF&HD z*7b64x={h7*;Qti<@nu2LfBmxkn?v+IyWOFpsx;Yeu4jPWxYs|=$X2?^Ji2MvjN3N-i>xVV;q0_b0>kZI^xu zwHiLiOfef$+{?9F0QjxWWjlB`dON0thmb=UhW`8X4kcyIn%C}C&T1&aD ztdvo&F)x?ywRJQdl$U$p7i||FdkG{}iYna-AMl>^`Ajuo6y!o$mri#X$Ai3eY!}8{ z4??sU4ze*kXwgp{{5L-IOh@t4KdHFeu06nD{BlD@;~Dx@V@gf|XL+Vh?Kyw|yjMhY zf)Ir8HukbmQ%ak{1@t(Rg8pOHC36jvotAzUh(pk2#T@B?FBfbzU?eRoYD;0AMa%GQ z^ZKSN9e^dQHKver8C^9dIt|vOCKH`wgtk3Fxv;du@jt6LQHCjnDEf7tTr+(KkWp%m z>YJ4fAnQ`Z;0Z=I6{8xPDzw}r5rM6`59LO#<+{Y7c_s|%3L*;pm7*giC(tVQ``gC7 zeIxEb$l*EALhMS}a-(SaIb&E~hb%cEy>u2&PA6Uk@T7O@*I)00-QFt2`6~ncHaRq) z+cD_Pesr+SHavHC=~```QS_5<6-5ni!{!W#@VB^B<;ocE8P}BW2ZI9naYL?!r(A+r zzEQjbzoFwxgzPx|Md(b+jZ=Ar$B8>b*>@Ts9BuYKjJHlL;BdG>sz=a~*u$rU@V69d?zdvl$uGB>p71{YKt6I)(HbvcC zj=J29XvYJJ_4E{pZzUI7{;wy|GUowrwv4hvQS{RBLSu;5GU$#8%2a4E2MF&L%66vj zKJ77hYorklrGQSTthL1Sozzt?&QJ%+4T72*usLgn+l!aoUZA5T>zTZ4D0kDLJ|P-F zNUkHxyuT>P_H!xuwYpl$ki)Id^C1G@$wY%KP}VLj)4fu^RG)j zwi0BsXz&d};!VnU_t{Wlbf`E%joSzS){k}}c3$Y$XQGMDiZpbI?V#VjUoWkJbjU^uw6?a9TSwg4N)i_ zjVLuKQF@KbzPl!_a~!K*OYH{`l0N|9p1^X0_U>D9!Rq(BTQW@WysmIv($&sYWe^+iE!T#TaP9I35c7G=Y=*#R#rN=(Z7qT`kTw!d-l;@b?}n8ME=i4>B?Sx%J32phI$ zWaIX~*+5)52iSVyj@a+`4k^U!0{rl=OUBDzb!mp=ahmQzE3I!(j8=Z=canGm`~5Kh z$5;0V|8?m_%^{4&48$`e|3Xr_$YH@RUzowTw`HyXpnX+0VkVj&uzhHDu@yt~sYL_t zsQ_LZ_@GI7uqo}8{C`lrAq1h86^Cz+pp{HUl zpcbu^9O9^yA^nMX>#l`x$nF(bwT>|NoCzr&{O3upkDJe}_KV2wq5>fIlf{&U7k1f} z2MIoPzQq@eD-`Oc@7>jc1qT3|=o~*p-C**su20=9bG-i93zwhN0>grRqXYiTl?F zTLQ3Xsd{vLC}*IbKnphFD9FKKtuGR}{Cc`a1vRSJl%KF{(3tS-d&0P3-Nc)1nTeXg z;V9?FCWWW2TK)B0`>IBWGh>mmh_SkK7jaF*0D8>m$8;}3E8!6a*Jh$+5vBcEk2Q9M z_5erNfP#pjrP;)G)T90{olY|%hN+UPVr8cOB+d=MVD)o3mh<=CRe;Fp`PZdW1(rnY z@tsA0-0Bgp1qf*FmIq$I)7KN-egLFOaf_9}i!=)C;%QG_zs%RXaGLnVAArtMmLj%N zYzt$jz92V7Q+ZK;N_}sMgQ`yDGhvqMLpYuz722*Nb zM`c(Rag+#QE+jx64eLtu?;|u@544Yf0nk+~pfV_d8y!EVI2Ho%rW)4H!$^EymmOzP(~l18|{@~e*vRNc&}iC$tQM=!XBq8=pe;UVov9&Aj{ z1uDwh9Wi-N7dCo4C41hAs(+lJC&~?rj`%Ft;oI(H7_6mpt@9Q=ta#NFu7)#4nn-h^ zEgRLL$^F@Pa>nC9lO<21^PfcdZQGMwQ@HqAb1vR6)5^qq@ol1|sJN~|aNrIQ@NM_7Uvu)Y(HjeL_mpHzC zTwqwHka5P$Q@P`3>Fqh%Wmu+p+}>Uu=4m`(MoB!}KhE?9t+IUSz3KF`IK(|LdO-(o z?GXL_eX3)0nw+(KM)B~%Xuh5_5k#RrH!|@4+EbW<(&f6?You_LoO^7+glN6-YQQPD z_^7k&(Us~p8x3S7<4N(%I#Gtfr6D-TW}fXvlzqa1u;$5)tANM8T(8yQS;XsQT5ikm z{v-e#|Df%Yf5FDf<$c?bAt`MK_CD=(M{xDWy5)kUv?How6W9zoQUF=HU0m;>Ri;U? z7RVr8r3Zbu3~V+f3Nq|Y*z}Udd)~GSCBji!G->0x$6x>x!)QH|=dJPr=TF3Tw=Px> zoBnz5*V&KnNTJ#>XFYBv0&Uwm9)5@Ys*^%ZkPq^cB-G?U{9fK;&@K zUzcPPCCwfUR~vkNb<~_3N}G?8L&jDrG&>4EO&=k?tlw}g1;=~A3S zq*51~m_+K=qwN46gFpQJWqzG9d?hEh_vHFKY!l10p}eCs8cv`6T{(krC|QQLcC;3h zU`{EutIiOmW7kEQi}(2W<(pkKsK2iZ{^n8?nY}h+x%AL%pcYUShxhuV3G!reX1%~f z4^|tyYO(pGSjJnzKUddMLi{rOQj#8Rfn{n#yMtV5KODyY=CbGb%-%2z z|JCJ|R*17ARVti3-IED6v1Kj}Awtqd=6*>H=M<3q4Ixax7LaZ=90I z2v))owuxol9lt1ePq-Cve ztrB;*`rg{TF*AwnIUmSIVNh+cY-4(Vp2(+M>@lQ)v?nR!$?)wI?>!4((x|6_&V2P5 zxs^BZ;9KuYS%?Zol38hX+8al>Z=5K~Rw11ypB%mKzB)*p4kvUt5W?)TRuL1SrEr1% zG%F2^X&N`@6ACY}YT;)}*>oA*P)w9yXekKR+7h6zQ4y*H5ax4$;lr!MZp4}6l*HL| zw8k1owa~E(98fD7H+ND*fvaM3i5Kb3LbURl!-EFwfYEuxg%c%*81JQfk=q*w7DGJD zD@I4RaTi-GTb6rBnl_#U^FjWsy;p2fzE{Z7%sewYf4f5atexn^zF}cDdg=pXaM)fu zMJgl0Whu`CxD?iak9jMu?~d(@cyp6*WYy==*wAmGb!+0USN*BNok7x831qwP7ROw< zGW3%3F;$OUavfO zQChQQoD+Po7G7qsVu^;R_M@~iBiNHi<9+W=*XwS;K}n=cit0c*=_x*9p?kf|?jKX%x@ft6%)&U2Izke~H?s8Vn-2w- zmL_j=%MIDb9?HTNRr-Im52o4?{<_4w=|IsCBg-hGavc1uArGUO>{b)LP8*j^W76z= zz=!$KINbZL$+CA5&Xy3FS^XsjHZK+yKQCsnNTL8fT<&zO$^EK;qV;-tRa2(*&l01a z>4E{idbj?v0!XeXM1hFf@3w^KNF3;s_m90A$C&{603@-@X7O$Mv$T`v({))NcGJYA zJ8LbZ!@iDvSaor#3lZPD{%e1aMtTd%OHe(*JhXP3XMZQV;9<9YF8BSi_yNBiG%JjW z&qUT`Wz~%Hh}YOW*0;>+hU6{Ry^*=T@sl7sC~lbtwE8xUdz(VN%Ame1#Q0ENqIV2s zG0dScCvgA5I{dFW^G}MVUL#q5xcjJbQ)3~nEG^uTyQs!3=zUyyFx$foN>gIh zW8t;;wO*C*fBn*@6b^Q)1V2K=`hw18fx`5{8vJK=2{5q6`*iE`?<>h>z5 zLx|G|1sO`H>ogg7(uv)h7<}oLkb;~b>(8+&~(VI61FG5LzB zCU@E_M~iYM3hpg9(~I$TH}xquB<_dP=o^8@U^<2F+>PS*HsmR;xAqUj_$kg= zq`(U+~3y3$GU-T%(Qd7r5@aqeY-t5{?t@dV(Z8dnN?sIhST^4mhWi}3)0PD ze7?C-`&){0bcqOq`G?shxJtk6S!%_PzH{?Og{6-}bi(Q>Cxj9FerzsZ8_BB+keNOu z%0&48f_Y0o2vEGV$j;G~w>ZaCq~CZ14F7crn)z(X;#WhpR&dC&gY;_NFzNGx6Uss1{|CkC?TeBp zB7h4@D}TtYJz}v(eYDhiaoF^JN?(J*jl+yIzbt1?PU~s8UMKd%uVi@U65 zOdV5UQgDDsPX0L;vH;g!nU3;uucQf68aBUO#Cd)c1!7mOS!k?ociZ0PQdMh{9c)N) zRn41y(~5PAY?4qTE<6`^oN;-2t*GF`;5P0>r`?whnI)@}$s~&R&!DY_X}JiMQthD; zc)G-&_jTd@qiJ`#Ta-bD$ZEyB*%O)b7LR>Pv?N=5Hu|;3;m$<^)&qfrHG1{5!&bSw z%g9~~AKqXuQ&{wyo05V4m^t(w;Lw&U`0Y!UOKuSJJSN0C^ZtI@5@XS7R65!hJEv0Uqi**fTicZ$jgMQvo32_hI?UBmppKYEE`T z%C_dBJGbSX3#by5`tN*nxnI3P`^FsqN{<4l7uGiV{&HN+FSts!oPQ zgS`kWH!Zpm`IG`&@NgcH>56Gh4%f4aH@jB4O)b@}k(2LO827Gudq3u+4#eV!-X>di zKA(eUto3=7P4Glt|90?ZE@djrX{wq!{9>7r|9<@-GRTogL^ zF@sFyp0xBNn}P+dn+I0#)u)%+F=bVcu1h6H^+io2Fr2q{G17ZIj*d0ShiEKBIB?B- zxQ+;M;srF~vr1z6AIOzR92!S*YWaGVZ#CZ{O3#f1V&q5=jTxhrT#QF0_2ETo z2h;1Y+tnG;3i~%<6y1?-OIoU*;9|O}RwMDS(lt}Rf0w6eykggBt>>>xOX{10%F}W3 zy1oSoM8;tZFPe8W>aKaP;@y*YU2`u7NTL6nPtv^pO;Wbv$Cpl}cD~u1s-FVmbqwMy zKf0BJOplYp50T00e^8>y!ayB^gI(XEsZsJ*p^Tv#B-8NA&65CA{K5_TO+oMaSNk$W z8cMBAFm&yCKtu7qU!bhHlwGFtv-!@>mp&N@qPZ-WBP)^JrlEC!oYx3r>eYW!f7VO< zk(PvoLb7w&hb{u?jdM)587ewo-`3v^qOjQ=)UPkmp0wD`=Jk~F893E&h|bqy7v+Qr zz7}?VWgXWmWcOaG-GZFS_)zC_e1j&yi0mek`?mtC^1F2Nw2O{=PK&}~*YnivdT}LnyAnql_)#XR&i{IA~pL9|E6st>jSPQEY%Km@j zhw}e9H0Ck@Vj=uA{yAo)-&PgTXO)haRfzy5ZMmLdWI`Y{MmFzQxeKwyW$Ok!CIHa! z;HB*~z_}%#5&|$fw}}9=A3;sysXV{Aia1h|lIYq$6{`XgP!;irEolWB`}WzNRF40F z6Zj7YsQ+Y3@NaIt)|5MBERkjBoJ{wOl1N%L^LS)2p4Hc0lQo$BjLiH=@>BcqyULlu zPjR~-idOEckkzL8ri3LLjyP^mSJxU{Mu)8Yy^>K&Ftj!yUd_&sg&47VTp-i_NLNZn z6e~$i?(F!LJpWD}%0m5H|LSK)m58?uEWFxDxo#iV>j;L*;6vda-5l-rgCt1dsaT&X zPbPciyWSVwFJ;ZkrM!Ol5zTgWNax4J7r(1NqO{`VrE@AbmoA4u`6!^hbrpXE{no*v zMV|C?NvCtI4%s2;514MofV22EU+sGVnW;quXp6Ud!t(hU-_5uF&JO(M`Va8T1F`ZV zt%6;5%%%{gd_MueMtP> zeCY`te9PK@P__{ClsH@_9nubYE2LA8*eYA#2Ba`Vc+n4kBDy6qT5pF5)K1@lHM($R zUR)d}E2dR5MdiCtWCTb;ER;APtTiN-bT9}H&h<+L{5Q3M2MR7A^uTprDBZDnlBv2` zA3T?KMWHf%=mN%XC50!Dt192+iZNNy675usJPpQ7UG&Pm3Ve2U{ln4&rUnl({zqn= z15XctHSyqX#v&a!3IM2S6lq^xzyqLD_mXOEJH7yl)XNvlz#di704A0v1nr$Z6y+&V zsT;unf7(?=>Fu6A_%YW$LADjiIa+L;vzF8L0G;}MsnrU6^}FxYxBDzk=8V!-4CY7^ zkO`+{jdzyIoS|um+6c+vIQ%UiHGuqdlQ+Z1ESkncR^s&D^<*cwbAsn3@}o;4a%Jcu zD;Z6$f|@c7H}b``&clXK@GyTimed<6a*jzG%24=Ch{$MD~Zn%v%5 zqP391kQDYb)9({^c)C>{F4lW&!JT(+0mFb!8IO)@RK2{Foxd(I&J*9*^5?Yiv}k_- zI|r8Ba^B@4-f{LQc1^a>S4wiiS^q}jLVLh-(2!34y-g~qO=nPGWFePsZS{! z57{dZ8~KSC#<~a!_js|~r_^e9DN}rmVu0}1C6|w+Fn$>eXjNAT6f^zRaiTh80wsUWA7i23jZ|+o= zdpBT+aqPEKv)j}Ju2#IgH$Ylnm_i#tO4$wF)|2)9A-!kg#JsED$ozO)^%a39=p9OL zcvE83s%ojUg2ehMMB-{>xAdzC*Oz3)Vq)<`qatX+&hTLhyGD83$o%;6)4IBr7FYs} zuEovGW$$Wz{o?m@rE5HykFU1bkH|sAVbb>m+K{EH(_1o+`jfo2>uiz(^cQE{>lS}% ztew;UymMwktTuO7XyaHFkn6I){|%1RWaI>^T{SIqX_?#td*o{+rK?$Bqga!FAcO&W zo_hYO7dIer53XJ;rL=ZsZhSa;xWFHfU%3@%iP>CWz2daK_q6Hmm1+B*La9?Fph?%M zyl&INEj_AHax&FQV=FMC$?tOKf&?BcoLXUB8wp2<5(Znq6%W6@3i9Na#7UcpH_fv| z7ByS1Pc4isUih3VQawlw9|-d!Q5_ns(a^E)Y2=?CT9jvJ4s%O79ir&~VOq`#W_*pnNScHh#udH#0#uAC5kM`AX6*Nm-FnCP1M0<%$E zf=jBSa>qTwjxAprD5brE4Fb2&|;^pnCMi3-b2yDBeMW>^0$i0#l5lqN(W=nG**s1DI%B^0ZA zoP(wW4y$vK<`$)L2FYz~fXVf|R-m%?!ryKH5)6j>wZ$4o+VIOHhEXM zZgexANPqP{0a{X%CSPSh*~7Ux9Ql0yL3clE*Sb0`v|ilKgpcF?in#q9#^*1|oTWHq zHIzmB2zDI|?jmWK#dSL^jhy=_zp=d=FWyuBfJc`B62&stLn^VEC^IYqy+MJbZToXn zjEy-h^B%v3adZgIhYgKW3=v!|tnl~_K6s*z&7C42xW5EO%s6UkP%OQ1IMd?GZ#FZM zTXGU7J8|7IELF?eAgVYl_Mp^SQ--N2PCUT~lp5A>C~0bvF^XTAFcA~-FvYmOc)!u8 zFgd3oKBO!ZCjsx&Q$u}nK&ME{^~>%H=Ci!4dLugnO0DMJSU-M4fcPe_wSW1kp}I{y z(7=pz0B6%Hk~EgI2L%cYcCTH9`ekC{LU)(73U?v2~t5oeKnDu&m{=gVl)cWpNI@p}dim@&2-Jd9$*bu1$3IIAa)Noo^ml!lD^!(TQ}2(ag25%@$H^E*P(`sx!I}>XCmch( zX5QqKe$Bym%e;9s!Ok+l>NBAr=GZ9y*;rZJV9^PoenqfzTa#+IktZH9Z(gp%cW;QJol1q7Vm$oF#CNI@a)@>ei#oXuHJ5uH$O6d@U>ACCB5WG5-Fqce z>k7A?zN>E!r;Yhz;_LoH)XF^KcWiANUr#G{;%=K>1#C9%NkdCiPMIszwW3kN&JOjX zySu8bDT*s;+aUGjG6#PJCg0))**ie!E23bMaT$#2o$vh=lNg5~T(i^#6GcDfzx z-0wPjTH^{NO(pn07q^VC=%O?kc%G@Y)q{M$VGMfH2?$>J@p(6(b@7)G(!cb6Yu~JX z!UMzi^zOXX<}yHisdF)LI8+~Taq+nEXK}8Buui?6JvLgoH-Wrh)q9#QX!@m?SRK^C zFN?PmF_=i;i-H{mTLiF~7#6KpQJ#wmBDb_2Y=kg7|AvR;v(}6`d9Un zQF(}pqR4WWOytcGE=D7LFL~%M);3lTSQo4yN!)Qm+EJDOAZ*A$jE)2 zXeu97HFG-FM>gov<0vBtGXxY@v*}E&=V@SH<;_|*Xw<;XShMYcnL`)(DtGj-o1HKi z7hYJbY91|a%Z#)#-W7xe>{hfae3$qR4Fwt}mQhz4O(XUFf8@LTx7}2zuMWotNeEew zz5G)jznqRhOy{T33BV!xa%xJH>81DA3&&iFlJzanr7nA!Tc1V8TShTPRz+b+RDk*L zz75g&1mUbE4w`qlWt7l42Jva=ijmW&%XaW8l;~aNWy(bBG3w(2hFM~ewC1thxWqXgIwFvt^D1YZ186konWkmG!j`7U7gP0>27us^ z{CA>@w^fV?36L8ENnbyA9Klx#U^?%;l(mA!rZr?39Wq)*jx3qlN~}4qMAJ3f*!#^? zt|chZ4*)C=$Afg*^N@kArMtSr31(u8glcZ8tV8N!f!j!Q9NN}VLE zRtK`%&y5s_Yms?(1m=+4uOq+57gG-PK3;QTb5R$se)(NJP@5I%B}FQDFE{t8>>`DH z^m3oq$vn2HG-P=RZ_A?_*Iy(U9Nc;en1m7CU)g9>O5VFyKE;5%ueWA7*7f)lR}Ssl zMRf6<#2#UwUAgzCju33{ILp?o7gLJ62*b81MT{kl&n4*zDB08N10-nEqR6yl$!lkn25>W0{>ma<&of|N2OX-mUU-l9A_J&xg>db&KaBj5VHQ`2>MKYtLMBeNqXsTjIsW zWssRzm$|JpP*#*^Yygm;Y!@Q2^ykl-omGW?r;T)nY93SC{qdYlXrmhMp+SjfHYv4Y zxB0A$AVX0epfSi0TCckwWhK7r&}c&5JVVEY@mO2H7TEsq%+&Y=UeIZ2|M9WUcb9L{ z>$gj6N;NdPC{msN>uWkrO$x{8sNS9zi3QyRveEha2&RAtWiyOLE?v1fJ&%d>Nj@?U zuDf%hc@sWBW0nLqdpsq#-^zyFkRndn3c3k$wPm7MH%?bQU}XHHO{Rm9m$Gf*e);W~ zT|335__Fs1(+c+Li=}OhZ%6AoMO`Xwxxj{h~{k5kLue`bI(mlWdNcyQe`R}r*6sN4 z0vPVvH-SCe&gDZ*fXTEQU6)0hng%kNcGD|rNscy?jw>ne{i9=Fh@#OAMPIxFKQ4=J zF*3(Y&mF?0nc7RD*AHo|guVN43+HCUbS}NAx${w50RODy)52{;Gtql1bT3|m=yz~% z-qx6Ufkem1hsK*(*vf2`v26nQLKEI}<4yCV#!0MVbI{vD8ne~%QhRE<_UbZ~)9d)` z0v*OhiCbyx6-tDWvZ(T8>p96YKv9h)n1ynarsvm4$IWPXvNmEj?|P`}H-O+-y=@7} z3uzcIX|PJHy~zCmb&>q0)0qMgQhB-5|K1h|0b!7nCR*6(Lse>Qz4*7X^K!_;dR{-n z66N!WHMc{pF`bGwd>lMl5oi2$^^nCYvV3LB@T}-sx;)xY(GJkT7!@}=UmsY^Y%kx- zf*#^J22a2KJN<0WYc`$606ll5^{QW)1ngdih4?fGHgF*uG9biGII>}2!7;7nnMTX z3ChJ@47xR=I*m~_LW>{TKR9x#WH6ovCB?3_#4luJ9Rq^a_vy5GSOeYfl40CoqcA=! z!H&YNPu9v=)swnGbyTJm4aRM@Aigkcnbk#t%@aNPu<7+7 zw|gWj9fm(C{E)#T{fZsPWsSq`69#$$coSsk%^ zgX13#2RB#*L>&{(h6OntY!zsj@B-H=B!Sn@j`Xu=moM460wR6lQkO}AbkvdlArijy ze`P-X110?DR~o8rlwWBj|G*6Yam$sEr)2GzHigUyOXgYx>M2o;>kyv_Xv*sX&W0ny z>_adzhT)$*cLiTd?HQ_kqQ;<4s>>7w<_n+yj}Q3IYxt*YSAJSzv59Lh|A)2z)BFApe)Ye)<-cOE|C_J; zU;SAP&9ZX}&GcX0^8d%Rf7%8AYMKA-wg029obIkd!ly53LA(YW{s3}k9Fp`mj)uvf zOh45VrV+1X=JfEEqSZvTK!Q@tn?-i~nQ1;|TNQcuqlceKLbomxpr5vX)-350kDVH$ zM}O4j|I<*8mA8uJlb%N3HlTV;Q%~74$rc}fZz3Z;totCgjjgS4%*@3#n7!YR&pStl z;Ht&3Dn6`_8$}wWWYtx^N_I|z7Z4DMRBjK#jS+SV%wP-?ia^b8t25<7Ye%?a>IP7C zAt5;`7_lZcdakpf2xyJBwA~`xX3Z8Ab)U)n z?iI%8mPUI(=E^E|xsU%@KjaIe`4-ZIw>rUPlH0JecIJs-N#%q^zW$}tB8Tz4vlM?=nM2mEkE+}&iWZz`E8lQ5B*Hgq? zQQT3SN5xB8$^DIGPeMqFJ!m{%`<5=svgQT)*HT-<5D~aY;QA2A(IS%1ugvI%A;(HK zT9oh_)f$kDc&CS7uG!zcO2l3h>tbQ1ijz&t2r8KPwTc1{53l3+Cxf1M_jO0VHz!(6 zVyuM~%v3#d{2BYAKP+14lr}G!JY_x7o!R2pMi1QAX?+44P>q#NRgo_Bi?cE01lJ0g zCQgYHT>F#F40UYv+Fs6OPdoF}ozbu4%_3Gey1bZXDA-O7#v?$9>17o1=Z?RXN?qZ5 zqQ3g^Dx_Ug5A%e660`5&DYc-(7D|@2E-{s1&vAsSj^T+uDJ7=w<5E?`8&Zg9p(rLd zUeWTiNP*g0F=)Oz@9`3dnL(0I?OHOjF)3I_vGM6h*lnsJc?5?E0^*Wy;L|&}r*m=3 z#`+I0Fu4I$tx0gqUbrRHhc&@M%99ll)WnnJn;<_K(PLLV(cZvT=Qd{Ky^$zqP1b2T z?|Xz287~=$!JFYmW{KkcDW}HGj&297g+Dzk>S%!Ys7odS#umo0w5b}{C3Af%m%Dws ze2A8K^<);M8vkYRwu?t@KXFS*LfrWE$p^F0SASRtODR7OW4XnbjI+OEsel?V=*{re zovvLs2=SlSu86dM@EIwYFQ6%I=x6=Suy)<7ellzOP#Qk4lGvRWJ+~YUR$OJdynUt= z6KY-E7*(euHMVa&^}JEsS-{j(HMB8M&boc#gJ)WiVzbLt6#M!1pA9EJJgAQ^ zvN}{kB>?jkqg9|NTe?Hqh^`QgV%c?ztZfB|34~ay?&5}=K=_<-I$PM*uM<j(0fD57WLlE2yBnRef3ZD<~M?@E8Y2{xKp>mSwLlgbz07=X{OmVhSTAL(Q$2dB&_YXHl;7!jB`a8|A#5Z$39U1 ztJyN3c~|*ClReLuG43BoudY_*fA+RJ94zCsG3wD(3HGi4jF9r{rB8;K=OQE}Y=-lyHji;v?&sBh-qMGJt zAgV7!r7&-;sTFy!P}!Y_(pSH=I>JHd6_8oErU6c8TqP^3z&-Gvk=*o-r%@)kq1-mVNE=qQO9&ez_)iR{4IK-raz z3qFJb$A5uxnQ^jryj1Q>{ckCAES4?3cnC7qEe^V&{ z5C2>BxQ8h~Az+5P&)d3>i%#5WkG-+z{9+7~Yn)`7A*BmhW+w=Z2SyyQ(6@oR;Gdp$ z(L}lj=%WWHt6fyO>!yPgnL8ss%~7Jp-r&bw608v$gC#FrSGJ})zf%}T*ctpH?~mq+ zKq7(<)!DkH2CGNEg0U=u&R|g(SQj0O(Yl$a@Z-f=YDsem3RH{cFWM_`3e6*x9lxSv zk!`(r)G{d{ovPgU^9)I_2XMT9;OnK{&E+Nyqc|#m&9p@q>$nAar<3*gr3Pb6b?7SFQ6}86Fr3oO2;BygVLaI;?5*liC}XQVb>b2Nv`-r{sq26r6-O=ouR2BOWfqJd`YrpQPvmO z+MfKX~uAzEPNXjaw*uy!4xc9#20#gA;=hzwcRTE6=PucBd27i`Yo0+U+t^!iH zK6ybYk7MU&=P%a0j-&$@T=(Z*NkOyZa=lw!=?}?PItsOSh5ATXNFJT6@*t;chEOaI z^Yy{ndi*IOjyLgFQ@{%^ZZOBiZc^2PO5W$^DNWf9fqJAEmOSAJ)wI@BHU2TIH=2Ik z=@T*ulRm=DU^^G&F6(L$Vdv@A0usnlbTe^j*3@hmR_YY0KIy6y2z^9q>^2Y81pLwj zet<+?DfTP3VmU*nJO&^?2J=vAfPop0+Js+~KHhEy- zDP@1iH*?18Np}MhZ%j_k%IBlb*z)(74LUW?z+WEA4{u8NhgmF{;rd4E0Et#>S!4g4b1$O)&|K?<9Js#I`AB7z|c5zgiNS zbFklt?CL2;MPROX4)t?7=nwa44XNr{b{`x-nk}ax>F|x zQ(-)>a~1TT5{>!v3u`1TOGw{?eS4WYP``+*r@I9eTW&S_SX)^!sVItT{(fpH1c6@L z$RMo=IGGUDp*X6^ht9QA?GGv=bkNI$$1Eu0DRUvPa1B0d;R*#hRUDdhfat9t0md`G?y;zmd`Uy>m*h-3K< zSrhR}Ncz9=82HZ&X}S%4#HGB+|2y>RKVSPh_v(Lm``>T*KgfIIxa(a-_=!>v9 zzxrjq-z;& zML)dMc7a(@#FS&y*0fGd6v6-XEX({a{ap{e5sHNDClL?cpfX;Hi^Z;;r9KDcf_!s~ zzvSCaBTIEEo%Z*Bye;zA={L_P7nJsRft|9m>1E;Mv4t2{I(e6;uJ847h5T{mZys)(F7ruM5wAIAt+Up(uEcYeQIq9N<4CdbCLaC#txPFDqy~PSVC`xoYY0?^;f#0`a$pj_d6Bg)hia&0wk6-`WdTUEe{%=d;i0db>5$dM4fIU3a;!`z7Ntx zyLvhB2ONW$RSoL)f(#KEqr6v!H+*t zAF|B-m9v;9*TF`3b@W=H{2Z*v$xi&-z*U3(t`!NsFD-=3M5sY5AHJB2PE56aTrpXg z<+{GwKHXke)Tp|=lW{Wis+mtE$Z+h?x{|%!5u$@e-;lj2Pz9S_*ZRv7zjCj-cP(@C zpJPE!MTW=h#z@s}Tx5~PgfhhjNs z%SiI4{l~AxUi&6J+#@hjD6#QW)RLd^In?{#ikR-G zzLqS_gIk1Kl|xOF0(^V38>Wa&P6xjo`e)af4QKXp4lw=Yz*Wmppg#3;5mm>F`tTHu z3S2ceM@N*UD~txDR6^tL*v`+Tx!{>&KdO`X<`VCL56<+FO5SlWnSP&i{C@W*CNwbJ z?RLIxs@cJuOMG@pNzSjBBYFCE8d?X74wE~jwQHgNj!RFHXj(Oc8XT+8IcHnznWMGf z_7-SYCs)!8M2efHTlxW?nHDMJoIwx20`qO=e$lXcCYQEb3bFqMAmjrQD6$pb#~!Z+ z`0dN?(Q*#e_wr_Eb3#nhM>`Bg0*<)FW9U+U-@ZI}cp{7?Ol$DCovw|v_OLxPW6{-i zEw^Mw9%7~GFK^w6Zrij!&weMOqJKeKZ+%$^AMY_TlNm|G4#I9ouXw<(_D>|M7luBM zjupOyY2z8Nwp%Gl?w`s8!@h7H6k*}Ym_afgF19boB?`R1O(tv<8hKTGRO)p+|wq)~R7JWf92Td@M_ zL|MEGSP)lA%dC0* zm~M&*J98uu`mMHYRr6`s#aAJ)X_y~lUyE%PDKVJI2Kd%D{Ug<3#*FJg53cq~PJN0% zRoyEEz=vZ}S{<#HV&CnwG*cqvWgyHL*tBI1k)r{sadGxyy*`gv_dtYOr)XB%%y?29 z>|i-Y|OJh=KbI?wN6i zTz-S8=nK)_=>OO=GvQ}8$5byn4Mi$AtAZos`~C8?9qOG|QV8GUQe&vy0;jPU)N&AuJ?Qk-syW#3 zTp*6KU{*uW5EUP?*zTu{RA}va?{Gb!fF1vC-R6j^H0u_W4q%^33C^+UmiTZ1j7?rf!rvuF%o=>CRabF~%K1D@)^4c;xh=Ca9f#MzWlRT9(t2wsWW zth@(WsO7lY)`8r`>m>4Nofu8m)zHAhwJMlON~l~2-yV&XF*@TIrL+5dyFuk+?ZWEK zobGJkd?{xGYa*cbVyjS=AD6G0SnrPueV72vokC-08c6&u&*^^`h$_OgXY#(6A?28j zfwh6xbJCM`9o}Giba`JgExQ{_5X9MAK_q*ydd&lBWIeuU6h$64@OpC^9>($xeAP3Z z%&dbLk;&sdY-?|E3~XZ_?O5@{X96Sp@{n~LjcGwcqg7Nqb;7eYj$47YwA{FwzR7i} zeT4X0nI11Lv8_->#i|Ap9N3`;0Ye-Kt6vrkc4`X5l=R&-qy5JiqZ_b%n~IcOp31m^ zJ&qkhBb&Y(S%30Ko4x-0=(6MOjpR@K`$n15x&#iw1px+4EK}w^tHG&!`GWpQHb3b> zb*jZ}k;3~8HDx7C5~ON)C&vu#H$ zR#IwXJVTH2Dg^yw^jYMJ>k!4H+fY3Jk*KvtQ<>gp z1LbzTkc}0QV^ZXE`s~q zc~Q3QeNTDO-BYE{~mL*u09|)w0D1oYi>cQq1^6n+bbK-dAwU*tC6Cw^?l z1-hj@R8kbXrpxe=d$WU zIEzX1Bx~&74NU!+#g=Wh=f_*V*vdGrsxR!b^OW$>SLlx-hYT;kL0QqqN;Ub3Q~ zVvQp^sd`AQp0n^qjAF=Di#7z&&^rBQ^2W{ywM1zGCACe|f#?P*{lvT;~^<@{QE`;(d4LeA%ciyxAId+%rPqu4gO?XWd zDVBGus*7`vdTdokFFq2H9J9lq#?+G#7{-kV`c&VBcwazsNZrS<3x^`iK>WKv!b}bl zP-+RNZOE#z?pi(czjl~X@AIy!Q#Cz^u~!fsj-?fcauw!{iqUh?Q$h)j!v!*g z7{3zl&WfiPi=XGjAdn>qThW21YR;jn_cY3ob5Pof=z=-1GuDh-~niMfa4Blf~1Wv`o1pSzpf3!WlC^ zzP}Gu5q;h9uzxUka^3ek3pdd>MRl3#g{3x$o(U=0`~#hIklEn zjS?J!K-X$UUg@HKUg(-xkQyU2Rk{~{n!Xqb#JHOEJlmhA=PXU}9EmYz8;o16hXnq{ zsRiD@;n$qJxi~7?J#HpJ21nr~Uulj=R}%1ngdN=&eY-G`?xo?`qKl#F`dSZateq1B z{o4iuW&dc_B0lD+bTo@{i(~7bOE=JAuyD;Js*tAHB}6%^+l-fV-zP44=!f%S-!@kI zW$VUc3+rsKbFs%Iy}M4*ny-;QTRs$dnbjeA*#fMQ=|qC?eB;FsE;f|`uoY+AR#j#V zxZL@h{(J3tRcLpOk5!xKsj75Oc)cN?gs>8sAa6X&Q7%{XDjA`PF2{Jiww+g&QJ;`#+* zI;W7ntX#LxJNF)i*15g$I|>g*YP(dq8Rpc;9b1Rx+*vM9r-TMaRG7fID^T`teZ4dfz1W;&Z`v}j)>!S!U|ZPZuH1oA!|KZJ z)iI~DH@_Q$nGw=PQ$YRbsP=*2xnI_XadUwM#zSmvFU#b6s)Drk->!`pPa9uEa|ex@ zjagB_$#IC?ilK#he<~<3e}EX|jG#kW4LXI|+l{}c5ua>#HUFmqy8om8@t-GOoRQ+X zc~XSS`0@+wlVY!)>C|P22QF<+&V1QwZB(i)uYHB~prJFkmwCs=$G*hy?d)=y2KK_v z_g*trL?}o_cEwTvEPZjcZG{{w*T@3f3XM_khcD)kAN3DvJmk|CdeH( zp2%KA=GZnz|Mp4{1mB;dW|Eho5rO zf@Yh9m-x#@9QQhzHbXY5<(k)%)2|G!;k_ih8~Ap%9P|*aQ!R0l@@rtp2*xd_IpZra zYmEX@pOreu$w~>0&>755NyO1_fc$0pF)3bMc^)%OeBTzYxnFmX9$xvW8-Jy`7w;cq zGzF=?_E0_*9zCZxr}k$1l?ghG?V4{T2hE~^)hS5SpfsE_t8ysSzGFi1ClAe9)h7n} z_GQB~Ra)TbI^W9r@NEP5pg&9ktE`>|1+3WBNoSQ@GT`;qr75P^%3nj9rg$m%hG|8} zXFH;IMS%Rre9{#QY2dTLAo5Izyiy8G!@qYeiby#f*kOUUtFBB-Us@W~XPzq&762Mk z>(rXshG7jtXKLq7>clt(7f{7JVJnZQw7F)g+kPV}5urqJ4ZmbBd%P?LWC2yBz*UJg zvx3d?Mvh%^)`%_CFF?46uhOm@R`5dL+kT7tROfHQUQbiMVlBl^jZfs?q3)L_< z*e^gdf&`_BQsT^{2p%4wEHL_`WYi@q@G&x{I_tFTnOmH`zNthj`|rC6DW)lAw1E4* z32{J-Viuim45v`q*xBxm84R(Q!9Skt>$hj~*A?-26RJ4*Y zb5gb`n&X}K<=9=vL9aOBI@c+0e;%^{i8ep4e~#&0`@qvOrS3^hdB-aLiU+crFHres zp(He+mpKYvq=QDbh3P131PuXEA6$@it;DSZn=hh?-4vr?3MtSq5ZEJIl++;61cl#W z)^+7+$RR^JdZF_7S4cZ<(c9!>O9lEaC%G9;nbKNLKW>>~jS{umANA(ul=mC)&{2?9 zBo33BFuc281lsHpY%&{Hy+o#@MQ+gDc=CgBfud5^10p;^x|~&V%uoCKrUA>fUjQcr$V_YP%aAm ztP$U0>(y|HN}>}VnXgtV?yoVg)ym1$rEjwjb^oet4T>o>>7&%V?K-RQtO(qK?z9s^ zB1v+t$BvsErXYECDVs)*~s*!fjl7Hv-TcUbA-te$NLyW2UN-@d;) zpYf+9w~cy|6DnOtup$xaXmixf06%Q;h0+~e$A3rvs;X=+7J`0YDe_BHgcSs%w+`%( zanaPzB$207=BjikCh_N7f9c z7_MxKU-^6L_lG*Wo_WEp2lDYH^`H1r z+0|cw^GcIK1AS;gboLFO0a4F!W}R2+nk{ON%uK(`zJI~*~H+~R=X7_; zYV_k8{*CwHPW9yo?$ElIS~wBe<`8*C9NknjidD$}IS>~_^69*&=c#62b>aC=M`{`_ z0c(?Y%Qljg_9Q<(ceY1cR Date: Thu, 3 Oct 2024 12:20:58 -0400 Subject: [PATCH 028/134] Update README.md Updated Development Status section Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 71383a3f0..482047bf3 100644 --- a/README.md +++ b/README.md @@ -6,20 +6,20 @@ Libocpp is a comprehensive C++ library implementation of the Open Charge Point P OCPP is a standardized communication protocol for electric vehicle charging stations and central management systems, developed by the Open Charge Alliance (OCA). For more information on OCPP, visit the [OCA website](https://openchargealliance.org/protocols/open-charge-point-protocol/). -| Development Status | -|:--| -|OCPP 2.0.1: Under active development, with core functionalities available | -|OCPP 1.6: Fully implemented and production-ready | - +### Development Status: +| OCPP 2.0.1 | OCPP 1.6 | +|:---|---| +|
  • Implementation is under active development
  • Core functionality is complete
  • Smart Charging and ISO 15118 support are in progress
  • Ongoing testing with various CSMS and against OCTT2 (OCPP Compliance Test Tool)
|
  • Complete implementation available
  • Supports all feature profiles: Core, Firmware Management, Local Auth List Management, Reservation, Smart Charging, and Remote Trigger
  • Fully tested with numerous Charging Station Management Systems (CSMS)
  • Enables communication for one charging station and multiple Electric Vehicle Supply Equipment (EVSE) using a single WebSocket connection
| ## Table of Contents | OCPP 2.0.1 | [OCPP 1.6](OCPP-1-6.md) | -|:--|:--| +|:---|:---| |
  1. Quickstart for OCPP 2.0.1
  2. Run OCPP 2.0.1 with EVerest
  3. Integrate OCPP 2.0.1 library with charging station
  4. Certification Profile Support
  5. CSMS Compatibility
  6. Database Initialization
|
  1. Quickstart for OCPP 1.6
  2. Run OCPP 1.6 with EVerest
  3. Integrate OCPP 1.6 library with charging station
  4. Feature Profile Support
  5. CSMS Compatibility
  6. Database Initialization
| For detailed information on each OCPP version, please refer to their respective README files linked above. + ## Get Involved We welcome contributions and feedback! To get involved with the EVerest project and this OCPP implementation, please refer to our [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) guides. From 348dd5bfc4feaa13c87890e0a35cb7ac313297fc Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Thu, 3 Oct 2024 12:29:22 -0400 Subject: [PATCH 029/134] Add files via upload Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/img/banner-ocpp.jpg | Bin 60432 -> 102273 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/img/banner-ocpp.jpg b/doc/img/banner-ocpp.jpg index f1262f31074845ff6a6ec1f5976d92bfb316d9ac..7209f1e76d92712c3eef663f4edfacdfbc3b2903 100644 GIT binary patch literal 102273 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

K!{N0GH(?Q6gl`7b~jV*OdK}8 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 Lh#Gg|&#C_cs8h(L literal 60432 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 Date: Thu, 3 Oct 2024 12:31:03 -0400 Subject: [PATCH 030/134] Update README.md Added header banner Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 482047bf3..d194e579b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +![Header](doc/img/banner-ocpp.jpg) + # C++ implementation of OCPP ![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) From fc58ec87d2bff9f1d9306a3413ed45e10bf69f9b Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Thu, 3 Oct 2024 12:35:46 -0400 Subject: [PATCH 031/134] Add files via upload Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/img/banner-ocpp.jpg | Bin 102273 -> 83550 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/img/banner-ocpp.jpg b/doc/img/banner-ocpp.jpg index 7209f1e76d92712c3eef663f4edfacdfbc3b2903..0de869d3d80432446bcb9549c7da610c857dc2b7 100644 GIT binary patch literal 83550 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 literal 102273 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

K!{N0GH(?Q6gl`7b~jV*OdK}8 z=Da&xV~_l{9NvS!hLwrL=j z1u!qd&!mf>8*nj0A7i8}o4@UB)$}! z`MBZ9rW5iCwzMDWU7)i~T~XNg@~bE()oJ>Y1;>=~(sx=G4&S_P;aMCC*Fl^A7v5Kv zAB|`?VoZFhO!*>YG&+6`{(r-|2_bo> zSn1>AYshs}g|dri8=@aMJIwr6ii5mlmhub7m(Y<9Mj0Bfr)?27*I!^)k8USoXK)#a z(p61ZiK=E`bXAa+ePe#!m9HPO@7zqb1Y1&7Y#OD$lshymnO1wGRa%q)cEJph6^*{V z^pbD6YcnUd&@0#rW;pIk0VLl0oMQ?A4e=!F0dGlGsyy=sYP}22$~Z^yjt^IA=Z8mW z3DXU`9aL#LB^`RT)Pv}T#36s{_m_tG-`lS4t6i<&G1@3nV_Rk<9Kc0YpFrHMpeWmtw(b(Ln%E`u)9gU?}%sJLk9WuIzM44@rwDfw~TuP$CJ z5^5OVWGr1XKNku~b8HT|J+K`rlP`T)SUGRAf8FAF!7WaacLg`wDlAfGG-ljiGAeUj zVfCTCJg=shwZ#^ zdGWVjoT}lDO(W%wx@A)?Hxl`WNUy|6HFZY$vGuOtJY-X9pJgDG3 zC+l65C}gaF#pjy@$@iN{Ttr~4Qh{yOj@VDfRdr)N2boGWo4V)={i^BL`5U}FszFJp z{Jj1^YKxGBO+IfgUt&GI(%dvfIJchgb9D!XsMMdt$t+|uDyDWX9?Jh4LdCM50U#|m zfyllW8}OLiM8)b*Rd7I`0HS+$J`cuqVXpSLkw3_x_3eRlke%g3fD6LIzyaFS3XB`hd87Ajf$B=V|i8_7pv;b*58v=R^nD<9doRV1Npn?#;A9{|TXS%^;~XOW;cA~sk&k|5^Cm%n^u{AA?Mk4_vY7&!u_kU zyXZ*N(-qlI^@8lu!IY;o3^z^-}zy@ zV*>o)J9NJu0SVw`QaKoA&Ta)0AP$*&DZqGB8vxl|(muo_K^99tqc;@cM}Kg9Zavms z{%6j~nWHhl{bn1gTb69RKSWLZw2e@-VqB&PUTMHA&3edx3pE*+U5o%VgG}BP^m&yW zZ?xLyq;O5`5HJBZ`nq^?MNN!VUVm>)=l^J);2m<`z^;;6pm!3|nUlKw`Nte}>7%*9 zkp!IQ`WSQD_dRpbc)gR5hndDKH335V(bt6wy&G8a^#mn;WDGymZ|$2eax>DJBVb?EU}KG0@zXsp{j$#ylM(qL-J z(hIkwC3z2g+03+`+VkZ1f-D0puRa#|9m{t)K;xEl#LR(k|3Ah1AF=EKT+sRV^n(2< zK$+pP(4FeNvFS~k>Ox-|zS0-D*?yfS7Z*^eFR*mObsOv$T)tE8yrWom_B`ZcXmAmq z%eT8g&dL~(QYJQ)#d$wjU(S$J6sG)a_K1lm!K|enymhuRQBP$oTK!EcEiN9-HV}l4 z(9T~NBjICcWeC-u813zQEEzr=e%qa*7OcB@{)p@9U*N?i8c!F7ca6uSXuEHFF|Bhy zS^V1XGF%!drrbp*10NIWFjw4^We+`^`z!4Q%P2l0iNQZJZ(5B0+_Oi^(+qNgp!SxV z+6w!Ky~c+s2(A28UHpUMRff^j9v|K3-^$VdA#@lq#@=W;^~tI=2o(MH&{DQUnelIB;)21Qadv}mt$;W4o%P`I4xoClJ zUvmwLa;9--=&OmD#&FE)V86^y70Dt?3s*$Z`MP_g;V|-`?7|6gG2MMS8Kfeg{a!zA4nDs!h4 z;34;nJhB;#@cH?-tPDt)6Xkh_kkBGk5Tja5!JJtg$wHrfpCJQAKa1{ z;rJEpqo@BWw_?_y7qZ`mYSMZc*Sro$Jjr0s61vwgnF}t^#!$Jt`D&o6)vaFxqT7Go$ zRlh`UD=6R)GDr?`G#AxWtd33Aq+uQMp}OKktj4V2Fq$+(csq3>7zm;63O-zk}2Tcx|~YobnE$?4;)QSDfi?M;%tZ}r1H zlh5=7-oYkN7R8^fHS-#Ww#<+(XP0@`NWkio)rm^zl?+`#?|t=shI*%r=&@VMVS7-H zTV)I-qcz*rL|RLUHL=T4Aq{U+qjbgqR%B6;N8O3m_-qn^Gsr7OLQN5c(gL|IC#CEZ zyMMe(q>X%Q9L-dCDie!gjQhCBEL}JYZ&S?N?nY~EwoPqQx=F>m8K}M|;?g&1ePjoT zFQsn>*qV=L+q7$zHZsl`9;8%e)tjF%z3h#@e&HYPz{Z+afVHUu(-oKU^4+Yd_?so= zw)qqO2X_nQ)YRT1e}osJ5-6mt!~o+LN7idKoP=N$5seTDxSM67%9Xs5a+=Y5JxyGaR+k7rT{e?|Mmh2Xz z)iLEpJ0sPmxyzAtxgKNsc!@$1%f`anhkYd|-Qb>Ex4}k!(1oa))03aX)E6QPUg7)K z=?`}OlP`_Mm~@8Hu%?fiu06?Je&nTUd^2`zZuDGNT0o13cC1rw02ytns6}i{&3FmbXZ$kH=}sZUS6Kvp@33k zJ!OAyeV2LkvB%d_+P~v>e%YLoUg?LU&1_XAl~;JL1f3_Og#X2xr>aD}tOnR2xD>2{ zn>Sdoaa}N+L-HSWq3>kID-BG6pa+-h6fwl@g7U(VIWCjxSn5Gc8Ck--$cFc+X};vd zl0k{Upl_xw zO2^UAMB!B}KGd@?NO$Y=B&MjxRI3pYu(9&G=j04~peWR}yEK0(a@8}4G?CI~Ll&H8F#zA`&W=*xdv;5VG$zO)f#fbwe)f3EdwiTXxQK+Wq6Gpa_Yb zIX4!nM6q|WZoWG2VB0x_#0|ccjtPn6Zu9Fe6v+1R=5*oJY-WUCN*0viF)}Y_89e*pYN+(A-zh$O)>{K`@T4DAMS+RWlx9uN3X-Ey}g(k$Sx<&Zz4 z>L=;|kSEcay5aQ)-6tGm*+_5i%2`|NTs(#2qKAlTG-dubhQn7{@nl1Yp}gI5NPqK16w%gupLpFJpe?6$dGwJulA zcONV5aE6QUC_j05{0tC_vIc-6;dLs79T@I=Wbc^P5|9wXY2k-x zjv9?6IzWye)!U`HtHnlhW|hYC#D(4}vs(-2Z_m!3Jlst~VUCyenBy4nC9BY^s2izd zO2U9-FNC=8X0hPb#aJT6r#Wt+*7rSsqXy)2M9fc6f$%(%%A)qV=gsq21V$xVgD9!H2Znk-MJ~o zozcAg^F3wWjI=Qor>+)Bs1qOQ0dqAc@Rkk854^1}mOM-sdtksj=pgJ}AfKL=KKf4Ht|q^>#7&$F@}RUAMoIah*aAA@-V`*9(548ioXV zb7Cq(NB>A7&vo{%tv!4qZr_a0>!HeVJ@#p&y{c-D25a%BuUq8#+Z8kvL38}_G9=ZH zGF-=uw#TDNjvf@EGf?BC_Q34NetAt`;$-i#dX5!Xh(AxR=an9;+cGCw-0)h`ryq{) z|sY$GXS{shLyq21I)DN1j-zV1QY)?w9Z^fa3@@L^^_eYkc@60>{spe<%wLZS) z>V)y>7Szkh)5DgFzE|J6PUcH8kJfadj&BGb5dDyh9xc(0#^KLr(J_k zy&?NL!Fs^QrzS`+Q6mQ-e|D4Vr7H!X9s#~HVGcHQgn`MN z3UwP5YR=OI@iy{&zT%>u#FJFOOQwSFWj^t%Xj!&@<#TXtk)B|RP3-d@lq%p*z+N!- zEPqU!pri~S^$7^wHB_vd8utc)li=nZ18;zSC}&unq=nxORe9S)Ydl&0P!&E5=L!uW z!DAqt;X=rx^uOjjW?5o?wz-u3DBuIQS|34`gxVjgFh>E3O@R?g!*s~S2w$Q#$xBW77na%}ve>_FC&mz&QvNKiqd&oJkb#_$y< zKQR7G)|1TJ@5>8ac&q*(UGi)5p+9`jm()E~c9>Cg$ui`d=RY?*4kiu?7oPonq8a8B+qzV zRRXh##wk0igk^?U8lzmfo|taC0g!%mdgS6`Rl?00jbJ4 z$6BtoN3_xpHr(YSJx=tCq)KzFx@os0SST6`8z~nrgPB)|L5oWliWrU?;`=a4@p4hkknAbjD$1f@!u`yf#e2X4x+f26x=Gs|07H8!k zz-~-FNN77pP3;fxOS{`%TaE67k)_nB18p7-oYd!W0bkQ^bXnVf4{hm^17ee0MhDgB ziAIhh>ZnZj>G9*+FGS%+gYlF9y(-k}x`$iNFRkaOPN!es9#Ap4;Ka~^6O_912DE;g!#}yQ7_wywfx5bKSexHmQXrNtlsUjvQ-SuTc!l2^OtKek0ly`7z zHL;T|r=%iwCO;wo;zNDUzqS+eUw%^6;*8a9=xaw+9{rDgzO- z7(%SnId&xqXrr3uCl$yetVH*u%*Q@&(oeP453#4i2< zLiOmwH>`E~a9Bn4(q`8!F2qj}=gz-as31-!Z1&2`XGbw~jq595=Q7UhnyERtb(ZVU zNnqW%25q^-3ybKl+qh|Q)XvJPf7s9UxO6@bHzc+^vnzz^eS^-L-#noOuTTh^)yKx6 zW`MpalPN+Upcr~yMk_-hq-)gA<#JIBfvf$u;`A~Bw5Gw<*^z(gro)}70}RVjZ9fWr zV_+i4MO(VFzoL;aD>ZJFWZ3vUua?`RZ~Z+agC5IEJ6uL4dac!{wnhR#w7-E@GIyAq zhw?(Z?kAPq*p&Z>QUTG^uL`LK^M|^|8^9aKS*ZgMwi$_{*-?OsOcZw&5N=FeJ1jmz z1NX^dZXbH%w^(Ls*a=)X>>|?xLbVt^)aThm1M)L}0Mi|J$bf&-5(0!PoL%UB*;r;? z8CroB%SfLYK8XP!V7(WIQ*igte~C^(KbfZ@r#e3vLg_)r77UNJCYP}`dkRM^gl+fY zjQw+aI;$=af8F-z%3oKlzH8k;S!+vprrP$$vfL!(v;_@H3=4D}+QGNvr=NOh){T>h z=0HCGQE34O=UPejF(ewL-^-rsRPv$!%iC!i?_rKh86HRY{T#UR@LCVOX zg&Y+oLUK^^OoP06CgBkvF?^_T7y=ItE&C^|iM9jS20&~+1XYJ1<&v|W;f0d})wq3AVd#Z}@R+Q`kv!E!$gMr~Ua(A;#*+le%xoCuSiffTWg66t9kGHC9xg@%SbPzq9s=scF4^*k&g8_zJ}`3jEPKzgq!R8k;n!7MQiu^Pv!Ycy{z8J{;ejj9bOT^ zGsp9PP9qFehH06h4T=m|zV^K7s)rTWF#J=&>LveeJhxQYf?uA>l!~2w@M>V=CCS|I ztZuoFOvUvhcgCZCFN44Rr);GE;%EQGo)wO_06&ACnKS0mM^MlLvtS4A_{lJkZoah$ zO(br{FgIP@d1N#O1{E-OZ1jD?SA)j4W8k_KdA4R3iQhb<@@21M)u;Lu6KLs@zCwBi z)Nbt+yb@F6Wddx6WwL`-28snHepXmGPRvf8@zgs70k-X~47kwKmSfFT;!LMj( zI=EPXhrNJqos{-tR;7J=*$`ZMFCSb5KI5;@6?88$;p95^$Ai-_^K&p@?K^%qB40D0 zyfZ`meum_uWX*t8qC5_oceD7yeNF@UsGI3dyjb2IkyJe0wD zC8EEIZe%}r@&JtyR;4u^osf+=-2yyXTRhox_q7bGzCr5hnxwUatHpXhPu$64lsPikfKi*G^{Z5j=O!4KcA4#4smOS0krsA~@!)=-;WjxeJ zbj`NseYZ`VSEix#bS<;gf-H);Ls{Dv+Hrx=%yFs{F)&|R?xL@kgsyr*G8;}6FOvB* z)dUwwG*7D=9BXi&OndjZ`XT{uO@V+a4@a1Pdv^XcnEt=}aAwzrK)@_L{x4dy|J}c4 zz6KhwsqexUnRl5Jn#ZU2^OZ;(Q2{99J5l^ANpt%P9Hfr4u1ReD=lh$Kz;Jd-k4{}u z3}&XlCBEzg;TYsZw|IGki}o>=AMyxHxtzpk%|i}Om1C?6Nv&xXoymWU#Q$w<+G75y^Tuisjs-x`YBO4@oHS!olGa4xH8s$ePewK$^;O?4WNurL$cz>*2e!KG1u# zB!u@n{?$C#;n_43I3haQf?i|Ooz-(gCh7%^&TceVB`KDRhJBgim;HJNSqCwv)>K+C zCX;u|Ba2{_dsyq9JDzW<_EyoVXtzcNF?<>=51|HJj;m)56Y6>5`ty%0i4ZRLgs-O` zwE`WdOS_BQdr2!g;?iqVL8+?)OMlL{p*SpNh#}g{aF=w+ugo@by6Ue}&A(1z3JNn( z<*Z9H_Qs3EFR@Iv*Gs_nF%%q$naC3l4q7O@{7o$TJb}E${-a(u<_`HwV6GJ3wTnCX zeRpK9Eo&SG^`H%$BwKkO!kjmLkSf0z*W(P#jP2FzjfwIjFkdc-yD)=^*HeKSM7bTv zq$y!o>FCD_*s&VKPB-k)x@r2N0dyG|JfbMo_INeevij z8MDd+^!KUWqJZ=266i?(U@tUiSM0D17&&YqOCs<_K!%?&qzfSL!7#KB{W-vg>#_rV zRV(PouZYo01Z|tSLH7CNPHwWS*oPJEI083XNYe)8ST)q?q>?Fx@?V($2=uG-s3xM; zjh19*_u?FxYhA&5naTtjB(X6%#@3sIj?~vb+jNvaZy`TD-4#;dU^Q(Y#5Wg|>9Y^F zRT}b@?;@4;%&6wu>`8wUcPzIzXbeua;i9Z)G@B)@2s7%XiOcj>l=L}1i)xd~85L-{ z+!n0*4)Ca!zO=+!ZbXzjks>&G&pZeE!&>~tJau3{i0U%F_AdPV=(F|kTRAgNe}b(k z>=r>P#@Fd@kSeL@+S~Ot-yQ6%R)_pivkuw&Lh^HSVVF%*pkC5c!{W(Lw}kS@Z^{RF zEDy}hTQWiHMv|!DOBQx>{pn78#+h1Up?exmL;VDtqFqIbVWy+s8b^-ujpP1gzt%6M zhm|m-gF|o%RN?&+Mmh+KB;YDL?wTH2 z6X8`YTv)O?3U)G~@x<-jO!j<(^45vD=U=gQ5dHWa##!(7`-0h7w4BCgzl~VAZrAM6 zo9a(*3#+9U)R(Ikit=9}sMze;Ea9M47paW)sH1+)cr!CM5E$a^`y4_8@%RegN~quP^0kr8*Q_&t zi+b+1_mo?pm*YXhtpAc179lnuxhL5#so(;yr9zjcQ;u*~DiTY|2 zG1uad`#HhH^c#F?B8$u(e9qlsIyWFRi3BwCl^iLBO)9-z7`CbDl3D^{v#+iJ zAM=IZbeK2BGjt0;FTuG(s@p3%RGn&;;iWZ)OU=LCzsz&A(=nJ3WPC~5GuVqaY3B-U zAln9c?t-Mc$lmiLas|2kgB+WA0HhH7VCWWRxPU+Xuxu$klSdcT_ON8_NzSHtUuV>m z{v$Wi-SE25e{qffF9Y2FW>?F9(j~A=qw5J9TVjbN4KzaXrm)*|zb*sT=hM`dvdzrDHnXGO(t6@Q*OWqEWDny+b2 zG61yK8R9xXJ4@j;!$CPsqHbKk0;*91g(OoTvqE14Ee!Q5mw@`EuV`p|_V+T)EBTs^ zz5O-4gV*Q|pflNJ_hE|VNnvNNP zFni2DKtF(O(?8`HoM}uiZRQVPCf$={mK>>|hY-I`JzHTOU=}f0HO2_xZzIT7TR3@Y z?*`-VA^!hQjqI5{+&*xCM!5e#Hw<@pg2+I1=ozx?RO7FyC$mfc$SkdnU&>b&Dn6I*vuo{_mAb0d)NGGgkqc`V_`+Ph zur0IEhnC|I>Jo?*kTY~30fC>l@)i?`90l?KR?#D2#tcpn(*~^xJXc5cG-i?o@Dk#e z0sCkXK>o#w)8Wh%RybhD2*ROvY;}(c4VjT^=!Ljnr?y9cB%DrPu@l}Z43MZY2;eLC zNkHJB36*dnc%1-jzTJTW!ijg7J*})0mI&6iyyJ}UD%e`#8E4@pXDCe-lpa7jm{k^f`n@9*qYs=OM% zORA^xZDqPN`-{9({5`9$b5XgL4~X$Ym3NSw`0jh8dXR)xFjeM$A9K4m><=m3D z)?dvgSZ)vnQ->ujuO1OLffsT1^*EE2ah)DXGrLD8RM4ADs9MR_o0VCIS*%yDA56-7 zsG6+(Jc`n~K}bDcHzwLXag!AxS140q+mul z#j>u`mNz=gss&vUhAc12mJ)Cqh$n9LA^N7~EA#>QO?1tTe}HNW>x~&#YlbPf4!JX- z)-;x$YRitMc9n*SKyl!(S~#}1xnra%i$@Ggc>wERJUre^i}>0T6Sf~W zhPm2zNeM(2CzL1T^I4dtmX=G*O8Om+hOEd0Q7X3cF8^nl?M}0~c%u?XVJ(B~us91@K&WYS8**Bq$$3DzH zVZM`>q1p=&Rs@7IkV6p1L)&c_*~-XaUk%F84jYt%6Eh?+kr9fQPT_WG_Q?L@P0?PwC3Dov zp~D2zM1Rs|cKnb3@6l2YkrVhCUye93O0Asp$ePRveDgkTw8q=(*1H!DI)^3?>t4Hg zab4|wVc+5kk008RCP;SZC=y*!8@J(6Nz3J(R(YPmC=bqj{gAhbm8O@>f*;s_;2cWs z86BXa+QLQq)kClIx68H_^Jqw_dze+jh*H-2_pf?LS?t;t-bZ(d{f+Ct)_DnZ1t)ia ztR~A{4u(Nt5_(s>A5A^ULT`6%qvi_%@|L1RlzOXR(fi@cm9JO5yDIQws+KN6n*7H_RR_hLzYLbpp9R<9B9xuctt?IQK z(^=T*9GFLdovTsh!1onBC}dZDdusR~IFx~z1WRVr26ZbRyrt_09XCqJy`P_2L_5O( zz2yj6hCmHa$?szDo}}-cOHRh(0fleeb^n3LMp-$AM2RtyPkol(YImLZNKfQ`_itx7 z0Z?u%VMslK=K%X>N1rS$=H{EULyg`ohy=}4ZcXE1tF*;UnZy1h{^JSwH#FbgiE_B) zzrS>rU7(Ji@3J-)+XONk)(l!28|bIKU6g=0(>;#30L-Yn`LbgzBj(!#}(_X%AC_SZ9B?}c5DJ$i3>xQ(_I6zh?aO4cQ1 zb=zxwR#E|sNiV?mF3779Hnxd)jn8>*)5Y%$xjOMcIi6i^8L z{UqeQrft2Io}K~L_@qF;uE_-ZuQ(CHHAaEd$tB3ke=4j015WhcUJc6h2V69CHGIc> zBhMx$Fmt>hoRozcEvyeGv`aP9jCx~aw5}t9hu$TM_B2-4*2kLX_VNcbmA#o(&))ES zm33=?x9q)R47L>$*`Cp8}7y3UsiJHZZM7$I7}HIl8_%S+|DTdWC!Dq5^eQ z25YmE>TMca606o)O*-#;@aX%Mx6=H+hQoe@9s?1>%_vqTMxbY&?i%0?C~*L(Om_%y z=Z&fWcH6FeIP(d3iym!-J`%D37RrdDcl6NRvcdqaS4^ZmXY%C>{5n-21ELAj(7Q&C z1nP<uKx!$lch^m*F#JBYKGk{?~2!l%aM z{$yk0VLD*Q$;eMnD?uBZ{zlDgd3MpF$U!1~wOge~e8I1(^6X+&1?=dvVhNZO+#msG z1mHkF^P9a{>k|A-dz@;gbMG{3Pm@S;5;oi(whWbYdA@H}>dx2y)H!>?2mjKrHf10W(v!W3l8t9JW4<99R0cb(@m~nDn_x1n(s#~2`U7fQ_9&R1y z66{iB5$u#TugzYV0GX#xc3|tK2a@tCyZ>1`p4PJUiwsHqla{9~%6r;roLRaiuqLbk z0Ovq8@_)1<4;`uff7tv<1fZ4>?+v7RLp)IPCb)_{_Db?(1Rq{yzxTpMd)ftGo6~(E zVb?sqpo1Svz&6KnTf;fs(wA;#sN1vzeP|Urxpmu|J^^%W&q0V{?8)VUruW<}PD;I8 zsN+E|7OrEA+!LKf1?f4s3(ZZhH58ycjv7cC%J_p+-(1|GuydBHF0-QEcq$7slajDW znUjLOxP>9QyS4sMlca`SkvIc;v%;~t?dGj-v>f49?bv;hBg3x8h`MI0>=zo zg_{93KtMV$pN`)7KTcy4{J)(=y8rDcYVW}5AS>VhP|VppLdPEBEC%2yWJqhIRvCE+ ze}Rq)yW|jD|0*Z$6+8fztYA@?Oqh)q=^D6_xn`*(JKI!4 zP#o+(SL8RjrKkO3BSz~a>AvI=tCQ@{vc!Sa`kS(+!c}ar;g31()`9RJnNT+nfR#2v zcjL|#$zLNFGrE==XS-3iNcSgE*Xn1QMcFE*z(zQ$y{DGN?F5CSfZ%)pLy^PHrAzMaR&v5@rRwfy<+xnYqi2>*#6hXNe-TX5&L#*7ixv5Hgj_ z3i>euMc~2+YRYyaIDK&yp2#WcB;uaxH zYhsTwekO~Ap;&zH(eey$2n{ig_}58qh-&pq=|}!a&zL zu<_>u3;&T{hG)x>=i*rH&HqaRD$8aqRl#U6)H3&+HZ*L4Y(uP z!LuOM7ip%H;sux=m z6;!6hRHjHZ*{y#Cd@B1S{wv+H`}RNSo|%qJ>Ds)+1OF`T{~7N&=AZAExhAk!CM>@Q z;3faieXYJn&k(tQf1ENE(n9jCAgWFn9;@DNSPo<=wwO735sO=4QCorQl4#VafqNM1Cnt3PG_H%6w@ zPZ`kZbjz1tN?5t)W#!I?PJJwWGrrR*yOR zna^3r>VPeu1OWUGY1@HuAK2~5TD1}ARABxefs&bkIpOCByb%xjeFeY=yWJtAm+)=_ z9Q2GW07K#g=Kce95Oe_k%~=8{i4cV!I9woJ0w3i9kr|DEkJ1if*Ac6j1pE7Vc+Ul8 zFUQ;r*afG;+Y=J1S{?B;GTi!%Qz`&*X8d%1+{vRlTdepV_RX-6v1VDu#Asv3g7}c+ z+YyTye=#r4Yw8{9UX~bobJ>g1KNPUfL+<*eKcwFcwT zS8lL$2T#UwWLBLkM(iz>SupG8HFm5qyZE1T;?rVfm#@JrdLrn?v(+a$B#PavuOl{; z(gT|&p1-S))J?F=$y+ylsp}6;o-nvSD3(07J8<#WFkV)A5&AXMLi(LA7nP2EbZ zz;@BCTUg_^QL?c%Z-mx_DXi>Kx-fl7x)PJJRw~s;Wl52*|74@ydG%N1t$?OdK&4;8 z_fOE=e`X8%YW)Au+H>Ws0)Vwl;DZG)O>+M-4}ANfFSHy#KuQ$)LoquKXmNZIhjQoo zkTo%41$ofx<{ygbTbCeSh=qz?P=jE+D#-PtM9&_mKVemm(`H(*ZCY;l2Y-!?_UHO0 zEeBm)P5^BY2P$-4BmchqTDz>!#Y`IcEm}yewI%xJVujGbfnv3&VCW*M*!x@S-80jl zwgCmsq@aACXyQZp!G?Jz>BW4?JWWonNy_9t{aPzreVc`jX%UNLvID!Yu>5?3W)~nP zIYR-GpK-vhOJ=bi0P-cPfvwS26sS>SmLPFM$bXZ8>pKyGx47Wx6b43bUErUM5AdGt z4uA@K#M=!eT6us-DeL2 z+MnWWjL)twvHJ0O?QY?NeJs9ov5aArtM!isu>!c+;ESKgO74cLj0 z-cF`=1{aqM95=^__Un4Cmkhgw!-wM19j~CpPlZK(iyCH6BTY*$L>}~!T}Z$2bWAu! zP->e*ie#z>b2r$cr$aB!rxnuj)jy2KO;25g)33YC<=4=0h&-G&rzOZbU~LHzel@$b zg;i#5$wo(h*gL>Ow9EHu(%9UcTpk7PTrE`pvjQ8S`G;lF;KgL4!8qdBC8`hGNF%@s zimU|y8P3?^r0%D}s_p^!?|DYGYRyUkKpScF%2~g5a!X6m!TQqJj9}6FHmtVxU9z)w zMUi?U+v}iUJ|}hV@2|84=C$ow(scuu5}4zA4Z9t7aP@Kynzv$sg3b6^qj{!Eqv$HL zYJ~}=t$yQ-%?y{5oA}1AKwvslWhbc+;jZ;HJU8(cv0#x{shHQB%J;H!`F{S)Nyq8B z6j@p2X_viOd-LPRTk>e^`wzqrCYCAJ$+ABbFCS?9p}23?i83L}fpu{t&3M(jgk|oh zWl9#SJd!w7fxOCn5s&+$gy0lqVJjiE81N&Zi88i+Cgfy{vQP9KHq;u>D{4nzB(nh0 zHNqW-e9UCnO`a6|zMc{$3m8<_5(jI0PHv}(_F1RJvr@t<{cc=2)W6#s8a7Ms0{ix} zXJB}){}3wDPzj%?*xg@|IHKFE!2Yf_I#!C~z{syIc3Ce?UOeen4p#9_v^Xx1dHJ>Q zVrfjce7VaE2U;lpFCoEyK_Qp^`Q@eAFbEI;aMA?=gk8YYZy;}W)NuvS;Q_e|b2dPR zbz4^vB|u6IO7tR*{~CiF*(E@{JuaFcqyBhfbl2*I=6}sR|E_o=8L~3BKaUH~zX zSp7u?=u+V>-nWOJeYRe;!MCQ8u2tInt+;ZF<*?U+W^QGnYVZC5ItjKG69BW3=u@}D z%2bKKf0V^{Kg9|HH>aZpfh>;BuwN(ma5)i;ztq zK@fxiQArTHNEW+@?2ua3z3-gu9fRQMV659#5M}dj*yQ2+28OOwzuvDe655zO+NZgr z`cz}0Mhm;x*Lo~*)wi0iZyMi_mF}gbDw>xjqoP`-9J?>Fn zgy?*+>o~(WFdu|G;TV>JuhQw!aluKm$FZLfa8${yRz;FLjxqsY2Yz}Z$ zPubh=PK&ck&{VYw#PR!{Gd=#&ghY>umEM z_Bhh0AJR$WS0q9uOpYa}K1>*n`KE+6WHa8Qh$A{q()L$-(fKMUCE&iC_mQNv4N3J|lW499JH##hq}S;0FDd9}ZCAN_K;t}@ z9iUA(TaUDl#n}#S!=Eziv)ub2zbcKqNk))61oMwS2Ym*&*HTbI$3{R7(!$YtWljm? zO{h)oZk;FU-ZNLPTEW=$d8aPdib(Zrb|y&?D?W9HHu^VTc@xP=nWn2kgZ9$;(sq;P z9_zWp1Fw79_Z6EacPBr>gUR(vmk3U2X&uxnXl}P;PCY_JbcYgdR3($yyq>_5=2BxV zjdT&AVSV$Oy8TMzC_q*ey&VAqc&j->#XwB2MGuDbLS!iOQ$W%t+!ni|Nv{?I#D{K9 z)`IX;(axWK=lEBpE3T#BvKTDOG*Y#Gn!$diO#LI-s!RPxvQ<+Wc|$JJQ+Cp=;>Apg zT%$pW#;8Eek%30hC}@q7fWq$0b{ixkSR$C0)n!=`w<7q7J6{we7rhQk5Zye2(_qNm zAv?3&9=8p#A?om5f9R&TMRKZRw$ofRhws1>pSNF|8!hvgc0_GRaNbiv?pPSuOXeou z)Q7ezVqnqMc(rl}pg0iBwFn;i?}z!{71rMPpAX@sudr1d>&s4dS5|vbAkfnLChSW0 z@twTGUVB*r%NuMs?RP$Jnc%a!)?g|d~2UR`nQ*vX7yPqlLpLFLDyn>9Yu$+ zB{3z&pRL@pGq*JSLz-H)fy}44?#Y09xlKUGfJ54s3O{fQcTr&5TZgMaTQx~s>UdVH zd`2})^jM`eY8BIW(=pVtBNS=5Z5`Bwp?XYER7l|Onv~lIxwE7PN0=i@ddi7@KI{It z!O>4!vycX#iYTQ{N8=*V1kNGJn@BL9;LUYdbl%DH&t+U(e5l}Q|GHZ5>N+PyvOfZr zma~FYW|y{#y|;CgpkdTyG`}`pzx=%`+-53y8z*G#loih9Gv2!e9_N|oxFS6q+`KP~&}}6* zihg3<(fd4EC9(e zg2LVDU@;v><2>wn>`v=;sL%6QG5!s{n}(A!~- zSmv`KUGlYqI71c+U#{ zd$L{dC$(6P6rH2;bD(`?%r8PmY^XVe&E2m$zE+n`N93T|x>VRC(auS!txrN8vvGI~ zNS~ts?9;_Nio>~n1v4jqA36`h)h*-;b=dH6WW{yCsg^X>1wOV-BhD4fh*5lxZhGDe zyR!!KH%#cju39ETpCOKEneZOUBO3;cz2a8l&|ibt$>>AyBWtvnTU`iD_BgX%0d>9h z$Rfh&bSWGsZxflk>BKVP8`5XqRPw5HCddE8CEf#8C0};$qB9%bZ!wUT24_LLr6mA* z_&!2oe+VKq430|xx+2V{XpA1XxzVoGk2l##Pv4nrQlZpMNak=(DO<4KIyUk;c*meE zmJZijW7n{I^F+w0-JXN(F%P#j6E<*7kT6|stT$Hco@Slpu49t%V~!8aG$KRe?3P%a zGGLJvrfw0eZ?4Uc@1{3TQTDM`yR9Q-a}NVTX|4X(W%|D%hW<&`=!AZM1SxY%RL3-tR!uTNd7l3HTe68{)MtvFkJI zY`=go_n+GD+9ID>-6^_R;+$&fl#;FWGbNW#!`xit0qUCxuxPpc6W6bj7j6RCnE6aa zv_AUqJx|VuSfFB^Da97@dqd+h)oPUJ(49y({`Nds zt;N^nBBPTP#_yx66xIAqR|+Z=*jkFO0)S8R`}81B9yHCf-)%_=itxWs`A+S(X!ezd z4)RXd{S!)}hNRtOAtE5|~{Ldz?-KlqdRDMa^q<3c)HI8ChCx0)su0}S1^OvHkmlm z3w-F!H~4b(ET3buxU_g%iSv%@Mv*12di)31)3bCM%G6|P&HV~>rk#|V1(h>05delj zlXPwZAOA=KBq2SXxMi}LIdsknaY0Q$5Dfq};*Dw=S)gPS2y)Xr?4~1G+TQy^fsq6# zNc9UOdh!ApirVNF{k_1i)jV$pC5*f+oeod#A!V;G1OFgFh5W)G_GO_2A{S zPWmttBH-8q{J9d?*_5y=7oU%T7^+*DIu1@I{{8FhLS!1RBiZ8 zn|px7yL3e_g!=bk?OF?>Z=Sg~!d0A+RCj?a68}R{9l?g5jkau?Nl z3HPuivgOHoSeNqao*Trk<(T&9rk9FL4$5#C{|u|MFSpXoE3IlSlXC_5VCWj>#U^>C zn#8EmEnFVE#O@`|pL*l3l=Y(E!l$upPmK?B#Zv##IGG0pJ*j-xc>9u^Vf6MG(^j{c zi0Quo&JCq8PmSBrcMHmdwJZCj^ah*KJztTY0s;>w_)0@#m~(#baszx9fphzd_~2@e zvS1$~Ntu6GU7^qIy)z)|>mt*kUuCTlJvghoYIY({7?nB6gk;G#2g zaBr}_26RspKgBAh#mHzO*9r_?uai{Xc6G}!;n`=P@x#7vUTpl*)1^zOED-!PL~0ms zJWs*@`cy$I={aLfXvz({5bd>=&#l|aaO4R@RL?!Aw9<`=1P^<}FH-_REFu0W);>r| z*i^I&>ynI)Hfd6mrz;Vk8mnSB3Ji0V${qW$$x ze{OTnkIgbXw+g-J2c~Nl`~p014LZ$h!Z!1vW@h46y=liHcuJBOdcJxkC}!z;dn1&4 ztB7w3JKwJ)i@1I>42pc{qgI%GVxGsK9I1yp=;U=rjM#)7sv)=T`6 zOPy+!_v^e$m8jY=Ke$B+dCmORwK|Q&s;NS4c%q*lJjvzatq+=RMNu~v78K*xcHmSX z^Tvq_0>tkA{PJur0wmt8F=p(MLl;|KvnFbT3q`nu(O%@pjzTpjNe+ZN;^k?^srN@k zyT`TV(!&$~=Ao{2hLNhfPqfTkpL;sB9;`@x9yw^jcu<}wM1s^wt@1b93UlEY*AEI;5rdm!EqGv<|BT2mw-)J z{dS}$h~>!&>6UEaSma^S)A;+l6g#W=k8ttBC{7)lQ2Gz)!Q|9FpN;YTSkWH7QE9|Y zznbTn_g;=|`qap9yva{0+vCkcI=TyYT4+!EZDh5J&k>JkR{LtUGaJDykTl=#&(^}s zZ7fu>X=xQqe!@5%iic2R?{Y-Ya&Hn=p>qhVOR^ZhvU3_`^pR#l-mn=SmlXOeP|ZPs zL+8V!_@3@_H*=xdx@XDEk;jWIX9U>f<}}uubwva)z&bH0n#dFi>t4&l@0x??ZVufV zhb31@TX{)Pt*?sIm+9V0D3rxM zX_!e{|4FK#q>K=^_c-( zk^%f|%5R_Rv1|BvNfj#jf2*Z}C7QWCJbxHVOcKY{D)#}UIPwgvyB$K3_Q#;_cKDVa_?3X-ydAEzD9&Pqgm zd3u4GhBQQ=$mg-W=Ma~pDqt%4xv_C_+U_vCjbKGPqi)9F?cd-R9*_s7kM^0ufh*21 z-*o1PGgOb~o;dm7U>nwaOYN6j>cZ}p&_T9R`D@MR=~pBvk0e+lQWgbDx^gw+*e?$@ zhMgynOVUO})`Qm_A5v!;4-tqX&H|ss2Bi8;Qoz#1RMm4Dh3?bLU|A7CYYdinr5}7c z98VxQO%KDkc9Mf&m<@8p$`S2zXD-xzcWhVLdF?ew&)XL;!P5H&jhP9!4;cN%- z;W3=T_@;X;b)bJ?xgUb%30ocnYE!m>|;p43UqC>@~d z195ETi5If3pKTxh?MTh3s=LktDS6W_j%8uQG`ik7g#CR z*|J^V4?6-7aQ(P#fd5(hUHw!_G4bfx0-Rf?Sx{mz z-NkYI-kL>bb*Q^r$r}l4NL$)JzUOWr+iUzOR-i?o6fcwEQyi1&Ho$CinwAOQ`0bztMgwNi)LK~ZMdH_ZN zPWfya-1A&Evl;KbT-;7zB)&?@%5p zj$Ju*hFh+i7V^g#!Io?N`6)TWpKb}%g~>KbuwY}!v)Ky0Y%A@|P}C6m_Q17W&#|gd z3;x(+7B3x(WAmxQff!l ziJ8nBB9<5rk(srakX!Ab+`O2W^(=U3xx4&h()2L;U#~|r{=7cw#dJ4a^kYM zIj<%oyLhjoN5MUpl7|T27aJvern(&ucFlROq;yYf1EsY1W|xQbYVY;xLd+Z#bw;cE z=9-=1&R8kSut3&ZDcxoy=&zhh>CY>9GnJyi=Q zoidQ0>^@0?_CZ;o*G*%!(~XN0F;(L!Vd}PO0g`i0R8{uFMVW#(&HATx=O;>(0Ly}Y zp?f`&stF5eUL*SAsj(LYx2j=5*yEJv15Tf3lW24O#U>tIp=aJmC~t4ebLgSxsuj>$ z<+C`>GNA3awnD>w(|J+l3%e?Z{W^%TFHNj>x>i|RyGn74zcvA7-7wy)UsEMNlUE8? z=t&}(;5yXJUXBt`Qnk#Z=BW>l<|QlGKiQXq1S){J$lJ7FtI~U2PoW$BYU%#ut-iRJ z4(3WreLF@oe7dF86``w*nn;+Jt}kEZGup1T*9<138n#sPtuZ_|d}k~PiaabUBN3NB z72L`5DezGg`iN8zHW`6=m2;a`QyS^$1h@+++r@PKT@nc>=TP0i3RJiSRoEFIiMrP5mQBOMuMwX0 zpAy0bCgoTXcw@C6Tjfn`D`IUb(|vzx98Y+WFA)~HxHO~ZiWpgQa31Tnf(29624ekB zO;tZd_D!TUA+w#O%cx$so4r8UP$yLAC;OTf+l5jArF!e+S|CpNBRDh?^^jE~n@)AO z7dxtSAJ2mYRz&6EYYlA;4wj+w}|jnY6MMF z(cK)aZvh)`)q))70zev##Ew@K~8^Sx*Uy?n^_R0mdm%7yC@X-5nF8 zPFP3t9U%qQ^PpQWG>*riH~9J$Rzy|X1|rkHD}OC1nJ*8)lL&Mo z!2{PfzH2=gYX)=ne>1Ykug)1`n`RT0-!PZuSLZ|V8}-SBqDrwee#32PA}C?M$)YF( zk9=l5hx`&l?WQAxuDzRs`;5`}`RIKWL<@Y zS25o>4cWH#DlXYpIMb+g3Mk+HXtp<#kKCI5rtJ~xP-%(buU*SpYZ}V1`C+}-$H#hG zCy7tGpYX9-_{#YZV~iz$<7vFu)&M#=<%Gr;K)$0{e0`v2@bfS1sb=rxah5XW8s9vT|PJ=vV1(zMSOW&>>csS#3< zTKp|-x|n#QIc;ocXq))m*mdd!P+W*hl$gZcuiGk}C7!`-m(*qnE{RI>W5i+ULZw4& z!>`8`G?T_jska6#eBIjGFq|gLiU2RABSubN39DZ#P>M`m9kyW~O{>duJA4{!$IrJr zRT7(WV^F0u4`S(YIJuLyqD!XbBF+Mn5m88^dZkc#12fTiB}^6%?QyY0gf|kCOmz3- zi~ed$-eYS|A~WjUSNnXa&^VlO==52tI%)@V-LLiK$~FwyKP?j$D9Tk=E8(cub4^3y z9JSq8O}pKE>`D$JaB|g$sVmb5#X@6>V-AiR)_bQsMnhqfIfeH@F=l6jc+IoF0qBOK zQ(>M2NFO5oBgQz;3o%Qr_>*oF-m&)^Yp}TNg(lW%m}sLF`Ab9a#mN#)Grq3vMi9hh zdS%HRD#b|5?;WYKGT_*FajN9zC`B#v?${*OfjPbs_fhC+S$x@~wb#5AVq%dw)soCH zEI1mB-MrAL`n>2A9WiwCbSSaRWWob^76rW?ZbXhi+ty2$L}K9KTM7p&pJR>4(>LNr>nhU4VJWbYU7hVAIe1gzL+;p zYi_7Wh&jW|4=m_5ps4r#2|Q>MRkr^C-LD)ikZ%$IqfiJDSY57B6YT(GD@pYlF=Yi3 z7r}wANG-=x0c(VZBhDtFxz-+|Hhy%WW+(UCPWjgrPX`Z_+ndMFUPBN{hUhz}F~x!2 z0#uYQ@%bm#$i7t%oMaL^d06?TafL{;YnPr`0aSKPqr}|2;ZSuT4kp9h3)A^N#8#ln zktMQE3&0z##=aF)z;%>lo`}49Y+ImjE%tQ^@I+gM2a-FYtfbB(#zktNY-$I@nkD6UbMIadlyu z_~TX_>|O`6XWfE)T$!74R$Z2-YWc^t!u$`@`yj*AzS`+oWxbWxQ6E6x6lGE*JKW+1 zo_>JQ*i&UwHH**!j<=j&2*3VKK($Xok>;=!n$2+EZR#u1po z-2ul2F^gfHD?AxC!Kpp?617a5ecV4Iqi7AN;X!vj&WSSRfvYEv+y!ZY}+L^$?KIwAB9||$B#8FQI zdea|($G;T+q4-KkQfVYpsROt=P?ZUw&B}nZPoxs~{(`zdzxCFZiPsFsmY|(DM)MpL~zOATGom> zde~Uol%}^R5lr3H#JzE49ms3M1+NFn>cnr7C)Gfx3L9s#S$44Nd{ zDY~uIA1I`#-hrLtG^zrY}$3$e<&^^ zg>?x^R9jO2x{vAp0o)_O@F7{qGw*XjfOj~{CB8?;cW49Y2OIGKLm&@2OZl6eyMj3t zkcOXM&mk98MP$wPAoStDk;I!B5QR4O2Jnt#s!QiuBq^fJxo(&i-r!}JAP!115A*My zzjusa$tkt54^zR%BK>cb`nyePA?1t1gI-|E{G5u^Zd|=|0R_IwYd+;JU8e#N&>J9v zZA6{w02N=&{xOT6%UPhnHZRY@F#2heHD3gEUxzN@2`ovb8!H3Wqfy~#0%CA7gP)Ye zmdIz}mKrjP&KnOm$UJkvU%U(0J)e5ksN^0fNt-1;|P%^mh;tPz=F40>Y$&sx)F;7{K^ETCxL9wkhDrd_`{aRk)z_ zMG%>QbDlGcUa3If4KWNhqn^l!IZzXg;iC7UMiPP34p2L2#VVNQ_XKg6j^8o%d7~9y zdss<(#r!vnG0Ig=$Y)G{zWH+Sy<(wNT5tSdnqFd zDiD^mY7oDCyOYmd(2|(2ie`tMSnz+}E|Mi^wBiaMHN}bdpWAkJwhzCiMkt7dtaqkS zM|Q0^?BXpSi!&fd=iT4R;$rhdGmCGKDN~?~34OW<#&}db;&8UwxCV_ENzWkZ%YRJ% z&ynr_W>zC@p;j2rO8?_!PVtUz7C4uJ6(lBccyz`VJFxexrZ`2ALe}OW|objT^i5WQU47; z*dc-FPW65h&L|BDI?1Wo+-bWA9$+?PY8FIMCH&hJD=2k+91zkeVH1Z*R97_KM@JkJ^LTfps zsS#2K*erpHodQQieQ{~+@&vcsf8<|8CE!790lGq+fSOt0{B^wV=qtiWAyi1+IRU_;N#FCi0x{tCL=WhC1ZX?tMV@ym*sKhcxXgH` z&5F0ffRpqfa?%u`-x>L^g?gC=76GAy$>S8WZlmMCGjy^I!-AxS3+WDE9*ZCS9lhGg z-~F^C5lcd_wJF31>UEp)_mJd_TWE_!>5P@9iu2d~Mh@rw@-s92_0@;SvLn-C zzP7;J1e^_xw}KMIYL?l{2@1Q2b3tOBmg?;X{9_3O7u;Ba-?$#Z+BNqb8V`@!UvYww zIr_K%ktfh{4(#%bjSfUcHxSVm3un~f*NVTq9tv|Jw%#QrieVN{c#(CRT_lg zifu&_w(qpaBG&?y>!LW)U@7bbvo&X7LO!I9>aD7;s+TS(Q&R8i<11WH1)jY)Q5YjR zsWl0WPX!!3zV-%Zh==4Tci<|kgdb=E8Q11lQqY@2KCNW_+}1x7$`8q0wJQc^;!6O1 z+I=5TWv=ysw!`VpZdC&p1#o{3QvUZ(7<}=jcXKNyM%j%!=GHN4&IG936MRA6u~o5z zacz{o+{N+WM&REgO!XA6WuUi=!C8XT%jte8$7r!U^w_|8+G}UyF+Z^!#X_NPMIM=J zbD5hO`o1M%fwZY2rX}+4H#oeiBQuh1(?4l{0?kyA7#ne{Br)h5CHB_O+3Vq&-Sc`I zFXi}Mf;oP4uvac_&Od&N*>2x4s8Ijy6c{1!3SItsmg5aKW?-Bxz~%>L zX&VMupJ2Xv6UAI!jl}`h9MOJ!ukqvnoc7+mjSPp&p5EQo%@-+K3@`lhREx1wq9+*? z8O`75vT*a@w`X$c6P?_G8_Fi>@KZh{VjH!ayDC>eWbEhSG_NWWjqLcl&!WVj=vTHu zAGj_@W%$nB?+Rfti(6xp-blb5Pp9>Q1TKc1un zDAqnNr=-mJ_S=BbX64BnC8aNabutuVQc!l)RZL12nLFCR%LRYK6e^Q{+~hks2xeMI zy;^KH(Mwq7x(H>|gPas(L>+9uEwB@)YfAMm@L3D}RJvK_(KNe_Au(0sBuJv@xhpv6 z8^{|ZY~x%IJCl3pd5FdebVB#ODn~B4MDKPyJV@RENzQ%jM8wyFEQab?0<*jxgTpRL zKOX_lPl@3l3TcQ-4xp<-p>;5{7tM5@Ie6%C1;|--U!ei8_DcGZ`%#TX$6-dvU&A+= zFJ>`AaB&1>hahW8CqMCFPmWRWj6%r!#ciY8fx6{euZOFkU3VzfzHhw>^Y1Ir zj`FEU8ahZA5YLFrQnrefE))ACUb(f!u9hvss^(Rcs002aL$r9+pcAIscS@_5uwDe> zPD|=56R0q`85i@|Sz06%36xz_^Mp_4$ZwMDJ32m1iU0E6|K-y0xueJ?|I?>jdyl02 zgn~iY!_hk~=~mpiKYk?1Fldj$Q`kD}MJ4;5`hMTl3v-rXx33dqPVAj7e6GPuZ|zlP zJzX^gC{&sS0pnFc0pJ=6f{Z^`<%wm8;Sy&_0jqM-=`*<+mfV;u)5ub+1mao>7yt_r zAi)*}ypo_&MEz_M>Ii+!qmu*O7WxKzPv@K4s3=QlxP)aa&hmK_ea5ZNKT;0AP)nr< z9F1Jlq;V z&PF=Z5r@DU@&n-TI~aFBi4iK3WDb~u2_ayuDJVzY;oggU0S8X|?VORjt<6>~jq3DN zCkoG_e41Jc-`Gt93yC?gY#z&o-`eDvfsAr#&`gBXX$E>*_k0)Nd-QAli;(Zw46c8kxIvNz< zFL(}Hf#>H|OgQ#G9_BP*)lJMc(=qWYc{way14Oveu{JA$_34-sYnjJ!1jXDx6cIDJ z=bTqo&~Y%ZtdIdOY&%gzPRepILKT)c8s09Vn8zeMc--@?1aM5}><*XNh5bz&hp*Dz zR{Z>N;>i@rB3LPw&9QwpfHSKl^5L}(qb_SZWh}IsHzA$KtY$G6&LQ1l0fG&u z;z(o<&cvb0^)R#Kx-Fv;1ID6t#kbf>(<~Ylkr%>pHr$B=6ESQ?75Xg<2tHHCujHWq zumD^M&p8%q_65EBDjfrW5eLmMe%-dkgwWZMAqvRab% z%~`v_ujRyVr6uy^^#jVkB9*T4Jm89guIYFIB}zy@5;zA)0_CdQw)4J|x7=hWwaaTJ zr)5v{0v=yP07243i!4j2z4j+kEiJTM)vWu8K;Ww@bniL zrzqQI;%XVOhz0cx;ue0Uo|+&Hh0uQb0cF$ay&ERU%q2`Yn{-|GZ9E{+2)a8> zRP~UU7u6Lv9)R3BUqbCOA|sqT+6oH-Xf1Eks>35-qA@*BNCNn?RAzN!1htbTQb=}o z#`imHwLWDI9RlpZ!FpchKlAiA$)<$6pPy^;5Il8$>HA`&rg%qRT%@v8_c&yuog6kN zj5cu@)RXfj{`__Q;+WcMoZnxmPJ!Cr7uR@?Rj5ieC-8nr9Y*<;@Hz+I<;YX)(3t_bN`%Ug=n_NXlm>U-LOOq|51mEt-f@v;y_W0GA!{!@5f2|-`hq7 zsii92W~Zyrmc!T?8Y=jXaP*G{hK-|T%0+d*&UErD1ztHt@jiV+TT zQw3e7oDUl9!|J}mf9=|#?S5OYcFDr^uJZD1~gQ;4tx+qP) zmcx-Zk9LW=_p4(9DIB4^n2+y-UHoq&At}~whsU__Ib6wFQsX<)6Bx$69YvJCP>0y5wc|rQ5u9@No z$nHXS(=}t?WN$HbDt+O7p=w@ST3pdzvl;ynHyZT3Ep(-Dh+7Lu>Qg9|?>2?@qcoQ< zNye)gW=cJuYuZ~#6(zRz0J#_{aqK?&RP0OMG#t1HuAUk`f3asiLs6q2d|ohLvobcd z<&3Hr92`0g_AI^t^|hN@h;!p?A2%#st*7G~6Zv@1h5g}T_C$)oEWEk`v&WPpjZjdK zZ*4!m?JN@lX9xIlTPCU_*$1 zj83q=jXpqE_!LMgT8=RSjWt-I3FG7vzJh0YZl#m$3HEok{*#vY_mX%RZ5C~ak;kVp$}HfNqlX zT3Yk8`6hvx_5trW$vj7D#5&Y@dLx#O$#Mb1H<7{#o#ae&DfmJ7_fExBL|(@ znsgi(`j?sMIxsHX0H0s?+$5aydqzuhnoErQ`e&e1wsQHJ%7Z?Zzn<+VyQc~ZTr8S# zsx<^n`!`kf$uIM3efqR`p51A9l7-z-IO z*z=r@pV{Afo3@4b_6oJ``U%(c){m2wWh#U#Q-P8}40Z4M=Je&v;B=ni<%$rt7(-ymt3M{K%VmsjPiwPkr>0+tRHh>nZDi&*3~6 zW70-%k#t#iF29z;4u7GuWERcG0$V#B5&OO8VYnZw26QYJne9%PgcrqLX2yo+v^3bk zjkyAT>-=CZTBGXZe1q%~>&foE`H4a+n|aYXYY{)ROk~cPzyO!8#+ye8Oh$KspQ=iI z`xBYz>HjtbeEepAn;BA2P?4qn@!+@oT9|G*@jQA?eyz>#^xm4UMe6{P_J@L_19YxL zVkQ<6Faxc^-dKYeGVM&56|zLX4K5V5vD)rhNm-;Wemomwzqh zHE~Tf)gTM!Uo&|r%i-=?`~c3)Ve6B>knr$wHGjbQN7<V`KZC>>` z5@@G6aS6;~zH%Bk^QOm}p~m-p+I|@N%0sa)Pa1Z`f_?sF z9cP{ef>rx7xoSJ|QhuIf=6jpNg>eKk-?kck=}+smi74~WnzilQqhscs&-WWJtBzoN@f!+{}TI|nJo_3r7SoS!9$ znMiNK)77%N+3ij?=j~Kc)(o@4k|d~gcR3KlcQ@11o_-dGe4r87GR2S5yvVgUlsdOM z^#H&;zl+F$y^V8G_azp5b8{te4&S}KfurooAC8M$bXWe-od2+nNV|Oyo&dxwoB$mR z-+{&Kz9^J&j%Z^sRd*dxx;P-X3=8O6-cGx1()*NOVz(pAF=_-?cPgx7QI?c!wpbBe zc{*>DS*B*0=wo|ycXr4(j_wad4g2FQW8Iza<^(q3`{M42^2j*9z$V|@CnlciW+}ph z2VE6pf908^YNEg8bcYJ=f3WwSVNI{!wx}JYMS2Gn5C~0rl`M4u0z#yPPDG?j2MJQL zq<5ruSk%ywUM13{hK_U+1f)qKEkKC(xAxxuv-f$VV$lu@V(PBi2q!UwnJm&{5wSrLbT9I+3kV zgDx5AFj=AV8SGs;9SY!@-BsX*?||G$F+o4{xsGW6%j|y))29ojv`dh(It;}MQ)PGb z%XIWYpKHsHF$B9O^Rw8o0Zr$_ByH)Dh4GL7<}<$I4_b?7@z)~6hpF%&sCv%xqDW5b zk6m@}TcISm!o{pAsOjvnQ~KVXhzRz^b-u%)C`+|CR(-FjVMd9;2ZuO<@mpHVnt%qFMrb+UziT5?AGX2ru8CU;>o(y@j~4;6F{uavphOIVa=Azn%stiH%kVq{7O4zPwD)4 zUeAqkPmsOQcr(m`+Q7+2peP5E3|sLhWwbSGnBdt==$8XZ%Y`N76QAo{pa4jWK;zrn ze4(8WoK(caR(7U`odaxK?R;+b;)fZ-FCg6`iM|39HiRnesXkl1vP>K=zk_&{N2O$% z0l8RHBu?$iYra-JHGBqwRWdo1rE2OWCRCo;Wcd%&a(a`x~S{Nf6L4;JMi zjRpW`z07zLQ$1Nv^#Y*R=FO*(M{~tSr=W1;uRq;ZFQb7MqQE>O{#L*uv@F2FSpl1O zllKC>=N5Qm|Le{r&o)5Z+yLxulI;V(uAb=B{JwH5MNmc3Apqu#9|Q0*-`+xw**{!L zb>;nf@#goH6B_Z$#|D?eHQ_4Rz^Dx{5uz-lqQesaI;(B(<~gtEpn@-QvmyuY^sJuH zL;^t?Booq9KS1;tYy$uGc{sVi3NyTLF}3mEB18Uz1^Hh%5dhH#-iNhZfGBDu(?g3$ z^u$HLpA%oVX}{-xA9u0M?Lg+lNQFjgPZz(Q)LM&t^NMcJ4&UB%G#2qDUi-WwTm@l7 z%`NGS&Dto2nRY1osX?n)CIAYn2Ja8qkeeF#!S$>U%!Z1wq}}lPMCQkC8}z#yQLb%w z$I?Rb)o2YpsXLPm946P<4RA|<^G@%_c)tB?LFgm$$Eu(A+JmSnOt7tutzk;hPFcS6 z_G0%kn4jAP+0PfIvRT_CD)8EB(50kAeRMiv1SY~v$L%V8sBNAB=IprUX(#jNx3Ujo z%~b?IuwrU8?#~JnHBUdYwRzjm7VD}NgB!}#UY6;&$6)1K1|Mefm%RD!ks_c8BoQc; zO%NyKV)WWpPnAxWIEe-utJ?`CX~)^`qZ*Lc{UNzi2CY-#`_*~|t+fOgS|FUn;!WQp ze7i%_=7D@cqCGmTGkrxI*~@$mSUNCZB_w;?X`MsNxw<`3;D%lG2t;bmTYeEs?kb_D z2DNM|W}Fz6LOFQ><+3LVI_@ZyN`7(RVn9;*{{n_}@8;13h}7i++e{9GO-oCv{JkK# zOy5oKC|0XTtwE7G1%o*G36tgJpn{;0KW@yC>be;!W^49fI$0oQ`)>@9^x)~9!) zJOGcQLe@UHhm#sj0TTbeUk&C@1jDZm3o-<*KTqMVI?n;gPS`dF306e28 zHbDFiZ&)YmVWNU=Zo$HY+D+ezQ@5jGZwt_Ow6V-+@rkMIEYXlTli+S*%JN5p_ zYdP{vE}EQIkUhG<93usW9loFG7$xhLDK>aiw%<&htT0MjFhG6i(d(Wn(@zjQ9FtB) z4JG?#)oFgc{0C?kB|W_`3Q>_F3AeOdZGhkXp`tulwVdQ%i-?CN{V}`3^!tk0hN%{| z3N*&{D^>fcWWJ>d)#bo#qt7C?Z0MjO;XWV32UsQVIxlQsE`iKNp6k4E-pqth#o18O z49I`=?7Tg)+by+$G72Xg9gbu&6_X$iQK(*%xjJNDitx$K5i1eurVKK!v5u*r*YyqB#=-D?gf#0=5 zq=+gwV9RS7VxdIdn!n;c05Ji>13q_It2^(Jp0!2I>J?GtP;|39mt@)8dmZ>HbK@W~ z{|l==+gT)^s9O%m?yo9~3PoaA(gCHeF8oZXG+yeY&bEFDOyz|OUNBc5mFeckK&qVNm4_Qi9nM)D7>NQo@ zXJ_JlM|gn{BVn9nw(s{1(e4Y+KbKj@+;l+RB?*@ipP95yJ4=rm%yVQklsW(XndjBC zsJGysdKL@tKk}C}LJ zl|D7OF|;PQbc>P+KVxQ4%fzYRq&8Kbn5Y9pHW00OLVsU5;wBuBX_O!TzB1B?R0e#B zvJgOr@oWY7We*C3JQ53R1-!Qz`d5#Hv96>Cqv*4f_gmfQU~U$o>LnlwxxGwA2mHQr z2Xq2oL^g{x?B)qy2wbS|t=a&}my)-umncZy=GjHlvkf48Yvj_kd-Ya}bvJZ>_1Kjs z&l))k+QU=>{5`IY1g#?vk;l)`GlBUj8y!F^vS4`G+<3CIl-&9_PvjEyg)k7&y2^tD zQ~__TJUZk~pmTv$ml@Ak)bnvy&5_-u8po?d^~1XXO$$2;z$xj6|01 zc#;-w^sg-Q4Fc9OP9SXZqejWSvN> zkXq1Z^lK$UK>ip1-e?P8+F-MCU05iIkKsjr8&~fi&pBhup({+6*du}N0kW*D%)knK zr-?ax?v zr_(Yr!p(@wmUJhk-?}bF)-19ju1B2;rjWv^?dXnTudU3H3GILNy<~$iD|w6CLP39; z0RLZ4b0E+M(>r6sFF}Yy07%OQj`(=%IfV2A%7FxgDQJAOEO0l?ALP*na{WM4E6XcO z{B7Zw_U;;a_vK-u@4lG0@^0ClhJPT^cWp5O6ep%`i*AmFMk?~W5OdOMG`S_;dyxROR~7#(14orzmA8XVJpUw>})>3vli)UgL`~)qiF)y>K%UJq>-xL(rl*wj!I@fSVOe3 zDe6Yaq>>4a0a?t7G&vVVG$w6!2!Fs|$PZxg=Bf!gB^(09k=ekW_uCCaM<`u*7`k%;cl0bb~@R1M=8FH(fEz zaGh}jN)r`hWy!R>Rx$Khq0K?p@No}LpbLGK1bv>@yI@^i?8=hhT;CV{kw+U+bGyeMengm+g^YnWkoZ z^NF|pYx{2f?6UCzY^|4rrni7*wt&JQ*{)mVzPtKOP4~gtT7+W#Nn_oJGo*42JY5%E zw%1xVQ>dpYpTGIk&>*W5^6;Mr^?3c=S1FIO*8fO!|_1cJi1|JmZ)zwU!?#^p9&X5lH;k5^I( zo!WBtF=@sAD#Xz1S&%!#ogc&LA`NC;ZY%7BSgez=bHi|sR4;q%U_HJx3_9cwTN@v~mS_t+ilN6wzFA0;%^RdB;y!{R$O^kf9PmA^&Tw6Ce~#%ZN@JQVY9 z4YU$`TJ(LNT7}=Q!Krq!+{qG-de!wBAcTAKhIB_F-)|9nD}_t7)dt|d#c>YJYntv;Vq<2ZwZq>1=3%cC4UZKNR^{*^pDG&W6%K)NfqT-CKV-HXdoZUod=Lp z{5(r`QspvT3T>noSB&9{+ID^p%69ZmJe}MUFgLy;5F4>v(3`4(gLk@%tQ9?Du>6QI zdcByW`F>qz=?j$gVTRhvq?mQVA+gDrq?n{Vz!h*X1>6g+Py#z-((PPx<$o zM2#y~B%#+*7e3QpKS7-UhdhXfJcDfPtSLaCa7N*cHS_Ch&z2U=cPu3dvk590>u?4K zztd5mf`7?OG}}4#w0z3ToXbz3X-dHw1Z{hBsciM?nGO~~&%&9BWj!P%oob%zrm2Ac z?9ihgE3gpO-k>qLHoZkbKPnn6Ln&Dn;i8-r%fzo6fCk|oI%n%Jxf|@*v<6J2IO5%F zU|cW`kdk(*X!-QZqNL5}3OkC+Y4X@=eN8uH-V7@qrb0=g#~0Ux0CPWrV<<>cOh(() zum#`^8-R|;*)YMy8%^&drB=UVT0A$>b+5iLZc4kpwziQB9jmV#h>&7GD{+WOEdDEMki)tR#}b zRs_b}?CBlVzWFL^nLv9T+2n_X@{NKeURDx@c==4$4jFYQU04NWLrLez+Ry4HcRx*W z4b_&0DZBGmf!*jP^`6zmyc2J{&w%)~L7LQjU&}D-tYR%##1xUn8OPtoIRt@A{{Q_qhjr|xj31O(JWWZnn zg?L2O{@Y5Dl@)c<=|}PT4vmskiN;y!nmNSvK2A8bTB?55(-I|Ky+#2lEtb^7p`vSP)9eBLttIsczg{5+;U1aQP=BM>bAjvx zST470-)Z=GoP}4Z}f7kf26+ zt*<1A#E>UvNqv6$+OCz|yMi6{Q*V*I4YdYW%}V5F9S=)8%<*0>;w8ldydJfecA-k1 zwG;^l9Ml1D#FfQg6@6jTSW;HLZTj{T5!%D!#MkGIJ7BepcBLkoj{NOF@9b(&ci5f2 z&y0H)$3pO|elUpeqa`TxTZeT$OVvZ^6ixLSZLG+@mG-T`@dt=%W>@(Q4eh@-ae-#o z9;a}&Qd%RJ z7f{FdW(#7iHg6Bs4nmntV++l87Q}ldkT>M!&O7s|r?$`M;%fH2b}yDiSJfwusz5qz zvtwvdEsi1*(JAUG`sHcK_4_DYt$9t2*PeHt8ljBXzAoL@p%I$weyShhDDI?JY|@`r zdpQ+C6bF6ekLlB7t(V7W$k(=x|BOEfadfvuK20&z^MzeAAoy0Pd*9KGse#@Zsk#_>v%Xiw zCR7goY}`Jnq8}q4#CA&`=Czp$VJv=jorbeePq%@?RE z_%JLlV`N5WMkbfcmzFdS&CShU?DI`wq+=$vr0b+KMCzoJ<3>jMB4sXXSWAol$s88! zm(UO_s{AL1bArD>{ZRkkIL}4rWx%_=xx)G9SBDS(UHioUues#^(Q_e-&?LHbvTptb zFLGWH4S@fcJ|>bX4oXT>RtHFkPr&auQXFA!AqORr0BS)ReRQmURNcvW?nzn&;QI#n zuO!R@251j&BX_FtqR6-Zzzci=Amle$0l+GdV0Q@R03_1-S%A^=4$paHI7Hm(0Gjgu zW}V_c_b9IYvp{?Oumt@Vbm!lBw155Cb>Os2=@yULl0q-uA4@gwZ{(Q3t4&#h3muJwm2Y@MctHWfY1 z4R6jT0(eMmKzG$c)(=n){4lMom!FB~Tl;CG1;SZ!r@XLZa;v7z793wcXMD9`^k{fn zRV_zMqF6_C?2a0z#_eA^^W7nbpl!+(997G`w#HnJEVFd$mZsL`goi=6I|*;X5D#NB z6|7QaO?VS!-z2b^7?<5bKhc)XbSSCLoRL0pIDP?uV5R^t<22jz+J2@7=XUJ)ve#;N zDu?|@cp?i0i*+<)bkwWREV7|Y-eLumATfy!1*W#@Yg;7dMY3}mc^5+d6-A5#u-Ocs z%Q587GV(&;0QBrD`l1(3V!(6_5t9I4-9`uz7?n?KqOq90ZJ;Ma5mY1UW;P z`pZsXM&PcY>g2!xL0YAYS|TsA>}4>VgEd`c^-$4{aiW}hi#{mrAt3I6pA;i%RRjso zLj8G$BtUe3t#Q_|ReOi^pcD*oWFeGVH4hc+ZuVu>3pC&%G2P9t!z6@xJfP?3Ke2J@ zF=XCQY;vHxAbydsd}e8cChFqTNX$lLDq*>PhYsxv0rDXEVInBxu7+oUzX`Fvz`Q}< zAC~#hUYx|Uc0pvbgoM?$b+C`sUk@W(P}JAEujPw$ijyP$+v^aU|Br@X|8AE^E(0Ee z1t_aUt_yJ_ZM3mFz%Sn$Ija$x_8G1v|=7w8yQKS1U{1+zZc6Myeo`zzyI zIMykF45k#<^65SUtpBKb64`vB%bn{*AivJhy4JN_4Nu)*_-CHx@DE6=6|niu*&rQ1 z(mF-rl8X_+OM#aV^e32pGb<(INP+NYnd5(5Mf~K8sH+T#Zyx(`;a|Z)TU)SGefsx| z^J4?{vpk&KcvdWA8d3}iW}DveQ&v%m7IG^Q`#HVB6YGZPr2lL<%7}g1<@~hx zwt;R^5H$ZX*8j>XHQEOAfqXZ0b+7p&0;D;6to1tIlE$uY#WmVHg8!*%S1xn54Jl`&CA=7+cR9P4fPk%R2Ld^5V%K zt;Q;%8VrwaopxuA)?NEUWYDw3lF9s7NtErA!b0Wy>+o@4Pw&MGdqk~Xl7q4<<(9mC z$;^h}YmX6|!hlsVdcC^2R7t;wffMVOEJlA}rL&CRo{Cio!&SlZOOID=MlD3W+O^)r zH$m(_YZ*F4LL zjWQ;%SdjoiQv+bCiK@Y0Y`O1!Hx|L%3>kTZNZ(8-3mvfff&0|RPo2kOngnc|Q6`tH z>m~C;Ge!FgLJA%DFv9@9ZHi`u{3t>I8YwCeAPWE0j~;O)Mg;=*(Zs+yhNMLd2ke;z zPHN6$yC6sE_+~Qi85G#U;4p>6bSfZ1QQFu0;7rE@jdYEZKhC$Jk7b)oq9ZcB>)Nur z`6a&cO5UW^?cQ>-o*$AQ=qKMxL44=b$5s1^fKeg_9x;c}^+2YL$*5k6cTgY9%g{)t zpk&9RtVLUmRM(u7?sgjHt63~E$Gc`;C$lueX3J*#B*-vFhDAmLXRmL_$%xy`_hAxT znKK$Dqzv@=itO_egCV_gQ=@}^w@EhQk?bQYd@m|bqN{5ETB@X1Obzj^VEDwx%X#K+ z9Z7(dfbKx!cZtEu*Lz#n90;+Nys0$n_W?Hpe8O1Kk4sx=JLwHoKSNCq?NW`^_V6+{ zK6lnge2y4>oRF?=pH_H&QsvX0A$Lc4U@vRIkIf*&)R2ca`}JH$N@v|=1Y{G1TuS?W zrQHT;ba@B43Frfs0o6L%gs48LPqs&2v;h8#LEgZ;kVcBIWCH48EAnWx+-UYv3jI9< z>v|y!l)7^N5xhzq@|S@f;O?GAu5?r1Tt;TApU|CR_SD@<#3PwQ<2I7In<+m>)e*yl zSp9+$!Y~%YF>C7=Q$L^)I(ZS_)WzRRVa@;KUDi~7qEnPs7|Jhvqhkuos;^JSxin5A#lm! z48nZh+I{%`2jRf@yRF5SPi$;89p`55EOc(Glx|Jp;hswe_p9I$PF4i@m^7&Y8*e8) zUzZ0(f^$_LYMy!v9ZqeLd(U8qDC@mr2vKAS>89MMZ zo7}2NU#6K0PBHE_uiNm9(!r#(EAd=McFz#=e_v7M9Y7O}5x@yel_9YJGb*$f*g%#i z`2wM;NZ>FZ_L7T#U(sz5AV-jy0Xhc>Tq>K-3MT<6(S>D`(=rvD*i~gxH0m<eys8Mz#77n z!qlKxNKM92L>27mwIQe@kr^+X%$L+*(Q?2#y1wmNWrU;d6i?FAdNB`T9jto%>s!Yp z^+N31jM)j4M%e3KQOUuXnOeY!3?2_&|5UqvzGR^<8OBWH?`M+ASTFpL;}}IW%#pK{ zH!%t|d=D!GPn3163kQHe`dEO&?qm!H^-zFMdONw}EI6fl`?I+!IvT+`9S)kgDG)^2 z5RXmoK=hwLf%aBrSF0h>_ejH7Ix(EJ&l3XJxS)kXKb!`N6SvUqHP3`bJNp2Q*DHx! zeUx6#bG@Tv0hR?_KdJGu3>(W!aBCR+q-+|c&lGkDh&MD*l{Rc*+lBK$^13F;81EK0 zb6iZ|3SotQLKFy0zfpztJaBwq7GPm4X04ifZv6V{)2`4(cpW}`QoYXwWPq<5OQU-w z*a#|he=M{q6=E%{d3VInl&yh1$_q=GzLV_0muzpUjM_4PvbJ^2ohk>hQ6t!A(9zkL zs3R{w*jQ8?;#TojqU%a>epskxn)6J1>nTN7&4Tz7V%d9th3^yINP)0xGqwZJ{w5OF`Jdk{g{&=~L=S`UrwjuiBL=OT zBAWecQeb(n+y}V%r%(+$YlUt8E=X1)~kFmMmXqPcCgso-PfXvAjM-(!#G?^j6$(swP4P zr$xoOuS&PQNuzsGw*719*1F4stc#~I_nXWY1fQ{E6kI^Xa@W@6lX|jU>D5Bzx3cf= z)e_B3gAB_zQrrP|Xk*Go`u3i3!%no0s8$kPNK`Oj;<(h-L5qulY4@|f&6&v>mJeRA z62>m&)uUoV*=D+4=hLKEzDF8n!8QvcT+Dx_NTcOCc>q6zi?#R*jt)7XE6W1^zM_Dj zAZv9}0)1F>IONzp7%-}-A!`Kk0oCo6J5bK{G%oz$`}t(2yr2{^h-XLsKM`)8f|*Ma zQuu!l=>DJ3ZzO==;nix0qH*zndt5j0&5ia`a1B$^qTCAuJ*&3@<#&@5>Lc&;{HKCPEY?&M8WDAaiEl`5qB&ziWU0`Oaz(i)_UEfBp0rV*T zg~q|nL-JrQ$Rs35tB!}61Z}QgRtk6X+C_4zqSB{J?{+)K$Zn_aPYTW_Up^ox#ZCLN z(7kqkQ;jE5h%%*h;^TaNp4A9cIOj^O!n?ZP<=e>oQ+i$=-3Y-j0fOKCifd@3usds)$>e);`F z5r0MZNJ~YeR79I^s!zu2Z7rjxC1T}0a;rPz$%63apGT&mApM&OZ{|J!v27H2tXfb( zdDpvYaZy9F3cY{%K2Lw{ulHSl@Ql`wm`=%5a4hC8Q=>?vEoL6bd_hL4s91`wgaQFw z@1;NOD1y2W8K$c*r@YKI4n@46`MZzm4!%!DNs|8-$`Dnig)ivFgx00r`Y)}u`P!5bNmjb}#qN1=34 z!Fs3?NPDwpvSBTLlc+f;NCSp{Hjre}Q zGiT`oR-%V+FrN{CGB-~FSp~nZ$Zl?RpMOt1j5ZMy_u6eiO?q2sF1W_6>(G92Ple$T zVV{T#w1ysg?}L)@Gnw@!NHon6m|df-;UiF}bV^qyRiKC>!FVSFicQopDeQyvS|m{PD1v zDWbj0bPy)T%}zjv2W50)=FP= z^wVU%DNUO<@2H3@I8BpiIwoOQrlqZ?A5x=JDKrz4&+}shCHKY7___5XrW8$&Nw;@~ zrO+zy(UeP$>cUS+STeu7jKEPSBD}?Omyn+WW}GxC@TbBTeasFn($h^ zYu{Yny3qU{R^{wt?ZF~&&7PAw+q>!$FKPbr$atlN#n@&L{Q%<{&^np;XrJSK<6y-jd3s1xcN}ex#$mmN^k*mScZ>wEhl=Wi9T;lz84lX!Ow3BFPNS%tj>y2cX$DBTs&%JXaK7$X$E5#H=V2G_vaI5O|jj`sN zI&aus%gH@SrOmk`o&+-$zCVtoW$PK#%+(HdHmPxD!@+WmBWIwSjmvp{M5k^t8{Rh3 z3Y$kk^m&R$g&ma!Vv32#9#gfveEZC|92ul&8ey&G#!vO(ep0^gP6#ENwu_0{{-OS= z{)Q%Vy|Wb&HM%Rsj>iJ9%9Xhs%{cv}rnIED=RhvvOBB0-!&IRr3gD_6YsP2)kUonERpVlk|c;GW)aeQ-S|m(i@r5@_EaDbUrS;mwQGp)z7n7A$ zPB-e!kj}&)EQ2ckxRL-ZGcT&2H(d!3pmwWv?#l>yq+r9mmTf7{p(knlg6ZMvf$+5E z(x{LhSi+^s;bA^=axo8!GNz6cd`AQ(Td?U+slra<=dZ1LBJ`yFSIJyM>E)0EO2CIn z{IKD&0gxSFfV$ia>ECxPIiq61f6UP@ z?PNCgz6Km?X6)LgYh>A8H#d_p*g&>ngg&@9Wn;VzRusZV{1mME629bN$!pVsNmvHWY z{{z$h+q%QQVA}s1!#V#{|NW*ECO^5m+*BzTbS-=tX z7C}B~II&_MUz&!4wYl8&ex5Dlg!PZK3~R)q{JCzxJ&%?df>g}m9+Cw=aAUo2|A(9S zNj11cjv{_ka5hK}$H_&R>~%61|LX|;_dIO+fz|=VQwQV}EGYFMDP^D`+;^J@GHGGTk8xTw zjwU26Z0wB%3rF_UEO!U?0UQndMdF$kQ^$zqyv_3==Y*7uC+j%n8jf_s?%_Kc1_ou* zF^gq7%)sIanQz^%=%n?0b#LPwN)$dqV&fU=R+$hrbUo=~yqFe0uB55Lo(}b#N*Kr0 zv`t0{{gfBc;1LJxvSQ=5dJ-L2KTl3Zen=t-o`%Nnt}epKk!pE>$qfS*U~^==50N`7 zz?AX_(0+EuKz?5lg-nVQ%UH%w$#H>7K%5BAUF10{i0FN=4~W$NECg_{o=E)a?<<*Y zkeQBk@(18thO#2braS~a@%)2JPLdD#p2|HySNh05h2XgcAP}GrxiTF@KZ2ZE^dAJ9 z(A+$vcS%pVgK4*_Q@L5ya&n%_M2+hn=cvoj25+lfypoN9n}M%!CBHwD-7|)pl(o7^ zQOR~iDN~!l$=;TB$2_6A!ftZ0oID}x7~1;x8Cz8A?ub2Fjz<-#o4zl0UVAM4`Kje= zfRn1?45xad8G*AyR6b_Yb}P%4f)E4pt~r(83nAnw>{3mz~Mr%AzyzlZ_#@{Hw`Ds zegN%=>55pj4Sn7>4oo>&p0^DzZzXf%l>5u5wjajj0b?nm^O=q(WdH>GScb-y zysq~-=`RY5rzfu)g=KJYpp0Ho`E(iV{ZP@C9<&1`AV6$F&fC$xF{Wk4?uCbWwD^hC zhkKaUJQxNj6$}s;^dUbDd%wbUsRz3~06SU!=>xgpug?-3C`42;Z%gib-3CY|NEu4> z!^X{7nz;^tTudxdb-nAk5q!l)Z>RwM5)X}XaPx^$zMq40yx?T?6i8d&QTp}lW)^nW z#=F8$V;4$Y>%=6w;Ki71UXZYcNJ^N-ao@&KH^n?I;a?*+hsI@3_Szgftd~s%`{^{# zEZ=OLF=C!{&Z_{Fr~V=0ZIr46ML=`9{Vh7bp#^JgUCEt_g+f%tx&{$jzC$pd8$-N=;sz zoWApMS7u>8>~|w*F@CUMgT7W^<-HdS$C0hl*6S)=ghfa2=`pt;H%$@#mLL{QuYcmK zmQgxY;3%n(f^(VjdLwPAOOEc>_-}hM)V5S~T1=sU9r|092O;Zvv5xviG23IJ{kl%| zE89DnkmnGfFkIgWS(a zqN-Q>{$^7GdIDX*a>LgAakt49!zOU|D7e297WcIQw=Dx?A~& z!Re0jirjOldVsw^&K-{#lquC1(iuu`hABfxb-T4S_UAd3?xtbQf-un76zJf? zMUHtBa~FwWs#3}`*Rjq_PWAAb3^!Lw-ON;8@$OB9mB(t1mZP>(`N3cGlV4vBMagqI zn+R3A+L*?y+mHP^2TT>?pr)yyi28*D_u}Z9kl{yFebqi8vF2)G4vh!TvKYdG+}~}X zVB*H}@c#;<`}|KR`tVUQP!(>|`VU4NUhjHT49Sc9DG=JL z!C#dRD`75Ln3Ucg^EiFIa6xsFhF2+E&kJMuWPdVgxzl#5&;ci`CC`+L+ZVyMH+&9S zW@Juv{RB71FjBJp($p>%dVD&mA0)*M6mYg@0zC%(wi&e6p*WF;v@zxc)|OX4 zaQO5ER)ng8Vbw9`J0RpjnIZQ<)os0Ew%HVU^cJv%kanj>*(tmt9TvuMJ=02fgEdA~ ztxyXjqN)ijOE?Y!hVjRhqU`z=4+}M!Z1g;0H z>Q~oWg1UvJ+ahO7Ir61nNM=BG(yAgafSb*NHv#B-dK7JPX1m@5t*+Hvxy0E z5J!TdMs}@)1$@<-xZPYPbm3E-x859kRA1|!tpS##v)2h39aenPDeMXP!99b^B$?7z z`4J^ENhniEtrcf-0!e22)l4Thg6CzEjeWJh(BE=H9`puNq6NA1&v~R7iaw%w0%dEC zJbT{uhdEsu|QO3x6D5b}lsxGYc!WjCOvw@w5Z1n;X4Sf>~dY?3(%F?n;jp zeuz?kJjz@?_A*trVcVe2RkNX(GGPvz2zd}Fgn+-qBjZVi`8%?|{+Mu*JC$|W>2f(5 z9?o!)-u-G$;4@;bQ(H{VNsPSj!5^gx|E1nbW*tF1i$@gljkp~PYNoo!^}gDWA5LOP zU6+t?XA6`JS!mQWj*-TSy;L918tAL3cNJIra;_Ur?QfAs@r#y@iv54*r&1Z) zOx1{r?&n%Ejv|$JubG8OYFuqivwn7?52D<%d#fCYKL2w%*tO){|jSp$+Lo+6P$9sS}mf9mL-J>2#_1_`wX< zr>SK}pO>aZ?qW}Tp0AjN8IFB>m8!R0m2;Y|xGnx(7XntMc<^jJ{?_RIMNUg${9fEZL4o7R+up6~p*Maxk!sdV zKNj|rxL}1qd}LJ1`=akBG5539HXf1^weyxbbnh5os~@0l`a&O!<}CK%@;%(k!LPjsIv%>Cb*!CD)J{<#=~drtsVCmm@B{ zotkQFMQ^}ZWZ%+7_rYCxAFj+b0*R+LicJf64%bV+&&TnKou@M78cMNR|G*Z9=3dne zt|U03YC~m&43ar*3(0Xd=C0kooh;WQx(T$}n0SNx>Qwp?T@(EQwrFq|y|HFW3Ig}J zC`BgR?IbZv6Kp==irHNQRs0XF)g^Py!TOo;zb2u7*RTBVeFd7U`Nm78Qn)Y(>^aG_ z`>Uuke%RGg=yDX{)>qq^H~H)iP6dVJDy>QdSz1P?3onF%_D3L#$7f zA^r1Be-?&s8t>h(On>ob&bC+ujhV@WMcKuXe!IbRu@Gcu?!*Dm4elYkAZU9I8kN;v zG(G&}J)x@m&$L`7;v6NyPc!WMS+tS~>CZ+d^wm)mZ$CAQX=n4_@X;INgR)5u_j7MU z^6D{nT6zSsH=bRq&lWLr@3nEBEnP2e{iLVcSJrSGt7!Olrh`FZJ+jKiKcHtm=5;v^ zU0>1esXHKUcjFi>#t)}mFNyO+JFB??`o(hb00=~Vfr$;;9$qwd+hD&T{0j3AXIuW)~=8J zBpUmfdxAR6v>IJ*{NvoY;Z=EBOXsv*b7Sar#WDwe!<)%=e0HYN!mkC`4FqRuU^){h zwd@@oXoJ;FAvx5as+tYks$*5p^@3)`iq>xzZwX1Kjpn7J8=xfSX!4zn3&n4%0qyH0 z2?U?sllEEA4brU(@!n0ES~*$LWtu-ShCp>h1R z>TgJJNs)Zqk-Bo9up|L6YOl6WKYcv>(MerDi84%G*PiZB$I+;$8C`CLkRE)kW7F%m zO*GlGp*887D*u(D8YbGz% zdjEaoSaM(RLVnPdk`iRZW>Cg}cSM`3T>00-bsdY{&g|Q45%p4+RKx&m6aH0?vY2UA(Qwu(8FMYjiZrbcN4If_S#_ESbPe zYs|TNQ;Y3MnTJ9JEMGy`&s@fSp_sDFY!$`t)oL@!(Ra>f>l8mEA<<_8Sl+)cUm6lS z+UZleP@G=I!a!%XInA-fKx7lVPJqOT!Xx{d*pXrAw>9DCdEKr|_rj>+BO%mB%ldu4 zuh2Bovz(rur-k&+kyY>+gNAWE&!G`o3MLPo+V5I7@?gx>*8*+AvUl-glDXF5K2F!; z0Dm+^u6%0M{NP^SvBEAh)#1l)0$Y=aIl)z|lVhKLbsJ77!coS$*cjd zFIJRzKCe;$;IHev{`zrM4yFsUz=Gw8-}wCP{-iXN(_X!|wj(O;;|fvd*RQ$W1@B?u z{0rIqqJ<^@FRUMMXx@<)rwB=3O@&&?tI3B z!R!N?4+>!fM5}J5GI7iJ~fhdVj`5G#AsT;oxokoRCWe8P%VDPD495>Ta z!R5lyMmgy~k)RmEtEj-uZfHA`D#yY?sT;6ug^tvRh8fyu2#LQ>p8b7g$aMe|513Lr zh)0;B`=D_^diOH|&w%N~qGy%U=~LDEdK24B8s0yrL=#sv@IQlX_zt-se~iEN+UJ1M ze-+uYqE|Wi!C4_V?4iu1j0Sg2bXf`cOPBU9P1flYnYR02{D52|#Y> zqy9}q297|CO3yr8@#Z?Sem5=DXUe$Ue~_9Z-%r<>pq^k<X0wme9_Bm(HoO8|Z%$fPkf99GO^9sntwX%}6*0(&*eSdDT0$sSC ze@{S$DT)3$)0-$)WR-s*2~gmsbeWg2h*r3>j6;&LEkzJoWFVFpfV#lfcj2zPbnwDu z@Noqe*xgyeiU8RDDX@$?2F_n8fA{bQAa#3~3v3Op@|rLm;Q1&z*A0RbFBMPcWIsex z-J|Gwf70-sGrI&??bAn8`Iv)burq~O{o=&;V`3=MOT&^dpI2&ETl9I(&S8+_h3i#= zKfpC=tnALL9dqC~f+;4p8}db)%flL_p;BgKQ99=dDdQcwUhA~|x!?nRgAf9>CdCi$k&3f-Qp8Qn0h?C9M6GAye=(|+*E7Tfo_ zyUKS75|A`$;U(-fSU8wK&4`5f2vUr8Lzo%=WXS*n~9WT>{ky~N+2Um08SFEjm z&g#n|zm{fSGh$UpQ?+D%p{%jJ@1R&cj3tn^o&j2w=Ufh2w=)g6${JD#`cfI?JxcEa z($XLazOwfb;QYoOoS@$IRb15p)Vc_Q;kjJrsf$rZ#uRdsAXm-OjFe~mEGE|J3)lv& z7ys+@@_%I|_n$QMKp$oZ!8{8t|KB5h{y&@M4x~!pCa*bmoXUT<8)h5CdWD_qXMoUx6U;xc?vjkuU_epN5b^&n z!S2p1rOy=(HinYJxYmaWm;W`R2h3Wba`T}tN^NwL``vABZB3e-W^GrpfL|yQgJDH-K=}WvWgaC(55zCf+i_)R>SOC z(~Y%=>9J()8QFfUcA3V*B;PpISKB~@PwWkv?8td2o8!1s6xC*>8etM67iIEG^ zr0kNdlT;jq2``0yqdFCaxIjtrH#{l5KIL0C9H-UVh{^*wdeGloUq1ST0PXl!UQTWJ z>t`$ed^WL*EY;8DqEQ1Z!Hw+9eY|*a4WF2IUaM)v6g)N&(E3CDNEjB{`N_?zi+4LQ zRzc0%S2_XqN(ya$Bg<9UzwxhDA(xLNs%f$YHRF!@Xp*Nr;;I=GUyCPg;H%>pocF_l zWy9ZRlHtdOPWY3-4EQjh^I1$-pueRj{(XjX^u+P+Gb88I;N%dXhf1fh)583=p8>K* zb|;|o0AF%uLPnUiuEIZ=aN6yLzt8+8Of`~6E-gn_#78=$vQ!t4>=H$B*; zt10I}OM3(nZxd3*Ll$HK|l@q`UsmdVXZ-o+=a&#KYQe_|6E|FfyKY7DQPW%PPIsL zM#gfaigx()@w`?g^onN3QmvqtT-?~^^UbGY(q@UCQ5g;-i6IA`on)W~c$1OOyu};> zU#Fj?q!VU(uuFdY&@3kbTtg!T6(8&sJgRcjt^;H!GTEG;2leJQxmtXC{FS?XQGme9JX=XFH7CFhL=VE(%%dBtvwdrNlHakl4n zjJ(fcGtUR?Cs>tp|G)kf~P`~1&KRb3Sv!9%VwdWv$R7ac_fyu$X-q{D~tP5(W9o`q`WeG zpx-J}B<{Anyd>7(qv@Zo#XvKKV4g!BAW3Q1fc;dT-_6{hne~a$olgDG(m5TTg6qo) ziBD422kJVBGwG|Su7I`C+OBzlPOHLBoO_S@q)1^LDjMm`n*OYOkNE?rKXDkOV+~Xx z7B&4aly&AvW`uO)DA=rX{(OLM(0i2ieUy;UKxmOvEwB!Y=&6$joV?LUNMyh75QsMY z&9u3U-*R+0d$l*7Zdd{9avG!SV;uzstt}h963bpj>nw_xKH%-|^6|S~%uNA0sr+Kb zEa26n8v$Z|gy|oy-Jw4u$v>Y=-jFet!Zh9D9!=IzmPD7^MBJC?j1|fV2DZYtUU}iS z9kRs-XmII{O+Mz(p7QAyU}rd0WnO2;{Wul85$fbTyHkIh^J-U9sk)kRYyUab zd~MyzvkZ@BaJ!p`4kFh5@#C;Pc>Gx4!2hqrMlay7#-I-g_W^ z%Fl#G@clu>>B9>tJZuU5PS=w*mi#|vOYQQ-VERdMXo#89P{x9CTJkvdWon`q?Js7M z?3D97^wmUIenEgJl35Vq7w#IuGAoPwUQu?xm704^NYd=4{;#gO4+O29&fWYcY8Nyh z-)#Xz?b0o;__A{8?2UIlufn<5vpeO~)@@iui*pmL6PmpqUa{g~PwslI0BbhI#t^=t zW4phVVvTW^DZt{gq^{N77?OlD9@dRarz4*rFaYM`EBfs~ zlI!uQg_2#b=Ek7dccT5g$V*DgS+=qAm%YqCU|#!}#qC|$&Zmt>9Lx$Tn}l}C9liqx z9fx$q($A9$?{#orG`Y6&v7eUDjbz|5j3H%u z>^mFgUn%}R;AfCL=xBv?7JO!@X%5ow>5nOXm5)>Qzs@OiLuyc)o3@N1gLX zt;m`>`%H$TzGSEFeE$#evl>a(8>s+zqH3xs;8$2&*L$}Q>AAHU*ZbUa)%VbSmW2kk z87lxHt?29bCixH-V9PQN=JGO4F_$Sya*guJd|KXnH^rgo>%Ko)B`RUHrM6}=$32L^ zlw?jYg{p~_`vtMd_o^`ty5CUmePu=JM}r3!FErvB+EO(0boUe-v}^4jK2JLi0%dEsIPJwP~$2QL0NDkgk^5)4!wCqA2; zY&(6pd4z2&Rb{+xA}6ylc*EE6$0V?E+OQ%T1wOKdDhJF0)F#^b{lqTX>+Ifljh(U5 zH@Zx_Eisv^HfrG!Rt8i{aeJ;fOw1~zdu3cvDPIa~4J0gdSz+P>kO|2i=7luXg!XIW zM_`_FwI~fm zxzTfvl4sJ*{B``PV-Ihu;mr&q4%esMcC@G&mS-|e7Zq=*&kilJA26IbTQ4kKxzF>7 zs(Q{X$l1_U|CCuz^t&FjhK(WJX+jl4iKd$kJeZ?(GK(jlZx95<^dIf6~k z6%wjU<>K5XT4ORM(3j&iRiJ&+j@~mxaO&EkU)283s|DnnT%^>X2gNkqt{rV__5N-| zFbhh1r(t()Zng*ZHMbI0J+Da(8ht9v@0i1?qUO$vE1&Na?E5JVr1on8Kol z4rc+ThGzkfybtELy4M1o2#Y-<6x2^5YxT#JY!ak`!o^k$G6xbncU?tV_B zRB*;EV=Z>Uw1*;r-8+KS8hwKA4VoV(@!hlutf)9ADHwH@i)N{jj)ZVQjV(4Ixt`{^ z0!f8x`UW==?aFlZ0Tg@j@R<9hG2pc_?EwGW7ubK;#5w@6{T?E`=-}d)1suF9*+r*D zOMc9aGW`BdL&|*vzPdr(%}(+UWgWz7=aNx)oNbSIMlpdF%fIVy2SdoVT@}gCq$;;2n zfthMxGW!l6B@&SFM#_vTFL34QnT^v`DmPwQP0Yx(w*0{Ex1bIEf6i@W9gf^WytuNf zFw^9HO^OCQYBxw%!BI4<gTEt@Yb8wba|aOLs-1J6(^5tdqMZFrQo@D}^yV->{ZFd4fKk#59z# zLv^xhsI8*|y%GEK40HNFqWkjCp8Xq9#mD+liy=e6d`vlUeLPF^``yFU&K<7mCdlf< z;}T16who7LZ}X!*BQ-*vldP_lU2OH#RZ2WaN_T#1n!C~NVQiWe4I1*qgd1Pfg;rlxz&OYeZyR_`hk7h}0D8`MTJOSblkV@$K^Q!-!$20sBeo zx19_2s@R%#jM(Y)OAUNo5Uc$bZ2*dzK+hW0t!=#WGanAwy#Y%nr~;bYZsu*G%iBfTu|l8>iP0kVl_F!#B_K?)Lnrd03NYxl zd*Y-lvwvFTmN1X+eKnYR^WWB={!`WCzQ7|Ifg03hMV+Pvkqf$gei;>wd5#+a`H_93 z=2aR5p4u!{k1fV?pC?}{|J5aWMmo0AKHEAyGXj6!&iE+PLH2UmtN9?()NZ6~-6jb4d{1dKv3Eyq02x}h5s+8ui0uMmi^s&tl zk43Mlwf}ls{NJeI{FhSBzxeSl843TnO0-|VNw=r2B}ZJO?2>vDRGM%FY!T8qgo|G` z!kfKzgn9{R(!$P7E_uhVY3mbdz^dQzcK`42+Q^Ymzh9#UF+La#DKdJZFs^GnCl4fz z-u9~~(sxbiT!&i z82?f4{x47I|Llvxc`Ec@;1)p5`@eID{YU?GaUBPT3-@>YhkfP$(IvMA&+Mv01tPWP;zNC~RH$EJ-BExj+|SI)Fr$ALW=8OJvf z4$W;=?IH`qbQY-cUS&eM?fI^J116^T74hfv9bkatRXoKvesEW`NSkZ_r`{G+{t|`Ymija`7mC$#&)jiK*CVgo!h8f!}n#+ z?nH$~GzPIGi;-Y~DZL7!bb~$4*-5N*eDO{ z;N0VO_jk)Fk33P5c`pR>aEcB4kc95XeIU3nXJZ%3VOHyqR?`}GxMGU8VoqRlA{NK&! z|IUo~e=yJeht8}2wsPj&KKRgwkrcs7%~@=(roQVb;F8x8hBkBKF&kmUsU^@_=smm0 zRCna}c4SDYv$NeL&g4fGZzrFJ8azxp)$4N?)JYhql{laP6-vv^7VCFnyEr?XN9qJdBrM}2qb&p?3KC`;Y#QWWtW zokIHWRHtW6&WpKg4CN{UTn^i5enAG4!SVLv{$}N9{!uW-FXgq?4re1`tSxzFn*e)MAQdU-zp?()~C+(VPUfl}z^Btiw zqj@~tGT$oFeowrgbazgp$KZ`A`Et#$=ZmQ%Wl2$uYNVZt$lMt8)Kiu~5Z#g3da<9b z?;y3JJYjjICmCwg*lAuuPD@_f-V`CWESHs_ZA!iZK^v@xk7^mk`@6zh%v;pgyHOFE zizTC&qA{PkS+4_pTiZL+wlQwKmS$Y+{7tc*(V6gUnZab;IZDDR7CgL?KFn&6C8UO! zD)5*SRoCfJ^iSe9OUelmm6QNT_vslcieFuvkOnnH#;La}^` z2EUO1l{umTC)^L)BHybf`LWYj9aAPv+BIa8245GNTtJ2jm6fyR%!X8DX-Z41Hpagy z)>#=i6IC; z^B(tv+}uEV=rn28)s1J{%k*!IpdtBQ#>mHzGBtDK%uQnjUj?h2R~cz3h^<2K7n3Oz zX{{Uhs;<#}sSAWHJRk}ROR0vI_XU(dlZ!U0pfio5K0n0Aupz9@GLA+flJQ&?MpB=v z=Oo>7^%6VWQe`_A?tuB3B ze0wD;Vht~kYvhxJt0F&>sS@(_YDmN;zisqXOPs& zbF`sDche2}!aE7ef1qNrlrAR5%4I6gjhZzlK=ph4Gd|C~%CJk+SADs!(td^6g=dQh zJ-tu!TbfK|Dt(X891U^aN!@X89o;Ydybe&-sO@Eo1MEr`?PEUpS@H5p^atJ&BiJ$L)7-erCIxS>UQ?#=j?~MR@zdp zs>W|I!Ya>64y>f0ng>gQmB*?{-~+vEjxm&hNOj?DRFpof=>wgn-(m z7?_>Uz~aU7*qBI>az+tfCvfeN#`-N<9(^+gpy?E|0|`hs1S_b^U01|qW~et4*CKN_o98MGc8o*$M+scc@ z&f0z`Y5?+#J+37Ea-81NG;o>}D(qtK?sU=O#ZJInn{G~dwQ~~*+v?319J6l4Yvd#iEl!X$Y)k0w9~HZ< z`!w);IA7&G+n3JqJv|7t6h~5q$ecw}xi+_t*hE_UcXrLQu{K{F1(k~z%bUbS(!H{- zXT?v0V|($;DR}h~^Q+-voAqO=SRqjDW`kjH_qCSH+D1PUi$_BS)gA<~Wh}TiHoZ+Z zugbUG)(TLn|5WzF@xv`GYj*0z!^w$fkR*kJ(m*3^r65a5)Ts~c+{?+QS z$)R6$hLizDqje-O!@|K`K!wL`vW z^JuhzrJ%Z$@t(zKl52ShN$h*OGNy1O>xJRXSfJxW{0wA6B9b_pif#(d`uJ&ipyAT5 zO+IR|G6&lgXd6^#3z`>+k5pg#%}?b5l_vpr>EqOTm~8Cl6Zm2DA@wo#Rd}ex<6wr= zyk*vpm7xvHHfC2I^SZTHt!w2YuZto}zoiSit2X;Q8sfjUY=qWTv<}L#O0ZW~>v3{p zm&c?K4B7RI|6JLT>I<)mb{+USX?wqj^T&ckdfI6V^CppEXw%wG5st=tvfVMK)gosd zbMRNIC~b4-a2J--C)Sa?MBKCrLyoudGVAE1T};m>)+_|eoCN$M5YbXA6_6s;ZV2IJ zY22G&(5+<(nwRW?GbI~@;~q=4A?(8oHkp@wz9Bzp+mxch;LW~NJCuRa;RovlTQv-^ znsO8ib{hsbN?iu)3$+E^nsJmN%q#4@52c=n=VGW!xODx-@okmYBEyFk?bTzL>+|IC z5^mxpUr@_O*-A2EULJ|fg)n=|a!A)P#>#EQw=_F`N+slOjN#^7S?(dd&}c%xtSXr} zP!9L#lJ5q)i)-l{XzkU$%XMd+p{CVZ*Vc}UA)Eufgek`0C@YPhu-_ubHRQ6Fj&+)C zY1TGzozAnv_xJT>qf}$@B$?_7Bu}F9UHb|%^e|^BCGKi8eNapOE7EWaJQX4yV;zV! znmp9knSr+-UN33#CbragIi~tX+>c6Pq#owpaW;e$)U35wr~Y76xMRjK%~Le-C7$ht zCBL@?oOP+OOx1APTa!QP4!=bh6^Ev8Acj)mrIiJTTRM%8#iI6xw5gu_uA{{h4HEbI z0$lIs9ZZg`9QOz)by)N~Yf4A*o!Y6$0F2sO!voUya$n%0mx{A>L?wDV2`dLxHXlh_ zcEo_?vYRey1`e(LhfoZXr~EY$@_KD2=2Q_1t`&|4-7JJ^NsmQX3&-zkGVHvP^^EF? zP9xj96NAr^Wh;HHEJHL0Y9%kexwP7(2G=OdGwZf2)8@Q+`Hzweamk-SdWfAqX?vH5 zS=m^7NYX7UOUuUwKK)Yn>M%Y6P3WcJX+1p(d>ge0pOIqc^|Wp-NOb@9xuEOr#>;9O z+vH~l%0b+JW}5^^zT3WR{knPgC$HdBH-)C1C%U2W{X#+Zo4 z$QbK>lAd(oN2!{O@se~K`~cTC^gGsGxyMlc z%kzK_QDsus%uUk+AgxOR_tL${?Y#wWyDFUIQiLG>mM_T5X+GhY@8U&MjLXzl+jmZt zV61l8UHK}E3INx@y7ld$Uy#-Z%nZ%TWbAg-rlM?JjlBs*q%^(z(FY}otI-O7{WjT0 zq7|qU%q^>?Ik!fAkdR!oF&kkTDQY}vq8ok?_@qAiyT)`e)JSAbe7i^l(fl%~9c>Yz zh>l=urwaG9y&}nf@mi%3*oxwVWrGZI4C?DAl-KK8q_=jo4W~nX9jVx@@k|^zUxmdPH;<|evYR%K;(YEN zf~7WlO=~{w{J@}|`~kG3GcsjT&IG&ZT4^N%v1vqacv0kYI}szymojV&nQIJO{8`w!f~Omq${2%r+$yHFkul3 z#>)4Dsp8M$j&kRKCdqDq^EcbLQKjxyRbtV(MJ^dD<5m#%zz-T5Y9x-pdy$f8C zqj1g?4429e=))u7tEhOBJ6{Z=#d90SPxeDG@*a%*j|XwiEjWA}sTpsk^ds%{scz5@>Aprd7r}Owm7{A)NSO3h0O!5-J_yhm-HjCbOW~@1nRZOX zl1hgjmzq?cN+-Xsc}Xz@Gl1t!D@ zMN}`_6xF~Etp}QzsV@jc4t%!P7j0^3o(M+U=Ol{e+rI}l(6Af&UvgFU!v@;_2;Q*z zdN=7v_KTMAU$^3m9twY?%4s3JrAeQjJ9wHE#rIQbPloaV)s4xusz!$bCBn0H7g6ne zp@zO^v~WIW&9bz6g;vS>r=CNyoxCtn`HH~rs{DUssv5}lA}pajkeIpbIVTAkaNU2M zrx}sow{y^ry7LvUgnZqk@_HiVJNRv*Xe6;_XN_3b~I_;d0lzg(VjRPWW!`IFP*UeJjh(D+yqe1eAI0xMzJN0{(nJxhwxq%T^{2RBI6pDOeu%9(SvIF?W`BO=$2W}s-{#yzCo7X{z6H* zX1b@j9p8hdMAwAbwAQEaaJ>0CTbN>=FU)7c7VFaW$yid=jzYS3TwAzO=u;s8+!clWK zeu`f_HbS1NX#t=MOOt==ej1(#KfB)irZz>7L%;m^djDS)gopxe=Er;)TF^e0%zn8h z7j>TCApMTnKLCSAQ*4docjmU<)3Up~8-%->!Ur=goj4T*19G1V$rb;$Y2MFhlQPRK z;yf5obC&J(|1Q{r(I-*w9%f3DUCmCVEEH%be_+9`zSg4ANMLvik(r*PYccZRivzlFuuCnQ;W*Rf$7$Lo`t5%Rvyk7Eijf)W16T*@}BCi*C2w0SSN z87ba$6Bh5qKW0b8y*b!xSEIT_(+mYV__8#zgl}XlDm2MPpye^|8RUMcRXRAO$8B0y zk(g`%yW;DTIH;iFCC)p1H&;}De{s+0>d+l?mMn6B0)hB0!*j^eQonR#$5M(CBUROw zOS(ivI7-g14T5V6wo#wA7I5I?_OtXC_4s`G3+r09n=|XYHtI^+@;i?nFnh)^C6|7} z-94LiF+wOW&V-v7tnAG1l}N7>`Hl1Ye-7OR7l~h>ZIHOd&uOE0+#|rTNWc@Nr<`&% zR`X(B#e#IVSx}7p&K0am|EB8{B4e2(sC$Eh-`6zl18KPxY=FJ?ye4T#DXq&4Bfh=5 z@w3q&wWf>*FKQ6N^%#YfDSB=4a8f zLqpI&l@`vsC^|6L(Ob(a9-~oPzGBFJ(aEgy+4A3Kf_6~apdS?^&$QLdF;M|?T)9a% z+#3K=oodr=mcabTshvB%YtF!jU`5+Y+-Yr&gEWu$;WSwee8dcmtR~c!#v|^dr|jqY zQ1gbo`QwGLtU2hTwuVN(>2|=OV)$gYCwJg|gc4OrtZUgx!as}WMiK@j#9!|mGo)ba ztC3=fAQD_ZA~L01Ll4bUx}T9!JBX$0&t2>=5%+k`U%45^vDa7-yS`$v?n2>mwU_Vi zS2Tc_XG)H}D>LdThFD6BMZX}4VFg4bjrx>+uHxI+Q~r%kz`uwW{x^>DKkXTSb$ z+3&LhlP}7>ej4Al`4phV@^ppwd7hwZRmQP{i}{SzO5kczk)I82`E`l$x=i|Ys$_pu znf*+U>Z<=TD!9q+)jssN;95i&;Ng0f1E}05@BMw|EJ%3Ck%!DN9^6ykJ}K8~BpbD1 zD4l0~&&ZmffkWkp*#G)sy6(-pnn&v58-dLcMuHAb(Dz*yoq;9@YK zh53fyVV;|yG@F-I%AQ>ug8~M=Xomu5_<_3sJr!^=E#}!B#1TxQ76id=c#gRXQA;Lc ze*2l(cMY#5E;-)wxnb?4GIYm?-LAfR+~w)@NBBw5`u7}$bqrw)`Sxqz964d!n4`?+ zMp-NZZIaW1HtJ^&CK(LAI#7!YAUvfuh3FL}AzAlhJQ|G`77oS1CfO8*a@? z(oB}v8AyZ}qj147#kTHIBhlU__7^fV7)hCE4!J~9)aQ({uDc=Qrtadu?EOLDihQ#A zyr!fD!crFO_PqkNQx>QiJf49GFKK;GYIiPQ6+H594ITa7J3Wk;sBNo^7@@j!3sX$& zv2l@-4K$-gxX=cWds>woA^p1Ckyc~K>ho|Xi!i^T!p^hF?Za2gBOSlJ=J>Vo_fy-~ zxomPWDRS?6$^NySl6XH}-Kg|9>6%nAq3d{+`n1zjFpv3furM@>c3r?#>1hMw2C3}3 zZO3Q>Fx%0S(>sTr-{>r4XPWp+bRqo-Rd)CtovqZ9c_*=3NVLw?Ny_mQ_phm*vJ`>)zlA&m>vpO&e*r%D?Q zC$5{vPQSgD3T@3NjCDJ7g_qxFU_Mc0@l;IL++ABWg z%1MjmO-NP6#-Za5WzCaC_4TdRVsZ|Hp)G+y7<+3kWAs`r-|`;vd^QAajIA^F^+g*O z$W&(E*GK;hY`Y$I-=r>k2^Fin5arCK#l@U+u3bp_?VIfWEE~9^UA8ubHSxZi{8i{R z8=I}m^@xf1%5^(reH`4&=T$)Q{3d(kBzxekhJ;mnFTY&oS1f3NFNIVwdv&v^AC_?4 z#~=q|)^EYs43V^ahh|YL{}7d&;X4D#u0EJC>mX5@CVr`jN^;RH*DovgH!~mg&lM>Y z$$6Kpvil-0JC!*BuPum*P^aj1!UeR>(@qI94W0Mhej2`qX?APWW5bctcAF(T!5EVV zaTbP#vl1BjTRvJ_hT|Atzaqre4#&K1wb8jSzN>!mm`~ONK_EFH-jje*X0<_{+7JXa zFnqaEa3np$S=rs#Kvs81ZX@?orL%7S(_DxnfE28NM;qzF~qK`EDMI?ro0@SXouF(B7!>8-qO@#lh$6lY1nka2~` z!Ai2ua@a!GP51+fbGPH2!{?N^=~+D>)WuqF>>wT@qQ5+j#W|`P6S+6EBUev+v{=8x z&0Zk<>Icb>-9H{z`$k^zk!s8peX_*?ho*cj*GBm17%Q)-?;R!NBujWSS#oD3ZFU(0 zKAO8TR?D4>B*_h|GK#l{QA|dvd;ZuIJJ152)~Enw_JC7sdnmhizC8SftqS(zqrl@U zOqEo9xWbzSw^Vagp#beiGSs@aPd;#;XvsIH=tyOs;H$G$aMtyFW5kvi%>2--QV(es z-ie5517ftBH6u^6o#rO-zHRLPw3r*7P|?gW;mb1KvInkI*HnTd%Rys_ed>;YP4Lc3 zb%n{g>sbPWyZlUwij69bb4?E^; zr=5jHZ$_lY4}SRjSKQTeL2toRV)YpT`0dfz7nxH$`qk5sMsG2^Lkej`4u zwiP<`+K5mpLRP#?WZyL!7&6tqb4>4S2_?LizihzqmxMu4LbPi_P+)^p0>=DP|B2mX z+kW+udp~5bTtaMl>4AjqcloMu|lrA?^}-Kr2&(S-By4-b=hvbkyoc;cE@&uLq6q zbTXx~4$J*=@bt#DV|DuJt^sv0Vhw3Rb=Zfm$Dd?jL5&pw*B@BMDi*&aT7 z$P$P^D3gAkIe|8D<-ulTwizk*^~NdaqqRJ*4i8#*?HVuR8?x!2dbfdXXy8R=`E0+M zGt)qDi@AzFxF_mfuqQF_+8;pACf-@xoho1&7c34lk|u>uT*lEGv~=d9&{RgK^U2Fk zq~(RZe;Bosy+FwI6NU-{9Wp!x>0J`S_)!-+=2a#lZ&!Z!v%c_k;dj_)>5If!lZVLL zV%cPj)K~qR`GgE4Lh;#Y?}wUkY7>{7c$V|UOtQilC4Uqv;@R^KQJ{*ae#@;`!7bA( zUW>VdQq-C%LilUD1G^BWAsL~e*76-z95kPAbRx|)VCfj_!SG!=RH&Z7RIavBmGdtX zS9}y#8z>KJ)f=e4<}0=|jz$h}VW%P1lh_jTQr25HyAki~lwPN(JhL*>58y28mr}M8 z^U5E-F`w2&uvqm&%=b&rtu~vkY6V^0YVGk8Pa+1EZM*!~(8HN{&v|EJcSIOJ933iP zJl*ObsC)|jnRvI~4m-_6xI3%`hCj8ulR}3@&kr(68#un8{rK$hiV#g5d*%1HZOdog zzd7(vyjs;561{vRWt#8%bwgdP+lhKzYohjo>KIuVc@)Wj! z9IF44eo8L8Tadw$?Tc;l_ns3$t>KGZ-<^w@p6m%3(S-J}^-GM}vD$8rC~{ryS-n=i`T} z1(mX1*o38IHxS%8$Pq<~(f%LG&}A`S76TeLhYIk5VglDD4&jm=b!ZFn70xorz)_oo z%wnv^=t-N6mRE4b+9m1r6^VlKf~yC+SN|CduhR}nbYz<*1W3ZsvK(W7-ZepWku))o zvAb(SjfP&|C6NNHe`O6l{sbSH(qldkVCr>qGT&%jbW?#^+dhi0B7e0g6uk#zNl%b- z@7X2G+x3YbO^j<1Y4uwkc2In1fxqC!UK{du77+iZrYz zwmx8MQ9zwe`14k?>dskeqR}K~_l6Zb-budo_J-KcA3Hdomp>t+yDryD(`-~^HTFjL z`Yq3k*EhyKPP|hF-aZ=HQtMMn{RJfQHBf`5zhX++icyFsq4cJnDe^h#M-Tjzxv6Jh zoF{c031&&?Sdy$q>fO-BX_PBPr_r&RNUN-XPn|W{b+GLxZOgk7V`xbtq8(#=J?ZmF zk3NR)WcJk3&}9)mZGQL!$UJqq>~#X?R6vnhuSt7oP@)t_{UQl|qtW_}8j&Z{iYl*}uVWHhzU-_3?biZ^A59% zv6uA@vx!TpeRmg%E((#95;CmrXm(S2Y(G3(lQL)*SBtx`qMpIcts;VyBvsi)s`5Ec zJ9)9hbwm4?3;O+iq{h|WU6j(_8%ep1gi6mS=L=y}2Yu5rmd?LcN8Z>^?0hxBQ$Vp` zk7s#7)fY|e7_h(j;4@2VLvIO<+g&es_>&Ak@zA;T-09xKb5FbK;Q1i)sNSc5tQH$r z)1!@4bBS;Ot^-H;3cPgq?vkBC?k&wgbM*Vdc(jpD;8@Z)?7QVE+%GOywD;pUtLl{+ zg&Zr|m_n*mgXi6Z*OpCT!dcGs%;d`T1)Mmc8mr@BzOc$%1aD$AE4r0J-NNQ8b zkenu=XkYd4O*NhpN5Aoqv=$fPDwvgjJHMBNiOI{G@ovU7r<-c*loZGq&%fZYa^lA| zMv;F3P4Um$yhyp5QbuQ6)Kxu4D5&!S*eM)kCOm(b_Q2wk31mv`S|{0mjKV5Ha4EBh z4wZfukgF44=oI6DcePX5utGsTXNZDphHimW&pj20r2Gy5Bv+K%YQbt{ErKFU=1(YugtQ4qhj|zKIXqT82gAPlL^j@`X`|D ze|Ad${l94KGxG30Q<1+$NR35uZh|ib7raLpmyy}5?b_0K8z(MRC$ zDJ^u7&Cof{Bw>;;BRZ6DQj+40dkr?v+_9Scg3##_X!I^7u5xVNTWD;_4)~y|b1R#2 zD1APuD84N3In}gybtSHhKY>fVY>34$hs!Ly(!hWcM(}A?3~d*_5m%45IhG);J$M4h!}N~k!L-}q14Ho{WNX@uFRUGu9ezgt*l^7tw*;*&dBF7i%g>a{U+Ty#G z-=*HgWZ_P8&q++lEG^0?RK>^8+)(Xyd*g@w*TQ{1S`#xcSyMe#o+EDuKUN2I9(H1% z(`~P7R2Av+fVJREdG|}|s+|8zd*>O|#JaC>%SJ>6HVD#XE7IGRjzlpuDi}U>zsAYxBGFv zyt8KJoq6Z||DWggWP-Do(;<+xFE0}8JaR47ZCuuyV&!%9ZLO&RU^}qIw&4sxgM_}Q z6x}OX1BkRlc~eQJ8T7%ftT~OQk@E8BDZ2XG4qw64{Kbqc3|!(g?8Tl~-R5*3zi@`a zE2^$w_jx_q_q;KR?ZMZ|DvF7}6Dg|52bz+RzDJsIatb6L&N_r4ypMCwjm}Bf+u|;5 zS-+GP7_o@Z-H}DBzW!FAeO$*DW7W1st1^gb>*)Au#ZY}Th1 zRAdOKm4*yli6MJ#mpS5>xP9PLmMMRwu@h70pKpL}J$(bLXg!$c)X%V;vaUwm+^>p@ zmsjig3HieV(IooHyNa?yfsw@`1!TuwV%bgrntQ`nJxioQ#t~FIiOlal^z}d?-V%-s z+_q5gg`I7UM%}{)PB3;qtYUp?!8d`ynm5jwzei^LdE)t3rbZ5=i1x>$1`GJ@Z6fm4 zSk@kr7xi?@%V`cSHTfzq_=TQB2*{4c>ea#LJ@{bBZKVSy3L4wQxfQLiBEUp_Tf596 z)nLT;Rp;&%n`*bJmBq12_8hmFHDM!6+CsaZ`)1yLQ@&-m{`T-^^2=}NGicukgE;I@ zfLhla#*!?IG#b)S-AE%1mWLL|t!tt;EHAAVC?{;dxaVUvlW!ekL*BLj9+oYno6{pU zy6vj)@`)QrSt-~Ru7-bY+h$X?zD}_6vDue1j9DxbH`a|{#x!AuAvcIf6W*IIgg7iY zKmyl)PPjRK3XIWiev=|`?0K?GWRHSN)w+m#9 zH}Oc%zu4^E{-vv5%<$e-47WJ#m%%{bO!RD}uyvrCxWH=9wh{!HbkN~6FPNHEop&?U z)yi<2jNf{wP}Vsxx8*z(ucuL%Qn>E1xa&8(oYF+pz11_+w6OWPWPR&sR?EHk2xwY7 zi<|$(J~0$6cJzpKi-t_ikxlUSRw708`>YO(fA`*Hxz>yf5KyJ8i1r3ILXi8Tp%n(Q z3x!9J8#HRu=Vr}8BmN6I5W(xV*I!5LH^c2nIE9yZ5uG`2a3m%UrXK668r9n4-~7@l z$t>`}&c0#nudGICrAP8OVO>)G+nh8t0L+wb^}~iJ@4{R|!(9=f1TBnjw#JW1z z7OqXfCcvcoo4(h^k&=rD{Q+U_KI1i#KBMf`;_2h$yU)z*AtSpRQjprjl92jCxUrje z#1kKh!i+IOVrKZOM(5k~wb8VzDUbGXy*!?2Io>K^1I5!-=2_cIOML-Jbu7aa4n0Q0PKLlaroW1-EpRkebLO6;ML=)Pv1iAWF5*sIL+wP=BQM*RqGLh=^e zwQg)T%3&@U5VyuCUKzf9YJQ#hOja$7(tGw;ckW(wo~Dv|J5WM$wQxT2v(J}7u-lwL2W|-jTzCkX*1M56?8lD!Gh$aP|{Q? zh*i|yu=PCkH|&OC`&u||yu_=cJAP*7yi35>MD`$Oes$mW!`Tl}AWg|K+P8a4%X(oOx94p;*H9o^<8zUoP2-b~}n=Zt7Y@Vww& zgrxBbwr2i02}ltE9(R29m$gtSW>%_eAqsIiz1^OFYS85YEuYhJzj4h4BLux;rW`eQ)2j%}t^rbS>j#QO7# z0H{d5Q>Osb_D$gpo+6J3>XZe4hwdR;T%v_egeeC{Umi3) zcG@cG9=P{5`CBNmZ7_`uVreq*4rvM>gUr{9B3ZolL~`++Z73pZpHC8Gp5gpOvJl{4gfHT~s@olTB_AWFu7yEOw z;&97jZq>b5W}s~6oNP6dqq7C=s=2jyTYF16ZUD<2*VJwo(p};(IXx(#WyhE@7i=Pu z?1nl8d?YQA@`a$%FbmG_o@&Je6R`eJ=dkq?j~>u=xxOg3tY^LaNSiZwPmnmLbwU&jh&W@!q4Kk~y+l2}g;cJr)#(RNk zgF-P%L0oSg)HyRRC!)K5oazpP?zgf zWGw36H(<)V6~I;L&YGUFkH$!~Y6g02jUzASa#xG!Oz3jgkMSR($*>N*2Q?adp8D+%QG%yc`ddM5DoL*tYX`~}Lb zDvtGX-BXUb^40_)MPIq?dGhA`paJQ}26_QYb+eGP7~M_PYtz5L_&z#uU>_Iw@%7e^ zRcM!Tl_#tj53OPKYY;k$K9ft?jPo^ArA7)q-{;qvFQ~cR`we?^mQoSPS zU|G6sJQk;*psZ(du|oe5bz(lDk50(7&eA@gjC+c|^`O22oJY?z*(%F;+}V%Ze-tqQ zR6aSbGVBwBxHNtF*xd%apj)MVFHKeO#I*)U**kObvr_T8s;X@9!6z#hJf#w0h9BOX z`%UgtV?(55Vi5=AMN~5Gr|ElmaPcp>A%HxXlY2QCKm3zDa82FQa4=zR7PleuCK*6?+7$0e(&I&D=e`eEw_+~+5)0EnZ{i{1^S1U2u6o`0LtV_3W-Bha~7y|0o@hx9b?}#*_OQ1S(HY@19 ze5=|wnwu&-wZqFR2(y)_Dj@z+J&n~O4=^G6(SryjeE$70<=E%%!0 z7%l6qblxdq_!?bG@PU%z56qJLqU z4jJ*b&zs#%Sh=WjgBU}6Io_?%6`Rdt*ra5+rv+DPGG6x8!zmygmiGGJm*T5xtI3ur z2VMsJ=Dfd;|G_RPF72#37_9Z^qK+=Jg{nNZH;#;>b|>R|_iF2^kJC5*JmEUX`U?#+ zw>J3aiKGcOzo}XJAd||PXBz_^WGxfw+A*MTxso}9-*A%L4WAa-wWZM68KKDHt^+14 zKT^B$&l4$n$B5V!%Sp!VI(4?`{IpeGSfT0$@4f(d7-=_V;3MaMF@e|o%E4Ptr}+)U zY)M7(!2}~JlN7zoL^pj6G2k}vZMk$L!{VZ0V-P+R>~m4Gs@!9U|SD)yKDq! zGE+C$%1DXwz(uq!Y=?4bO)DpKA~{dmXiBlISXv1*{604}FWu5;!X9wKxV{OEfLbOX zt81S{URy;q&MkYJ5Z!;| z7J*$HVV+(&*%|5DItAKSTL%J*=xFk{FREv%)>TkB{+EKD_RxAIUF~XkW&O*92_uvT z#lyI7f1arDFET-KU}%1IrDgMFqA&L#;fLFJNSyp=$e6tCh`W5y(I#W71K3{y-+3%& z=S|gidnBV$YQh&}tX~_DoG_|Nmcbs{-87VGbDHw}-Pzf3-ZB4!nY+Jq!`TV9`K^Ip z7}($HvMI1Rez&kQLdQmgmo&9=B3h!mSAJ`C9V$A0ZGF;CyFgMb%Z~EkL#PsL3GfCQ z=7%+4mX=sOB3bIZX^xpUh7W+A*T8#nK;G7d!1!>SvAl`@RHucaWYO=yLUb1-Ri>3q zx0HzPL+~&q+r2N%>AVM7@syRAd^Qu=IlU4R-W40vA9AbqVk5>B#Z&f<^k`E^X|o-T z6>M==6?FCQV}(46#yB}s<|N$(m+d7enpJ(B#i)^-Js*(*A$fXZ_O(I9hU<7pXz3K< zlqUaT=;Jm%%ME*RT4}@$R$~G;TnsF4^mD1T9SS+yQzA-)U2mc$5%kdN?rkk3)eVt_ zEviw+_?!&0XllyQwFM4Mt!0(xpPkFs1I!6^S zj}X%nQ$%iHPq5P(&+mrO?wa!WMP3i>b3;AHy`bw$^-G8>O>Jt$=?+s4Lk#m3biB@- z5ky({KA8atieE#~6$Ttqd{o6!+K&nX@?F#$@1p4SE~5T^g@*Y60MloiJpCk(3c;Cd zDH=-)oBW(Mf<6O?!U{!~V;WC-0GSzElvLgY)0n_%J#TGu_TxNM=kg@xt zB<~0?le;{xvXv*#M`^vndm;70#6-NXEjkb6e8BOj(YY(M;$oyc^ZX4)MDmU}LiT#! zoON9LLqEYC5DGg{eWAPt$W03?F-q#{A$v{&O0vwS7d>p1GNuE^2nqlNN!YJuasej%Nw5JsI|}RYFm!ER@UNNRZ9pt5Pz|`v zy2V%xOqzxclTd&7`fTm8RP@I#r~8bdQGCkmLL~GUCvN&l+%bXh{12Vnli!uR9z!%fXvms> zTQe1T+I4?*K=6U3Sk{uTm&$`@1ZXDAuY>lu2d7X8#jC#iw18Ti;WQG9$E13J_Gv+( zq@6C2Ht_eg*`c#E-zlcc0gO|&97nFVB?4NGUzD3Rx-3jRaJ zYKW*wCM}BRhn6G+#ctH3mv62}-A=VN9c6!BPm`lz-!AhoHg9Fqw%?~;TZrcE z*?wQkC3Hdm{K;qCp)tI16sScHM1x?R5{8!_&4mQX>h?e*kN9BaQqNHnL|vOQI9Cz@ zTAaVAJ3!1IXUtMGa~Uw zfzUa_{nBQk{PHJLwNAffzJ*KtI?ODltxRyv!`?gS`!1{A@VDY;)W!lXIyjhI@BBx!lWWub+N zau`9vt4NH&*g(z#BtRj)Tc5Rk9+mq$)Z5Z#v?OWH8EF@)MI{bSd3h^uWZ<%}oI!LrGDa_9H+(dgX z_je%qj_*09KwTm+UXs)D{C3#Z&-5MY?|UCoFKAwx71y}-wMhQ)s!gs{kOF*mX))GC zLh5Y2Mekw~I}h~FRr3G4uK#zr>i=Y0;D0v>{?F0rU06#?+T#6x3q|FhzRbVInb2@- zKwZ_A2w?OB4-o(o`rHIN3jKk`p8WH~%P#iCiv9Cp1-?f>(J+i%!M=$eYTnXhnI4&A zbSsuC__=9_c-SBLgGT1gl6AZQ$_o92*w~-$Kx5^xvs;|roM9xbdrynQx zo39%5u1}DG(GKRBs^|q&EoHOdB=Tc{F3@*A)2tCX|HU*J$E>C7@2*7!J74}`6sBpR ze-kpjF0?Z><0My;Idr?kTmyJ{IuknEmcdeg@y$&*1(W3+Gf-%$ z)HT}s!2t1TsN-{?>~lO<_lOOXJW8Mr`zW^r?yB{T2xia`if6u*Hasbwy(8a+@lie` z5`8(`o)p|*meezaIxk;k4kkXT$wn|u2>$OqhaIPhxU#v~Up-*wA1PIK-r0A78XioH zGAud2HUsEzUWPpnh0k1ymRHT2u^7k#_*H&73s@!7Y3pB? zGug1IQggMq)W$zeDGb+CG!!PDA7wW1uduc_mo3mIuwz&LE>`Q`gBv?}pp2aF+OGUh z!@2&ITk!XhV*hjP(SZ{Tu4CwbV(7meQ}XTD@ex|_KLaiM+Y|l!&+z|~=pWAO|DQzv Lh#Gg|&#C_cs8h(L From bba1601a6525a5798c8e0662c08045da5efcb968 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 05:41:22 -0400 Subject: [PATCH 032/134] Create ocpp_201_smart_charging.md Moved OCPP 2.0.1 Smart Charging content to separate page Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_smart_charging.md | 261 +++++++++++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 doc/ocpp_201_smart_charging.md diff --git a/doc/ocpp_201_smart_charging.md b/doc/ocpp_201_smart_charging.md new file mode 100644 index 000000000..b8ab280d8 --- /dev/null +++ b/doc/ocpp_201_smart_charging.md @@ -0,0 +1,261 @@ +# OCPP 2.0.1: Smart Charging + +Work to fully support OCPP 2.0.1 Smart Charging is ongoing. Most functional requirements for General Smart Charging use cases (that is, K01–K10) are now supported. For an up-to-date overview of which features are currently supported, please refer to the [OCPP 2.0.1 Status](doc/ocpp_201_status.md) document. + +## Key implemented features include: +- [K01 SetChargingProfile](#K01-SetChargingProfile) +- [K08 Get Composite Schedule](#K08-Get-Composite-Schedule) +- [K09 Get Charging Profiles](#K09-Get-Charging-Profiles) +- [K10 Clear Charging Profile](#K10-Clear-Charging-Profile) + +----- + +### K01 SetChargingProfile + +Allows the CSMS to influence the charging power or current drawn from a specific EVSE or the +entire Charging Station over a period of time. + +```mermaid +sequenceDiagram + CSMS->>+ChargePoint : SetChargingProfileRequest(call) + + ChargePoint->>+DeviceModel : SmartChargingCtrlrAvailable? + DeviceModel-->>-ChargePoint : Component + + rect Red + break SmartChargingCtrlrAvailable = false + ChargePoint-->>CSMS : Smart Charging NotSupported CallError + end + end + + ChargePoint->>+SmartCharging : validate_and_add_profile(call.msg.Profile, call.msg.EVSE ID) + + SmartCharging->>SmartCharging : validate_profile(Profile, EVSE ID) + + rect Red + break Invalid Profile + SmartCharging-->>ChargePoint : SetChargingProfileResponse: Rejected + ChargePoint-->>CSMS : SetChargingProfileResponse: Rejected + end + end + + SmartCharging->>+SmartCharging : add_profile(Profile, EVSE ID) + SmartCharging->>-EVerest : signal_set_charging_profiles_callback + + SmartCharging-->>-ChargePoint : SetChargingProfileResponse: Accepted + + ChargePoint-->>-CSMS : SetChargingProfileResponse: Accepted +``` + +Profile validation returns the following errors to the caller when a Profile +is `Rejected`: + +- `ChargingProfileFirstStartScheduleIsNotZero` + + The `startPeriod` of the first `chargingSchedulePeriod` needs to be 0. + [K01.FR.31] + +- `ChargingProfileNoChargingSchedulePeriods` + + Happens when the `ChargingProfile` doesn't have any Charging Schedule + Periods. + +- `ChargingScheduleChargingRateUnitUnsupported` + + Happens when a chargingRateUnit is passed in that is not configured in the + `ChargingScheduleChargingRateUnit`. [K01.FR.26] + +- `ChargingSchedulePeriodInvalidPhaseToUse` + + Happens when an invalid `phaseToUse` is passed in. + + [K01.FR.19] [K01.FR.48] + +- `ChargingSchedulePeriodPhaseToUseACPhaseSwitchingUnsupported` + + Happens when phaseToUse is passed in and the EVSE does not have + `ACPhaseSwitchingSupported` defined and set to true. + [K01.FR.20] [K01.FR.48] + +- `ChargingSchedulePeriodsOutOfOrder` + + `ChargingSchedulePeriod.startPeriod` elements need to be in increasing + values. [K01.FR.35] + +- `ChargingStationMaxProfileCannotBeRelative` + + Happens when a `ChargingStationMaxProfile.chargingProfileKind` is set to + `Relative`. [K01.FR.38] + +- `ChargingStationMaxProfileEvseIdGreaterThanZero` + + Happens when a `ChargingStationMaxProfile` is attempted to be set with an + EvseID isn't `0`. [K01.FR.03] + +- `ChargingProfileMissingRequiredStartSchedule` + + Happens when an `Absolute` or `Recurring` `ChargingProfile` doesn't have + a `startSchedule`. [K01.FR.40] + +- `ChargingProfileExtraneousStartSchedule` + + Happens when a Relative `ChargingProfile` has a `startSchedule`. + [K01.FR.41] + +- `EvseDoesNotExist` + + Happens when the `evseId`of a `SetChargingProfileRequest` does not exist. + [K01.FR.28] + +- `ExistingChargingStationExternalConstraints` + + Happens when a `SetChargingProfileRequest` Profile has a purpose of + `ChargingStationExternalConstraints` and one already exists with the same + `ChargingProfile.id` exists. [K01.FR.05] + +- `InvalidProfileType` + + Happens when a `ChargingStationMaxProfile` is attempted to be set with a + `ChargingProfile` that isn't a `ChargingStationMaxProfile`. + +- `TxProfileEvseHasNoActiveTransaction` + + Happens when a `SetChargingProfileRequest` with a `TxProfile` is submitted + and there is no transaction active on the specified EVSE. [K01.FR.09] + +- `TxProfileEvseIdNotGreaterThanZero` + + `TxProfile` needs to have an `evseId` greater than 0. [K01.FR.16] + +- `TxProfileMissingTransactionId` + + A `transactionId` is required for `SetChargingProfileRequest`s with a + `TxProfile` in order to match the profile to a specific transation. [K01.FR.03] + +- `TxProfileTransactionNotOnEvse` + + Happens when the provided `transactionId` is not known. [K01.FR.33] + +- `TxProfileConflictingStackLevel` + + Happens when a `TxProfile` has a `stackLevel` and `transactionId` + combination already exists in a `TxProfile` with a different id in + order to ensure that no two charging profiles with same stack level and + purpose can be valid at the same time. [K01.FR.39] + +----- + +### K08 Get Composite Schedule + +The CSMS requests the Charging Station to report the Composite Charging +Schedule, as calculated by the Charging Station for a specific point of +time, and may change over time due to external causes such as local +balancing based on grid connection capacity and EVSE availablity. + +The Composite Schedule is the result of result of merging the time periods +set in the `ChargingStationMaxProfile`, `ChargingStationExternalConstraints`, +`TxDefaultProfile` and `TxProfile` type profiles. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: GetCompositeSchedule(call) + + ChargePoint->>+DeviceModel : ChargingScheduleChargingRateUnit? + DeviceModel-->>-ChargePoint : Component + + rect Red + break call.msg.chargingRateUnit is not supported + ChargePoint-->>CSMS : ChargingScheduleChargingRateUnitUnsupported CallError + end + end + + ChargePoint->>+EvseManager : does_evse_exist(call.msg.evseId) + EvseManager-->>-ChargePoint : bool + rect Red + break EVSE does not exist + ChargePoint-->>CSMS : EvseDoesNotExist CallError + end + end + + ChargePoint->>+SmartChargingHandler : get_valid_profiles(call.msg.evseId) + + SmartChargingHandler-->>-ChargePoint : vector + + ChargePoint->>+SmartChargingHandler : calculate_composite_schedule
(vector>+Profile: calculate_composite_schedule(profiles) + Profile-->>-SmartChargingHandler: composite_schedule + end + + note right of SmartChargingHandler: Create consolidated CompositeSchedule
from all 4 Profile types + + + SmartChargingHandler->>+Profile: calculate_composite_schedule(ExternalConstraints, Max, TxDefault, Tx) + Profile-->>-SmartChargingHandler: CompositeSchedule + + SmartChargingHandler-->>-ChargePoint: CompositeSchedule + + ChargePoint-->>-CSMS : GetCompositeScheduleResponse(CompositeSchedule) +``` + +----- + +### K09 Get Charging Profiles + +Returns to the CSMS the Charging Schedules/limits installed on a Charging Station based on the +passed in criteria. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: GetChargingProfiles(criteria) + + ChargePoint->>+SmartChargingHandler : get_reported_profiles(criteria) + + loop filter ChargingProfiles + SmartChargingHandler->>SmartChargingHandler: filter on ChargingProfile criteria + end + + SmartChargingHandler-->>-ChargePoint : Vector + + ChargePoint-->>CSMS : GetChargingProfilesResponse(profiles) + + alt no Profiles + rect Red + ChargePoint-->>CSMS : GetChargingProfilesResponse(NoProfiles) + ChargePoint->>CSMS : return + end + + else Profiles + ChargePoint-->>CSMS : GetChargingProfilesResponse(Accepted) + end + + ChargePoint->>ChargePoint : determine profiles_to_report + + ChargePoint-->>-CSMS : ReportChargingProfilesRequest(profiles_to_report) +``` + +----- + +### K10 Clear Charging Profile + +Clears Charging Profiles installed on a Charging Station based on the +passed in criteria. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: ClearChargingProfileRequest(criteria) + + alt no Profiles matching criteria + rect Red + ChargePoint-->>CSMS : ClearChargingProfileResponse(Unknown) + + end + + else found matching Profiles + ChargePoint-->>-CSMS : ClearChargingProfileResponse(Accepted) + end +``` From 27c1ebcedd347ae3edc428fa9ba18fe31746aa0b Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 06:50:18 -0400 Subject: [PATCH 033/134] Update ocpp_201_README.md Updated content and separated Smart Charging content to its own page. Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 397 ++++++++--------------------------------- 1 file changed, 72 insertions(+), 325 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 0d77dfaf5..82684a80f 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -1,65 +1,57 @@ -# C++ implementation of OCPP 2.0.1 - ![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) +----- + +# EVerest OCPP 2.0.1 Implementation (libocpp) This is a C++ library implementation of OCPP for version 2.0.1 (see [OCPP protocols at OCA website](https://openchargealliance.org/protocols/open-charge-point-protocol/)). -It enables charging stations to communicate with cloud backends for remote -control, monitoring and billing of charging processes. +It enables charging stations to communicate with cloud backends for remote control, monitoring and billing of charging processes. Libocpp can be used for the communication of one charging station and multiple EVSE using a single websocket connection. -The implementation of OCPP 2.0.1 is currently under development. +OCPP 2.0.1 is currently under development. -## Get Involved - -See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. ## Table of contents -- [Support for OCPP 2.0.1](#support-for-ocpp-201) - - [Feature Profile Support OCPP 2.0.1](#feature-profile-support-ocpp-201) -- [CSMS Compatibility OCPP 2.0.1](#csms-compatibility-ocpp-201) -- [Run OCPP2.0.1 with EVerest](#run-ocpp201-with-everest) -- [Integrate this library with your Charging Station Implementation for OCPP2.0.1](#integrate-this-library-with-your-charging-station-implementation-for-ocpp201) - - [Register event callbacks and on\_handlers](#register-event-callbacks-and-on_handlers) +- [Functionality Support](#functionality-support) +- [Integration with EVerest](#integration-with-eVerestt) +- [Standalone Integration](#standalone-integration) + - [Key Integration Points](#key-integration-points) + - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) + - [Register event callbacks and on_handlers](#register-event-callbacks-and-on-handlers) - [Initialize the database](#initialize-the-database) -- [Install libocpp](#install-libocpp) - [Quickstart for OCPP 2.0.1](#quickstart-for-ocpp-201) +- [Build and Install libocpp](#build-and-install-libocpp) - [Building the doxygen documentation](#building-the-doxygen-documentation) - [Unit testing](#unit-testing) - [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) -## Support for OCPP 2.0.1 -The development of OCPP2.0.1 is in progress. -[Current implementation status.](/doc/ocpp_201_status.md) +## Functionality Support -### Feature Profile Support OCPP 2.0.1 +The development of OCPP 2.0.1 implementation is in progress — [OCPP 2.0.1 status](/doc/ocpp_201_status.md). The following table shows the current support for OCPP 2.0.1 functionalities in libocpp: -| Feature Profile | Supported | -| -------------------------- | ------------------------- | -| Core | :heavy_check_mark: yes | -| Advanced Security | WIP | -| Local Auth List Management | | -| Smart Charging | WIP | -| Advanced Device Management | | -| Advanced User Interface | | -| Reservation | | -| ISO 15118 support | WIP | +| OCPP 2.0.1 Functionality | Supported | +| ------------------------------------------------- | -------------------------- | +| Core | :heavy_check_mark: Yes | +| Advanced Security | :construction: In Progress | +| Local Auth List Management | :hourglass: Planned | +| [Smart Charging](/doc/ocpp_201_smart_charging.md) | :construction: In Progress | +| Advanced Device Management | :hourglass: Planned | +| Advanced User Interface | :hourglass: Planned | +| Reservation | :hourglass: Planned | +| ISO 15118 support | :construction: In Progress | -| Whitepapers & Application Notes | Supported | -| ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | -| [OCPP & California Pricing Requirements](https://www.openchargealliance.org/uploads/files/ocpp_and_dms_evse_regulation-v2.0.pdf) | WIP | +| Whitepapers & Application Notes | Supported | +| -------------------------------------- | -------------------------- | +| OCPP & California Pricing Requirements | :construction: In Progress | -## CSMS Compatibility OCPP 2.0.1 +## CSMS Compatibility -The current, ongoing implementation of OCPP 2.0.1 has been tested against a -few CSMS and is continuously tested against OCTT2. - -Additionally, the implementation has been tested against those CSMS: +The ongoing development of OCPP 2.0.1 implementation is continuously tested against OCTT2 (OCPP Compliance Testing Tool 2), and has been tested against several Charging Station Management Systems (CSMS): - [CitrineOS](https://lfenergy.org/projects/citrineos/) - Chargepoint @@ -72,23 +64,22 @@ Additionally, the implementation has been tested against those CSMS: - Switch EV - SWTCH -## Run OCPP2.0.1 with EVerest - -This library is automatically integrated as the OCPP and OCPP201 module within [everest-core](https://github.com/EVerest/everest-core) - the complete software stack for your charging station. It is recommended to use EVerest together with this OCPP implementation. +## Integration with EVerest -If you run libocpp with OCPP1.6 with EVerest, the build process of [everest-core](https://github.com/EVerest/everest-core) will take care of installing all necessary dependencies for you. This includes the initialization of the device model database using the [config.json](config/v201/config.json) file. +The libocpp OCPP 2.0.1 module is automatically integrated within [everest-core](https://github.com/EVerest/everest-core) — the complete software stack for your charging station. -## Integrate this library with your Charging Station Implementation for OCPP +When you run libocpp with OCPP 2.0.1 through EVerest, the build process of everest-core handles the installation of all necessary dependencies. This includes initializing the device model database using the [config.json](config/v201/config.json) file. -OCPP is a protocol that affects, controls and monitors many areas of a charging station's operation. +## Standalone Integration -If you want to integrate this library with your charging station implementation, you have to register a couple of **callbacks** and integrate **event handlers**. This is necessary for the library to interact with your charging station according to the requirements of OCPP. +If you wish to integrate libocpp's OCPP 2.0.1 implementation directly into your charging station software without using the full EVerest stack, you'll need to register several **callbacks** and implement **event handlers**. This allows libocpp to interact with your charging station according to OCPP requirements. -Libocpp needs registered **callbacks** in order to execute control commands defined within OCPP (e.g Reset.req or RemoteStartTransaction.req) +### Key Integration Points -The implementation must call **event handlers** of libocpp so that the library can track the state of the charging station and trigger OCPP messages accordingly (e.g. MeterValues.req , StatusNotification.req) +1. **Callbacks**: Register these to allow libocpp to execute control commands defined in OCPP (e.g., Reset.req or RemoteStartTransaction.req). +2. **Event Handlers**: Implement these so your software can call libocpp's event handlers, enabling the library to track the charging station's state and trigger appropriate OCPP messages (e.g., MeterValues.req, StatusNotification.req). -Your reference within libocpp to interact is a single instance to the class [ChargePoint](include/ocpp/v16/charge_point.hpp) for OCPP 1.6 or to the class [ChargePoint](include/ocpp/v201/charge_point.hpp) for OCPP 2.0.1. +The main interface for integration is the [ChargePoint](include/ocpp/v201/charge_point.hpp) class. ### Overview of the required callbacks and events and what libocpp expects to happen @@ -102,256 +93,6 @@ In EVerest the OCPP module leverages several other modules to perform tasks that The following sections explain the steps you can follow to implement their functionality on your own and integrate the libocpp directly into your charging station software without relying on EVerest. However, in most cases it's much easier to write an EVerest driver using the *everest-core/interfaces/board_support_AC.yaml* interface. -## Usage for OCPP 2.0.1 - -### Smart Charging - -Work to fully support OCPP 2.0.1 Smart Charging is ongoing. Most functional requirements for General Smart Charging use cases (that is, K01–K10) are now supported. For an up-to-date overview of which features are currently supported, please refer to the [OCPP 2.0.1 Status](doc/ocpp_201_status.md) document. - -#### K01 SetChargingProfile - -Allows the CSMS to influence the charging power or current drawn from a specific EVSE or the -entire Charging Station over a period of time. - -```mermaid -sequenceDiagram - CSMS->>+ChargePoint : SetChargingProfileRequest(call) - - ChargePoint->>+DeviceModel : SmartChargingCtrlrAvailable? - DeviceModel-->>-ChargePoint : Component - - rect Red - break SmartChargingCtrlrAvailable = false - ChargePoint-->>CSMS : Smart Charging NotSupported CallError - end - end - - ChargePoint->>+SmartCharging : validate_and_add_profile(call.msg.Profile, call.msg.EVSE ID) - - SmartCharging->>SmartCharging : validate_profile(Profile, EVSE ID) - - rect Red - break Invalid Profile - SmartCharging-->>ChargePoint : SetChargingProfileResponse: Rejected - ChargePoint-->>CSMS : SetChargingProfileResponse: Rejected - end - end - - SmartCharging->>+SmartCharging : add_profile(Profile, EVSE ID) - SmartCharging->>-EVerest : signal_set_charging_profiles_callback - - SmartCharging-->>-ChargePoint : SetChargingProfileResponse: Accepted - - ChargePoint-->>-CSMS : SetChargingProfileResponse: Accepted -``` - -Profile validation returns the following errors to the caller when a Profile -is `Rejected`: - -- `ChargingProfileFirstStartScheduleIsNotZero` - - The `startPeriod` of the first `chargingSchedulePeriod` needs to be 0. - [K01.FR.31] - -- `ChargingProfileNoChargingSchedulePeriods` - - Happens when the `ChargingProfile` doesn't have any Charging Schedule - Periods. - -- `ChargingScheduleChargingRateUnitUnsupported` - - Happens when a chargingRateUnit is passed in that is not configured in the - `ChargingScheduleChargingRateUnit`. [K01.FR.26] - -- `ChargingSchedulePeriodInvalidPhaseToUse` - - Happens when an invalid `phaseToUse` is passed in. - - [K01.FR.19] [K01.FR.48] - -- `ChargingSchedulePeriodPhaseToUseACPhaseSwitchingUnsupported` - - Happens when phaseToUse is passed in and the EVSE does not have - `ACPhaseSwitchingSupported` defined and set to true. - [K01.FR.20] [K01.FR.48] - -- `ChargingSchedulePeriodsOutOfOrder` - - `ChargingSchedulePeriod.startPeriod` elements need to be in increasing - values. [K01.FR.35] - -- `ChargingStationMaxProfileCannotBeRelative` - - Happens when a `ChargingStationMaxProfile.chargingProfileKind` is set to - `Relative`. [K01.FR.38] - -- `ChargingStationMaxProfileEvseIdGreaterThanZero` - - Happens when a `ChargingStationMaxProfile` is attempted to be set with an - EvseID isn't `0`. [K01.FR.03] - -- `ChargingProfileMissingRequiredStartSchedule` - - Happens when an `Absolute` or `Recurring` `ChargingProfile` doesn't have - a `startSchedule`. [K01.FR.40] - -- `ChargingProfileExtraneousStartSchedule` - - Happens when a Relative `ChargingProfile` has a `startSchedule`. - [K01.FR.41] - -- `EvseDoesNotExist` - - Happens when the `evseId`of a `SetChargingProfileRequest` does not exist. - [K01.FR.28] - -- `ExistingChargingStationExternalConstraints` - - Happens when a `SetChargingProfileRequest` Profile has a purpose of - `ChargingStationExternalConstraints` and one already exists with the same - `ChargingProfile.id` exists. [K01.FR.05] - -- `InvalidProfileType` - - Happens when a `ChargingStationMaxProfile` is attempted to be set with a - `ChargingProfile` that isn't a `ChargingStationMaxProfile`. - -- `TxProfileEvseHasNoActiveTransaction` - - Happens when a `SetChargingProfileRequest` with a `TxProfile` is submitted - and there is no transaction active on the specified EVSE. [K01.FR.09] - -- `TxProfileEvseIdNotGreaterThanZero` - - `TxProfile` needs to have an `evseId` greater than 0. [K01.FR.16] - -- `TxProfileMissingTransactionId` - - A `transactionId` is required for `SetChargingProfileRequest`s with a - `TxProfile` in order to match the profile to a specific transation. [K01.FR.03] - -- `TxProfileTransactionNotOnEvse` - - Happens when the provided `transactionId` is not known. [K01.FR.33] - -- `TxProfileConflictingStackLevel` - - Happens when a `TxProfile` has a `stackLevel` and `transactionId` - combination already exists in a `TxProfile` with a different id in - order to ensure that no two charging profiles with same stack level and - purpose can be valid at the same time. [K01.FR.39] - -#### K08 Get Composite Schedule - -The CSMS requests the Charging Station to report the Composite Charging -Schedule, as calculated by the Charging Station for a specific point of -time, and may change over time due to external causes such as local -balancing based on grid connection capacity and EVSE availablity. - -The Composite Schedule is the result of result of merging the time periods -set in the `ChargingStationMaxProfile`, `ChargingStationExternalConstraints`, -`TxDefaultProfile` and `TxProfile` type profiles. - -```mermaid -sequenceDiagram - - CSMS->>+ChargePoint: GetCompositeSchedule(call) - - ChargePoint->>+DeviceModel : ChargingScheduleChargingRateUnit? - DeviceModel-->>-ChargePoint : Component - - rect Red - break call.msg.chargingRateUnit is not supported - ChargePoint-->>CSMS : ChargingScheduleChargingRateUnitUnsupported CallError - end - end - - ChargePoint->>+EvseManager : does_evse_exist(call.msg.evseId) - EvseManager-->>-ChargePoint : bool - rect Red - break EVSE does not exist - ChargePoint-->>CSMS : EvseDoesNotExist CallError - end - end - - ChargePoint->>+SmartChargingHandler : get_valid_profiles(call.msg.evseId) - - SmartChargingHandler-->>-ChargePoint : vector - - ChargePoint->>+SmartChargingHandler : calculate_composite_schedule
(vector>+Profile: calculate_composite_schedule(profiles) - Profile-->>-SmartChargingHandler: composite_schedule - end - - note right of SmartChargingHandler: Create consolidated CompositeSchedule
from all 4 Profile types - - - SmartChargingHandler->>+Profile: calculate_composite_schedule(ExternalConstraints, Max, TxDefault, Tx) - Profile-->>-SmartChargingHandler: CompositeSchedule - - SmartChargingHandler-->>-ChargePoint: CompositeSchedule - - ChargePoint-->>-CSMS : GetCompositeScheduleResponse(CompositeSchedule) -``` - -#### K09 Get Charging Profiles - -Returns to the CSMS the Charging Schedules/limits installed on a Charging Station based on the -passed in criteria. - -```mermaid -sequenceDiagram - - CSMS->>+ChargePoint: GetChargingProfiles(criteria) - - ChargePoint->>+SmartChargingHandler : get_reported_profiles(criteria) - - loop filter ChargingProfiles - SmartChargingHandler->>SmartChargingHandler: filter on ChargingProfile criteria - end - - SmartChargingHandler-->>-ChargePoint : Vector - - ChargePoint-->>CSMS : GetChargingProfilesResponse(profiles) - - alt no Profiles - rect Red - ChargePoint-->>CSMS : GetChargingProfilesResponse(NoProfiles) - ChargePoint->>CSMS : return - end - - else Profiles - ChargePoint-->>CSMS : GetChargingProfilesResponse(Accepted) - end - - ChargePoint->>ChargePoint : determine profiles_to_report - - ChargePoint-->>-CSMS : ReportChargingProfilesRequest(profiles_to_report) -``` - -#### K10 Clear Charging Profile - -Clears Charging Profiles installed on a Charging Station based on the -passed in criteria. - -```mermaid -sequenceDiagram - - CSMS->>+ChargePoint: ClearChargingProfileRequest(criteria) - - alt no Profiles matching criteria - rect Red - ChargePoint-->>CSMS : ClearChargingProfileResponse(Unknown) - - end - - else found matching Profiles - ChargePoint-->>-CSMS : ClearChargingProfileResponse(Accepted) - end -``` - ### Register event callbacks and on_handlers - `all_connectors_unavailable_callback` @@ -488,36 +229,11 @@ sequenceDiagram - Use provided sql database or implement your own storage drive -## Install libocpp - -For Debian GNU/Linux 11 you will need the following dependencies: - -```bash - sudo apt install build-essential cmake python3-pip libboost-all-dev libsqlite3-dev libssl-dev -``` - -OpenSSL version 3.0 or above is required. - -Clone this repository. - -```bash - git clone https://github.com/EVerest/libocpp -``` - -In the libocpp folder create a folder named build and cd into it. -Execute cmake and then make install: - -```bash - mkdir build && cd build - cmake .. - make install -``` - ## Quickstart for OCPP 2.0.1 Libocpp provides a small standalone OCPP2.0.1 client that you can control using command line. -Install the dependencies and libocpp as described in [Install libocpp](#install-libocpp). +Install the dependencies and libocpp as described in [Build and Install libocpp](#build-and-install-libocpp). Make sure you modify the following config entries in the [config.json](config/v201/config.json) file according to the CSMS you want to connect to before executing make install. @@ -538,7 +254,7 @@ Change into libocpp/build and execute cmake and then make install: make -j$(nproc) install ``` -Use the following command to start the charge point. Replace the config with [config-docker.json](config/v16/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. +Use the following command to start the charge point. Replace the config with [config-docker.json](config/v201/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. ```bash ./dist/bin/charge_point \ @@ -558,7 +274,32 @@ Type `help` to see a list of possible commands. You will find the generated doxygen documentation at: `build/dist/docs/html/index.html` -The main reference for the integration of libocpp for OCPP2.0.1 is the ocpp::v201::ChargePoint class defined in libocpp/include/ocpp/v201/charge_point.hpp . +The main reference for the integration of libocpp for OCPP2.0.1 is the ocpp::v201::ChargePoint class defined in libocpp/include/ocpp/v201/charge_point.hpp. + +## Build and install libocpp + +For Debian GNU/Linux 11 you will need the following dependencies: + +```bash + sudo apt install build-essential cmake python3-pip libboost-all-dev libsqlite3-dev libssl-dev +``` + +OpenSSL version 3.0 or above is required. + +Clone this repository. + +```bash + git clone https://github.com/EVerest/libocpp +``` + +In the libocpp folder create a folder named build and cd into it. +Execute cmake and then make install: + +```bash + mkdir build && cd build + cmake .. + make install +``` ## Unit testing @@ -603,3 +344,9 @@ In order to connect through a custom network iface, a custom internal config var } ``` +--- + +## Get Involved + +See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. + From a9292e91031af8473d2856c4fc350d46fcebdf62 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 06:52:25 -0400 Subject: [PATCH 034/134] Update ocpp_201_README.md Updated broken link Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 82684a80f..db4a22c04 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -16,7 +16,7 @@ OCPP 2.0.1 is currently under development. ## Table of contents - [Functionality Support](#functionality-support) -- [Integration with EVerest](#integration-with-eVerestt) +- [Integration with EVerest](#integration-with-everestt) - [Standalone Integration](#standalone-integration) - [Key Integration Points](#key-integration-points) - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) From 0f88f139538aa710863c1b7a18b7f8dc5a831488 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 06:52:40 -0400 Subject: [PATCH 035/134] Update ocpp_201_README.md Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index db4a22c04..df3c0cbb3 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -16,7 +16,7 @@ OCPP 2.0.1 is currently under development. ## Table of contents - [Functionality Support](#functionality-support) -- [Integration with EVerest](#integration-with-everestt) +- [Integration with EVerest](#integration-with-everest) - [Standalone Integration](#standalone-integration) - [Key Integration Points](#key-integration-points) - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) From 7c2869f5dd8fe2026030717f30dd31d40058d9af Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 06:54:00 -0400 Subject: [PATCH 036/134] Update ocpp_201_README.md Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index df3c0cbb3..d95faf8b0 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -20,7 +20,7 @@ OCPP 2.0.1 is currently under development. - [Standalone Integration](#standalone-integration) - [Key Integration Points](#key-integration-points) - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) - - [Register event callbacks and on_handlers](#register-event-callbacks-and-on-handlers) + - [Register event callbacks and on_handlers](#register-event-callbacks-and-on_handlers) - [Initialize the database](#initialize-the-database) - [Quickstart for OCPP 2.0.1](#quickstart-for-ocpp-201) - [Build and Install libocpp](#build-and-install-libocpp) From 0837dd9da8ecc485f680be4a1fd4c7b8dc1b1e69 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 06:59:00 -0400 Subject: [PATCH 037/134] Update ocpp_201_README.md Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index d95faf8b0..35a6f4d2e 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -16,6 +16,7 @@ OCPP 2.0.1 is currently under development. ## Table of contents - [Functionality Support](#functionality-support) +- [CSMS Compatibility](#csms-compatibility) - [Integration with EVerest](#integration-with-everest) - [Standalone Integration](#standalone-integration) - [Key Integration Points](#key-integration-points) From c946e53900b1a017439d780a6c35db1aa0be571f Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 07:05:28 -0400 Subject: [PATCH 038/134] Update README.md Updated table of contents Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index d194e579b..22d6f2b05 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,41 @@ -![Header](doc/img/banner-ocpp.jpg) -# C++ implementation of OCPP +![Header](doc/img/banner-ocpp.jpg) ![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) -Libocpp is a comprehensive C++ library implementation of the Open Charge Point Protocol (OCPP) for versions 1.6 and 2.0.1. +--- -OCPP is a standardized communication protocol for electric vehicle charging stations and central management systems, developed by the Open Charge Alliance (OCA). For more information on OCPP, visit the [OCA website](https://openchargealliance.org/protocols/open-charge-point-protocol/). +# EVerest OCPP Module (libocpp) -### Development Status: -| OCPP 2.0.1 | OCPP 1.6 | -|:---|---| -|

|
  • Complete implementation available
  • Supports all feature profiles: Core, Firmware Management, Local Auth List Management, Reservation, Smart Charging, and Remote Trigger
  • Fully tested with numerous Charging Station Management Systems (CSMS)
  • Enables communication for one charging station and multiple Electric Vehicle Supply Equipment (EVSE) using a single WebSocket connection
| +The EVerest OCPP module, also known as libocpp, is a C++ implementation of the Open Charge Point Protocol (OCPP) versions 1.6 and 2.0.1. It is designed to seamlessly integrate with the EVerest software stack for electric vehicle (EV) charging stations. -## Table of Contents +## What is OCPP? -|
OCPP 2.0.1 | [OCPP 1.6](OCPP-1-6.md) | -|:---|:---| -|
  1. Quickstart for OCPP 2.0.1
  2. Run OCPP 2.0.1 with EVerest
  3. Integrate OCPP 2.0.1 library with charging station
  4. Certification Profile Support
  5. CSMS Compatibility
  6. Database Initialization
|
  1. Quickstart for OCPP 1.6
  2. Run OCPP 1.6 with EVerest
  3. Integrate OCPP 1.6 library with charging station
  4. Feature Profile Support
  5. CSMS Compatibility
  6. Database Initialization
| +The Open Charge Point Protocol (OCPP) is an open standard for communication between electric vehicle (EV) charging stations and central management systems. Developed by the Open Charge Alliance (OCA), OCPP ensures interoperability among various charging station manufacturers and management systems, playing a vital role in the growth of EV infrastructure. -For detailed information on each OCPP version, please refer to their respective README files linked above. +## Development Status +| Version | Status | +|---------|--------| +| OCPP 2.0.1 | :construction: Under active development | +| OCPP 1.6 | :white_check_mark: Complete implementation | + +## Table of Contents + +| OCPP 2.0.1 | OCPP 1.6 | +|------------|----------| +| • [Quickstart Guide](/doc/ocpp_201_README.md#quickstart-for-ocpp-201) | • [Quickstart Guide](/doc/ocpp_16_README.md) | +| • [Build and Install libocpp](/doc/ocpp_201_README.md#build-and-install-libocpp) | • [Build and Install libocpp](/doc/ocpp_16_README.md#build-and-install-libocpp) | +| • [Functionality Support](/doc/ocpp_201_README.md#integration-with-everest) | • [Functionality Support](/doc/ocpp_16_README.md) | +| • [Integration with EVerest](/doc/ocpp_201_README.md#integration-with-everest) | • [Integration with EVerest](/doc/ocpp_16_README.md) | +| • [Standalone Integration](/doc/ocpp_201_README.md#standalone-integration1) | • [Standalone Integration](/doc/ocpp_16_README.md) | +| • [Unit testing](doc/ocpp_201_README.md#unit-testing) | • [Unit testing](doc/ocpp_16_README.md#unit-testing) | +| • [CSMS Compatibility](/doc/ocpp_201_README.md#csms-compatibility) | • [CSMS Compatibility](/doc/ocpp_16_README.md) | ## Get Involved -We welcome contributions and feedback! To get involved with the EVerest project and this OCPP implementation, please refer to our [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) guides. +We welcome contributions from the community! Whether you're interested in adding features, fixing bugs, or improving documentation, your help is valuable. Check out our [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) guide to get started. + +For more information on how to engage with the EVerest community, please refer to our [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) document. -Your involvement helps drive the future of open-source EV charging infrastructure! +Together, we can drive the future of EV charging infrastructure! From 8f91583c8bb285794490812360a2573126d4decf Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:03:26 -0400 Subject: [PATCH 039/134] Update ocpp_16_README.md updated ocpp 1.6 content and table fo contents Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 278 +++++++++++------------------------------- 1 file changed, 72 insertions(+), 206 deletions(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 153d60789..f1268be60 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -1,52 +1,52 @@ -# C++ implementation of OCPP 1.6 ![Github Actions](https://github.com/EVerest/libocpp/actions/workflows/build_and_test.yaml/badge.svg) -This C++ library provides a complete and production-ready solution for integrating OCPP 1.6 into your electric vehicle (EV) charging stations. Our implementation enables seamless communication between charging stations and central management systems, supporting remote control, monitoring, and billing functionalities. +----- -NOTE: [EVerest OCPP 2.0.1](OCPP-2-0-1.md) is under active development, with core functionalities available. +# EVerest OCPP 1.6 Implementation (libocpp) +This C++ library provides a complete and production-ready solution for integrating OCPP 1.6 into your electric vehicle (EV) charging stations. Our implementation enables seamless communication between charging stations and central management systems, supporting remote control, monitoring, and billing functionalities. ## Table of contents -- [Feature Profile Support OCPP 1.6](#feature-profile-support-ocpp-16) -- [CSMS Compatibility OCPP 1.6](#csms-compatibility-ocpp-16) +- [Functionality Support](#functionality-support) +- [CSMS Compatibility](#csms-compatibility) - [Integration with EVerest](#integration-with-everest) - - [Run OCPP1.6 with EVerest](#run-ocpp16-with-everest) - - [Integrate this library with your Charging Station Implementation for OCPP1.6](#integrate-this-library-with-your-charging-station-implementation-for-ocpp16) - - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) - - [ChargePoint() constructor](#chargepoint-constructor) - - [registering callbacks](#registering-callbacks) - - [Functions that need to be triggered from the outside after new information is availble (on\_... functions in the charge point API)](#functions-that-need-to-be-triggered-from-the-outside-after-new-information-is-availble-on_-functions-in-the-charge-point-api) - - [The following functions are triggered depending on different so called "Session Events" from the EvseManager](#the-following-functions-are-triggered-depending-on-different-so-called-session-events-from-the-evsemanager) - - [Authorization](#authorization) - - [Install libocpp](#install-libocpp) - - [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) - - [Building the doxygen documentation](#building-the-doxygen-documentation) - - [Unit testing](#unit-testing) - - [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) - - [Support for security profile 2 and 3 with TPM in OCPP 1.6 using libwebsockets](#support-for-security-profile-2-and-3-with-tpm-in-ocpp-16-using-libwebsockets) - -## OCPP 1.6 Support - -The following tables show the current support for the listed OCPP 1.6 feature profiles / functional blocks and application notes. - -All documentation and the issue tracking can be found in our main repository here: https://github.com/EVerest/ - -### Feature Profile Support OCPP 1.6 - -| Feature Profile | Supported | -| -------------------------- | ------------------------- | -| Core | :heavy_check_mark: yes | -| Firmware Management | :heavy_check_mark: yes | -| Local Auth List Management | :heavy_check_mark: yes | -| Reservation | :heavy_check_mark: yes | -| Smart Charging | :heavy_check_mark: yes | -| Remote Trigger | :heavy_check_mark: yes | +- [Standalone Integration](#standalone-integration) + - [Key Integration Points](#key-integration-points) + - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) + - [Usage for OCPP 1.6](#usage-for-ocpp-16) + - [hargePoint() constructo](#chargepoint-constructor) + - [registering callback](#registering-callbacks) + - [Authorizatio](#authorization) + - [Initialize the database](#initialize-the-database) +- [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) +- [Build and Install libocpp](#build-and-install-libocpp) +- [Building the doxygen documentation](#building-the-doxygen-documentation) +- [Unit testing](#unit-testing) +- [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) +- [Support for security profile 2 and 3 with TPM in OCPP 1.6 using libwebsockets](#support-for-security-profile-2-and-3-with-tpm-in-ocpp-16-using-libwebsockets) + +## Functionality Support + +The EVerest OCPP 1.6 implementation (libocpp) provides comprehensive support for OCPP 1.6 functionalities. Below is an overview of the supported features: + +| OCPP 1.6 Functionality | Supported | +| ---------------------------- | ---------------------------- | +| Core | :heavy_check_mark: Yes | +| Firmware Management | :heavy_check_mark: Yes | +| Local Auth List Management | :heavy_check_mark: Yes | +| Reservation | :heavy_check_mark: Yes | +| Smart Charging | :heavy_check_mark: Yes | +| Remote Trigger | :heavy_check_mark: Yes | + +| Whitepapers & Application Notes | Supported | +| ------------------------------------------- | ---------------------- | +| OCPP 1.6 Security Whitepaper (3rd edition) | :heavy_check_mark: Yes | +| Using ISO 15118 Plug & Charge with OCPP 1.6 | :heavy_check_mark: Yes | +| OCPP & California Pricing Requirements | :heavy_check_mark: Yes | ## CSMS Compatibility -### CSMS Compatibility OCPP 1.6 - The EVerest implementation of OCPP 1.6 has been tested against the OCPP Compliance Test Tool (OCTT and OCTT2) during the implementation. @@ -85,23 +85,20 @@ If you provide a CSMS that is not yet listed here, feel free to ## Integration with EVerest -This library is automatically integrated as the OCPP and OCPP201 module within [everest-core](https://github.com/EVerest/everest-core) - the complete software stack for your charging station. It is recommended to use EVerest together with this OCPP implementation. - -### Run OCPP1.6 with EVerest +The libocpp OCPP 1.6 module is automatically integrated within [everest-core](https://github.com/EVerest/everest-core) — the complete software stack for your charging station. -If you run libocpp with OCPP1.6 with EVerest, the build process of [everest-core](https://github.com/EVerest/everest-core) will take care of installing all necessary dependencies for you. +When you run libocpp with OCPP 1.6 through EVerest, the build process of everest-core handles the installation of all necessary dependencies. This includes initializing the device model database using the [config.json](/config/v16/config.json) file. -## Integrate this library with your Charging Station Implementation for OCPP +## Standalone Integration -OCPP is a protocol that affects, controls and monitors many areas of a charging station's operation. +If you wish to integrate libocpp's OCPP 1.6 implementation directly into your charging station software without using the full EVerest stack, you'll need to register several **callbacks** and implement **event handlers**. This allows libocpp to interact with your charging station according to OCPP requirements. -If you want to integrate this library with your charging station implementation, you have to register a couple of **callbacks** and integrate **event handlers**. This is necessary for the library to interact with your charging station according to the requirements of OCPP. +### Key Integration Points -Libocpp needs registered **callbacks** in order to execute control commands defined within OCPP (e.g Reset.req or RemoteStartTransaction.req) +1. **Callbacks**: Register these to allow libocpp to execute control commands defined in OCPP (e.g., Reset.req or RemoteStartTransaction.req). +2. **Event Handlers**: Implement these so your software can call libocpp's event handlers, enabling the library to track the charging station's state and trigger appropriate OCPP messages (e.g., MeterValues.req, StatusNotification.req). -The implementation must call **event handlers** of libocpp so that the library can track the state of the charging station and trigger OCPP messages accordingly (e.g. MeterValues.req , StatusNotification.req) - -Your reference within libocpp to interact is a single instance to the class [ChargePoint](include/ocpp/v16/charge_point.hpp) for OCPP 1.6. +The main interface for integration is the [ChargePoint](include/ocpp/v16/charge_point.hpp) class. ### Overview of the required callbacks and events and what libocpp expects to happen @@ -388,167 +385,11 @@ In EVerest authorization is handled by the Auth module and various auth token pr To use libocpp as a auth token validator (e.g. before starting a transaction) you can call the "authorize_id_token" function of the ChargePoint object. -### Register event callbacks and on_handlers - -- `all_connectors_unavailable_callback` - - Notifies that all connectors are unavailable. Used to handle charge availability - requests and firmware updates. - -- `boot_notification_callback` - - Callback to notify of a system boot - -- `clear_customer_information_callback` - - Called to clear customer information based on passed in Customer Certificate, the - IdToken for this request, and the Customer Identified that the request refers to. - If IdToken is passed in will delete authorization cache entry from database. - -- `configure_network_connection_profile_callback` - - Called to configure a network connection profile when none is configured. - -- `connector_effective_operative_status_changed_callback` - - Notifies the user of liboccp that the Operative/Inoperative state of a specific EVSE - has changed. - -- `cs_effective_operative_status_changed_callback` - - Used to notify the user of libocpp that the Operative/Inoperative state of the - charging station itself has changed. Will also call - `evse_effective_operative_status_changed_callback` for each EVSE, and - `connector_effective_operative_status_changed_callback` for each connector whose - status has changed. - -- `data_transfer_callback` - - Used to handle arbitrary data transfers. - -- `evse_effective_operative_status_changed_callback` - - Notifies the user of libocpp that the Operative/Inoperative state of an EVSE has - changed. If as a result the state of connectors changed as well, libocpp will - additionally call the connector_effective_operative_status_changed_callback for - each connector. - -- `get_customer_information_callback` - - Returns human readable customer information based on the CertificateHashDataType, - IdToken and Customer Identifier passed in. - -- `get_log_request_callback` - - Callback to return logs - -- `is_reservation_for_token_callback` - - Check if the current reservation for the given evse id is made for the id - token / group id token. - -- `is_reset_allowed_callback` - - Callback if reset is allowed. If evse_id has a value, reset only applies - to the given evse id. If it has no value, applies to complete charging station. - -- `ocpp_messages_callback` - - Callback to congfigure ocpp message logging. - -- `pause_charging_callback` - - Used to request pausing of charging, the "connector" parameter instructing which - connector/EVSE to pause. - -- `remote_start_transaction_callback` - - Called when the request can be accepted. The boolean authorize_remote_start - indicates if Authorize.req needs to follow or not - -- `reset_callback` - - Performs a reset of the requested type - -- `security_event_callback` - - Used to react to a security event callback. This callback is - called only if the SecurityEvent occured internally within libocpp. - Typically this callback is used to log security events in the security log. - -- `set_charging_profiles_callback` - - Indicates when a charging profile is received and accepted. - -- `stop_transaction_callback` - - Used to stop a transaction. Called when the idTagInfo.status of a - StartTransaction.conf is not Accepted, when a RemoteStopTransaction.req is - received, or when an UnlockConnector.req is received. - -- `time_sync_callback` - - Called on boot notification if the TimeSource ControllerComponent contains - Heartbeat. - -- `transaction_event_callback` - - Called when a transaction_event was sent to the CSMS. - -- `transaction_event_response_callback` - - Called when a transaction_event_response was received from the CSMS. - -- `unlock_connector_callback` - - Used by libocpp to force unlock a connector - -- `update_firmware_request_callback` - - Initiates a firmware update request. Triggers a security event notification - if the certificate is Invalid or Revoked. - -- `validate_network_profile_callback` - - Validates the submitted Network Profile. Is Rejected if - - No callback registered to validate network profile - - CSMS attempted to set a network profile with a lower securityProfile - - CSMS attempted to set a network profile that could not be validated - - Network profile could not be written to the device model storage - -- `variable_changed_callback` - - Called when a variable has been changed by the CSMS ### Initialize the database - Use provided sql database or implement your own storage drive -## Install libocpp - -For Debian GNU/Linux 11 you will need the following dependencies: - -```bash - sudo apt install build-essential cmake python3-pip libboost-all-dev libsqlite3-dev libssl-dev -``` - -OpenSSL version 3.0 or above is required. - -Clone this repository. - -```bash - git clone https://github.com/EVerest/libocpp -``` - -In the libocpp folder create a folder named build and cd into it. -Execute cmake and then make install: - -```bash - mkdir build && cd build - cmake .. - make install -``` - ## Quickstart for OCPP 1.6 Libocpp provides a small standalone OCPP1.6 client that you can control using command line. @@ -594,7 +435,32 @@ Type `help` to see a list of possible commands. You will find the generated doxygen documentation at: `build/dist/docs/html/index.html` -The main reference for the integration of libocpp for OCPP1.6 is the ocpp::v16::ChargePoint class defined in libocpp/include/ocpp/v16/charge_point.hpp . +The main reference for the integration of libocpp for OCPP1.6 is the ocpp::v16::ChargePoint class defined in libocpp/include/ocpp/v16/charge_point.hpp. + +## Build and Install libocpp + +For Debian GNU/Linux 11 you will need the following dependencies: + +```bash + sudo apt install build-essential cmake python3-pip libboost-all-dev libsqlite3-dev libssl-dev +``` + +OpenSSL version 3.0 or above is required. + +Clone this repository. + +```bash + git clone https://github.com/EVerest/libocpp +``` + +In the libocpp folder create a folder named build and cd into it. +Execute cmake and then make install: + +```bash + mkdir build && cd build + cmake .. + make install +``` ## Unit testing From b71cec43f6eca776973bbeb63b31c883dbc4f0e3 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:06:39 -0400 Subject: [PATCH 040/134] Update ocpp_16_README.md updated broken links Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index f1268be60..9a791639a 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -98,7 +98,7 @@ If you wish to integrate libocpp's OCPP 1.6 implementation directly into your ch 1. **Callbacks**: Register these to allow libocpp to execute control commands defined in OCPP (e.g., Reset.req or RemoteStartTransaction.req). 2. **Event Handlers**: Implement these so your software can call libocpp's event handlers, enabling the library to track the charging station's state and trigger appropriate OCPP messages (e.g., MeterValues.req, StatusNotification.req). -The main interface for integration is the [ChargePoint](include/ocpp/v16/charge_point.hpp) class. +The main interface for integration is the [ChargePoint](/include/ocpp/v16/charge_point.hpp) class. ### Overview of the required callbacks and events and what libocpp expects to happen @@ -119,7 +119,7 @@ The following sections explain the steps you can follow to implement their funct The main entrypoint for libocpp for OCPP1.6 is the ocpp::v16::ChargePoint constructor. This is defined in libocpp/include/ocpp/v16/charge_point.hpp and takes the following parameters: -- config: a std::string that contains the libocpp 1.6 config. There are example configs that work with a [SteVe](https://github.com/steve-community/steve) installation [running in Docker](https://github.com/EVerest/everest-utils/tree/main/docker/steve), for example: [config-docker.json](config/v16/config-docker.json) +- config: a std::string that contains the libocpp 1.6 config. There are example configs that work with a [SteVe](https://github.com/steve-community/steve) installation [running in Docker](https://github.com/EVerest/everest-utils/tree/main/docker/steve), for example: [config-docker.json](/config/v16/config-docker.json) - share_path: a std::filesystem path containing the path to the OCPP modules folder, for example pointing to */usr/share/everest/modules/OCPP*. This path contains the following files and directories and is installed by the libocpp install target: @@ -160,7 +160,7 @@ This is defined in libocpp/include/ocpp/v16/charge_point.hpp and takes the follo - message_log_path: this points to the directory in which libocpp can put OCPP communication logfiles for debugging purposes. This behavior can be controlled by the "LogMessages" (set to true by default) and "LogMessagesFormat" (set to ["log", "html", "session_logging"] by default, "console" and "console_detailed" are also available) configuration keys in the "Internal" section of the config file. Please note that this is intended for debugging purposes only as it logs all communication, including authentication messages. -- evse_security: this is a pointer to an implementation of the [evse_security](include/ocpp/common/evse_security.hpp) interface. This allows you to include your custom implementation of the security related operations according to this interface. If you set this value to nullptr, the internal implementation of the security related operations of libocpp will be used. In this case you need to specify the parameter security_configuration +- evse_security: this is a pointer to an implementation of the [evse_security](/include/ocpp/common/evse_security.hpp) interface. This allows you to include your custom implementation of the security related operations according to this interface. If you set this value to nullptr, the internal implementation of the security related operations of libocpp will be used. In this case you need to specify the parameter security_configuration - security_configuration: this parameter should only be set in case the evse_security parameter is nullptr. It specifies the file paths that are required to set up the internal evse_security implementation. Note that you need to specify bundle files for the CA certificates and directories for the certificates and keys @@ -396,7 +396,7 @@ Libocpp provides a small standalone OCPP1.6 client that you can control using co Install the dependencies and libocpp as described in [Install libocpp](#install-libocpp). -Make sure you modify the following config entries in the [config.json](config/v16/config.json) file according to the CSMS you want to connect to before executing make install. +Make sure you modify the following config entries in the [config.json](/config/v16/config.json) file according to the CSMS you want to connect to before executing make install. ```json { @@ -415,7 +415,7 @@ Change into libocpp/build and execute cmake and then make install: make -j$(nproc) install ``` -Use the following command to start the charge point. Replace the config with [config-docker.json](config/v16/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. +Use the following command to start the charge point. Replace the config with [config-docker.json](/config/v16/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. ```bash ./dist/bin/charge_point \ @@ -481,7 +481,7 @@ Run any required tests from build/tests. ## Building with FetchContent instead of EDM -In [doc/build-with-fetchcontent](doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. +In [doc/build-with-fetchcontent](/doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. ### Support for TPM keys From fb9652fb81cd26ed1cfa2d1b6faa57ea21d33986 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:07:51 -0400 Subject: [PATCH 041/134] Update ocpp_201_README.md updated broken links Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 35a6f4d2e..8f0792989 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -80,7 +80,7 @@ If you wish to integrate libocpp's OCPP 2.0.1 implementation directly into your 1. **Callbacks**: Register these to allow libocpp to execute control commands defined in OCPP (e.g., Reset.req or RemoteStartTransaction.req). 2. **Event Handlers**: Implement these so your software can call libocpp's event handlers, enabling the library to track the charging station's state and trigger appropriate OCPP messages (e.g., MeterValues.req, StatusNotification.req). -The main interface for integration is the [ChargePoint](include/ocpp/v201/charge_point.hpp) class. +The main interface for integration is the [ChargePoint](/include/ocpp/v201/charge_point.hpp) class. ### Overview of the required callbacks and events and what libocpp expects to happen @@ -236,7 +236,7 @@ Libocpp provides a small standalone OCPP2.0.1 client that you can control using Install the dependencies and libocpp as described in [Build and Install libocpp](#build-and-install-libocpp). -Make sure you modify the following config entries in the [config.json](config/v201/config.json) file according to the CSMS you want to connect to before executing make install. +Make sure you modify the following config entries in the [config.json](/config/v201/config.json) file according to the CSMS you want to connect to before executing make install. ```json { @@ -255,7 +255,7 @@ Change into libocpp/build and execute cmake and then make install: make -j$(nproc) install ``` -Use the following command to start the charge point. Replace the config with [config-docker.json](config/v201/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. +Use the following command to start the charge point. Replace the config with [config-docker.json](/config/v201/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. ```bash ./dist/bin/charge_point \ @@ -321,7 +321,7 @@ Run any required tests from build/tests. ## Building with FetchContent instead of EDM -In [doc/build-with-fetchcontent](doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. +In [doc/build-with-fetchcontent](/doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. ### Support for TPM keys From a5c9ad15d2a0beab111cb0d00aeb9482546d7731 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:09:48 -0400 Subject: [PATCH 042/134] Update ocpp_16_README.md updated broken links Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 9a791639a..bfb74fe73 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -15,7 +15,7 @@ This C++ library provides a complete and production-ready solution for integrati - [Key Integration Points](#key-integration-points) - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) - [Usage for OCPP 1.6](#usage-for-ocpp-16) - - [hargePoint() constructo](#chargepoint-constructor) + - [ChargePoint() constructor](#chargepoint-constructor) - [registering callback](#registering-callbacks) - [Authorizatio](#authorization) - [Initialize the database](#initialize-the-database) From 24ded76b94778a5aa6b3fef668428c7d9df26fb7 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:10:43 -0400 Subject: [PATCH 043/134] Update ocpp_16_README.md updated broken links Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index bfb74fe73..c377906ca 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -16,8 +16,8 @@ This C++ library provides a complete and production-ready solution for integrati - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) - [Usage for OCPP 1.6](#usage-for-ocpp-16) - [ChargePoint() constructor](#chargepoint-constructor) - - [registering callback](#registering-callbacks) - - [Authorizatio](#authorization) + - [registering callbacks](#registering-callbacks) + - [Authorization](#authorization) - [Initialize the database](#initialize-the-database) - [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) - [Build and Install libocpp](#build-and-install-libocpp) From e120ab05b8b9b8a8efe71d55a708ba58ab19a0f9 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:14:13 -0400 Subject: [PATCH 044/134] Update README.md Updated links in table of contents Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 22d6f2b05..eff2614ab 100644 --- a/README.md +++ b/README.md @@ -24,13 +24,13 @@ The Open Charge Point Protocol (OCPP) is an open standard for communication betw | OCPP 2.0.1 | OCPP 1.6 | |------------|----------| -| • [Quickstart Guide](/doc/ocpp_201_README.md#quickstart-for-ocpp-201) | • [Quickstart Guide](/doc/ocpp_16_README.md) | +| • [Quickstart Guide](/doc/ocpp_201_README.md#quickstart-for-ocpp-201) | • [Quickstart Guide](/doc/ocpp_16_README.md#quickstart-for-ocpp-16) | | • [Build and Install libocpp](/doc/ocpp_201_README.md#build-and-install-libocpp) | • [Build and Install libocpp](/doc/ocpp_16_README.md#build-and-install-libocpp) | -| • [Functionality Support](/doc/ocpp_201_README.md#integration-with-everest) | • [Functionality Support](/doc/ocpp_16_README.md) | -| • [Integration with EVerest](/doc/ocpp_201_README.md#integration-with-everest) | • [Integration with EVerest](/doc/ocpp_16_README.md) | -| • [Standalone Integration](/doc/ocpp_201_README.md#standalone-integration1) | • [Standalone Integration](/doc/ocpp_16_README.md) | +| • [Functionality Support](/doc/ocpp_201_README.md#integration-with-everest) | • [Functionality Support](/doc/ocpp_16_README.md#functionality-support) | +| • [Integration with EVerest](/doc/ocpp_201_README.md#integration-with-everest) | • [Integration with EVerest](/doc/ocpp_16_README.md#integration-with-everest) | +| • [Standalone Integration](/doc/ocpp_201_README.md#standalone-integration) | • [Standalone Integration](/doc/ocpp_16_README.md#standalone-integration) | | • [Unit testing](doc/ocpp_201_README.md#unit-testing) | • [Unit testing](doc/ocpp_16_README.md#unit-testing) | -| • [CSMS Compatibility](/doc/ocpp_201_README.md#csms-compatibility) | • [CSMS Compatibility](/doc/ocpp_16_README.md) | +| • [CSMS Compatibility](/doc/ocpp_201_README.md#csms-compatibility) | • [CSMS Compatibility](/doc/ocpp_16_README.md#csms-compatibility) | ## Get Involved From 6155b1eccd22870445c57265569fc5068129cf49 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:23:57 -0400 Subject: [PATCH 045/134] Update ocpp_16_README.md Update table of contents links Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index c377906ca..a259a50e9 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -22,9 +22,11 @@ This C++ library provides a complete and production-ready solution for integrati - [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) - [Build and Install libocpp](#build-and-install-libocpp) - [Building the doxygen documentation](#building-the-doxygen-documentation) -- [Unit testing](#unit-testing) +- [Unit Testing](#unit-testing) - [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) -- [Support for security profile 2 and 3 with TPM in OCPP 1.6 using libwebsockets](#support-for-security-profile-2-and-3-with-tpm-in-ocpp-16-using-libwebsockets) +- [Support for TPM keys](#support-for-tpm-keys) +- [Support for websocket++](#support-for-websocket++) +- [Support for iface](#support-for-iface) ## Functionality Support @@ -462,7 +464,7 @@ Execute cmake and then make install: make install ``` -## Unit testing +## Unit Testing GTest is required for building the test cases target. To build the target and run the tests you can reference the script `.ci/build-kit/install_and_test.sh`. @@ -483,7 +485,7 @@ Run any required tests from build/tests. In [doc/build-with-fetchcontent](/doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. -### Support for TPM keys +## Support for TPM keys In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. @@ -495,7 +497,7 @@ The old websocket++ implementation has been deprecated. For enabling websocket++ cmake .. -DLIBOCPP_ENABLE_DEPRECATED_WEBSOCKETPP=ON ``` -### Support for iface +## Support for iface In order to connect through a custom network iface, a custom internal config variable 'IFace' can be used. From 716eff3e2a40d77f4a7edd9c45fc67c3ee789141 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:25:08 -0400 Subject: [PATCH 046/134] Update ocpp_16_README.md updated table of contents links Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index a259a50e9..1cbeab783 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -25,7 +25,7 @@ This C++ library provides a complete and production-ready solution for integrati - [Unit Testing](#unit-testing) - [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) - [Support for TPM keys](#support-for-tpm-keys) -- [Support for websocket++](#support-for-websocket++) +- [Support for websocket++](#support-for-websocket) - [Support for iface](#support-for-iface) ## Functionality Support From bfaaede773eb2e22296bbc864b0ee2c04c86608d Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:27:49 -0400 Subject: [PATCH 047/134] Update ocpp_16_README.md updated link Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 1cbeab783..e2c3978df 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -396,7 +396,7 @@ To use libocpp as a auth token validator (e.g. before starting a transaction) yo Libocpp provides a small standalone OCPP1.6 client that you can control using command line. -Install the dependencies and libocpp as described in [Install libocpp](#install-libocpp). +Install the dependencies and libocpp as described in [Build and Install libocpp](#build-and-install-libocpp). Make sure you modify the following config entries in the [config.json](/config/v16/config.json) file according to the CSMS you want to connect to before executing make install. From 82078b4a124059f690035e64242c4669a46113c7 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:33:42 -0400 Subject: [PATCH 048/134] Update ocpp_201_README.md added Smart Charging content back Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 275 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 265 insertions(+), 10 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 8f0792989..75f10140d 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -22,6 +22,7 @@ OCPP 2.0.1 is currently under development. - [Key Integration Points](#key-integration-points) - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) - [Register event callbacks and on_handlers](#register-event-callbacks-and-on_handlers) + - [Smart Charging](#smart-charging) - [Initialize the database](#initialize-the-database) - [Quickstart for OCPP 2.0.1](#quickstart-for-ocpp-201) - [Build and Install libocpp](#build-and-install-libocpp) @@ -34,16 +35,16 @@ OCPP 2.0.1 is currently under development. The development of OCPP 2.0.1 implementation is in progress — [OCPP 2.0.1 status](/doc/ocpp_201_status.md). The following table shows the current support for OCPP 2.0.1 functionalities in libocpp: -| OCPP 2.0.1 Functionality | Supported | -| ------------------------------------------------- | -------------------------- | -| Core | :heavy_check_mark: Yes | -| Advanced Security | :construction: In Progress | -| Local Auth List Management | :hourglass: Planned | -| [Smart Charging](/doc/ocpp_201_smart_charging.md) | :construction: In Progress | -| Advanced Device Management | :hourglass: Planned | -| Advanced User Interface | :hourglass: Planned | -| Reservation | :hourglass: Planned | -| ISO 15118 support | :construction: In Progress | +| OCPP 2.0.1 Functionality | Supported | +| -------------------------- | -------------------------- | +| Core | :heavy_check_mark: Yes | +| Advanced Security | :construction: In Progress | +| Local Auth List Management | :hourglass: Planned | +| Smart Charging | :construction: In Progress | +| Advanced Device Management | :hourglass: Planned | +| Advanced User Interface | :hourglass: Planned | +| Reservation | :hourglass: Planned | +| ISO 15118 support | :construction: In Progress | | Whitepapers & Application Notes | Supported | | -------------------------------------- | -------------------------- | @@ -226,6 +227,260 @@ The following sections explain the steps you can follow to implement their funct Called when a variable has been changed by the CSMS +### Smart Charging + +Work to fully support OCPP 2.0.1 Smart Charging is ongoing. Most functional requirements for General Smart Charging use cases (that is, K01–K10) are now supported. For an up-to-date overview of which features are currently supported, please refer to the [OCPP 2.0.1 Status](/doc/ocpp_201_status.md) document. + +#### K01 SetChargingProfile + +Allows the CSMS to influence the charging power or current drawn from a specific EVSE or the +entire Charging Station over a period of time. + +```mermaid +sequenceDiagram + CSMS->>+ChargePoint : SetChargingProfileRequest(call) + + ChargePoint->>+DeviceModel : SmartChargingCtrlrAvailable? + DeviceModel-->>-ChargePoint : Component + + rect Red + break SmartChargingCtrlrAvailable = false + ChargePoint-->>CSMS : Smart Charging NotSupported CallError + end + end + + ChargePoint->>+SmartCharging : validate_and_add_profile(call.msg.Profile, call.msg.EVSE ID) + + SmartCharging->>SmartCharging : validate_profile(Profile, EVSE ID) + + rect Red + break Invalid Profile + SmartCharging-->>ChargePoint : SetChargingProfileResponse: Rejected + ChargePoint-->>CSMS : SetChargingProfileResponse: Rejected + end + end + + SmartCharging->>+SmartCharging : add_profile(Profile, EVSE ID) + SmartCharging->>-EVerest : signal_set_charging_profiles_callback + + SmartCharging-->>-ChargePoint : SetChargingProfileResponse: Accepted + + ChargePoint-->>-CSMS : SetChargingProfileResponse: Accepted +``` + +Profile validation returns the following errors to the caller when a Profile +is `Rejected`: + +- `ChargingProfileFirstStartScheduleIsNotZero` + + The `startPeriod` of the first `chargingSchedulePeriod` needs to be 0. + [K01.FR.31] + +- `ChargingProfileNoChargingSchedulePeriods` + + Happens when the `ChargingProfile` doesn't have any Charging Schedule + Periods. + +- `ChargingScheduleChargingRateUnitUnsupported` + + Happens when a chargingRateUnit is passed in that is not configured in the + `ChargingScheduleChargingRateUnit`. [K01.FR.26] + +- `ChargingSchedulePeriodInvalidPhaseToUse` + + Happens when an invalid `phaseToUse` is passed in. + + [K01.FR.19] [K01.FR.48] + +- `ChargingSchedulePeriodPhaseToUseACPhaseSwitchingUnsupported` + + Happens when phaseToUse is passed in and the EVSE does not have + `ACPhaseSwitchingSupported` defined and set to true. + [K01.FR.20] [K01.FR.48] + +- `ChargingSchedulePeriodsOutOfOrder` + + `ChargingSchedulePeriod.startPeriod` elements need to be in increasing + values. [K01.FR.35] + +- `ChargingStationMaxProfileCannotBeRelative` + + Happens when a `ChargingStationMaxProfile.chargingProfileKind` is set to + `Relative`. [K01.FR.38] + +- `ChargingStationMaxProfileEvseIdGreaterThanZero` + + Happens when a `ChargingStationMaxProfile` is attempted to be set with an + EvseID isn't `0`. [K01.FR.03] + +- `ChargingProfileMissingRequiredStartSchedule` + + Happens when an `Absolute` or `Recurring` `ChargingProfile` doesn't have + a `startSchedule`. [K01.FR.40] + +- `ChargingProfileExtraneousStartSchedule` + + Happens when a Relative `ChargingProfile` has a `startSchedule`. + [K01.FR.41] + +- `EvseDoesNotExist` + + Happens when the `evseId`of a `SetChargingProfileRequest` does not exist. + [K01.FR.28] + +- `ExistingChargingStationExternalConstraints` + + Happens when a `SetChargingProfileRequest` Profile has a purpose of + `ChargingStationExternalConstraints` and one already exists with the same + `ChargingProfile.id` exists. [K01.FR.05] + +- `InvalidProfileType` + + Happens when a `ChargingStationMaxProfile` is attempted to be set with a + `ChargingProfile` that isn't a `ChargingStationMaxProfile`. + +- `TxProfileEvseHasNoActiveTransaction` + + Happens when a `SetChargingProfileRequest` with a `TxProfile` is submitted + and there is no transaction active on the specified EVSE. [K01.FR.09] + +- `TxProfileEvseIdNotGreaterThanZero` + + `TxProfile` needs to have an `evseId` greater than 0. [K01.FR.16] + +- `TxProfileMissingTransactionId` + + A `transactionId` is required for `SetChargingProfileRequest`s with a + `TxProfile` in order to match the profile to a specific transation. [K01.FR.03] + +- `TxProfileTransactionNotOnEvse` + + Happens when the provided `transactionId` is not known. [K01.FR.33] + +- `TxProfileConflictingStackLevel` + + Happens when a `TxProfile` has a `stackLevel` and `transactionId` + combination already exists in a `TxProfile` with a different id in + order to ensure that no two charging profiles with same stack level and + purpose can be valid at the same time. [K01.FR.39] + +----- + +#### K08 Get Composite Schedule + +The CSMS requests the Charging Station to report the Composite Charging +Schedule, as calculated by the Charging Station for a specific point of +time, and may change over time due to external causes such as local +balancing based on grid connection capacity and EVSE availablity. + +The Composite Schedule is the result of result of merging the time periods +set in the `ChargingStationMaxProfile`, `ChargingStationExternalConstraints`, +`TxDefaultProfile` and `TxProfile` type profiles. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: GetCompositeSchedule(call) + + ChargePoint->>+DeviceModel : ChargingScheduleChargingRateUnit? + DeviceModel-->>-ChargePoint : Component + + rect Red + break call.msg.chargingRateUnit is not supported + ChargePoint-->>CSMS : ChargingScheduleChargingRateUnitUnsupported CallError + end + end + + ChargePoint->>+EvseManager : does_evse_exist(call.msg.evseId) + EvseManager-->>-ChargePoint : bool + rect Red + break EVSE does not exist + ChargePoint-->>CSMS : EvseDoesNotExist CallError + end + end + + ChargePoint->>+SmartChargingHandler : get_valid_profiles(call.msg.evseId) + + SmartChargingHandler-->>-ChargePoint : vector + + ChargePoint->>+SmartChargingHandler : calculate_composite_schedule
(vector>+Profile: calculate_composite_schedule(profiles) + Profile-->>-SmartChargingHandler: composite_schedule + end + + note right of SmartChargingHandler: Create consolidated CompositeSchedule
from all 4 Profile types + + + SmartChargingHandler->>+Profile: calculate_composite_schedule(ExternalConstraints, Max, TxDefault, Tx) + Profile-->>-SmartChargingHandler: CompositeSchedule + + SmartChargingHandler-->>-ChargePoint: CompositeSchedule + + ChargePoint-->>-CSMS : GetCompositeScheduleResponse(CompositeSchedule) +``` + +----- + +#### K09 Get Charging Profiles + +Returns to the CSMS the Charging Schedules/limits installed on a Charging Station based on the +passed in criteria. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: GetChargingProfiles(criteria) + + ChargePoint->>+SmartChargingHandler : get_reported_profiles(criteria) + + loop filter ChargingProfiles + SmartChargingHandler->>SmartChargingHandler: filter on ChargingProfile criteria + end + + SmartChargingHandler-->>-ChargePoint : Vector + + ChargePoint-->>CSMS : GetChargingProfilesResponse(profiles) + + alt no Profiles + rect Red + ChargePoint-->>CSMS : GetChargingProfilesResponse(NoProfiles) + ChargePoint->>CSMS : return + end + + else Profiles + ChargePoint-->>CSMS : GetChargingProfilesResponse(Accepted) + end + + ChargePoint->>ChargePoint : determine profiles_to_report + + ChargePoint-->>-CSMS : ReportChargingProfilesRequest(profiles_to_report) +``` + +----- + +#### K10 Clear Charging Profile + +Clears Charging Profiles installed on a Charging Station based on the +passed in criteria. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: ClearChargingProfileRequest(criteria) + + alt no Profiles matching criteria + rect Red + ChargePoint-->>CSMS : ClearChargingProfileResponse(Unknown) + + end + + else found matching Profiles + ChargePoint-->>-CSMS : ClearChargingProfileResponse(Accepted) + end +``` + ### Initialize the database - Use provided sql database or implement your own storage drive From 5717a36ecbe0e74c012b4f3ff060a0ff5bddf893 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:34:37 -0400 Subject: [PATCH 049/134] Delete doc/ocpp_201_smart_charging.md add content back to OCPP 2.0.1 Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_smart_charging.md | 261 --------------------------------- 1 file changed, 261 deletions(-) delete mode 100644 doc/ocpp_201_smart_charging.md diff --git a/doc/ocpp_201_smart_charging.md b/doc/ocpp_201_smart_charging.md deleted file mode 100644 index b8ab280d8..000000000 --- a/doc/ocpp_201_smart_charging.md +++ /dev/null @@ -1,261 +0,0 @@ -# OCPP 2.0.1: Smart Charging - -Work to fully support OCPP 2.0.1 Smart Charging is ongoing. Most functional requirements for General Smart Charging use cases (that is, K01–K10) are now supported. For an up-to-date overview of which features are currently supported, please refer to the [OCPP 2.0.1 Status](doc/ocpp_201_status.md) document. - -## Key implemented features include: -- [K01 SetChargingProfile](#K01-SetChargingProfile) -- [K08 Get Composite Schedule](#K08-Get-Composite-Schedule) -- [K09 Get Charging Profiles](#K09-Get-Charging-Profiles) -- [K10 Clear Charging Profile](#K10-Clear-Charging-Profile) - ------ - -### K01 SetChargingProfile - -Allows the CSMS to influence the charging power or current drawn from a specific EVSE or the -entire Charging Station over a period of time. - -```mermaid -sequenceDiagram - CSMS->>+ChargePoint : SetChargingProfileRequest(call) - - ChargePoint->>+DeviceModel : SmartChargingCtrlrAvailable? - DeviceModel-->>-ChargePoint : Component - - rect Red - break SmartChargingCtrlrAvailable = false - ChargePoint-->>CSMS : Smart Charging NotSupported CallError - end - end - - ChargePoint->>+SmartCharging : validate_and_add_profile(call.msg.Profile, call.msg.EVSE ID) - - SmartCharging->>SmartCharging : validate_profile(Profile, EVSE ID) - - rect Red - break Invalid Profile - SmartCharging-->>ChargePoint : SetChargingProfileResponse: Rejected - ChargePoint-->>CSMS : SetChargingProfileResponse: Rejected - end - end - - SmartCharging->>+SmartCharging : add_profile(Profile, EVSE ID) - SmartCharging->>-EVerest : signal_set_charging_profiles_callback - - SmartCharging-->>-ChargePoint : SetChargingProfileResponse: Accepted - - ChargePoint-->>-CSMS : SetChargingProfileResponse: Accepted -``` - -Profile validation returns the following errors to the caller when a Profile -is `Rejected`: - -- `ChargingProfileFirstStartScheduleIsNotZero` - - The `startPeriod` of the first `chargingSchedulePeriod` needs to be 0. - [K01.FR.31] - -- `ChargingProfileNoChargingSchedulePeriods` - - Happens when the `ChargingProfile` doesn't have any Charging Schedule - Periods. - -- `ChargingScheduleChargingRateUnitUnsupported` - - Happens when a chargingRateUnit is passed in that is not configured in the - `ChargingScheduleChargingRateUnit`. [K01.FR.26] - -- `ChargingSchedulePeriodInvalidPhaseToUse` - - Happens when an invalid `phaseToUse` is passed in. - - [K01.FR.19] [K01.FR.48] - -- `ChargingSchedulePeriodPhaseToUseACPhaseSwitchingUnsupported` - - Happens when phaseToUse is passed in and the EVSE does not have - `ACPhaseSwitchingSupported` defined and set to true. - [K01.FR.20] [K01.FR.48] - -- `ChargingSchedulePeriodsOutOfOrder` - - `ChargingSchedulePeriod.startPeriod` elements need to be in increasing - values. [K01.FR.35] - -- `ChargingStationMaxProfileCannotBeRelative` - - Happens when a `ChargingStationMaxProfile.chargingProfileKind` is set to - `Relative`. [K01.FR.38] - -- `ChargingStationMaxProfileEvseIdGreaterThanZero` - - Happens when a `ChargingStationMaxProfile` is attempted to be set with an - EvseID isn't `0`. [K01.FR.03] - -- `ChargingProfileMissingRequiredStartSchedule` - - Happens when an `Absolute` or `Recurring` `ChargingProfile` doesn't have - a `startSchedule`. [K01.FR.40] - -- `ChargingProfileExtraneousStartSchedule` - - Happens when a Relative `ChargingProfile` has a `startSchedule`. - [K01.FR.41] - -- `EvseDoesNotExist` - - Happens when the `evseId`of a `SetChargingProfileRequest` does not exist. - [K01.FR.28] - -- `ExistingChargingStationExternalConstraints` - - Happens when a `SetChargingProfileRequest` Profile has a purpose of - `ChargingStationExternalConstraints` and one already exists with the same - `ChargingProfile.id` exists. [K01.FR.05] - -- `InvalidProfileType` - - Happens when a `ChargingStationMaxProfile` is attempted to be set with a - `ChargingProfile` that isn't a `ChargingStationMaxProfile`. - -- `TxProfileEvseHasNoActiveTransaction` - - Happens when a `SetChargingProfileRequest` with a `TxProfile` is submitted - and there is no transaction active on the specified EVSE. [K01.FR.09] - -- `TxProfileEvseIdNotGreaterThanZero` - - `TxProfile` needs to have an `evseId` greater than 0. [K01.FR.16] - -- `TxProfileMissingTransactionId` - - A `transactionId` is required for `SetChargingProfileRequest`s with a - `TxProfile` in order to match the profile to a specific transation. [K01.FR.03] - -- `TxProfileTransactionNotOnEvse` - - Happens when the provided `transactionId` is not known. [K01.FR.33] - -- `TxProfileConflictingStackLevel` - - Happens when a `TxProfile` has a `stackLevel` and `transactionId` - combination already exists in a `TxProfile` with a different id in - order to ensure that no two charging profiles with same stack level and - purpose can be valid at the same time. [K01.FR.39] - ------ - -### K08 Get Composite Schedule - -The CSMS requests the Charging Station to report the Composite Charging -Schedule, as calculated by the Charging Station for a specific point of -time, and may change over time due to external causes such as local -balancing based on grid connection capacity and EVSE availablity. - -The Composite Schedule is the result of result of merging the time periods -set in the `ChargingStationMaxProfile`, `ChargingStationExternalConstraints`, -`TxDefaultProfile` and `TxProfile` type profiles. - -```mermaid -sequenceDiagram - - CSMS->>+ChargePoint: GetCompositeSchedule(call) - - ChargePoint->>+DeviceModel : ChargingScheduleChargingRateUnit? - DeviceModel-->>-ChargePoint : Component - - rect Red - break call.msg.chargingRateUnit is not supported - ChargePoint-->>CSMS : ChargingScheduleChargingRateUnitUnsupported CallError - end - end - - ChargePoint->>+EvseManager : does_evse_exist(call.msg.evseId) - EvseManager-->>-ChargePoint : bool - rect Red - break EVSE does not exist - ChargePoint-->>CSMS : EvseDoesNotExist CallError - end - end - - ChargePoint->>+SmartChargingHandler : get_valid_profiles(call.msg.evseId) - - SmartChargingHandler-->>-ChargePoint : vector - - ChargePoint->>+SmartChargingHandler : calculate_composite_schedule
(vector>+Profile: calculate_composite_schedule(profiles) - Profile-->>-SmartChargingHandler: composite_schedule - end - - note right of SmartChargingHandler: Create consolidated CompositeSchedule
from all 4 Profile types - - - SmartChargingHandler->>+Profile: calculate_composite_schedule(ExternalConstraints, Max, TxDefault, Tx) - Profile-->>-SmartChargingHandler: CompositeSchedule - - SmartChargingHandler-->>-ChargePoint: CompositeSchedule - - ChargePoint-->>-CSMS : GetCompositeScheduleResponse(CompositeSchedule) -``` - ------ - -### K09 Get Charging Profiles - -Returns to the CSMS the Charging Schedules/limits installed on a Charging Station based on the -passed in criteria. - -```mermaid -sequenceDiagram - - CSMS->>+ChargePoint: GetChargingProfiles(criteria) - - ChargePoint->>+SmartChargingHandler : get_reported_profiles(criteria) - - loop filter ChargingProfiles - SmartChargingHandler->>SmartChargingHandler: filter on ChargingProfile criteria - end - - SmartChargingHandler-->>-ChargePoint : Vector - - ChargePoint-->>CSMS : GetChargingProfilesResponse(profiles) - - alt no Profiles - rect Red - ChargePoint-->>CSMS : GetChargingProfilesResponse(NoProfiles) - ChargePoint->>CSMS : return - end - - else Profiles - ChargePoint-->>CSMS : GetChargingProfilesResponse(Accepted) - end - - ChargePoint->>ChargePoint : determine profiles_to_report - - ChargePoint-->>-CSMS : ReportChargingProfilesRequest(profiles_to_report) -``` - ------ - -### K10 Clear Charging Profile - -Clears Charging Profiles installed on a Charging Station based on the -passed in criteria. - -```mermaid -sequenceDiagram - - CSMS->>+ChargePoint: ClearChargingProfileRequest(criteria) - - alt no Profiles matching criteria - rect Red - ChargePoint-->>CSMS : ClearChargingProfileResponse(Unknown) - - end - - else found matching Profiles - ChargePoint-->>-CSMS : ClearChargingProfileResponse(Accepted) - end -``` From 77203aecb2e4d89dd4ca31665b2e7ae52fb42a80 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:36:54 -0400 Subject: [PATCH 050/134] Update README.md updated table of contents Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eff2614ab..84dfd4b42 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ The Open Charge Point Protocol (OCPP) is an open standard for communication betw ## Table of Contents -| OCPP 2.0.1 | OCPP 1.6 | +| [OCPP 2.0.1](/doc/ocpp_201_README.md) | [OCPP 1.6](/doc/ocpp_16_README.md) | |------------|----------| | • [Quickstart Guide](/doc/ocpp_201_README.md#quickstart-for-ocpp-201) | • [Quickstart Guide](/doc/ocpp_16_README.md#quickstart-for-ocpp-16) | | • [Build and Install libocpp](/doc/ocpp_201_README.md#build-and-install-libocpp) | • [Build and Install libocpp](/doc/ocpp_16_README.md#build-and-install-libocpp) | From adff0e4c27d497fbf793b29deec246c5da177ac4 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:39:30 -0400 Subject: [PATCH 051/134] Update README.md updated table of contents Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 84dfd4b42..7e856c96e 100644 --- a/README.md +++ b/README.md @@ -9,20 +9,14 @@ The EVerest OCPP module, also known as libocpp, is a C++ implementation of the Open Charge Point Protocol (OCPP) versions 1.6 and 2.0.1. It is designed to seamlessly integrate with the EVerest software stack for electric vehicle (EV) charging stations. -## What is OCPP? +### What is OCPP? The Open Charge Point Protocol (OCPP) is an open standard for communication between electric vehicle (EV) charging stations and central management systems. Developed by the Open Charge Alliance (OCA), OCPP ensures interoperability among various charging station manufacturers and management systems, playing a vital role in the growth of EV infrastructure. -## Development Status - -| Version | Status | -|---------|--------| -| OCPP 2.0.1 | :construction: Under active development | -| OCPP 1.6 | :white_check_mark: Complete implementation | ## Table of Contents -| [OCPP 2.0.1](/doc/ocpp_201_README.md) | [OCPP 1.6](/doc/ocpp_16_README.md) | +| [OCPP 2.0.1](/doc/ocpp_201_README.md) :construction: Under active development | [OCPP 1.6](/doc/ocpp_16_README.md) :white_check_mark: Complete implementation | |------------|----------| | • [Quickstart Guide](/doc/ocpp_201_README.md#quickstart-for-ocpp-201) | • [Quickstart Guide](/doc/ocpp_16_README.md#quickstart-for-ocpp-16) | | • [Build and Install libocpp](/doc/ocpp_201_README.md#build-and-install-libocpp) | • [Build and Install libocpp](/doc/ocpp_16_README.md#build-and-install-libocpp) | From 66172763a682376382bce9c173eb06ad44b95eb7 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 08:46:00 -0400 Subject: [PATCH 052/134] Update README.md updated table of contents Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7e856c96e..e40eb567c 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The Open Charge Point Protocol (OCPP) is an open standard for communication betw ## Table of Contents -| [OCPP 2.0.1](/doc/ocpp_201_README.md) :construction: Under active development | [OCPP 1.6](/doc/ocpp_16_README.md) :white_check_mark: Complete implementation | +| [OCPP 2.0.1](/doc/ocpp_201_README.md) – Under active development :construction: | [OCPP 1.6](/doc/ocpp_16_README.md) – Complete implementation :white_check_mark: | |------------|----------| | • [Quickstart Guide](/doc/ocpp_201_README.md#quickstart-for-ocpp-201) | • [Quickstart Guide](/doc/ocpp_16_README.md#quickstart-for-ocpp-16) | | • [Build and Install libocpp](/doc/ocpp_201_README.md#build-and-install-libocpp) | • [Build and Install libocpp](/doc/ocpp_16_README.md#build-and-install-libocpp) | From 88e22e497da7400825ec0faecef36113fa126a40 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 10:27:01 -0400 Subject: [PATCH 053/134] Update README.md updated text content Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e40eb567c..89cddf88b 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ The EVerest OCPP module, also known as libocpp, is a C++ implementation of the O ### What is OCPP? -The Open Charge Point Protocol (OCPP) is an open standard for communication between electric vehicle (EV) charging stations and central management systems. Developed by the Open Charge Alliance (OCA), OCPP ensures interoperability among various charging station manufacturers and management systems, playing a vital role in the growth of EV infrastructure. +OCPP is an open standard for communication between EV charging stations and central management systems. Developed by the Open Charge Alliance (OCA), OCPP ensures interoperability among various charging station manufacturers and management systems, playing a vital role in the EV infrastructure. ## Table of Contents From 949ee6eda4875e309f00cbbf6a26bc9a234e765b Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 11:09:36 -0400 Subject: [PATCH 054/134] Update ocpp_201_README.md Updated Standalone Integration section Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 218 +++++++++++++---------------------------- 1 file changed, 67 insertions(+), 151 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 75f10140d..0a2e201fb 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -20,10 +20,10 @@ OCPP 2.0.1 is currently under development. - [Integration with EVerest](#integration-with-everest) - [Standalone Integration](#standalone-integration) - [Key Integration Points](#key-integration-points) - - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) - - [Register event callbacks and on_handlers](#register-event-callbacks-and-on_handlers) - - [Smart Charging](#smart-charging) + - [Callbacks to register](#callbacks-to-register) + - [Event handlers to call](#event-handlers-to-call) - [Initialize the database](#initialize-the-database) + - [OCPP 2.0.1 Use Cases](#ocpp-201-use-cases) - [Quickstart for OCPP 2.0.1](#quickstart-for-ocpp-201) - [Build and Install libocpp](#build-and-install-libocpp) - [Building the doxygen documentation](#building-the-doxygen-documentation) @@ -78,157 +78,75 @@ If you wish to integrate libocpp's OCPP 2.0.1 implementation directly into your ### Key Integration Points -1. **Callbacks**: Register these to allow libocpp to execute control commands defined in OCPP (e.g., Reset.req or RemoteStartTransaction.req). -2. **Event Handlers**: Implement these so your software can call libocpp's event handlers, enabling the library to track the charging station's state and trigger appropriate OCPP messages (e.g., MeterValues.req, StatusNotification.req). +1. **Callbacks**: Register these to allow libocpp to execute commands defined in OCPP (e.g., Reset.req or RemoteStartTransaction.req). +2. **Event Handlers**: Call these to notify libocpp of events, enabling the library to track the charging station's state and trigger appropriate OCPP messages (e.g., MeterValues.req, StatusNotification.req). + +> [!note] +> The public API for these integrations are found in the [ChargePoint](/include/ocpp/v201/charge_point.hpp). + + +### Callbacks to register + +| Callbacks | Description | +| ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| all_connectors_unavailable_callback | Notifies that all connectors are unavailable. Used to handle charge availability requests and firmware updates. | +| boot_notification_callback | Callback to notify of a system boot | +| clear_customer_information_callback | Called to clear customer information based on passed in Customer Certificate, the IdToken for this request, and the Customer Identified that the request refers to. If IdToken is passed in will delete authorization cache entry from database. | +| configure_network_connection_profile_callback | Called to configure a network connection profile when none is configured. | +| connector_effective_operative_status_changed_callback | Notifies the user of liboccp that the Operative/Inoperative state of a specific EVSE has changed. | +| cs_effective_operative_status_changed_callback | Used to notify the user of libocpp that the Operative/Inoperative state of the charging station itself has changed. Will also call evse_effective_operative_status_changed_callback for each EVSE, and connector_effective_operative_status_changed_callback for each connector whose status has changed. | +| data_transfer_callback | Used to handle arbitrary data transfers. | +| evse_effective_operative_status_changed_callback | Notifies the user of libocpp that the Operative/Inoperative state of an EVSE has changed. If as a result the state of connectors changed as well, libocpp will additionally call the connector_effective_operative_status_changed_callback for each connector. | +| get_customer_information_callback | Returns human readable customer information based on the CertificateHashDataType, IdToken and Customer Identifier passed in. | +| get_log_request_callback | Callback to return logs | +| is_reservation_for_token_callback | Check if the current reservation for the given evse id is made for the id token / group id token. | +| is_reset_allowed_callback | Callback if reset is allowed. If evse_id has a value, reset only applies to the given evse id. If it has no value, applies to complete charging station. | +| ocpp_messages_callback | Callback to congfigure ocpp message logging. | +| pause_charging_callback | Used to request pausing of charging, the "connector" parameter instructing which connector/EVSE to pause. | +| remote_start_transaction_callback | Called when the request can be accepted. The boolean authorize_remote_start indicates if Authorize.req needs to follow or not | +| reset_callback | Performs a reset of the requested type | +| security_event_callback | Used to react to a security event callback. This callback is called only if the SecurityEvent occured internally within libocpp. Typically this callback is used to log security events in the security log. | +| set_charging_profiles_callback | Indicates when a charging profile is received and accepted. | +| stop_transaction_callback | Used to stop a transaction. Called when the idTagInfo.status of a StartTransaction.conf is not Accepted, when a RemoteStopTransaction.req is received, or when an UnlockConnector.req is received. | +| time_sync_callback | Called on boot notification if the TimeSource ControllerComponent contains Heartbeat. | +| transaction_event_callback | Called when a transaction_event was sent to the CSMS. | +| transaction_event_response_callback | Called when a transaction_event_response was received from the CSMS. | +| unlock_connector_callback | Used by libocpp to force unlock a connector | +| update_firmware_request_callback | Initiates a firmware update request. Triggers a security event notification if the certificate is Invalid or Revoked. | +| validate_network_profile_callback | Validates the submitted Network Profile. Is Rejected if:
\- No callback registered to validate network profile
\- CSMS attempted to set a network profile with a lower securityProfile
\- CSMS attempted to set a network profile that could not be validated
\- Network profile could not be written to the device model storage | +| variable_changed_callback | Called when a variable has been changed by the CSMS | + +### Event handlers to call +**table** -The main interface for integration is the [ChargePoint](/include/ocpp/v201/charge_point.hpp) class. - -### Overview of the required callbacks and events and what libocpp expects to happen - -The following section will give you a high level overview of how to integrate libocpp with your application. Please use the [Doxygen Documentation](#building-the-doxygen-documentation) as an additional source for the ChargePoint API. - -In EVerest the OCPP module leverages several other modules to perform tasks that relate to authorization, reservations, charging session handling and system tasks like rebooting or firmware updates. - -- Auth orchestrates authorization, utilizing different token providers like RFID reads and token validators. Libocpp mainly acts as a token validator, but in the case of RemoteStartTransactions it acts as a token provider as well -- EvseManager manages the charging session and charging state machine by communicating with a "board support package", a driver for the charging hardware that abstracts away the control pilot, relay control, power meters, etc. The EvseManager also handles reservations. -- System handles firmware updates, log uploads and resets - -The following sections explain the steps you can follow to implement their functionality on your own and integrate the libocpp directly into your charging station software without relying on EVerest. However, in most cases it's much easier to write an EVerest driver using the *everest-core/interfaces/board_support_AC.yaml* interface. - -### Register event callbacks and on_handlers - -- `all_connectors_unavailable_callback` - - Notifies that all connectors are unavailable. Used to handle charge availability - requests and firmware updates. - -- `boot_notification_callback` - - Callback to notify of a system boot - -- `clear_customer_information_callback` - - Called to clear customer information based on passed in Customer Certificate, the - IdToken for this request, and the Customer Identified that the request refers to. - If IdToken is passed in will delete authorization cache entry from database. - -- `configure_network_connection_profile_callback` - - Called to configure a network connection profile when none is configured. - -- `connector_effective_operative_status_changed_callback` - - Notifies the user of liboccp that the Operative/Inoperative state of a specific EVSE - has changed. - -- `cs_effective_operative_status_changed_callback` - - Used to notify the user of libocpp that the Operative/Inoperative state of the - charging station itself has changed. Will also call - `evse_effective_operative_status_changed_callback` for each EVSE, and - `connector_effective_operative_status_changed_callback` for each connector whose - status has changed. - -- `data_transfer_callback` - - Used to handle arbitrary data transfers. - -- `evse_effective_operative_status_changed_callback` - - Notifies the user of libocpp that the Operative/Inoperative state of an EVSE has - changed. If as a result the state of connectors changed as well, libocpp will - additionally call the connector_effective_operative_status_changed_callback for - each connector. - -- `get_customer_information_callback` - - Returns human readable customer information based on the CertificateHashDataType, - IdToken and Customer Identifier passed in. - -- `get_log_request_callback` - - Callback to return logs - -- `is_reservation_for_token_callback` - - Check if the current reservation for the given evse id is made for the id - token / group id token. - -- `is_reset_allowed_callback` - - Callback if reset is allowed. If evse_id has a value, reset only applies - to the given evse id. If it has no value, applies to complete charging station. - -- `ocpp_messages_callback` - - Callback to congfigure ocpp message logging. - -- `pause_charging_callback` - - Used to request pausing of charging, the "connector" parameter instructing which - connector/EVSE to pause. - -- `remote_start_transaction_callback` - - Called when the request can be accepted. The boolean authorize_remote_start - indicates if Authorize.req needs to follow or not - -- `reset_callback` - - Performs a reset of the requested type - -- `security_event_callback` - - Used to react to a security event callback. This callback is - called only if the SecurityEvent occured internally within libocpp. - Typically this callback is used to log security events in the security log. - -- `set_charging_profiles_callback` - - Indicates when a charging profile is received and accepted. - -- `stop_transaction_callback` - - Used to stop a transaction. Called when the idTagInfo.status of a - StartTransaction.conf is not Accepted, when a RemoteStopTransaction.req is - received, or when an UnlockConnector.req is received. - -- `time_sync_callback` - - Called on boot notification if the TimeSource ControllerComponent contains - Heartbeat. - -- `transaction_event_callback` - - Called when a transaction_event was sent to the CSMS. - -- `transaction_event_response_callback` - - Called when a transaction_event_response was received from the CSMS. - -- `unlock_connector_callback` - - Used by libocpp to force unlock a connector - -- `update_firmware_request_callback` - - Initiates a firmware update request. Triggers a security event notification - if the certificate is Invalid or Revoked. - -- `validate_network_profile_callback` - - Validates the submitted Network Profile. Is Rejected if - - No callback registered to validate network profile - - CSMS attempted to set a network profile with a lower securityProfile - - CSMS attempted to set a network profile that could not be validated - - Network profile could not be written to the device model storage - -- `variable_changed_callback` +### Initialize the database - Called when a variable has been changed by the CSMS +Use [provided SQLite database](/doc/database_migrations.md) or implement your own storage drive. + +### OCPP 2.0.1 Use Cases + +| Clause | Use Case Name | +| ------ | --------------------------------- | +| A | Security | +| B | Provisioning | +| C | Authorization | +| D | LocalAuthorizationList Management | +| E | Transactions | +| F | RemoteControl | +| G | Availability | +| H | Reservation | +| I | TariffAndCost | +| J | MeterValues | +| K | SmartCharging | +| L | FirmwareManagement | +| M | ISO 15118 CertificateManagement | +| N | Diagnostics | +| O | DisplayMessage | +| P | DataTransfer | ### Smart Charging +Smart Charging is a use case within OCPP. Work to fully support OCPP 2.0.1 Smart Charging is ongoing. Most functional requirements for General Smart Charging use cases (that is, K01–K10) are now supported. For an up-to-date overview of which features are currently supported, please refer to the [OCPP 2.0.1 Status](/doc/ocpp_201_status.md) document. #### K01 SetChargingProfile @@ -481,9 +399,7 @@ sequenceDiagram end ``` -### Initialize the database -- Use provided sql database or implement your own storage drive ## Quickstart for OCPP 2.0.1 From b4f61af5fbb9a3b0ba15c5323df55ec6566ed108 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 11:30:17 -0400 Subject: [PATCH 055/134] Update ocpp_201_README.md update table of contents Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 63 +++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 25 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 0a2e201fb..40eedfd7d 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -36,7 +36,7 @@ OCPP 2.0.1 is currently under development. The development of OCPP 2.0.1 implementation is in progress — [OCPP 2.0.1 status](/doc/ocpp_201_status.md). The following table shows the current support for OCPP 2.0.1 functionalities in libocpp: | OCPP 2.0.1 Functionality | Supported | -| -------------------------- | -------------------------- | +| :------------------------- | :------------------------- | | Core | :heavy_check_mark: Yes | | Advanced Security | :construction: In Progress | | Local Auth List Management | :hourglass: Planned | @@ -47,7 +47,7 @@ The development of OCPP 2.0.1 implementation is in progress — [OCPP 2.0.1 stat | ISO 15118 support | :construction: In Progress | | Whitepapers & Application Notes | Supported | -| -------------------------------------- | -------------------------- | +| :------------------------------------- | :------------------------- | | OCPP & California Pricing Requirements | :construction: In Progress | @@ -88,7 +88,7 @@ If you wish to integrate libocpp's OCPP 2.0.1 implementation directly into your ### Callbacks to register | Callbacks | Description | -| ----------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| :---------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | all_connectors_unavailable_callback | Notifies that all connectors are unavailable. Used to handle charge availability requests and firmware updates. | | boot_notification_callback | Callback to notify of a system boot | | clear_customer_information_callback | Called to clear customer information based on passed in Customer Certificate, the IdToken for this request, and the Customer Identified that the request refers to. If IdToken is passed in will delete authorization cache entry from database. | @@ -125,8 +125,8 @@ Use [provided SQLite database](/doc/database_migrations.md) or implement your ow ### OCPP 2.0.1 Use Cases -| Clause | Use Case Name | -| ------ | --------------------------------- | +| Clause | Use Case Name | +| :----- | :-------------------------------- | | A | Security | | B | Provisioning | | C | Authorization | @@ -399,7 +399,7 @@ sequenceDiagram end ``` - +----- ## Quickstart for OCPP 2.0.1 @@ -436,17 +436,17 @@ Use the following command to start the charge point. Replace the config with [co Type `help` to see a list of possible commands. -## Building the doxygen documentation + +In the libocpp folder create a folder named build and cd into it. +Execute cmake and then make install: ```bash - cmake -S . -B build - cmake --build build --target doxygen-ocpp + mkdir build && cd build + cmake .. + make install ``` -You will find the generated doxygen documentation at: -`build/dist/docs/html/index.html` - -The main reference for the integration of libocpp for OCPP2.0.1 is the ocpp::v201::ChargePoint class defined in libocpp/include/ocpp/v201/charge_point.hpp. +----- ## Build and install libocpp @@ -464,14 +464,13 @@ Clone this repository. git clone https://github.com/EVerest/libocpp ``` -In the libocpp folder create a folder named build and cd into it. -Execute cmake and then make install: +----- -```bash - mkdir build && cd build - cmake .. - make install -``` +## Building with FetchContent instead of EDM + +In [doc/build-with-fetchcontent](/doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. + +----- ## Unit testing @@ -490,11 +489,23 @@ make -j$(nproc) install Run any required tests from build/tests. -## Building with FetchContent instead of EDM +----- -In [doc/build-with-fetchcontent](/doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. +## Building the doxygen documentation + +```bash + cmake -S . -B build + cmake --build build --target doxygen-ocpp +``` + +You will find the generated doxygen documentation at: +`build/dist/docs/html/index.html` + +The main reference for the integration of libocpp for OCPP2.0.1 is the ocpp::v201::ChargePoint class defined in libocpp/include/ocpp/v201/charge_point.hpp. + +----- -### Support for TPM keys +## Support for TPM keys In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. @@ -506,7 +517,9 @@ The old websocket++ implementation has been deprecated. For enabling websocket++ cmake .. -DLIBOCPP_ENABLE_DEPRECATED_WEBSOCKETPP=ON ``` -### Support for iface +----- + +## Support for iface In order to connect through a custom network iface, a custom internal config variable 'IFace' can be used. @@ -516,7 +529,7 @@ In order to connect through a custom network iface, a custom internal config var } ``` ---- +----- ## Get Involved From 3f690377021e6f407b6144b470f901529a8159db Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 11:38:03 -0400 Subject: [PATCH 056/134] Update ocpp_201_README.md update table of contents Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 40eedfd7d..5f8a752da 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -26,10 +26,9 @@ OCPP 2.0.1 is currently under development. - [OCPP 2.0.1 Use Cases](#ocpp-201-use-cases) - [Quickstart for OCPP 2.0.1](#quickstart-for-ocpp-201) - [Build and Install libocpp](#build-and-install-libocpp) -- [Building the doxygen documentation](#building-the-doxygen-documentation) -- [Unit testing](#unit-testing) - [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) - +- [Unit testing](#unit-testing) +- [Building the doxygen documentation](#building-the-doxygen-documentation) ## Functionality Support @@ -509,6 +508,8 @@ The main reference for the integration of libocpp for OCPP2.0.1 is the ocpp::v20 In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. +----- + ## Support for websocket++ The old websocket++ implementation has been deprecated. For enabling websocket++ support use the following cmake option: From 05656d1123910756239f61015614790c29a31233 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 4 Oct 2024 11:58:26 -0400 Subject: [PATCH 057/134] Update ocpp_201_README.md removed contribution call out Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 5f8a752da..5e9d9a741 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -530,9 +530,3 @@ In order to connect through a custom network iface, a custom internal config var } ``` ------ - -## Get Involved - -See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. - From 0075a4fb070f6cb3022bc0311af23a10cc3982b1 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Mon, 7 Oct 2024 14:01:15 -0400 Subject: [PATCH 058/134] Update ocpp_16_README.md Updated standalone integration section Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index e2c3978df..9cbe38710 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -12,7 +12,6 @@ This C++ library provides a complete and production-ready solution for integrati - [CSMS Compatibility](#csms-compatibility) - [Integration with EVerest](#integration-with-everest) - [Standalone Integration](#standalone-integration) - - [Key Integration Points](#key-integration-points) - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) - [Usage for OCPP 1.6](#usage-for-ocpp-16) - [ChargePoint() constructor](#chargepoint-constructor) @@ -93,14 +92,15 @@ When you run libocpp with OCPP 1.6 through EVerest, the build process of everest ## Standalone Integration -If you wish to integrate libocpp's OCPP 1.6 implementation directly into your charging station software without using the full EVerest stack, you'll need to register several **callbacks** and implement **event handlers**. This allows libocpp to interact with your charging station according to OCPP requirements. +OCPP is a protocol that affects, controls and monitors many areas of a charging station's operation. -### Key Integration Points +If you want to integrate this library with your charging station implementation, you have to register a couple of **callbacks** and integrate **event handlers**. This is necessary for the library to interact with your charging station according to the requirements of OCPP. -1. **Callbacks**: Register these to allow libocpp to execute control commands defined in OCPP (e.g., Reset.req or RemoteStartTransaction.req). -2. **Event Handlers**: Implement these so your software can call libocpp's event handlers, enabling the library to track the charging station's state and trigger appropriate OCPP messages (e.g., MeterValues.req, StatusNotification.req). +Libocpp needs registered **callbacks** in order to execute control commands defined within OCPP (e.g Reset.req or RemoteStartTransaction.req) -The main interface for integration is the [ChargePoint](/include/ocpp/v16/charge_point.hpp) class. +The implementation must call **event handlers** of libocpp so that the library can track the state of the charging station and trigger OCPP messages accordingly (e.g. MeterValues.req , StatusNotification.req) + +Your reference within libocpp to interact is a single instance to the class [ChargePoint](/include/ocpp/v16/charge_point.hpp) for OCPP 1.6 ### Overview of the required callbacks and events and what libocpp expects to happen From 5025ea84431d52b5b1c9374789c8cf7216090802 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Mon, 7 Oct 2024 14:24:39 -0400 Subject: [PATCH 059/134] Update README.md updated intro text Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 89cddf88b..455feaee7 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,8 @@ # EVerest OCPP Module (libocpp) -The EVerest OCPP module, also known as libocpp, is a C++ implementation of the Open Charge Point Protocol (OCPP) versions 1.6 and 2.0.1. It is designed to seamlessly integrate with the EVerest software stack for electric vehicle (EV) charging stations. +EVerest's Open Charge Point Protocol (OCPP) modules are based on `libocpp`, a standalone C++ library implementing client-side OCPP 1.6 and 2.0.1 communications. The library is designed to enable OCPP communications in electric vehicle charging stations, regardless of whether or not the stations are running EVerest. + ### What is OCPP? From 64fd9089323e9e05433427ff3d918430f7e20ae1 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Mon, 7 Oct 2024 14:38:13 -0400 Subject: [PATCH 060/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 9cbe38710..3840cbbd2 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -118,7 +118,7 @@ The following sections explain the steps you can follow to implement their funct #### ChargePoint() constructor -The main entrypoint for libocpp for OCPP1.6 is the ocpp::v16::ChargePoint constructor. +The main entrypoint for `libocpp` for OCPP 1.6 is the `ocpp::v16::ChargePoint` constructor. This is defined in libocpp/include/ocpp/v16/charge_point.hpp and takes the following parameters: - config: a std::string that contains the libocpp 1.6 config. There are example configs that work with a [SteVe](https://github.com/steve-community/steve) installation [running in Docker](https://github.com/EVerest/everest-utils/tree/main/docker/steve), for example: [config-docker.json](/config/v16/config-docker.json) From 2f9b882fe56bf2c5019e6543cc886ea9a9937d5f Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:55:34 -0400 Subject: [PATCH 061/134] Update README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 455feaee7..6375d2b7b 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ EVerest's Open Charge Point Protocol (OCPP) modules are based on `libocpp`, a st ### What is OCPP? -OCPP is an open standard for communication between EV charging stations and central management systems. Developed by the Open Charge Alliance (OCA), OCPP ensures interoperability among various charging station manufacturers and management systems, playing a vital role in the EV infrastructure. +[OCPP](https://en.wikipedia.org/wiki/Open_Charge_Point_Protocol) is an open standard for communication between EV charging stations and central management systems. Developed by the [Open Charge Alliance (OCA)](https://openchargealliance.org/), OCPP ensures interoperability among various charging station manufacturers and management systems, playing a vital role in the EV charging ecosystem. ## Table of Contents From c4feac2e926ee5bc9817eab869f09d7fbb6378ca Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:55:53 -0400 Subject: [PATCH 062/134] Update README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6375d2b7b..722cd8ed2 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ --- -# EVerest OCPP Module (libocpp) +# EVerest OCPP Module (`libocpp`) EVerest's Open Charge Point Protocol (OCPP) modules are based on `libocpp`, a standalone C++ library implementing client-side OCPP 1.6 and 2.0.1 communications. The library is designed to enable OCPP communications in electric vehicle charging stations, regardless of whether or not the stations are running EVerest. From e93b0690c9c7cc3314fe7e832f20fdaa1abcde55 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:56:10 -0400 Subject: [PATCH 063/134] Update README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 722cd8ed2..11a1aeb8b 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ # EVerest OCPP Module (`libocpp`) -EVerest's Open Charge Point Protocol (OCPP) modules are based on `libocpp`, a standalone C++ library implementing client-side OCPP 1.6 and 2.0.1 communications. The library is designed to enable OCPP communications in electric vehicle charging stations, regardless of whether or not the stations are running EVerest. +EVerest's Open Charge Point Protocol (OCPP) modules are based on this library—`libocpp`—a standalone C++ library implementing client-side OCPP 1.6 and 2.0.1 communications. This library can be used independently of EVerest to enable OCPP communication for a charging station. ### What is OCPP? From 1422eddce301756a51ebb98665b81cfab48ab894 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:56:18 -0400 Subject: [PATCH 064/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 3840cbbd2..693955d04 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -12,7 +12,7 @@ This C++ library provides a complete and production-ready solution for integrati - [CSMS Compatibility](#csms-compatibility) - [Integration with EVerest](#integration-with-everest) - [Standalone Integration](#standalone-integration) - - [Overview of the required callbacks and events and what libocpp expects to happen](#overview-of-the-required-callbacks-and-events-and-what-libocpp-expects-to-happen) + - [Overview of Expected Callbacks and Event Handlers](#overview-of-expected-callbacks-and-event-handlers) - [Usage for OCPP 1.6](#usage-for-ocpp-16) - [ChargePoint() constructor](#chargepoint-constructor) - [registering callbacks](#registering-callbacks) From 15152a4de07f6a13a5a3e27575fcb7002b0ac699 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:56:29 -0400 Subject: [PATCH 065/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 693955d04..77c27ca77 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -51,7 +51,7 @@ The EVerest OCPP 1.6 implementation (libocpp) provides comprehensive support for The EVerest implementation of OCPP 1.6 has been tested against the OCPP Compliance Test Tool (OCTT and OCTT2) during the implementation. -The following table shows CSMS with which this library was tested. +The following table shows CSMSs with which this library was tested. If you provide a CSMS that is not yet listed here, feel free to [contact us](https://lists.lfenergy.org/g/everest)! From 40594e39d85c6da878b586c0f20cfc175e9641c4 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:56:43 -0400 Subject: [PATCH 066/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 77c27ca77..b8bac34cb 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -104,7 +104,7 @@ Your reference within libocpp to interact is a single instance to the class [Cha ### Overview of the required callbacks and events and what libocpp expects to happen -The following section will give you a high level overview of how to integrate libocpp with your application. Please use the [Doxygen Documentation](#building-the-doxygen-documentation) as an additional source for the ChargePoint API. +The following section will give you a high-level overview of how to integrate `libocpp` with your application. Please use the [Doxygen documentation](#building-the-doxygen-documentation) as an additional source of information about the `ChargePoint` API. In EVerest the OCPP module leverages several other modules to perform tasks that relate to authorization, reservations, charging session handling and system tasks like rebooting or firmware updates. From a99599cbcd53f7c1595c71e699b8b26f245da653 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:56:49 -0400 Subject: [PATCH 067/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index b8bac34cb..22327cd54 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -94,7 +94,7 @@ When you run libocpp with OCPP 1.6 through EVerest, the build process of everest OCPP is a protocol that affects, controls and monitors many areas of a charging station's operation. -If you want to integrate this library with your charging station implementation, you have to register a couple of **callbacks** and integrate **event handlers**. This is necessary for the library to interact with your charging station according to the requirements of OCPP. +> [!IMPORTANT] Integrating this library with your charging station requires both (a) defining **callbacks** that enable control of your station by `libocpp` and (b) calling `libocpp` **event handlers** in your charging station's systems in response to new events and data in order to keep `libocpp` up to date on station information. Libocpp needs registered **callbacks** in order to execute control commands defined within OCPP (e.g Reset.req or RemoteStartTransaction.req) From 19e9613295243c9081a0b21be4858cf36a22e85e Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:57:02 -0400 Subject: [PATCH 068/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 22327cd54..150357f51 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -92,7 +92,9 @@ When you run libocpp with OCPP 1.6 through EVerest, the build process of everest ## Standalone Integration -OCPP is a protocol that affects, controls and monitors many areas of a charging station's operation. +OCPP is a protocol that affects, controls, and monitors many areas of a charging station's operation. The `libocpp` library is just the messenger for this protocol. It is intended to provide mechanisms for connecting to and authenticating with a CSMS, sending and receiving the OCPP messages that govern behaviors in the standard, and to the track state required for a charging station to conform to the protocol all while minimizing hardware- or implementation-specific functionality. + +The actual substance of how a charging station reacts to or initiates an OCPP command (such as `Reset.req` or `RemoteStartTransaction.req`) is left to the rest of the charging station's systems. This is done by providing means of (a) registering **callbacks** that can be triggered by a `libocpp` `ChargePoint` in response to certain events and (b) reacting to various **event handlers** defined on a `ChargePoint` in other areas of the charging station's codebase. > [!IMPORTANT] Integrating this library with your charging station requires both (a) defining **callbacks** that enable control of your station by `libocpp` and (b) calling `libocpp` **event handlers** in your charging station's systems in response to new events and data in order to keep `libocpp` up to date on station information. From 8b972eba12753309bbc00090d6dfbc097f18223d Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 08:57:22 -0400 Subject: [PATCH 069/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 150357f51..d5dee4345 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -98,11 +98,14 @@ The actual substance of how a charging station reacts to or initiates an OCPP co > [!IMPORTANT] Integrating this library with your charging station requires both (a) defining **callbacks** that enable control of your station by `libocpp` and (b) calling `libocpp` **event handlers** in your charging station's systems in response to new events and data in order to keep `libocpp` up to date on station information. -Libocpp needs registered **callbacks** in order to execute control commands defined within OCPP (e.g Reset.req or RemoteStartTransaction.req) +### Terminology +Throughout this document and the `libocpp` codebase, the following conventions are followed: -The implementation must call **event handlers** of libocpp so that the library can track the state of the charging station and trigger OCPP messages accordingly (e.g. MeterValues.req , StatusNotification.req) +- A **callback** is a function providing the actual station-specific implementation of an OCPP command. It allows a `libocpp` `ChargePoint` to control other systems within a charging station. By convention, each callback on a `ChargePoint` has a name suffixed with `_callback` (for instance, `unlock_connector_callback`). A suitable `std::function` can be **registered** as a callback on a `ChargePoint` by providing it as an argument for the relevant `register_` function (such as `register_unlock_connector_callback`). -Your reference within libocpp to interact is a single instance to the class [ChargePoint](/include/ocpp/v16/charge_point.hpp) for OCPP 1.6 +- An **event handler** is a public function defined on a `ChargePoint` that allows a charging station to update the state being tracked by the `ChargePoint` based on new information (meter values, charging session events, etc.) and (indirectly) send messages to a CSMS. By convention, the names of event handlers on the `ChargePoint` are each prefixed with `on_` (for instance, `on_meter_values`). + +The complete set of callbacks and event handlers defined on an OCPP 1.6 `ChargePoint` can be viewed in the latter's [header file](/include/ocpp/v16/charge_point.hpp). ### Overview of the required callbacks and events and what libocpp expects to happen From 85a1e8d9bd351f50b014f115d9c0f41d32d82817 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 09:25:16 -0400 Subject: [PATCH 070/134] Add files via upload updated banner Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/img/banner-ocpp.jpg | Bin 83550 -> 112746 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/img/banner-ocpp.jpg b/doc/img/banner-ocpp.jpg index 0de869d3d80432446bcb9549c7da610c857dc2b7..62a61c1e7316f20efa6f7e33e4d3da6515eea934 100644 GIT binary patch delta 97783 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

I(vW8=Ccz2D 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

p99z#^EtoRl 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

GLtEEfA75%yhmb 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:v`{0!3Yn=;3{lA&FPxpaQ3< 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 Date: Tue, 8 Oct 2024 11:25:25 -0400 Subject: [PATCH 071/134] Add files via upload Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/img/banner-ocpp.jpg | Bin 112746 -> 111686 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/img/banner-ocpp.jpg b/doc/img/banner-ocpp.jpg index 62a61c1e7316f20efa6f7e33e4d3da6515eea934..63c75beea8d58f7b55a574510a4bef13bae8fc42 100644 GIT binary patch delta 94428 zcmb5VcRZVW{5PC)I#E@7b6V71MQu49w5TmMsV!8ks_km+?bxk(lr&bPM(j}{6h-aY z5=E^_tOk+X`Tg$ud0zMZd;Ol*^E~+@*XxyB$@R^Z&w7vVHsNaj&#Rvr83D0NTd29o z6Qzp^z)RD{K=dS(B)JAnd^o=)h2{@1sEaosyiN`jc5`W-?Fc|E!nAIFLuB4^O=7gQ zYbbW%j#H%rk*sG~T{P4U%tr&B$z02q@rA3l;ytnI%1`LD&HJWxe=ez+>Q_Ih%>D7c z)=&9H`z0u=`>;etQY@Fc128Q)^&b7LS!MUG2^(35X_iD_3RLz1!trR1eFZ2J9eKzc+ME;E{{y z@{(5(vE@`yPp!bEIClG>lYZiBxL@5P{cxWFkQ3 zSyHnZRDRR_qQ$)vFz>VRNv6ZvL+1f=nXzm_)w}n*lz9g=@9jh*|v2y=Q_Nz zX5utu0JALg8KGwGv7tD<5G;`fVbMGLR?P!(IrE=LwG1F4`ii-UqS1j%X1x?y0;L%T zW%bAdjGU3dL4ElUN__1WXI(5z>exWYycsIW#V#A~_bn?)Lm0} zp>z$t7KefKp%me!A6X~JU9W+Nh*My7RyO|5xCs^XLXZc2qO%iAdQ>W1>VSKZp0?~N zS}5QBT)jGoNCn|F*FsPfBrXJ;cdmz0rd&DJ2Y$qtQ9-w=8GTOqW;gba)m~FUpCju4 z@;f3lL6G2u>hlu2n}>t$`K_W@?fx0LT0*>pi)>%@V6H!REU+X1n@N=0gMZNrE&1m2 zJt&eKk?kYZM^TlgO^kJ1_M#Ufz zLJ7U*|90|iS@d<6G&scnh~E>Uf-cim5%q@h)gnKw9l!GSEIp0P4)6V~9H~xH4H4{1 zrC*-8o-!NMeC7aTuth3;JKEvu2^%r$(_)=a{O)X-wdc*}uSQAE49@8}-7VE;%E!

wK2#Jub}9Jv>8NZ&;`eg2 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 j Date: Tue, 8 Oct 2024 12:27:20 -0400 Subject: [PATCH 072/134] Update ocpp_16_README.md Converted callbacks and on_ functions to tables Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 194 +++++++++--------------------------------- 1 file changed, 41 insertions(+), 153 deletions(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index d5dee4345..88bfb54ac 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -224,167 +224,55 @@ TODO: in a future version of libocpp the callbacks will be organised in a struct Some general notes: the "connector" parameter of some of the callbacks refers to the connector number as understood in the OCPP 1.6 specification, "0" means the whole charging station, the connectors with EVSEs used for charging cars start at "1". -- `register_pause_charging_callback` - - this callback is used by libocpp to request pausing of charging, the "connector" parameter tells you which connector/EVSE has to pause charging - -- `register_resume_charging_callback` - - this callback is used by libocpp the request resuming of charging, the "connector" parameter tells you which connector/EVSE can resume charging - -- `register_stop_transaction_callback` - - in EVerest this calls the EvseManagers stop_transaction command which "Stops transactions and cancels charging externally, charging can only be resumed by replugging car. EVSE will also stop transaction automatically e.g. on disconnect, so this only needs to be called if the transaction should end before." - this will then signal the following events: - - ChargingFinished - - TransactionFinished - -- `register_unlock_connector_callback` - - can be used by libocpp to force unlock a connector - -- `register_reserve_now_callback` - - libocpp can use this to reserve a connector, reservation handling is outsourced to a reservation manager in EVerest that implements the reservation interface (everest-core/interfaces/reservation.yaml) - -- `register_upload_diagnostics_callback` - - uses a function (in EVerest provided by the System module) to upload the requested diagnostics file - -- `register_upload_logs_callback` - - uses a function (in EVerest provided by the System module) to upload the requested log file - -- `register_update_firmware_callback` - - uses a function (in EVerest provided by the System module) to perform a firmware update - -- `register_signed_update_firmware_callback` - - uses a function (in EVerest provided by the System module) to perform a signed firmware update - -- `register_provide_token_callback` - - this callback is used in a remote start transaction to provide a token (prevalidated or not) to the authorization system - -- `register_set_connection_timeout_callback` - - used by libocpp to set the authorization or plug in connection timeout in the authorization system based on the "ConnectionTimeout" configuration key - -- `register_disable_evse_callback` - - used to disable the EVSE (ChangeAvailability.req) - -- `register_enable_evse_callback` - - used to enable the EVSE (ChangeAvailability.req) - -- `register_cancel_reservation_callback` - - used to cancel a reservation in the reservation manager (CancelReservation.req) - -- `register_signal_set_charging_profiles_callback` - - used to signal that new charging schedule(s) have been set, you can then use - get_all_composite_charging_schedules(duration_s) to get the new valid charging schedules - -- `register_is_reset_allowed_callback` - - used to inquire (in EVerest from the System module) if a reset is allowed - -- `register_reset_callback` - - used to perform a reset of the requested type - -- `register_connection_state_changed_callback` - - used to inform about the connection state to the CSMS (connected = true, disconnected = false) - -- `register_configuration_key_changed_callback` - - used to react on a changed configuration key. This callback is called when the specified configuration key has been changed by the CSMS +| Callbacks | Description | +| :----------------------------------------------- | :-------------------------------------- | +| `register_pause_charging_callback` | this callback is used by libocpp to request pausing of charging, the "connector" parameter tells you which connector/EVSE has to pause charging | +| `register_resume_charging_callback` | this callback is used by libocpp the request resuming of charging, the "connector" parameter tells you which connector/EVSE can resume charging | +| `register_stop_transaction_callback` | in EVerest this calls the EvseManagers stop_transaction command which "Stops transactions and cancels charging externally, charging can only be resumed by replugging car. EVSE will also stop transaction automatically e.g. on disconnect, so this only needs to be called if the transaction should end before." this will then signal the following events:
• ChargingFinished
• TransactionFinished | +| `register_unlock_connector_callback` | can be used by libocpp to force unlock a connector | +| `register_reserve_now_callback` | libocpp can use this to reserve a connector, reservation handling is outsourced to a reservation manager in EVerest that implements the reservation interface (everest-core/interfaces/reservation.yaml) | +| `register_upload_diagnostics_callback` | uses a function (in EVerest provided by the System module) to upload the requested diagnostics file | +| `register_upload_logs_callback` | uses a function (in EVerest provided by the System module) to upload the requested log file | +| `register_update_firmware_callback` | uses a function (in EVerest provided by the System module) to perform a firmware update | +| `register_signed_update_firmware_callback` | uses a function (in EVerest provided by the System module) to perform a signed firmware update | +| `register_provide_token_callback` | this callback is used in a remote start transaction to provide a token (prevalidated or not) to the authorization system | +| `register_set_connection_timeout_callback` | used by libocpp to set the authorization or plug in connection timeout in the authorization system based on the "ConnectionTimeout" configuration key | +| `register_disable_evse_callback` | used to disable the EVSE (ChangeAvailability.req) | +| `register_enable_evse_callback` | used to enable the EVSE (ChangeAvailability.req) | +| `register_cancel_reservation_callback` | used to cancel a reservation in the reservation manager (CancelReservation.req) | +| `register_signal_set_charging_profiles_callback` | used to signal that new charging schedule(s) have been set, you can then use get_all_composite_charging_schedules(duration_s) to get the new valid charging schedules | +| `register_is_reset_allowed_callback` | used to inquire (in EVerest from the System module) if a reset is allowed | +| `register_reset_callback` | used to perform a reset of the requested type | +| `register_connection_state_changed_callback` | used to inform about the connection state to the CSMS (connected = true, disconnected = false) | +| `register_configuration_key_changed_callback` | used to react on a changed configuration key. This callback is called when the specified configuration key has been changed by the CSMS | #### Functions that need to be triggered from the outside after new information is availble (on_... functions in the charge point API) -- `on_log_status_notification(int32_t request_id, std::string log_status)` - - can be used to notify libocpp of a log status notification - -- `on_firmware_update_status_notification(int32_t request_id, std::string firmware_update_status)` - - can be used to notify libocpp of a firmware update status notification - -- `on_meter_values(int32_t connector, const Powermeter& powermeter)` - - provides a Powermeter struct to libocpp (for sending meter values during charging sessions or periodically) - -- `on_max_current_offered(int32_t connector, int32_t max_current)` - - the maximum current offered to the EV on this connector (in ampere) +| on_ functions | Description | +| :-------- | :---------- | +| `on_log_status_notification(int32_t request_id, std::string log_status)` | can be used to notify libocpp of a log status notification | +| `on_firmware_update_status_notification(int32_t request_id, std::string firmware_update_status)` | can be used to notify libocpp of a firmware update status notification | +| `on_meter_values(int32_t connector, const Powermeter& powermeter)` | provides a Powermeter struct to libocpp (for sending meter values during charging sessions or periodically) | +| `on_max_current_offered(int32_t connector, int32_t max_current)` | the maximum current offered to the EV on this connector (in ampere) | #### The following functions are triggered depending on different so called "Session Events" from the EvseManager each of these functions will have a small note what the Session Event was and what it triggers in libocpp -- `on_enabled(int32_t connector)` - - Notifies libocpp that the connector is functional and operational - -- `on_disabled(int32_t connector)` - - Notifies libocpp that the connector is disabled - -- `on_transaction_started` - - Notifies libocpp that a transaction at the given connector has started, this means that authorization is available and the car is plugged in. - - Some of its parameters: - - - `session_id` is an internal session_id originating in the EvseManager to keep track of the transaction, this is NOT to be mistaken for the transactionId from the StartTransactionResponse in OCPP! - - `id_token` is the token with which the transaction was authenticated - - `meter_start` contains the meter value in Wh for the connector at start of the transaction - - `timestamp` at the start of the transaction - -- `on_transaction_stopped` - - Notifies libocpp that the transaction on the given connector with the given reason has been stopped. - - Some of its parameters: - - - `timestamp` at the end of the transaction - - `energy_wh_import` contains the meter value in Wh for the connector at end of the transaction - -- `on_suspend_charging_ev` - - Notifies libocpp that the EV has paused charging - -- `on_suspend_charging_evse` - - Notifies libocpp that the EVSE has paused charging - -- `on_resume_charging` - - Notifies libocpp that charging has resumed - -- `on_session_started` - - this is mostly used for logging and changing the connector state - -- `on_session_stopped` - - this is mostly used for logging and changing the connector state - -- `on_error` - - Notify libocpp of an error - -- `on_reservation_start` - - Notifies libocpp that a reservation has started - -- `on_reservation_end` - - Notifies libocpp that a reservation has ended +| on _ functions | Description | +| :------------------------------- | :----------------------------------------- | +| `on_enabled(int32_t connector)` | Notifies libocpp that the connector is functional and operational | +| `on_disabled(int32_t connector)` | Notifies libocpp that the connector is disabled | +| `on_transaction_started` | Notifies libocpp that a transaction at the given connector has started, this means that authorization is available and the car is plugged in.
Some of its parameters:
• session_id is an internal session_id originating in the EvseManager to keep track of the transaction, this is NOT to be mistaken for the transactionId from the StartTransactionResponse in OCPP!
• id_token is the token with which the transaction was authenticated
• meter_start contains the meter value in Wh for the connector at start of the transaction
• timestamp at the start of the transaction
| +| `on_transaction_stopped` | Notifies libocpp that the transaction on the given connector with the given reason has been stopped.
Some of its parameters:
• timestamp at the end of the transaction
• energy_wh_import contains the meter value in Wh for the connector at end of the transaction
| +| `on_suspend_charging_ev` | Notifies libocpp that the EV has paused charging | +| `on_suspend_charging_evse` | Notifies libocpp that the EVSE has paused charging | +| `on_resume_charging` | Notifies libocpp that charging has resumed | +| `on_session_started` | this is mostly used for logging and changing the connector state | +| `on_session_stopped` | this is mostly used for logging and changing the connector state | +| `on_error` | Notify libocpp of an error | +| `on_reservation_start` | Notifies libocpp that a reservation has started | +| `on_reservation_end` | Notifies libocpp that a reservation has ended | #### Authorization From 1350e8d3ddd5c6419fa8f37bc68587c3e0da2a85 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 12:45:00 -0400 Subject: [PATCH 073/134] Update ocpp_201_README.md Added `` to callbacks Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 56 +++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 5e9d9a741..cd053a16f 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -86,34 +86,34 @@ If you wish to integrate libocpp's OCPP 2.0.1 implementation directly into your ### Callbacks to register -| Callbacks | Description | -| :---------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| all_connectors_unavailable_callback | Notifies that all connectors are unavailable. Used to handle charge availability requests and firmware updates. | -| boot_notification_callback | Callback to notify of a system boot | -| clear_customer_information_callback | Called to clear customer information based on passed in Customer Certificate, the IdToken for this request, and the Customer Identified that the request refers to. If IdToken is passed in will delete authorization cache entry from database. | -| configure_network_connection_profile_callback | Called to configure a network connection profile when none is configured. | -| connector_effective_operative_status_changed_callback | Notifies the user of liboccp that the Operative/Inoperative state of a specific EVSE has changed. | -| cs_effective_operative_status_changed_callback | Used to notify the user of libocpp that the Operative/Inoperative state of the charging station itself has changed. Will also call evse_effective_operative_status_changed_callback for each EVSE, and connector_effective_operative_status_changed_callback for each connector whose status has changed. | -| data_transfer_callback | Used to handle arbitrary data transfers. | -| evse_effective_operative_status_changed_callback | Notifies the user of libocpp that the Operative/Inoperative state of an EVSE has changed. If as a result the state of connectors changed as well, libocpp will additionally call the connector_effective_operative_status_changed_callback for each connector. | -| get_customer_information_callback | Returns human readable customer information based on the CertificateHashDataType, IdToken and Customer Identifier passed in. | -| get_log_request_callback | Callback to return logs | -| is_reservation_for_token_callback | Check if the current reservation for the given evse id is made for the id token / group id token. | -| is_reset_allowed_callback | Callback if reset is allowed. If evse_id has a value, reset only applies to the given evse id. If it has no value, applies to complete charging station. | -| ocpp_messages_callback | Callback to congfigure ocpp message logging. | -| pause_charging_callback | Used to request pausing of charging, the "connector" parameter instructing which connector/EVSE to pause. | -| remote_start_transaction_callback | Called when the request can be accepted. The boolean authorize_remote_start indicates if Authorize.req needs to follow or not | -| reset_callback | Performs a reset of the requested type | -| security_event_callback | Used to react to a security event callback. This callback is called only if the SecurityEvent occured internally within libocpp. Typically this callback is used to log security events in the security log. | -| set_charging_profiles_callback | Indicates when a charging profile is received and accepted. | -| stop_transaction_callback | Used to stop a transaction. Called when the idTagInfo.status of a StartTransaction.conf is not Accepted, when a RemoteStopTransaction.req is received, or when an UnlockConnector.req is received. | -| time_sync_callback | Called on boot notification if the TimeSource ControllerComponent contains Heartbeat. | -| transaction_event_callback | Called when a transaction_event was sent to the CSMS. | -| transaction_event_response_callback | Called when a transaction_event_response was received from the CSMS. | -| unlock_connector_callback | Used by libocpp to force unlock a connector | -| update_firmware_request_callback | Initiates a firmware update request. Triggers a security event notification if the certificate is Invalid or Revoked. | -| validate_network_profile_callback | Validates the submitted Network Profile. Is Rejected if:
\- No callback registered to validate network profile
\- CSMS attempted to set a network profile with a lower securityProfile
\- CSMS attempted to set a network profile that could not be validated
\- Network profile could not be written to the device model storage | -| variable_changed_callback | Called when a variable has been changed by the CSMS | +| callbacks | description | +| :------------------------------------------------------ | :---------- | +| `all_connectors_unavailable_callback` | Notifies that all connectors are unavailable. Used to handle charge availability requests and firmware updates. | +| `boot_notification_callback` | Callback to notify of a system boot | +| `clear_customer_information_callback` | Called to clear customer information based on passed in Customer Certificate, the IdToken for this request, and the Customer Identified that the request refers to. If IdToken is passed in will delete authorization cache entry from database. | +| `configure_network_connection_profile_callback` | Called to configure a network connection profile when none is configured. | +| `connector_effective_operative_status_changed_callback` | Notifies the user of liboccp that the Operative/Inoperative state of a specific EVSE has changed. | +| `cs_effective_operative_status_changed_callback` | Used to notify the user of libocpp that the Operative/Inoperative state of the charging station itself has changed. Will also call evse_effective_operative_status_changed_callback for each EVSE, and connector_effective_operative_status_changed_callback for each connector whose status has changed. | +| `data_transfer_callback` | Used to handle arbitrary data transfers. | +| `evse_effective_operative_status_changed_callback` | Notifies the user of libocpp that the Operative/Inoperative state of an EVSE has changed. If as a result the state of connectors changed as well, libocpp will additionally call the connector_effective_operative_status_changed_callback for each connector. | +| `get_customer_information_callback` | Returns human readable customer information based on the CertificateHashDataType, IdToken and Customer Identifier passed in. | +| `get_log_request_callback` | Callback to return logs | +| `is_reservation_for_token_callback` | Check if the current reservation for the given evse id is made for the id token / group id token. | +| `is_reset_allowed_callback` | Callback if reset is allowed. If evse_id has a value, reset only applies to the given evse id. If it has no value, applies to complete charging station. | +| `ocpp_messages_callback` | Callback to congfigure ocpp message logging. | +| `pause_charging_callback` | Used to request pausing of charging, the "connector" parameter instructing which connector/EVSE to pause. | +| `remote_start_transaction_callback` | Called when the request can be accepted. The boolean authorize_remote_start indicates if Authorize.req needs to follow or not | +| `reset_callback` | Performs a reset of the requested type | +| `security_event_callback` | Used to react to a security event callback. This callback is called only if the SecurityEvent occured internally within libocpp. Typically this callback is used to log security events in the security log. | +| `set_charging_profiles_callback` | Indicates when a charging profile is received and accepted. | +| `stop_transaction_callback` | Used to stop a transaction. Called when the idTagInfo.status of a StartTransaction.conf is not Accepted, when a RemoteStopTransaction.req is received, or when an UnlockConnector.req is received. | +| `time_sync_callback` | Called on boot notification if the TimeSource ControllerComponent contains Heartbeat. | +| `transaction_event_callback` | Called when a transaction_event was sent to the CSMS. | +| `transaction_event_response_callback` | Called when a transaction_event_response was received from the CSMS. | +| `unlock_connector_callback` | Used by libocpp to force unlock a connector | +| `update_firmware_request_callback` | Initiates a firmware update request. Triggers a security event notification if the certificate is Invalid or Revoked. | +| `validate_network_profile_callback` | Validates the submitted Network Profile. Is Rejected if:
• No callback registered to validate network profile
• CSMS attempted to set a network profile with a lower securityProfile
• CSMS attempted to set a network profile that could not be validated
• Network profile could not be written to the device model storage
| +| `variable_changed_callback` | Called when a variable has been changed by the CSMS | ### Event handlers to call **table** From 57441660dd8f49c2705d96823dd86f14c2873834 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:12:26 -0400 Subject: [PATCH 074/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 88bfb54ac..4b6272f76 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -14,7 +14,7 @@ This C++ library provides a complete and production-ready solution for integrati - [Standalone Integration](#standalone-integration) - [Overview of Expected Callbacks and Event Handlers](#overview-of-expected-callbacks-and-event-handlers) - [Usage for OCPP 1.6](#usage-for-ocpp-16) - - [ChargePoint() constructor](#chargepoint-constructor) + - [`ChargePoint` constructor](#chargepoint-constructor) - [registering callbacks](#registering-callbacks) - [Authorization](#authorization) - [Initialize the database](#initialize-the-database) From 7360f584dd862178bb21a8a7faef9fb366fe93d7 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:13:01 -0400 Subject: [PATCH 075/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 4b6272f76..33121f05a 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -19,7 +19,7 @@ This C++ library provides a complete and production-ready solution for integrati - [Authorization](#authorization) - [Initialize the database](#initialize-the-database) - [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) -- [Build and Install libocpp](#build-and-install-libocpp) +- [Build and Install `libocpp`](#build-and-install-libocpp) - [Building the doxygen documentation](#building-the-doxygen-documentation) - [Unit Testing](#unit-testing) - [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) From 7edce1c9fbfff3042fad370712bc6292a3792f54 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:13:14 -0400 Subject: [PATCH 076/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 33121f05a..235d7e533 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -107,7 +107,7 @@ Throughout this document and the `libocpp` codebase, the following conventions a The complete set of callbacks and event handlers defined on an OCPP 1.6 `ChargePoint` can be viewed in the latter's [header file](/include/ocpp/v16/charge_point.hpp). -### Overview of the required callbacks and events and what libocpp expects to happen +### Overview of Expected Callbacks and Event Handlers The following section will give you a high-level overview of how to integrate `libocpp` with your application. Please use the [Doxygen documentation](#building-the-doxygen-documentation) as an additional source of information about the `ChargePoint` API. From 5a6abfe95b0b9905982e4fa4fcc8e826fc31c141 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:13:24 -0400 Subject: [PATCH 077/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 235d7e533..5828a9d1f 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -121,7 +121,7 @@ The following sections explain the steps you can follow to implement their funct ### Usage for OCPP 1.6 -#### ChargePoint() constructor +#### `ChargePoint` Constructor The main entrypoint for `libocpp` for OCPP 1.6 is the `ocpp::v16::ChargePoint` constructor. This is defined in libocpp/include/ocpp/v16/charge_point.hpp and takes the following parameters: From 3caf8a8eeb0f7ad4f0df32914950f45b88b964ed Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:16:33 -0400 Subject: [PATCH 078/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 5828a9d1f..cdcc4cd25 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -15,7 +15,7 @@ This C++ library provides a complete and production-ready solution for integrati - [Overview of Expected Callbacks and Event Handlers](#overview-of-expected-callbacks-and-event-handlers) - [Usage for OCPP 1.6](#usage-for-ocpp-16) - [`ChargePoint` constructor](#chargepoint-constructor) - - [registering callbacks](#registering-callbacks) + - [Registering Callbacks](#registering-callbacks) - [Authorization](#authorization) - [Initialize the database](#initialize-the-database) - [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) From c5e7f02602af30e7699956892a0bbf5338e2a3f1 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:16:48 -0400 Subject: [PATCH 079/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index cdcc4cd25..add24408d 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -17,7 +17,7 @@ This C++ library provides a complete and production-ready solution for integrati - [`ChargePoint` constructor](#chargepoint-constructor) - [Registering Callbacks](#registering-callbacks) - [Authorization](#authorization) - - [Initialize the database](#initialize-the-database) + - [Initialize the Database](#initialize-the-database) - [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) - [Build and Install `libocpp`](#build-and-install-libocpp) - [Building the doxygen documentation](#building-the-doxygen-documentation) From 915e7011b1aba643af92d0ad3ab55caa8a1bcc84 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:17:13 -0400 Subject: [PATCH 080/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index add24408d..c3d184525 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -20,7 +20,7 @@ This C++ library provides a complete and production-ready solution for integrati - [Initialize the Database](#initialize-the-database) - [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) - [Build and Install `libocpp`](#build-and-install-libocpp) -- [Building the doxygen documentation](#building-the-doxygen-documentation) +- [Building the Doxygen Documentation](#building-the-doxygen-documentation) - [Unit Testing](#unit-testing) - [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) - [Support for TPM keys](#support-for-tpm-keys) From d32ef406cfd90c5b4411f4398e6b4db214d79678 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:17:25 -0400 Subject: [PATCH 081/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index c3d184525..888f145e2 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -22,7 +22,7 @@ This C++ library provides a complete and production-ready solution for integrati - [Build and Install `libocpp`](#build-and-install-libocpp) - [Building the Doxygen Documentation](#building-the-doxygen-documentation) - [Unit Testing](#unit-testing) -- [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) +- [Building with FetchContent Instead of EDM](#building-with-fetchcontent-instead-of-edm) - [Support for TPM keys](#support-for-tpm-keys) - [Support for websocket++](#support-for-websocket) - [Support for iface](#support-for-iface) From d4f26f834c72d4b96be085fac6488684b65b80ea Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:17:40 -0400 Subject: [PATCH 082/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 888f145e2..be8807ce9 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -23,9 +23,9 @@ This C++ library provides a complete and production-ready solution for integrati - [Building the Doxygen Documentation](#building-the-doxygen-documentation) - [Unit Testing](#unit-testing) - [Building with FetchContent Instead of EDM](#building-with-fetchcontent-instead-of-edm) -- [Support for TPM keys](#support-for-tpm-keys) -- [Support for websocket++](#support-for-websocket) -- [Support for iface](#support-for-iface) +- [Support for TPM Keys](#support-for-tpm-keys) +- [Support for `websocket++`](#support-for-websocket) +- [Support for `iface`](#support-for-iface) ## Functionality Support From c70d11df38b0bac6feff78bc75261446c19134de Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:17:52 -0400 Subject: [PATCH 083/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index be8807ce9..07fc57389 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -29,7 +29,7 @@ This C++ library provides a complete and production-ready solution for integrati ## Functionality Support -The EVerest OCPP 1.6 implementation (libocpp) provides comprehensive support for OCPP 1.6 functionalities. Below is an overview of the supported features: +The EVerest OCPP 1.6 implementation (`libocpp`) provides comprehensive support for OCPP 1.6 functionalities. Below is an overview of the supported features: | OCPP 1.6 Functionality | Supported | | ---------------------------- | ---------------------------- | From 5fe7bcf4c4462ae267e09e137c8d31f669532274 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:18:11 -0400 Subject: [PATCH 084/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 07fc57389..715ea118a 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -33,12 +33,12 @@ The EVerest OCPP 1.6 implementation (`libocpp`) provides comprehensive support f | OCPP 1.6 Functionality | Supported | | ---------------------------- | ---------------------------- | -| Core | :heavy_check_mark: Yes | -| Firmware Management | :heavy_check_mark: Yes | -| Local Auth List Management | :heavy_check_mark: Yes | -| Reservation | :heavy_check_mark: Yes | -| Smart Charging | :heavy_check_mark: Yes | -| Remote Trigger | :heavy_check_mark: Yes | +| Core | :heavy_check_mark: Yes | +| Firmware Management | :heavy_check_mark: Yes | +| Local Auth List Management | :heavy_check_mark: Yes | +| Reservation | :heavy_check_mark: Yes | +| Smart Charging | :heavy_check_mark: Yes | +| Remote Trigger | :heavy_check_mark: Yes | | Whitepapers & Application Notes | Supported | | ------------------------------------------- | ---------------------- | From 438ca9e67b504921b4a9d2fcd428f29832f11ae0 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:28:05 -0400 Subject: [PATCH 085/134] Update ocpp_201_README.md Updated table of contents Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index cd053a16f..b08db92a5 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -22,13 +22,17 @@ OCPP 2.0.1 is currently under development. - [Key Integration Points](#key-integration-points) - [Callbacks to register](#callbacks-to-register) - [Event handlers to call](#event-handlers-to-call) - - [Initialize the database](#initialize-the-database) + - [Initialize the Database](#initialize-the-database) - [OCPP 2.0.1 Use Cases](#ocpp-201-use-cases) - [Quickstart for OCPP 2.0.1](#quickstart-for-ocpp-201) -- [Build and Install libocpp](#build-and-install-libocpp) -- [Building with FetchContent instead of EDM](#building-with-fetchcontent-instead-of-edm) -- [Unit testing](#unit-testing) -- [Building the doxygen documentation](#building-the-doxygen-documentation) +- [Build and Install `libocpp`](#build-and-install-libocpp) +- [Building with FetchContent Instead of EDM](#building-with-fetchcontent-instead-of-edm) +- [Unit Testing](#unit-testing) +- [Building the Doxygen Documentation](#building-the-doxygen-documentation) +- [Support for TPM Keys](#support-for-tpm-keys) +- [Support for websocket++](#support-for-websocket) +- [Support for iface](#support-for-iface) + ## Functionality Support @@ -118,7 +122,7 @@ If you wish to integrate libocpp's OCPP 2.0.1 implementation directly into your ### Event handlers to call **table** -### Initialize the database +### Initialize the Database Use [provided SQLite database](/doc/database_migrations.md) or implement your own storage drive. @@ -447,7 +451,7 @@ Execute cmake and then make install: ----- -## Build and install libocpp +## Build and Install libocpp For Debian GNU/Linux 11 you will need the following dependencies: @@ -465,13 +469,13 @@ Clone this repository. ----- -## Building with FetchContent instead of EDM +## Building with FetchContent Instead of EDM In [doc/build-with-fetchcontent](/doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. ----- -## Unit testing +## Unit Testing GTest is required for building the test cases target. To build the target and run the tests you can reference the script `.ci/build-kit/install_and_test.sh`. @@ -490,21 +494,21 @@ Run any required tests from build/tests. ----- -## Building the doxygen documentation +## Building the Doxygen Documentation ```bash cmake -S . -B build cmake --build build --target doxygen-ocpp ``` -You will find the generated doxygen documentation at: +You will find the generated Doxygen documentation at: `build/dist/docs/html/index.html` The main reference for the integration of libocpp for OCPP2.0.1 is the ocpp::v201::ChargePoint class defined in libocpp/include/ocpp/v201/charge_point.hpp. ----- -## Support for TPM keys +## Support for TPM Keys In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. From b125d5a43de223aa9c2b36882633346b8c591a6a Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:43:50 -0400 Subject: [PATCH 086/134] Update ocpp_16_README.md updated content Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 56 +++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 715ea118a..4a33a7254 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -51,10 +51,27 @@ The EVerest OCPP 1.6 implementation (`libocpp`) provides comprehensive support f The EVerest implementation of OCPP 1.6 has been tested against the OCPP Compliance Test Tool (OCTT and OCTT2) during the implementation. -The following table shows CSMSs with which this library was tested. +The following table shows CSMS with which this library was tested. If you provide a CSMS that is not yet listed here, feel free to [contact us](https://lists.lfenergy.org/g/everest)! +| CSMS | | +| :------------------------------ | :-------- | +| chargecloud | gridundco | +| chargeIQ | ihomer (Infuse CPMS) | +| Chargetic | iLumen | +| Compleo | JibeCompany (CharlieV CMS and Chargebroker proxy) | +| Current | MSI | +| Daimler Truck | [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) | +| eDRV | PUMP (PUMP Connect) | +| Electrip Global | Scoptvision (Scopt Powerconnect) | +| EnergyStacks | Siemens | +| EV-Meter | [SteVe](https://github.com/steve-community/steve) | +| ev.energy | Syntech | +| Fastned | Trialog | +| Fraunhofer IAO (ubstack CHARGE) | ubitricity | +| Green Motion | Weev Energy | + - chargecloud - chargeIQ - Chargetic @@ -283,11 +300,13 @@ To use libocpp as a auth token validator (e.g. before starting a transaction) yo ### Initialize the database -- Use provided sql database or implement your own storage drive +Use provided sql database or implement your own storage drive. + +----- ## Quickstart for OCPP 1.6 -Libocpp provides a small standalone OCPP1.6 client that you can control using command line. +Libocpp provides a small standalone OCPP 1.6 client that you can control using command line. Install the dependencies and libocpp as described in [Build and Install libocpp](#build-and-install-libocpp). @@ -320,7 +339,9 @@ Use the following command to start the charge point. Replace the config with [co Type `help` to see a list of possible commands. -## Building the doxygen documentation +----- + +## Building the Doxygen Documentation ```bash cmake -S . -B build @@ -332,6 +353,8 @@ You will find the generated doxygen documentation at: The main reference for the integration of libocpp for OCPP1.6 is the ocpp::v16::ChargePoint class defined in libocpp/include/ocpp/v16/charge_point.hpp. +----- + ## Build and Install libocpp For Debian GNU/Linux 11 you will need the following dependencies: @@ -374,32 +397,35 @@ make -j$(nproc) install Run any required tests from build/tests. -## Building with FetchContent instead of EDM +----- + +## Building with FetchContent Instead of EDM In [doc/build-with-fetchcontent](/doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. -## Support for TPM keys +----- + +## Support for TPM Keys + +In order to use the TPM keys, it is mandatory to use the default `libwebsocket` implementation. -In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. +----- -## Support for websocket++ +## Support for `websocket++` -The old websocket++ implementation has been deprecated. For enabling websocket++ support use the following cmake option: +The old `websocket++` implementation has been deprecated. For enabling `websocket++` support use the following cmake option: ```bash cmake .. -DLIBOCPP_ENABLE_DEPRECATED_WEBSOCKETPP=ON ``` +----- -## Support for iface +## Support for `iface` -In order to connect through a custom network iface, a custom internal config variable 'IFace' can be used. +In order to connect through a custom network `iface`, a custom internal config variable 'IFace' can be used. ```json "Internal": { "IFace" : "enp43s0" } ``` - -## Get Involved - -See the [COMMUNITY.md](https://github.com/EVerest/EVerest/blob/main/COMMUNITY.md) and [CONTRIBUTING.md](https://github.com/EVerest/EVerest/blob/main/CONTRIBUTING.md) of the EVerest project to get involved. From 0ab94629eaadfc97374e6dcfbce2781ddbde1353 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:46:50 -0400 Subject: [PATCH 087/134] Update ocpp_16_README.md Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 4a33a7254..b2e10ec88 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -298,7 +298,7 @@ In EVerest authorization is handled by the Auth module and various auth token pr To use libocpp as a auth token validator (e.g. before starting a transaction) you can call the "authorize_id_token" function of the ChargePoint object. -### Initialize the database +### Initialize the Database Use provided sql database or implement your own storage drive. From 304782c4e3ebf4710549cc3fc72674329b968258 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:48:43 -0400 Subject: [PATCH 088/134] Update ocpp_16_README.md Edits to capitalizations Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 33 ++------------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index b2e10ec88..8b17379f2 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -14,7 +14,7 @@ This C++ library provides a complete and production-ready solution for integrati - [Standalone Integration](#standalone-integration) - [Overview of Expected Callbacks and Event Handlers](#overview-of-expected-callbacks-and-event-handlers) - [Usage for OCPP 1.6](#usage-for-ocpp-16) - - [`ChargePoint` constructor](#chargepoint-constructor) + - [`ChargePoint` Constructor](#chargepoint-constructor) - [Registering Callbacks](#registering-callbacks) - [Authorization](#authorization) - [Initialize the Database](#initialize-the-database) @@ -72,35 +72,6 @@ If you provide a CSMS that is not yet listed here, feel free to | Fraunhofer IAO (ubstack CHARGE) | ubitricity | | Green Motion | Weev Energy | -- chargecloud -- chargeIQ -- Chargetic -- Compleo -- Current -- Daimler Truck -- ev.energy -- eDRV -- Fastned -- [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) -- Electrip Global -- EnergyStacks -- EV-Meter -- Fraunhofer IAO (ubstack CHARGE) -- Green Motion -- gridundco -- ihomer (Infuse CPMS) -- iLumen -- JibeCompany (CharlieV CMS and Chargebroker proxy) -- MSI -- PUMP (PUMP Connect) -- Scoptvision (Scopt Powerconnect) -- Siemens -- [SteVe](https://github.com/steve-community/steve) -- Syntech -- Trialog -- ubitricity -- Weev Energy - ## Integration with EVerest The libocpp OCPP 1.6 module is automatically integrated within [everest-core](https://github.com/EVerest/everest-core) — the complete software stack for your charging station. @@ -233,7 +204,7 @@ This is defined in libocpp/include/ocpp/v16/charge_point.hpp and takes the follo │ └── V2G_ROOT_CA.key ``` -#### registering callbacks +#### Registering Callbacks You can (and in many cases MUST) register a number of callbacks so libocpp can interact with the charger. In EVerest most of this functionality is orchestrated by the "EvseManager" module, but you can also register your own callbacks interacting directly with your chargers software. Following is a list of callbacks that you must register and a few words about their purpose. From a9212d5b093164f78006f1a076e0806374bf3088 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:49:54 -0400 Subject: [PATCH 089/134] Update ocpp_16_README.md Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 8b17379f2..18a3209f5 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -247,7 +247,7 @@ Some general notes: the "connector" parameter of some of the callbacks refers to each of these functions will have a small note what the Session Event was and what it triggers in libocpp -| on _ functions | Description | +| on_ functions | Description | | :------------------------------- | :----------------------------------------- | | `on_enabled(int32_t connector)` | Notifies libocpp that the connector is functional and operational | | `on_disabled(int32_t connector)` | Notifies libocpp that the connector is disabled | From 29600c048cde675291680ffcbfe2d1598d427eff Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:57:19 -0400 Subject: [PATCH 090/134] Update ocpp_16_README.md Updated table of contents Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 18a3209f5..85ef9246e 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -20,9 +20,9 @@ This C++ library provides a complete and production-ready solution for integrati - [Initialize the Database](#initialize-the-database) - [Quickstart for OCPP 1.6](#quickstart-for-ocpp-16) - [Build and Install `libocpp`](#build-and-install-libocpp) -- [Building the Doxygen Documentation](#building-the-doxygen-documentation) -- [Unit Testing](#unit-testing) - [Building with FetchContent Instead of EDM](#building-with-fetchcontent-instead-of-edm) +- [Unit Testing](#unit-testing) +- [Building the Doxygen Documentation](#building-the-doxygen-documentation) - [Support for TPM Keys](#support-for-tpm-keys) - [Support for `websocket++`](#support-for-websocket) - [Support for `iface`](#support-for-iface) @@ -84,7 +84,8 @@ OCPP is a protocol that affects, controls, and monitors many areas of a charging The actual substance of how a charging station reacts to or initiates an OCPP command (such as `Reset.req` or `RemoteStartTransaction.req`) is left to the rest of the charging station's systems. This is done by providing means of (a) registering **callbacks** that can be triggered by a `libocpp` `ChargePoint` in response to certain events and (b) reacting to various **event handlers** defined on a `ChargePoint` in other areas of the charging station's codebase. -> [!IMPORTANT] Integrating this library with your charging station requires both (a) defining **callbacks** that enable control of your station by `libocpp` and (b) calling `libocpp` **event handlers** in your charging station's systems in response to new events and data in order to keep `libocpp` up to date on station information. +> [!IMPORTANT] +> Integrating this library with your charging station requires both (a) defining **callbacks** that enable control of your station by `libocpp` and (b) calling `libocpp` **event handlers** in your charging station's systems in response to new events and data in order to keep `libocpp` up to date on station information. ### Terminology Throughout this document and the `libocpp` codebase, the following conventions are followed: @@ -312,20 +313,6 @@ Type `help` to see a list of possible commands. ----- -## Building the Doxygen Documentation - -```bash - cmake -S . -B build - cmake --build build --target doxygen-ocpp -``` - -You will find the generated doxygen documentation at: -`build/dist/docs/html/index.html` - -The main reference for the integration of libocpp for OCPP1.6 is the ocpp::v16::ChargePoint class defined in libocpp/include/ocpp/v16/charge_point.hpp. - ------ - ## Build and Install libocpp For Debian GNU/Linux 11 you will need the following dependencies: @@ -351,6 +338,15 @@ Execute cmake and then make install: make install ``` +----- + +## Building with FetchContent Instead of EDM + +In [doc/build-with-fetchcontent](/doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. + +----- + + ## Unit Testing GTest is required for building the test cases target. @@ -370,9 +366,17 @@ Run any required tests from build/tests. ----- -## Building with FetchContent Instead of EDM +## Building the Doxygen Documentation -In [doc/build-with-fetchcontent](/doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. +```bash + cmake -S . -B build + cmake --build build --target doxygen-ocpp +``` + +You will find the generated doxygen documentation at: +`build/dist/docs/html/index.html` + +The main reference for the integration of libocpp for OCPP1.6 is the ocpp::v16::ChargePoint class defined in libocpp/include/ocpp/v16/charge_point.hpp. ----- From d28fd3032a59c67f4dde0cd9eac1adfa60e808d5 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:59:12 -0400 Subject: [PATCH 091/134] Update ocpp_201_README.md Added `` to content Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index b08db92a5..49fcbf310 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -20,8 +20,8 @@ OCPP 2.0.1 is currently under development. - [Integration with EVerest](#integration-with-everest) - [Standalone Integration](#standalone-integration) - [Key Integration Points](#key-integration-points) - - [Callbacks to register](#callbacks-to-register) - - [Event handlers to call](#event-handlers-to-call) + - [Callbacks to Register](#callbacks-to-register) + - [Event Handlers to Call](#event-handlers-to-call) - [Initialize the Database](#initialize-the-database) - [OCPP 2.0.1 Use Cases](#ocpp-201-use-cases) - [Quickstart for OCPP 2.0.1](#quickstart-for-ocpp-201) @@ -30,8 +30,8 @@ OCPP 2.0.1 is currently under development. - [Unit Testing](#unit-testing) - [Building the Doxygen Documentation](#building-the-doxygen-documentation) - [Support for TPM Keys](#support-for-tpm-keys) -- [Support for websocket++](#support-for-websocket) -- [Support for iface](#support-for-iface) +- [Support for `websocket++`](#support-for-websocket) +- [Support for `iface`](#support-for-iface) ## Functionality Support @@ -88,7 +88,7 @@ If you wish to integrate libocpp's OCPP 2.0.1 implementation directly into your > The public API for these integrations are found in the [ChargePoint](/include/ocpp/v201/charge_point.hpp). -### Callbacks to register +### Callbacks to Register | callbacks | description | | :------------------------------------------------------ | :---------- | @@ -119,7 +119,7 @@ If you wish to integrate libocpp's OCPP 2.0.1 implementation directly into your | `validate_network_profile_callback` | Validates the submitted Network Profile. Is Rejected if:
• No callback registered to validate network profile
• CSMS attempted to set a network profile with a lower securityProfile
• CSMS attempted to set a network profile that could not be validated
• Network profile could not be written to the device model storage
| | `variable_changed_callback` | Called when a variable has been changed by the CSMS | -### Event handlers to call +### Event Handlers to Call **table** ### Initialize the Database @@ -451,7 +451,7 @@ Execute cmake and then make install: ----- -## Build and Install libocpp +## Build and Install `libocpp` For Debian GNU/Linux 11 you will need the following dependencies: @@ -510,13 +510,13 @@ The main reference for the integration of libocpp for OCPP2.0.1 is the ocpp::v20 ## Support for TPM Keys -In order to use the TPM keys, it is mandatory to use the default libwebsocket implementation. +In order to use the TPM keys, it is mandatory to use the default `libwebsocket` implementation. ----- -## Support for websocket++ +## Support for `websocket++` -The old websocket++ implementation has been deprecated. For enabling websocket++ support use the following cmake option: +The old `websocket++` implementation has been deprecated. For enabling `websocket++` support use the following cmake option: ```bash cmake .. -DLIBOCPP_ENABLE_DEPRECATED_WEBSOCKETPP=ON @@ -524,9 +524,9 @@ The old websocket++ implementation has been deprecated. For enabling websocket++ ----- -## Support for iface +## Support for `iface` -In order to connect through a custom network iface, a custom internal config variable 'IFace' can be used. +In order to connect through a custom network `iface`, a custom internal config variable 'IFace' can be used. ```json "Internal": { From ef3089c23fe9a523f6f8ad02a7bf647a17183f83 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:00:13 -0400 Subject: [PATCH 092/134] Update ocpp_16_README.md Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 85ef9246e..c8751994f 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -313,7 +313,7 @@ Type `help` to see a list of possible commands. ----- -## Build and Install libocpp +## Build and Install `libocpp` For Debian GNU/Linux 11 you will need the following dependencies: From 3418df90ba62d9c8cdf3f05cd007c740db00339e Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:09:41 -0400 Subject: [PATCH 093/134] Update ocpp_201_README.md converted list of CSMS to table Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 49fcbf310..9348717ff 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -56,18 +56,20 @@ The development of OCPP 2.0.1 implementation is in progress — [OCPP 2.0.1 stat ## CSMS Compatibility -The ongoing development of OCPP 2.0.1 implementation is continuously tested against OCTT2 (OCPP Compliance Testing Tool 2), and has been tested against several Charging Station Management Systems (CSMS): - -- [CitrineOS](https://lfenergy.org/projects/citrineos/) -- Chargepoint -- Current -- ihomer (Infuse CPMS) -- Instituto Tecnológico de la Energía (ITE) -- [MaEVe (Thoughtworks)](https://github.com/thoughtworks/maeve-csms) -- [Monta](https://monta.com) -- [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) -- Switch EV -- SWTCH +The ongoing development of OCPP 2.0.1 implementation is continuously tested against OCTT2 (OCPP Compliance Testing Tool 2), and has been tested against the following Charging Station Management Systems (CSMS): + +| CSMS | +| :----------------------------------------------------------------------------------- | +| Chargepoint | +| [CitrineOS](https://lfenergy.org/projects/citrineos/) | +| Current | +| ihomer (Infuse CPMS) | +| Instituto Tecnológico de la Energía (ITE) | +| [MaEVe (Thoughtworks)](https://github.com/thoughtworks/maeve-csms) | +| [Monta](https://monta.com) | +| [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) | +| Switch EV | +| SWTCH | ## Integration with EVerest From 2ee0be2764ed32de2f29631ea5fd88e0aaf835e2 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:33:17 -0400 Subject: [PATCH 094/134] Update ocpp_201_README.md Created table for Smart Charging errors section Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 112 ++++++++--------------------------------- 1 file changed, 20 insertions(+), 92 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 9348717ff..6a9fae35b 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -194,98 +194,26 @@ sequenceDiagram Profile validation returns the following errors to the caller when a Profile is `Rejected`: -- `ChargingProfileFirstStartScheduleIsNotZero` - - The `startPeriod` of the first `chargingSchedulePeriod` needs to be 0. - [K01.FR.31] - -- `ChargingProfileNoChargingSchedulePeriods` - - Happens when the `ChargingProfile` doesn't have any Charging Schedule - Periods. - -- `ChargingScheduleChargingRateUnitUnsupported` - - Happens when a chargingRateUnit is passed in that is not configured in the - `ChargingScheduleChargingRateUnit`. [K01.FR.26] - -- `ChargingSchedulePeriodInvalidPhaseToUse` - - Happens when an invalid `phaseToUse` is passed in. - - [K01.FR.19] [K01.FR.48] - -- `ChargingSchedulePeriodPhaseToUseACPhaseSwitchingUnsupported` - - Happens when phaseToUse is passed in and the EVSE does not have - `ACPhaseSwitchingSupported` defined and set to true. - [K01.FR.20] [K01.FR.48] - -- `ChargingSchedulePeriodsOutOfOrder` - - `ChargingSchedulePeriod.startPeriod` elements need to be in increasing - values. [K01.FR.35] - -- `ChargingStationMaxProfileCannotBeRelative` - - Happens when a `ChargingStationMaxProfile.chargingProfileKind` is set to - `Relative`. [K01.FR.38] - -- `ChargingStationMaxProfileEvseIdGreaterThanZero` - - Happens when a `ChargingStationMaxProfile` is attempted to be set with an - EvseID isn't `0`. [K01.FR.03] - -- `ChargingProfileMissingRequiredStartSchedule` - - Happens when an `Absolute` or `Recurring` `ChargingProfile` doesn't have - a `startSchedule`. [K01.FR.40] - -- `ChargingProfileExtraneousStartSchedule` - - Happens when a Relative `ChargingProfile` has a `startSchedule`. - [K01.FR.41] - -- `EvseDoesNotExist` - - Happens when the `evseId`of a `SetChargingProfileRequest` does not exist. - [K01.FR.28] - -- `ExistingChargingStationExternalConstraints` - - Happens when a `SetChargingProfileRequest` Profile has a purpose of - `ChargingStationExternalConstraints` and one already exists with the same - `ChargingProfile.id` exists. [K01.FR.05] - -- `InvalidProfileType` - - Happens when a `ChargingStationMaxProfile` is attempted to be set with a - `ChargingProfile` that isn't a `ChargingStationMaxProfile`. - -- `TxProfileEvseHasNoActiveTransaction` - - Happens when a `SetChargingProfileRequest` with a `TxProfile` is submitted - and there is no transaction active on the specified EVSE. [K01.FR.09] - -- `TxProfileEvseIdNotGreaterThanZero` - - `TxProfile` needs to have an `evseId` greater than 0. [K01.FR.16] - -- `TxProfileMissingTransactionId` - - A `transactionId` is required for `SetChargingProfileRequest`s with a - `TxProfile` in order to match the profile to a specific transation. [K01.FR.03] - -- `TxProfileTransactionNotOnEvse` - - Happens when the provided `transactionId` is not known. [K01.FR.33] - -- `TxProfileConflictingStackLevel` - - Happens when a `TxProfile` has a `stackLevel` and `transactionId` - combination already exists in a `TxProfile` with a different id in - order to ensure that no two charging profiles with same stack level and - purpose can be valid at the same time. [K01.FR.39] +| Errors | Description | +| :------------------------------------------------------------ | :-------------------------------------------------------------- | +| `ChargingProfileFirstStartScheduleIsNotZero` | The `startPeriod` of the first `chargingSchedulePeriod` needs to be 0.
[K01.FR.31] | +| `ChargingProfileNoChargingSchedulePeriods` | Happens when the `ChargingProfile` doesn't have any Charging Schedule Periods. | +| `ChargingScheduleChargingRateUnitUnsupported` | Happens when a chargingRateUnit is passed in that is not configured in the `ChargingScheduleChargingRateUnit`. [K01.FR.26] | +| `ChargingSchedulePeriodInvalidPhaseToUse` | Happens when an invalid `phaseToUse` is passed in. [K01.FR.19] [K01.FR.48] | +| `ChargingSchedulePeriodPhaseToUseACPhaseSwitchingUnsupported` | Happens when phaseToUse is passed in and the EVSE does not have `ACPhaseSwitchingSupported` defined and set to true. [K01.FR.20] [K01.FR.48] | +| `ChargingSchedulePeriodsOutOfOrder` | `ChargingSchedulePeriod.startPeriod` elements need to be in increasing values. [K01.FR.35] | +| `ChargingStationMaxProfileCannotBeRelative` | Happens when a `ChargingStationMaxProfile.chargingProfileKind` is set to `Relative`. [K01.FR.38] | +| `ChargingStationMaxProfileEvseIdGreaterThanZero` | Happens when a `ChargingStationMaxProfile` is attempted to be set with an EvseID isn't `0`. [K01.FR.03] | +| `ChargingProfileMissingRequiredStartSchedule` | Happens when an `Absolute` or `Recurring` `ChargingProfile` doesn't have a `startSchedule`. [K01.FR.40] | +| `ChargingProfileExtraneousStartSchedule` | Happens when a Relative `ChargingProfile` has a `startSchedule`. [K01.FR.41] | +| `EvseDoesNotExist` | Happens when the `evseId`of a `SetChargingProfileRequest` does not exist. [K01.FR.28] | +| `ExistingChargingStationExternalConstraints` | Happens when a `SetChargingProfileRequest` Profile has a purpose of `ChargingStationExternalConstraints` and one already exists with the same `ChargingProfile.id` exists. [K01.FR.05] | +| `InvalidProfileType` | Happens when a `ChargingStationMaxProfile` is attempted to be set with a `ChargingProfile` that isn't a `ChargingStationMaxProfile`. | +| `TxProfileEvseHasNoActiveTransaction` | Happens when a `SetChargingProfileRequest` with a `TxProfile` is submitted and there is no transaction active on the specified EVSE. [K01.FR.09] | +| `TxProfileEvseIdNotGreaterThanZero` | `TxProfile` needs to have an `evseId` greater than 0. [K01.FR.16] | +| `TxProfileMissingTransactionId` | A `transactionId` is required for`SetChargingProfileRequest`s with a `TxProfile` in order to match the profile to a specific transation. [K01.FR.03] | +| `TxProfileTransactionNotOnEvse` | Happens when the provided `transactionId` is not known. [K01.FR.33] | +| `TxProfileConflictingStackLevel` | Happens when a TxProfile has a stackLevel and transactionId combination already exists in a TxProfile with a different id in order to ensure that no two charging profiles with same stack level and purpose can be valid at the same time. [K01.FR.39] | ----- From ca92df23b3cbc3b794d8b2385a0b4bc55a1d0933 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:32:08 -0400 Subject: [PATCH 095/134] Update ocpp_201_README.md Updated Event handlers to call section Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 6a9fae35b..488384804 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -122,7 +122,7 @@ If you wish to integrate libocpp's OCPP 2.0.1 implementation directly into your | `variable_changed_callback` | Called when a variable has been changed by the CSMS | ### Event Handlers to Call -**table** +Event handlers to call are found in the [ChargePoint](https://github.com/EVerest/libocpp/blob/2124d055f9cc8f253d3a2441ec2d70686174d0ed/include/ocpp/v201/charge_point.hpp#L116). ### Initialize the Database From 9f2e63b83b6e36934108ea1ab2b59df16ac72e65 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:35:54 -0400 Subject: [PATCH 096/134] Update ocpp_201_README.md Updated quick links to different sections Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 488384804..58b89e32b 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -83,8 +83,8 @@ If you wish to integrate libocpp's OCPP 2.0.1 implementation directly into your ### Key Integration Points -1. **Callbacks**: Register these to allow libocpp to execute commands defined in OCPP (e.g., Reset.req or RemoteStartTransaction.req). -2. **Event Handlers**: Call these to notify libocpp of events, enabling the library to track the charging station's state and trigger appropriate OCPP messages (e.g., MeterValues.req, StatusNotification.req). +1. [**Callbacks**](#callbacks-to-register): Register these to allow libocpp to execute commands defined in OCPP (e.g., Reset.req or RemoteStartTransaction.req). +2. [**Event Handlers**](#event-handlers-to-call): Call these to notify libocpp of events, enabling the library to track the charging station's state and trigger appropriate OCPP messages (e.g., MeterValues.req, StatusNotification.req). > [!note] > The public API for these integrations are found in the [ChargePoint](/include/ocpp/v201/charge_point.hpp). @@ -126,7 +126,7 @@ Event handlers to call are found in the [ChargePoint](https://github.com/EVerest ### Initialize the Database -Use [provided SQLite database](/doc/database_migrations.md) or implement your own storage drive. +Use provided [SQLite database](/doc/database_migrations.md) or implement your own storage drive. ### OCPP 2.0.1 Use Cases From 6ab94ca0158094f9299c4e0147faa50758b45583 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 11:38:33 -0400 Subject: [PATCH 097/134] Update ocpp_201_README.md added quick link to SmartCharging use case Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 58b89e32b..b51c306d0 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -142,7 +142,7 @@ Use provided [SQLite database](/doc/database_migrations.md) or implement your ow | H | Reservation | | I | TariffAndCost | | J | MeterValues | -| K | SmartCharging | +| K | [SmartCharging](#smart-charging) | | L | FirmwareManagement | | M | ISO 15118 CertificateManagement | | N | Diagnostics | From 6d72d49f7aebd57c8f2b40fc06dc46c1615e4338 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:50:39 -0400 Subject: [PATCH 098/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index b51c306d0..7d7825a55 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -2,15 +2,13 @@ ----- -# EVerest OCPP 2.0.1 Implementation (libocpp) -This is a C++ library implementation of OCPP for version 2.0.1 -(see [OCPP protocols at OCA website](https://openchargealliance.org/protocols/open-charge-point-protocol/)). +# OCPP 2.0.1 in `libocpp` -It enables charging stations to communicate with cloud backends for remote control, monitoring and billing of charging processes. +The `ocpp::v201` namespace exposes a `ChargePoint` class capable of client-side OCPP 2.0.1 communications. It enables charging stations to communicate with a cloud backend over a websocket for the remote control of charging stations and administration of charging sessions. -Libocpp can be used for the communication of one charging station and multiple EVSE using a single websocket connection. +> [!NOTE] For more information about the differences between versions of the Open Charge Point Protocol, please refer to the [Open Charge Alliance's website](https://openchargealliance.org/protocols/open-charge-point-protocol/). -OCPP 2.0.1 is currently under development. +The OCPP 2.0.1 implementation in `libocpp` is nearing completion, but there remain areas of active development. The OCA also does not currently plan to provide an official validation tool for all functionality within the protocol until the end of 2024. A high-level overview of supported functionality is provided [below](#supported-certification-profiles). For a more granular and up-to-date analysis of available OCPP 2.0.1 features in `libocpp`, please refer to the [OCPP 2.0.1 Status document](ocpp_201_status.md). ## Table of contents From fe9482fc33aa04e5ffb92f6b69b211fd874e6b3e Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:51:31 -0400 Subject: [PATCH 099/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 7d7825a55..1d68a793b 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -11,9 +11,9 @@ The `ocpp::v201` namespace exposes a `ChargePoint` class capable of client-side The OCPP 2.0.1 implementation in `libocpp` is nearing completion, but there remain areas of active development. The OCA also does not currently plan to provide an official validation tool for all functionality within the protocol until the end of 2024. A high-level overview of supported functionality is provided [below](#supported-certification-profiles). For a more granular and up-to-date analysis of available OCPP 2.0.1 features in `libocpp`, please refer to the [OCPP 2.0.1 Status document](ocpp_201_status.md). -## Table of contents +## Table of Contents -- [Functionality Support](#functionality-support) +- [Supported Certification Profiles](#supported-certification-profiles) - [CSMS Compatibility](#csms-compatibility) - [Integration with EVerest](#integration-with-everest) - [Standalone Integration](#standalone-integration) @@ -21,7 +21,7 @@ The OCPP 2.0.1 implementation in `libocpp` is nearing completion, but there rema - [Callbacks to Register](#callbacks-to-register) - [Event Handlers to Call](#event-handlers-to-call) - [Initialize the Database](#initialize-the-database) - - [OCPP 2.0.1 Use Cases](#ocpp-201-use-cases) + - [OCPP 2.0.1 Use Cases in `libocpp`](#ocpp-201-use-cases-in-libocpp) - [Quickstart for OCPP 2.0.1](#quickstart-for-ocpp-201) - [Build and Install `libocpp`](#build-and-install-libocpp) - [Building with FetchContent Instead of EDM](#building-with-fetchcontent-instead-of-edm) From 6e9190d0f770601062a437c601e2cafaafa6b2c4 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:52:01 -0400 Subject: [PATCH 100/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 1d68a793b..e9dfb48ef 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -32,9 +32,9 @@ The OCPP 2.0.1 implementation in `libocpp` is nearing completion, but there rema - [Support for `iface`](#support-for-iface) -## Functionality Support +## Supported Certification Profiles -The development of OCPP 2.0.1 implementation is in progress — [OCPP 2.0.1 status](/doc/ocpp_201_status.md). The following table shows the current support for OCPP 2.0.1 functionalities in libocpp: +Some optional OCPP 2.0.1 features are still being actively developed by the `libocpp` community. The following table shows which portions of the OCPP 2.0.1 implementation within `libocpp` are still being built out, broken down by [OCPP 2.0.1 Certification Profile](https://openchargealliance.org/certificationocpp/certification-ocpp-2-0-1/): | OCPP 2.0.1 Functionality | Supported | | :------------------------- | :------------------------- | From ee2c9fe7b245d98eb72bd136babab6f89cf8919f Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:52:18 -0400 Subject: [PATCH 101/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index e9dfb48ef..50bc796c0 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -45,7 +45,7 @@ Some optional OCPP 2.0.1 features are still being actively developed by the `lib | Advanced Device Management | :hourglass: Planned | | Advanced User Interface | :hourglass: Planned | | Reservation | :hourglass: Planned | -| ISO 15118 support | :construction: In Progress | +| ISO 15118 Support | :construction: In Progress | | Whitepapers & Application Notes | Supported | | :------------------------------------- | :------------------------- | From 034531382e6294cf080751732fe6dc21e6daa20c Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:52:30 -0400 Subject: [PATCH 102/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 50bc796c0..ccf2250b4 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -60,7 +60,7 @@ The ongoing development of OCPP 2.0.1 implementation is continuously tested agai | :----------------------------------------------------------------------------------- | | Chargepoint | | [CitrineOS](https://lfenergy.org/projects/citrineos/) | -| Current | +| [Current](https://www.current.eco/) | | ihomer (Infuse CPMS) | | Instituto Tecnológico de la Energía (ITE) | | [MaEVe (Thoughtworks)](https://github.com/thoughtworks/maeve-csms) | From b37f848db081d791742ab448661aadb0ec1c85f5 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:52:41 -0400 Subject: [PATCH 103/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index ccf2250b4..98053944f 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -67,7 +67,7 @@ The ongoing development of OCPP 2.0.1 implementation is continuously tested agai | [Monta](https://monta.com) | | [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) | | Switch EV | -| SWTCH | +| [SWTCH Energy](https://swtchenergy.com/) | ## Integration with EVerest From f5fe31c103f34c8778d556b5a8cc9ab8b1ee5bf7 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:52:59 -0400 Subject: [PATCH 104/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 98053944f..e4f00f0cd 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -58,7 +58,7 @@ The ongoing development of OCPP 2.0.1 implementation is continuously tested agai | CSMS | | :----------------------------------------------------------------------------------- | -| Chargepoint | +| [ChargePoint](https://www.chargepoint.com/businesses/software) | | [CitrineOS](https://lfenergy.org/projects/citrineos/) | | [Current](https://www.current.eco/) | | ihomer (Infuse CPMS) | From a47681eb06390024d25409426371ec460ed30aa2 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:53:15 -0400 Subject: [PATCH 105/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index e4f00f0cd..cfbbe116c 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -62,7 +62,7 @@ The ongoing development of OCPP 2.0.1 implementation is continuously tested agai | [CitrineOS](https://lfenergy.org/projects/citrineos/) | | [Current](https://www.current.eco/) | | ihomer (Infuse CPMS) | -| Instituto Tecnológico de la Energía (ITE) | +| [Instituto Tecnológico de la Energía (ITE) HySGrid+](https://www.ite.es/i-d-i/proyectos/hysgrid/) | | [MaEVe (Thoughtworks)](https://github.com/thoughtworks/maeve-csms) | | [Monta](https://monta.com) | | [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) | From bd6f5561ed9b37a036389179fb23f0d360d4d252 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:53:24 -0400 Subject: [PATCH 106/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index cfbbe116c..be39c8771 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -66,7 +66,7 @@ The ongoing development of OCPP 2.0.1 implementation is continuously tested agai | [MaEVe (Thoughtworks)](https://github.com/thoughtworks/maeve-csms) | | [Monta](https://monta.com) | | [Open Charging Cloud (GraphDefined)](https://github.com/OpenChargingCloud/WWCP_OCPP) | -| Switch EV | +| [Switch EV](https://www.switch-ev.com/platform) | | [SWTCH Energy](https://swtchenergy.com/) | ## Integration with EVerest From 6ac0eac4c4c59b55a4cd4ffdd01f1069b142b3ce Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:54:06 -0400 Subject: [PATCH 107/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index be39c8771..eaede70d6 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -71,9 +71,11 @@ The ongoing development of OCPP 2.0.1 implementation is continuously tested agai ## Integration with EVerest -The libocpp OCPP 2.0.1 module is automatically integrated within [everest-core](https://github.com/EVerest/everest-core) — the complete software stack for your charging station. +EVerest provides a simplified OCPP 2.0.1 integration path through its `OCPP201` module. -When you run libocpp with OCPP 2.0.1 through EVerest, the build process of everest-core handles the installation of all necessary dependencies. This includes initializing the device model database using the [config.json](config/v201/config.json) file. +When setting up a development environment (or building) EVerest through the [`everest-core`](https://github.com/EVerest/everest-core) project, a version of `libocpp` will be pulled down as a dependency. If you wish to use the `OCPP201` module, you will want to defined your charging station's Device Model in the [`config.json` file](config/v201/config.json) for the `libocpp` repository pulled in by `everest-core` as a dependency. This configuration will be incorporated into `everest-core` during the latter's build process. + +Once `everest-core` has been built with your station-specific `libocpp` configuration, you can then specify and configure `OCPP201` as a module in the [runtime configuration](https://everest.github.io/nightly/general/04_detail_module_concept.html#wiring-it-all-together-the-run-configuration) of your EVerest deployment. ## Standalone Integration From e8e0487a8501658d85412e0673a38d936f288199 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:55:29 -0400 Subject: [PATCH 108/134] Update doc/ocpp_16_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index c8751994f..5621b843d 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -51,7 +51,7 @@ The EVerest OCPP 1.6 implementation (`libocpp`) provides comprehensive support f The EVerest implementation of OCPP 1.6 has been tested against the OCPP Compliance Test Tool (OCTT and OCTT2) during the implementation. -The following table shows CSMS with which this library was tested. +The following table shows CSMSs with which this library was tested. If you provide a CSMS that is not yet listed here, feel free to [contact us](https://lists.lfenergy.org/g/everest)! From 81c3ffb548964c9ef4dd10a26bed15a6aaa97579 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:56:46 -0400 Subject: [PATCH 109/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index eaede70d6..981f57aa7 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -128,7 +128,15 @@ Event handlers to call are found in the [ChargePoint](https://github.com/EVerest Use provided [SQLite database](/doc/database_migrations.md) or implement your own storage drive. -### OCPP 2.0.1 Use Cases +## OCPP 2.0.1 Use Cases in `libocpp` + +The OCPP 2.0.1 specification is broken down into concrete functional requirements using a three-tier system. At the top, there are sixteen **functional blocks** lettered A through P that describe the high-level desired capabilities of actors adhering to the standard. These functional blocks are then broken into **use cases** that describe different scenarios in which one or more charging stations, local controllers, and charging station management systems might find themselves. The required and optional behaviors of these systems in these scenarios are then declared as **functional requirements** within each use case. + +This section includes an overview of how a subset of the OCPP 2.0.1 use cases that supported by `libocpp` are implemented in conjunction with callbacks provided by the charging station. We hope it serves as a useful guide to portions of the `libocpp` API and illustrates patterns of interaction between `libocpp` and other systems within a charging station. + +> [!NOTE] Our goal is not to reproduce the entire OCPP 2.0.1 specification in this document. Rather we intend to illustrate how various use cases are realized using `ChargePoint` methods in `libocpp` in conjunction with callback implementations and event handlers. +> +> Please refer to the [OCPP 2.0.1 standard](https://openchargealliance.org/protocols/open-charge-point-protocol/#OCPP2.0.1) for more details. Functional blocks, use cases, and functional requirements are addressed in Part 2 of Edition 2. | Clause | Use Case Name | | :----- | :-------------------------------- | From 39ff6c53a0766a54c07750adeb3fa44035b9059c Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:57:16 -0400 Subject: [PATCH 110/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 981f57aa7..b0a3ee848 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -81,13 +81,14 @@ Once `everest-core` has been built with your station-specific `libocpp` configur If you wish to integrate libocpp's OCPP 2.0.1 implementation directly into your charging station software without using the full EVerest stack, you'll need to register several **callbacks** and implement **event handlers**. This allows libocpp to interact with your charging station according to OCPP requirements. -### Key Integration Points +### Terminology +Throughout this document and the `libocpp` codebase, the following conventions are followed: -1. [**Callbacks**](#callbacks-to-register): Register these to allow libocpp to execute commands defined in OCPP (e.g., Reset.req or RemoteStartTransaction.req). -2. [**Event Handlers**](#event-handlers-to-call): Call these to notify libocpp of events, enabling the library to track the charging station's state and trigger appropriate OCPP messages (e.g., MeterValues.req, StatusNotification.req). +- A **callback** is a function providing the actual station-specific implementation of an OCPP command. It allows a `libocpp` `ChargePoint` to control other systems within a charging station. By convention, each callback on a `ChargePoint` has a name suffixed with `_callback` (for instance, `unlock_connector_callback`). A `Callbacks` `struct` containing a complete set of desired callback implementations (as suitable `std::function` instances) should be provided to a 2.0.1 `ChargePoint` at construction time. -> [!note] -> The public API for these integrations are found in the [ChargePoint](/include/ocpp/v201/charge_point.hpp). +- An **event handler** is a public function defined on a `ChargePoint` that allows a charging station to update the state being tracked by the `ChargePoint` based on new information (meter values, charging session events, etc.) and (indirectly) send messages to a CSMS. By convention, the names of event handlers on the `ChargePoint` are each prefixed with `on_` (for instance, `on_meter_value`). + +The complete set of callbacks and event handlers defined on an OCPP 2.0.1 `ChargePoint` can be viewed in the latter's [header file](/include/ocpp/v201/charge_point.hpp). Please use the [Doxygen documentation](#building-the-doxygen-documentation) as an additional source of information about the `ChargePoint` API. ### Callbacks to Register From fd25e70ca9ff583086000d0a7174b447fc2a022d Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 12:58:29 -0400 Subject: [PATCH 111/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index b0a3ee848..ae31b61bb 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -158,10 +158,15 @@ This section includes an overview of how a subset of the OCPP 2.0.1 use cases th | O | DisplayMessage | | P | DataTransfer | -### Smart Charging +### Smart Charging Use Cases -Smart Charging is a use case within OCPP. -Work to fully support OCPP 2.0.1 Smart Charging is ongoing. Most functional requirements for General Smart Charging use cases (that is, K01–K10) are now supported. For an up-to-date overview of which features are currently supported, please refer to the [OCPP 2.0.1 Status](/doc/ocpp_201_status.md) document. +The use cases within the Smart Charging functional block are subdivided into the following three categories of use cases: + +1. General Smart Charging (Use Cases K01–K10) +2. External Charging Limit-based Smart Charging (K11–K14) +3. ISO 15118-based Smart Charging (K15–K17) + +Support for General and External Charging Limit-based Smart Charging is largely complete, with ISO 15118-based Smart Charging under active development. For an up-to-date overview of exactly which features are currently supported as well as design decisions that have been made to address optional or ambiguous functional requirements, please refer to the [OCPP 2.0.1 Status document](ocpp_201_status.md). #### K01 SetChargingProfile From e8002bbd9ecf4f477848955b858afedd5a5f91ca Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 13:00:57 -0400 Subject: [PATCH 112/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index ae31b61bb..8ad68d385 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -79,7 +79,12 @@ Once `everest-core` has been built with your station-specific `libocpp` configur ## Standalone Integration -If you wish to integrate libocpp's OCPP 2.0.1 implementation directly into your charging station software without using the full EVerest stack, you'll need to register several **callbacks** and implement **event handlers**. This allows libocpp to interact with your charging station according to OCPP requirements. +OCPP is a protocol that affects, controls, and monitors many areas of a charging station's operation. The `libocpp` library is just the messenger for this protocol. It is intended to provide mechanisms for connecting to and authenticating with a CSMS, sending and receiving the OCPP messages that govern behaviors in the standard, and to the track state required for a charging station to conform to the protocol all while minimizing hardware- or implementation-specific functionality. + +The actual substance of how a charging station reacts to an OCPP command (such as `ResetRequest`) or when it should consider sending a command to the CSMS (such as `NotifyChargingLimitRequest`) is left to the rest of the charging station's systems. This is done by providing means of (a) registering **callbacks** that can be triggered by a `libocpp` `ChargePoint` in response to certain events and (b) reacting to various **event handlers** defined on a `ChargePoint` in other areas of the charging station's codebase. + +> [!IMPORTANT] +> Integrating this library with your charging station requires both (a) defining **callbacks** that enable control of your station by `libocpp` and (b) calling `libocpp` **event handlers** in your charging station's systems in response to new events and data in order to keep `libocpp` up to date on station information. ### Terminology Throughout this document and the `libocpp` codebase, the following conventions are followed: From ef3e2fb7fbf1acafd9999a4a268ef75a7aa024ab Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 13:01:44 -0400 Subject: [PATCH 113/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 8ad68d385..30ba5d65f 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -127,8 +127,10 @@ The complete set of callbacks and event handlers defined on an OCPP 2.0.1 `Charg | `validate_network_profile_callback` | Validates the submitted Network Profile. Is Rejected if:
• No callback registered to validate network profile
• CSMS attempted to set a network profile with a lower securityProfile
• CSMS attempted to set a network profile that could not be validated
• Network profile could not be written to the device model storage
| | `variable_changed_callback` | Called when a variable has been changed by the CSMS | -### Event Handlers to Call -Event handlers to call are found in the [ChargePoint](https://github.com/EVerest/libocpp/blob/2124d055f9cc8f253d3a2441ec2d70686174d0ed/include/ocpp/v201/charge_point.hpp#L116). +### Event Handlers + + +The complete set of event handlers defined on an OCPP 2.0.1 `ChargePoint` can be viewed in the latter's [header file](/include/ocpp/v201/charge_point.hpp). Please use the [Doxygen documentation](#building-the-doxygen-documentation) as an additional source of information about the `ChargePoint` API. ### Initialize the Database From 9c0119e532f3480ac88ea3d65bf31eca5aefdf39 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 13:02:14 -0400 Subject: [PATCH 114/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 30ba5d65f..3efd169dc 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -134,7 +134,7 @@ The complete set of event handlers defined on an OCPP 2.0.1 `ChargePoint` can be ### Initialize the Database -Use provided [SQLite database](/doc/database_migrations.md) or implement your own storage drive. +To initialize the database where a `ChargePoint` will persist state, please use the provided [SQLite database](/doc/database_migrations.md) or implement your own storage drive. ## OCPP 2.0.1 Use Cases in `libocpp` From 3055a25123c0c5f4f1f1af2e3097d87939791d04 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 13:02:43 -0400 Subject: [PATCH 115/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 3efd169dc..563b1793a 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -146,24 +146,24 @@ This section includes an overview of how a subset of the OCPP 2.0.1 use cases th > > Please refer to the [OCPP 2.0.1 standard](https://openchargealliance.org/protocols/open-charge-point-protocol/#OCPP2.0.1) for more details. Functional blocks, use cases, and functional requirements are addressed in Part 2 of Edition 2. -| Clause | Use Case Name | -| :----- | :-------------------------------- | -| A | Security | -| B | Provisioning | -| C | Authorization | -| D | LocalAuthorizationList Management | -| E | Transactions | -| F | RemoteControl | -| G | Availability | -| H | Reservation | -| I | TariffAndCost | -| J | MeterValues | -| K | [SmartCharging](#smart-charging) | -| L | FirmwareManagement | -| M | ISO 15118 CertificateManagement | -| N | Diagnostics | -| O | DisplayMessage | -| P | DataTransfer | +| Functional Block | Subject. | +| :--------------- | :------------------------------------------ | +| A | Security | +| B | Provisioning | +| C | Authorization | +| D | Local Authorization List Management | +| E | Transactions | +| F | Remote Control | +| G | Availability | +| H | Reservation | +| I | Tariff and Cost | +| J | Meter Values | +| K | [Smart Charging](#smart-charging-use-cases) | +| L | Firmware Management | +| M | ISO 15118 Certificate Management | +| N | Diagnostics | +| O | Display Message | +| P | Data Transfer | ### Smart Charging Use Cases From 38e7c002d0f96537b38a1888ed90b0d2a729ce48 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 13:10:34 -0400 Subject: [PATCH 116/134] Update ocpp_16_README.md Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 5621b843d..c8751994f 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -51,7 +51,7 @@ The EVerest OCPP 1.6 implementation (`libocpp`) provides comprehensive support f The EVerest implementation of OCPP 1.6 has been tested against the OCPP Compliance Test Tool (OCTT and OCTT2) during the implementation. -The following table shows CSMSs with which this library was tested. +The following table shows CSMS with which this library was tested. If you provide a CSMS that is not yet listed here, feel free to [contact us](https://lists.lfenergy.org/g/everest)! From 770e9312ec7f0906085dfc5479a1a9aa6c5d17ce Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 14:17:29 -0400 Subject: [PATCH 117/134] Update ocpp_201_README.md Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 563b1793a..ad4b01b20 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -6,7 +6,8 @@ The `ocpp::v201` namespace exposes a `ChargePoint` class capable of client-side OCPP 2.0.1 communications. It enables charging stations to communicate with a cloud backend over a websocket for the remote control of charging stations and administration of charging sessions. -> [!NOTE] For more information about the differences between versions of the Open Charge Point Protocol, please refer to the [Open Charge Alliance's website](https://openchargealliance.org/protocols/open-charge-point-protocol/). +> [!NOTE] +> For more information about the differences between versions of the Open Charge Point Protocol, please refer to the [Open Charge Alliance's website](https://openchargealliance.org/protocols/open-charge-point-protocol/). The OCPP 2.0.1 implementation in `libocpp` is nearing completion, but there remain areas of active development. The OCA also does not currently plan to provide an official validation tool for all functionality within the protocol until the end of 2024. A high-level overview of supported functionality is provided [below](#supported-certification-profiles). For a more granular and up-to-date analysis of available OCPP 2.0.1 features in `libocpp`, please refer to the [OCPP 2.0.1 Status document](ocpp_201_status.md). From 2a4630562ec41961c6475f403f705a2de624a3e7 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Wed, 9 Oct 2024 14:51:11 -0400 Subject: [PATCH 118/134] Update ocpp_201_README.md updated content Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index ad4b01b20..c8cda704f 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -143,11 +143,12 @@ The OCPP 2.0.1 specification is broken down into concrete functional requirement This section includes an overview of how a subset of the OCPP 2.0.1 use cases that supported by `libocpp` are implemented in conjunction with callbacks provided by the charging station. We hope it serves as a useful guide to portions of the `libocpp` API and illustrates patterns of interaction between `libocpp` and other systems within a charging station. -> [!NOTE] Our goal is not to reproduce the entire OCPP 2.0.1 specification in this document. Rather we intend to illustrate how various use cases are realized using `ChargePoint` methods in `libocpp` in conjunction with callback implementations and event handlers. +> [!NOTE] +> Our goal is not to reproduce the entire OCPP 2.0.1 specification in this document. Rather we intend to illustrate how various use cases are realized using `ChargePoint` methods in `libocpp` in conjunction with callback implementations and event handlers. > > Please refer to the [OCPP 2.0.1 standard](https://openchargealliance.org/protocols/open-charge-point-protocol/#OCPP2.0.1) for more details. Functional blocks, use cases, and functional requirements are addressed in Part 2 of Edition 2. -| Functional Block | Subject. | +| Functional Block | Subject | | :--------------- | :------------------------------------------ | | A | Security | | B | Provisioning | From f6f48461fea006765999b07b607b7ae7c10b30e6 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:24:27 -0400 Subject: [PATCH 119/134] Update ocpp_16_README.md updated grammar Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index c8751994f..5621b843d 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -51,7 +51,7 @@ The EVerest OCPP 1.6 implementation (`libocpp`) provides comprehensive support f The EVerest implementation of OCPP 1.6 has been tested against the OCPP Compliance Test Tool (OCTT and OCTT2) during the implementation. -The following table shows CSMS with which this library was tested. +The following table shows CSMSs with which this library was tested. If you provide a CSMS that is not yet listed here, feel free to [contact us](https://lists.lfenergy.org/g/everest)! From 610a4ee51da48e3ed3966727fb2414063e08b974 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:26:43 -0400 Subject: [PATCH 120/134] Update ocpp_16_README.md updated readme title to match ocpp 2.0.1 readme Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_16_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_16_README.md b/doc/ocpp_16_README.md index 5621b843d..c9632b19b 100644 --- a/doc/ocpp_16_README.md +++ b/doc/ocpp_16_README.md @@ -2,7 +2,7 @@ ----- -# EVerest OCPP 1.6 Implementation (libocpp) +# OCPP 1.6 in `libocpp` This C++ library provides a complete and production-ready solution for integrating OCPP 1.6 into your electric vehicle (EV) charging stations. Our implementation enables seamless communication between charging stations and central management systems, supporting remote control, monitoring, and billing functionalities. From f030ac2b06db502ee63281ae468724edcf94a80e Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 11 Oct 2024 04:32:47 -0400 Subject: [PATCH 121/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index c8cda704f..78380e7a6 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -355,7 +355,6 @@ sequenceDiagram end ``` ------ ## Quickstart for OCPP 2.0.1 From c8233feeba3fe97085a18cdce54c5ffce7c386f9 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 11 Oct 2024 04:32:55 -0400 Subject: [PATCH 122/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 78380e7a6..d066d0661 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -332,7 +332,6 @@ sequenceDiagram ChargePoint-->>-CSMS : ReportChargingProfilesRequest(profiles_to_report) ``` ------ #### K10 Clear Charging Profile From 7cb3470e82dd3b2450b89ea8fc9d570f1b767a0a Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 11 Oct 2024 04:33:03 -0400 Subject: [PATCH 123/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index d066d0661..d23680c13 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -295,7 +295,6 @@ sequenceDiagram ChargePoint-->>-CSMS : GetCompositeScheduleResponse(CompositeSchedule) ``` ------ #### K09 Get Charging Profiles From 7e3b272f34c959f3172a42a45df0fac67ceb8042 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 11 Oct 2024 04:33:14 -0400 Subject: [PATCH 124/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index d23680c13..cf1bd729c 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -238,7 +238,6 @@ is `Rejected`: | `TxProfileTransactionNotOnEvse` | Happens when the provided `transactionId` is not known. [K01.FR.33] | | `TxProfileConflictingStackLevel` | Happens when a TxProfile has a stackLevel and transactionId combination already exists in a TxProfile with a different id in order to ensure that no two charging profiles with same stack level and purpose can be valid at the same time. [K01.FR.39] | ------ #### K08 Get Composite Schedule From cc61f36dcf4859698c527b215f4f847731896142 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 11 Oct 2024 04:33:39 -0400 Subject: [PATCH 125/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index cf1bd729c..bf11f7a92 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -355,7 +355,16 @@ sequenceDiagram ## Quickstart for OCPP 2.0.1 -Libocpp provides a small standalone OCPP2.0.1 client that you can control using command line. +This section walks you through how to sanity check that your `libocpp` development environment is set up effectively. The process will involve the following: + +1. Ensuring you've installed `libocpp`'s system dependencies +2. Standing up and configuring a CSMS (that is, an OCPP server) locally +3. Updating the default OCPP device model file +4. Updating the CSMS to make it aware of your test station's device model +5. Building `libocpp` as an OCPP 2.0.1 client executable +6. Running this freshly built binary + +This approach can also be used later in development for testing an actual station's device model and configuration is valid in the eyes of a CSMS. Install the dependencies and libocpp as described in [Build and Install libocpp](#build-and-install-libocpp). From 748b94681b113003c4db98c2af8947b30dc72af3 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 11 Oct 2024 04:33:59 -0400 Subject: [PATCH 126/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index bf11f7a92..83bdf7f7a 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -366,7 +366,8 @@ This section walks you through how to sanity check that your `libocpp` developme This approach can also be used later in development for testing an actual station's device model and configuration is valid in the eyes of a CSMS. -Install the dependencies and libocpp as described in [Build and Install libocpp](#build-and-install-libocpp). +### Installing System Dependencies +Before proceeding further in this section, please ensure you have installed the system dependencies of `libocpp` as described in the [Build and Install `libocpp`](#build-and-install-libocpp) section. Make sure you modify the following config entries in the [config.json](/config/v201/config.json) file according to the CSMS you want to connect to before executing make install. From b18fb24a68f411490666c0d5686b7436c4aae75d Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 11 Oct 2024 04:34:36 -0400 Subject: [PATCH 127/134] Update doc/ocpp_201_README.md Co-authored-by: Dan Moore <9156191+drmrd@users.noreply.github.com> Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 376 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 366 insertions(+), 10 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 83bdf7f7a..eee792b58 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -369,16 +369,372 @@ This approach can also be used later in development for testing an actual statio ### Installing System Dependencies Before proceeding further in this section, please ensure you have installed the system dependencies of `libocpp` as described in the [Build and Install `libocpp`](#build-and-install-libocpp) section. -Make sure you modify the following config entries in the [config.json](/config/v201/config.json) file according to the CSMS you want to connect to before executing make install. - -```json -{ - "Internal": { - "ChargePointId": "", - "CentralSystemURI": "" - } -} -``` +### Configuring Your Charging Station + +Before building the client binary, you will want to update the [`libocpp` configuration file](/config/v201/config.json) with accurate information about your desired charging station's hardware and how to access your CSMS. This configuration file includes an OCPP 2.0.1 device model for a charging station with two EVSEs, support for multiple network profiles, certificate-based authentication, etc. It also offers a host of `libocpp`-specific settings in an `InternalCtrlr` settings block. + +Tailoring a device model to your station hardware and software is a large subject that deserves its own documentation. For now, we recommend at least validating the following about variables in the `InternalCtrlr`: + +1. the `ChargePointId` variable matches the ID you've set (or plan to set) for this charging station in the CSMS, and +2. within the value of the `NetworkConnectionProfiles` variable, the `ocppCsmsUrl` field for the network connection profile you plan to use matches the websocket URL for your CSMS. + +For completeness, we've also provided a table below of each `InternalCtrlr` variable as well as available metadata about the variable coming from the [`InternalCtrlr`'s JSON Schema file](/config/v201/component_config/standardized/InternalCtrlr.json). + +

InternalCtrlr Variables +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariableTypeDefaultDescription
InternalCtrlrEnabledbooleantrueNone Provided
ChargePointIdstringNone Provided
NetworkConnectionProfilesstring + "[{\"configurationSlot\": 1, \"connectionData\": {\"messageTimeout\": 30, \"ocppCsmsUrl\": \"ws://localhost:9000\", \"ocppInterface\": \"Wired0\", \"ocppTransport\": \"JSON\", \"ocppVersion\": \"OCPP20\", \"securityProfile\": 1}}]" + + List of NetworkConnectionProfiles that define the functional and + technical parameters of a communication link. Must be a (JSON) string + with the format of SetNetworkProfileRequest. +
ChargeBoxSerialNumberstringNone Provided
ChargePointModelstringNone Provided
ChargePointSerialNumberstringNone Provided
ChargePointVendorstringNone Provided
FirmwareVersionstringNone Provided
ICCIDstringNone Provided
IMSIstringNone Provided
MeterSerialNumberstringNone Provided
MeterTypestringNone Provided
SupportedCiphers12string + "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-GCM-SHA384" + None Provided
SupportedCiphers13string + "TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256" + None Provided
AuthorizeConnectorZeroOnConnectorOnebooleantrueNone Provided
LogMessagesbooleantrueNone Provided
LogMessagesFormatstring"log,html,security" + Supported log formats are console, log, + html, console_detailed, + callback and security. + "security" logs security events into a seperate logfile +
LogRotationbooleanfalseEnable log rotation
LogRotationDateSuffixbooleanfalse + Use a datetime suffix in log rotation files instead of the traditional + .0, .1 +
LogRotationMaximumFileSizeinteger0 + Maximum file size in bytes for the log file after which it will be + rotated. Setting this to 0 disables log rotation. +
LogRotationMaximumFileCountinteger0 + Maximum amount of files before rotated logs will be deleted. Setting + this to 0 disables log rotation. +
SupportedChargingProfilePurposeTypesstring"ChargePointMaxProfile,TxDefaultProfile,TxProfile"None Provided
MaxCompositeScheduleDurationinteger31536000None Provided
NumberOfConnectorsinteger1None Provided
UseSslDefaultVerifyPathsbooleantrueUse default verify paths for validating CSMS server certificate
VerifyCsmsCommonNamebooleantrueNone Provided
UseTPMbooleanfalseNone Provided
VerifyCsmsAllowWildcardsbooleanfalseNone Provided
IFacestring""None Provided
EnableTLSKeylogbooleanfalseNone Provided
TLSKeylogFilestring/tmp/ocpp_tlskey.logNone Provided
OcspRequestIntervalinteger604800 + Interval in seconds used to request OCSP revocation status information + on the CSO Sub-CA certificates +
WebsocketPingPayloadstringhello thereNone Provided
WebsocketPongTimeoutinteger5None Provided
MonitorsProcessingIntervalinteger1 + Defines the interval at which the periodic monitors will be processed, + in seconds +
MaxCustomerInformationDataLengthinteger51200Maximum number of characters of Customer Information data
V2GCertificateExpireCheckInitialDelaySecondsinteger60 + Seconds to wait after boot notification to first check the V2G leaf + certificate for expiration and potential renewal +
V2GCertificateExpireCheckIntervalSecondsinteger43200 + Seconds between two checks for V2G leaf certificate expiration and + potential renewal +
ClientCertificateExpireCheckInitialDelaySecondsinteger60 + Seconds to wait after boot notification to first check the client + certificate for expiration and potential renewal +
ClientCertificateExpireCheckIntervalSecondsinteger43200 + Seconds between two checks for client certificate expiration and + potential renewal +
UpdateCertificateSymlinksbooleanfalseNone Provided
MessageQueueSizeThresholdinteger + Threshold for the size of in-memory message queues used to buffer + messages (and store e.g. while offline). If threshold is exceeded, + messages will be dropped according to OCPP specification to avoid + memory issues. +
MaxMessageSizeinteger32000 + Maximum size in bytes for messages sent to the CSMS via websocket. If + a message exceeds this size and is eligible to be split into multiple + messages, it will be split. Otherwise, this value is ignored. +
SupportedCriteriastring"Enabled,Active,Problem,Available" + List of criteria supported for a get custom report. + Enabled,Active,Problem,Available +
RoundClockAlignedTimestampsbooleanfalse + If enabled the metervalues configured with the + AlignedDataCtrlr will be rounded to the exact time + intervals +
ResumeTransactionsOnBootbooleanfalse + If enabled the transactions that were active before shutdown will be + resumed, if possible +
+
+

+
Change into libocpp/build and execute cmake and then make install: From 19fd0c17670aa8a58304e2280e97ff03f3c92c79 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Fri, 11 Oct 2024 04:47:17 -0400 Subject: [PATCH 128/134] Update ocpp_201_README.md Updated table of contents Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- doc/ocpp_201_README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index eee792b58..3caed6d27 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -18,11 +18,10 @@ The OCPP 2.0.1 implementation in `libocpp` is nearing completion, but there rema - [CSMS Compatibility](#csms-compatibility) - [Integration with EVerest](#integration-with-everest) - [Standalone Integration](#standalone-integration) - - [Key Integration Points](#key-integration-points) - [Callbacks to Register](#callbacks-to-register) - - [Event Handlers to Call](#event-handlers-to-call) + - [Event Handlers](#event-handlers) - [Initialize the Database](#initialize-the-database) - - [OCPP 2.0.1 Use Cases in `libocpp`](#ocpp-201-use-cases-in-libocpp) +- [OCPP 2.0.1 Use Cases in `libocpp`](#ocpp-201-use-cases-in-libocpp) - [Quickstart for OCPP 2.0.1](#quickstart-for-ocpp-201) - [Build and Install `libocpp`](#build-and-install-libocpp) - [Building with FetchContent Instead of EDM](#building-with-fetchcontent-instead-of-edm) @@ -99,7 +98,7 @@ The complete set of callbacks and event handlers defined on an OCPP 2.0.1 `Charg ### Callbacks to Register -| callbacks | description | +| Callbacks | Description | | :------------------------------------------------------ | :---------- | | `all_connectors_unavailable_callback` | Notifies that all connectors are unavailable. Used to handle charge availability requests and firmware updates. | | `boot_notification_callback` | Callback to notify of a system boot | From dd25107a2026482e3ffb908912848d18b288b596 Mon Sep 17 00:00:00 2001 From: wancen-afs <168112187+wancen-afs@users.noreply.github.com> Date: Tue, 15 Oct 2024 09:31:03 -0400 Subject: [PATCH 129/134] Update README.md updated ocpp 2.0.1 table of contents Signed-off-by: wancen-afs <168112187+wancen-afs@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 11a1aeb8b..a1d55f96c 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ EVerest's Open Charge Point Protocol (OCPP) modules are based on this library— |------------|----------| | • [Quickstart Guide](/doc/ocpp_201_README.md#quickstart-for-ocpp-201) | • [Quickstart Guide](/doc/ocpp_16_README.md#quickstart-for-ocpp-16) | | • [Build and Install libocpp](/doc/ocpp_201_README.md#build-and-install-libocpp) | • [Build and Install libocpp](/doc/ocpp_16_README.md#build-and-install-libocpp) | -| • [Functionality Support](/doc/ocpp_201_README.md#integration-with-everest) | • [Functionality Support](/doc/ocpp_16_README.md#functionality-support) | +| • [Supported Certification Profiles](/doc/ocpp_201_README.md#supported-certification-profiles) | • [Functionality Support](/doc/ocpp_16_README.md#functionality-support) | | • [Integration with EVerest](/doc/ocpp_201_README.md#integration-with-everest) | • [Integration with EVerest](/doc/ocpp_16_README.md#integration-with-everest) | | • [Standalone Integration](/doc/ocpp_201_README.md#standalone-integration) | • [Standalone Integration](/doc/ocpp_16_README.md#standalone-integration) | | • [Unit testing](doc/ocpp_201_README.md#unit-testing) | • [Unit testing](doc/ocpp_16_README.md#unit-testing) | From afe5d967a9809d9d543d499dc287a0cb1350ed3e Mon Sep 17 00:00:00 2001 From: Daniel Moore <9156191+drmrd@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:29:19 -0400 Subject: [PATCH 130/134] Finish a basic "Quickstart Guide" for OCPP 2.0.1 Signed-off-by: Daniel Moore <9156191+drmrd@users.noreply.github.com> --- doc/ocpp_201_README.md | 111 +++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 53 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index 3caed6d27..b2483b844 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -23,7 +23,6 @@ The OCPP 2.0.1 implementation in `libocpp` is nearing completion, but there rema - [Initialize the Database](#initialize-the-database) - [OCPP 2.0.1 Use Cases in `libocpp`](#ocpp-201-use-cases-in-libocpp) - [Quickstart for OCPP 2.0.1](#quickstart-for-ocpp-201) -- [Build and Install `libocpp`](#build-and-install-libocpp) - [Building with FetchContent Instead of EDM](#building-with-fetchcontent-instead-of-edm) - [Unit Testing](#unit-testing) - [Building the Doxygen Documentation](#building-the-doxygen-documentation) @@ -356,22 +355,57 @@ sequenceDiagram This section walks you through how to sanity check that your `libocpp` development environment is set up effectively. The process will involve the following: -1. Ensuring you've installed `libocpp`'s system dependencies -2. Standing up and configuring a CSMS (that is, an OCPP server) locally -3. Updating the default OCPP device model file -4. Updating the CSMS to make it aware of your test station's device model +1. Download `libocpp` from GitHub +2. Ensuring you've installed `libocpp`'s system dependencies +3. Standing up and configuring a CSMS (that is, an OCPP server) locally +4. Updating the default OCPP device model file 5. Building `libocpp` as an OCPP 2.0.1 client executable 6. Running this freshly built binary This approach can also be used later in development for testing an actual station's device model and configuration is valid in the eyes of a CSMS. + +### Download `libocpp` +You'll first want to download the source code for `libocpp` from this repository: + +```bash +git clone https://github.com/EVerest/libocpp.git +``` + + ### Installing System Dependencies -Before proceeding further in this section, please ensure you have installed the system dependencies of `libocpp` as described in the [Build and Install `libocpp`](#build-and-install-libocpp) section. +To be able to build `libocpp`, your system needs a compatible compiler, build tools, and development libraries and headers for several dependencies installed. For instance, on Debian GNU/Linux 11, these can be installed as follows: -### Configuring Your Charging Station +```bash + sudo apt install build-essential \ + cmake \ + ninja-build \ + libboost-all-dev \ + libsqlite3-dev \ + libssl-dev \ + python3-pip +``` + +> [!WARNING] +> OpenSSL version 3.0 or above is required. + + +### Standing up a CSMS +The configuration of a `libocpp` deployment includes information about the websocket URL(s) one or more `ChargePoint`s will use to communicate with a CSMS that supports OCPP 2.0.1. Before continuing, ensure that you have access to such an application for testing purposes. If not, there are free options that play nicely with EVerest and support simple local deployments _via_ containers. These include [CitrineOS](https://citrineos.github.io/) and [MaEVe](https://github.com/thoughtworks/maeve-csms/). + +Once you have access to a CSMS, you can (1) register a new charge point ID for testing and (2) provide this charge point ID and the CSMS websocket URL as the `ChargePointId` and within the `NetworkConnectionProfiles` variable in the `InternalCtrlr`, respectively. Instructions for accomplishing step (1) should be provided in your CSMS's documentation. More information about step (2) is provided in the [next section](#configuring-your-charging-station). + +### Configuring Your Charging Station Before building the client binary, you will want to update the [`libocpp` configuration file](/config/v201/config.json) with accurate information about your desired charging station's hardware and how to access your CSMS. This configuration file includes an OCPP 2.0.1 device model for a charging station with two EVSEs, support for multiple network profiles, certificate-based authentication, etc. It also offers a host of `libocpp`-specific settings in an `InternalCtrlr` settings block. +> [!INFO] +> We are editing this configuration prior to compiling `libocpp` here for convenience, but it is not a requirement. Doing so simply copies your customized configuration into the appropriate location in the `libocpp` installation directory. Specifically, you can provide any config file to `charge_point` by passing it to the `--config` parameter at runtime, providing its path relative to +> ``` +> /share/everest/modules/OCPP +> ``` +> (For instance, `` in this tutorial is `build/dist` within your `libocpp` repository.) + Tailoring a device model to your station hardware and software is a large subject that deserves its own documentation. For now, we recommend at least validating the following about variables in the `InternalCtrlr`: 1. the `ChargePointId` variable matches the ID you've set (or plan to set) for this charging station in the CSMS, and @@ -735,59 +769,28 @@ For completeness, we've also provided a table below of each `InternalCtrlr` vari

-Change into libocpp/build and execute cmake and then make install: - -```bash - cd build - cmake -DLIBOCPP16_BUILD_EXAMPLES=ON -DCMAKE_INSTALL_PREFIX=./dist .. - make -j$(nproc) install -``` - -Use the following command to start the charge point. Replace the config with [config-docker.json](/config/v201/config-docker.json) if you want to test with the [SteVe](https://github.com/steve-community/steve#docker) CSMS running in a docker container. - -```bash - ./dist/bin/charge_point \ - --maindir ./dist \ - --conf config.json -``` - -Type `help` to see a list of possible commands. - -In the libocpp folder create a folder named build and cd into it. -Execute cmake and then make install: +### Building `libocpp` as an OCPP 2.0.1 Client Executable +From the root directory of the `libocpp` repository, you can then configure, build, and install this library (including the charge point client) using CMake and Ninja: ```bash - mkdir build && cd build - cmake .. - make install + cmake -B build -G Ninja -DBUILD_TESTING=ON \ + -DCMAKE_INSTALL_PREFIX="./build/dist" \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + cmake -B -DCMAKE_INSTALL_PREFIX=./dist .. + make -j$(nproc) install ``` ------ - -## Build and Install `libocpp` -For Debian GNU/Linux 11 you will need the following dependencies: +### Running the `libocpp` Charge Point Binary +Congratulations! You've successfully built `libocpp`! The `build/dist` directory should now contain an installation of `libocpp` including a simple OCPP client binary at `build/dist/bin/charge_point`. It can be run by providing a working directory and `libocpp` configuration file as follows: ```bash - sudo apt install build-essential cmake python3-pip libboost-all-dev libsqlite3-dev libssl-dev + ./dist/bin/charge_point --maindir ./dist --conf config.json ``` -OpenSSL version 3.0 or above is required. - -Clone this repository. - -```bash - git clone https://github.com/EVerest/libocpp -``` - ------ - -## Building with FetchContent Instead of EDM - -In [doc/build-with-fetchcontent](/doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. +Type `help` to see a list of possible commands. ------ ## Unit Testing @@ -804,9 +807,14 @@ cd build make -j$(nproc) install ``` + +## Building with FetchContent Instead of EDM + +In [doc/build-with-fetchcontent](/doc/build-with-fetchcontent) you can find an example how to build libocpp with FetchContent instead of EDM. + + Run any required tests from build/tests. ------ ## Building the Doxygen Documentation @@ -820,13 +828,11 @@ You will find the generated Doxygen documentation at: The main reference for the integration of libocpp for OCPP2.0.1 is the ocpp::v201::ChargePoint class defined in libocpp/include/ocpp/v201/charge_point.hpp. ------ ## Support for TPM Keys In order to use the TPM keys, it is mandatory to use the default `libwebsocket` implementation. ------ ## Support for `websocket++` @@ -836,7 +842,6 @@ The old `websocket++` implementation has been deprecated. For enabling `websocke cmake .. -DLIBOCPP_ENABLE_DEPRECATED_WEBSOCKETPP=ON ``` ------ ## Support for `iface` From 37facb95523191710c55424406689183fe12ffc4 Mon Sep 17 00:00:00 2001 From: Daniel Moore <9156191+drmrd@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:34:09 -0400 Subject: [PATCH 131/134] Omit future-facing sections of 2.0.1 Quickstart Guide Signed-off-by: Daniel Moore <9156191+drmrd@users.noreply.github.com> --- doc/ocpp_201_README.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index b2483b844..cd6e6efd9 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -355,12 +355,18 @@ sequenceDiagram This section walks you through how to sanity check that your `libocpp` development environment is set up effectively. The process will involve the following: -1. Download `libocpp` from GitHub -2. Ensuring you've installed `libocpp`'s system dependencies + + +1. Download `libocpp` from GitHub +2. Ensuring you've installed `libocpp`'s system dependencies +7. Running unit tests This approach can also be used later in development for testing an actual station's device model and configuration is valid in the eyes of a CSMS. @@ -389,7 +395,10 @@ To be able to build `libocpp`, your system needs a compatible compiler, build to > [!WARNING] > OpenSSL version 3.0 or above is required. - + + -## Unit Testing +### Unit Testing GTest is required for building the test cases target. To build the target and run the tests you can reference the script `.ci/build-kit/install_and_test.sh`. From 1e2f4e0a1f24f49ba1c1ed4bc5698340e358e868 Mon Sep 17 00:00:00 2001 From: Daniel Moore <9156191+drmrd@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:44:35 -0400 Subject: [PATCH 132/134] Move 2.0.1 use case documentation into a dedicated guide Signed-off-by: Daniel Moore <9156191+drmrd@users.noreply.github.com> --- doc/ocpp_201_README.md | 215 +---------------------------- doc/ocpp_201_use_cases_in_depth.md | 214 ++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+), 213 deletions(-) create mode 100644 doc/ocpp_201_use_cases_in_depth.md diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index cd6e6efd9..a157a8b01 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -135,220 +135,9 @@ The complete set of event handlers defined on an OCPP 2.0.1 `ChargePoint` can be To initialize the database where a `ChargePoint` will persist state, please use the provided [SQLite database](/doc/database_migrations.md) or implement your own storage drive. -## OCPP 2.0.1 Use Cases in `libocpp` - -The OCPP 2.0.1 specification is broken down into concrete functional requirements using a three-tier system. At the top, there are sixteen **functional blocks** lettered A through P that describe the high-level desired capabilities of actors adhering to the standard. These functional blocks are then broken into **use cases** that describe different scenarios in which one or more charging stations, local controllers, and charging station management systems might find themselves. The required and optional behaviors of these systems in these scenarios are then declared as **functional requirements** within each use case. - -This section includes an overview of how a subset of the OCPP 2.0.1 use cases that supported by `libocpp` are implemented in conjunction with callbacks provided by the charging station. We hope it serves as a useful guide to portions of the `libocpp` API and illustrates patterns of interaction between `libocpp` and other systems within a charging station. - -> [!NOTE] -> Our goal is not to reproduce the entire OCPP 2.0.1 specification in this document. Rather we intend to illustrate how various use cases are realized using `ChargePoint` methods in `libocpp` in conjunction with callback implementations and event handlers. -> -> Please refer to the [OCPP 2.0.1 standard](https://openchargealliance.org/protocols/open-charge-point-protocol/#OCPP2.0.1) for more details. Functional blocks, use cases, and functional requirements are addressed in Part 2 of Edition 2. - -| Functional Block | Subject | -| :--------------- | :------------------------------------------ | -| A | Security | -| B | Provisioning | -| C | Authorization | -| D | Local Authorization List Management | -| E | Transactions | -| F | Remote Control | -| G | Availability | -| H | Reservation | -| I | Tariff and Cost | -| J | Meter Values | -| K | [Smart Charging](#smart-charging-use-cases) | -| L | Firmware Management | -| M | ISO 15118 Certificate Management | -| N | Diagnostics | -| O | Display Message | -| P | Data Transfer | - -### Smart Charging Use Cases - -The use cases within the Smart Charging functional block are subdivided into the following three categories of use cases: - -1. General Smart Charging (Use Cases K01–K10) -2. External Charging Limit-based Smart Charging (K11–K14) -3. ISO 15118-based Smart Charging (K15–K17) - -Support for General and External Charging Limit-based Smart Charging is largely complete, with ISO 15118-based Smart Charging under active development. For an up-to-date overview of exactly which features are currently supported as well as design decisions that have been made to address optional or ambiguous functional requirements, please refer to the [OCPP 2.0.1 Status document](ocpp_201_status.md). - -#### K01 SetChargingProfile - -Allows the CSMS to influence the charging power or current drawn from a specific EVSE or the -entire Charging Station over a period of time. - -```mermaid -sequenceDiagram - CSMS->>+ChargePoint : SetChargingProfileRequest(call) - - ChargePoint->>+DeviceModel : SmartChargingCtrlrAvailable? - DeviceModel-->>-ChargePoint : Component - - rect Red - break SmartChargingCtrlrAvailable = false - ChargePoint-->>CSMS : Smart Charging NotSupported CallError - end - end - - ChargePoint->>+SmartCharging : validate_and_add_profile(call.msg.Profile, call.msg.EVSE ID) - - SmartCharging->>SmartCharging : validate_profile(Profile, EVSE ID) - - rect Red - break Invalid Profile - SmartCharging-->>ChargePoint : SetChargingProfileResponse: Rejected - ChargePoint-->>CSMS : SetChargingProfileResponse: Rejected - end - end - - SmartCharging->>+SmartCharging : add_profile(Profile, EVSE ID) - SmartCharging->>-EVerest : signal_set_charging_profiles_callback - - SmartCharging-->>-ChargePoint : SetChargingProfileResponse: Accepted - - ChargePoint-->>-CSMS : SetChargingProfileResponse: Accepted -``` - -Profile validation returns the following errors to the caller when a Profile -is `Rejected`: - -| Errors | Description | -| :------------------------------------------------------------ | :-------------------------------------------------------------- | -| `ChargingProfileFirstStartScheduleIsNotZero` | The `startPeriod` of the first `chargingSchedulePeriod` needs to be 0.
[K01.FR.31] | -| `ChargingProfileNoChargingSchedulePeriods` | Happens when the `ChargingProfile` doesn't have any Charging Schedule Periods. | -| `ChargingScheduleChargingRateUnitUnsupported` | Happens when a chargingRateUnit is passed in that is not configured in the `ChargingScheduleChargingRateUnit`. [K01.FR.26] | -| `ChargingSchedulePeriodInvalidPhaseToUse` | Happens when an invalid `phaseToUse` is passed in. [K01.FR.19] [K01.FR.48] | -| `ChargingSchedulePeriodPhaseToUseACPhaseSwitchingUnsupported` | Happens when phaseToUse is passed in and the EVSE does not have `ACPhaseSwitchingSupported` defined and set to true. [K01.FR.20] [K01.FR.48] | -| `ChargingSchedulePeriodsOutOfOrder` | `ChargingSchedulePeriod.startPeriod` elements need to be in increasing values. [K01.FR.35] | -| `ChargingStationMaxProfileCannotBeRelative` | Happens when a `ChargingStationMaxProfile.chargingProfileKind` is set to `Relative`. [K01.FR.38] | -| `ChargingStationMaxProfileEvseIdGreaterThanZero` | Happens when a `ChargingStationMaxProfile` is attempted to be set with an EvseID isn't `0`. [K01.FR.03] | -| `ChargingProfileMissingRequiredStartSchedule` | Happens when an `Absolute` or `Recurring` `ChargingProfile` doesn't have a `startSchedule`. [K01.FR.40] | -| `ChargingProfileExtraneousStartSchedule` | Happens when a Relative `ChargingProfile` has a `startSchedule`. [K01.FR.41] | -| `EvseDoesNotExist` | Happens when the `evseId`of a `SetChargingProfileRequest` does not exist. [K01.FR.28] | -| `ExistingChargingStationExternalConstraints` | Happens when a `SetChargingProfileRequest` Profile has a purpose of `ChargingStationExternalConstraints` and one already exists with the same `ChargingProfile.id` exists. [K01.FR.05] | -| `InvalidProfileType` | Happens when a `ChargingStationMaxProfile` is attempted to be set with a `ChargingProfile` that isn't a `ChargingStationMaxProfile`. | -| `TxProfileEvseHasNoActiveTransaction` | Happens when a `SetChargingProfileRequest` with a `TxProfile` is submitted and there is no transaction active on the specified EVSE. [K01.FR.09] | -| `TxProfileEvseIdNotGreaterThanZero` | `TxProfile` needs to have an `evseId` greater than 0. [K01.FR.16] | -| `TxProfileMissingTransactionId` | A `transactionId` is required for`SetChargingProfileRequest`s with a `TxProfile` in order to match the profile to a specific transation. [K01.FR.03] | -| `TxProfileTransactionNotOnEvse` | Happens when the provided `transactionId` is not known. [K01.FR.33] | -| `TxProfileConflictingStackLevel` | Happens when a TxProfile has a stackLevel and transactionId combination already exists in a TxProfile with a different id in order to ensure that no two charging profiles with same stack level and purpose can be valid at the same time. [K01.FR.39] | - - -#### K08 Get Composite Schedule - -The CSMS requests the Charging Station to report the Composite Charging -Schedule, as calculated by the Charging Station for a specific point of -time, and may change over time due to external causes such as local -balancing based on grid connection capacity and EVSE availablity. - -The Composite Schedule is the result of result of merging the time periods -set in the `ChargingStationMaxProfile`, `ChargingStationExternalConstraints`, -`TxDefaultProfile` and `TxProfile` type profiles. - -```mermaid -sequenceDiagram - - CSMS->>+ChargePoint: GetCompositeSchedule(call) - - ChargePoint->>+DeviceModel : ChargingScheduleChargingRateUnit? - DeviceModel-->>-ChargePoint : Component - - rect Red - break call.msg.chargingRateUnit is not supported - ChargePoint-->>CSMS : ChargingScheduleChargingRateUnitUnsupported CallError - end - end - - ChargePoint->>+EvseManager : does_evse_exist(call.msg.evseId) - EvseManager-->>-ChargePoint : bool - rect Red - break EVSE does not exist - ChargePoint-->>CSMS : EvseDoesNotExist CallError - end - end - - ChargePoint->>+SmartChargingHandler : get_valid_profiles(call.msg.evseId) - - SmartChargingHandler-->>-ChargePoint : vector - - ChargePoint->>+SmartChargingHandler : calculate_composite_schedule
(vector>+Profile: calculate_composite_schedule(profiles) - Profile-->>-SmartChargingHandler: composite_schedule - end - - note right of SmartChargingHandler: Create consolidated CompositeSchedule
from all 4 Profile types - - - SmartChargingHandler->>+Profile: calculate_composite_schedule(ExternalConstraints, Max, TxDefault, Tx) - Profile-->>-SmartChargingHandler: CompositeSchedule - SmartChargingHandler-->>-ChargePoint: CompositeSchedule - - ChargePoint-->>-CSMS : GetCompositeScheduleResponse(CompositeSchedule) -``` - - -#### K09 Get Charging Profiles - -Returns to the CSMS the Charging Schedules/limits installed on a Charging Station based on the -passed in criteria. - -```mermaid -sequenceDiagram - - CSMS->>+ChargePoint: GetChargingProfiles(criteria) - - ChargePoint->>+SmartChargingHandler : get_reported_profiles(criteria) - - loop filter ChargingProfiles - SmartChargingHandler->>SmartChargingHandler: filter on ChargingProfile criteria - end - - SmartChargingHandler-->>-ChargePoint : Vector - - ChargePoint-->>CSMS : GetChargingProfilesResponse(profiles) - - alt no Profiles - rect Red - ChargePoint-->>CSMS : GetChargingProfilesResponse(NoProfiles) - ChargePoint->>CSMS : return - end - - else Profiles - ChargePoint-->>CSMS : GetChargingProfilesResponse(Accepted) - end - - ChargePoint->>ChargePoint : determine profiles_to_report - - ChargePoint-->>-CSMS : ReportChargingProfilesRequest(profiles_to_report) -``` - - -#### K10 Clear Charging Profile - -Clears Charging Profiles installed on a Charging Station based on the -passed in criteria. - -```mermaid -sequenceDiagram - - CSMS->>+ChargePoint: ClearChargingProfileRequest(criteria) - - alt no Profiles matching criteria - rect Red - ChargePoint-->>CSMS : ClearChargingProfileResponse(Unknown) - - end - - else found matching Profiles - ChargePoint-->>-CSMS : ClearChargingProfileResponse(Accepted) - end -``` +## OCPP 2.0.1 Use Cases in `libocpp` +For an in-depth guide to use cases from the OCPP 2.0.1 standard and how these use cases are implemented in `libocpp`, please see [this guide](/doc/ocpp_201_use_cases_in_depth.md). ## Quickstart for OCPP 2.0.1 diff --git a/doc/ocpp_201_use_cases_in_depth.md b/doc/ocpp_201_use_cases_in_depth.md new file mode 100644 index 000000000..255f8a1e1 --- /dev/null +++ b/doc/ocpp_201_use_cases_in_depth.md @@ -0,0 +1,214 @@ +## OCPP 2.0.1 Use Cases in `libocpp` + +The OCPP 2.0.1 specification is broken down into concrete functional requirements using a three-tier system. At the top, there are sixteen **functional blocks** lettered A through P that describe the high-level desired capabilities of actors adhering to the standard. These functional blocks are then broken into **use cases** that describe different scenarios in which one or more charging stations, local controllers, and charging station management systems might find themselves. The required and optional behaviors of these systems in these scenarios are then declared as **functional requirements** within each use case. + +This section includes an overview of how a subset of the OCPP 2.0.1 use cases that supported by `libocpp` are implemented in conjunction with callbacks provided by the charging station. We hope it serves as a useful guide to portions of the `libocpp` API and illustrates patterns of interaction between `libocpp` and other systems within a charging station. + +> [!NOTE] +> Our goal is not to reproduce the entire OCPP 2.0.1 specification in this document. Rather we intend to illustrate how various use cases are realized using `ChargePoint` methods in `libocpp` in conjunction with callback implementations and event handlers. +> +> Please refer to the [OCPP 2.0.1 standard](https://openchargealliance.org/protocols/open-charge-point-protocol/#OCPP2.0.1) for more details. Functional blocks, use cases, and functional requirements are addressed in Part 2 of Edition 2. + +| Functional Block | Subject | +| :--------------- | :------------------------------------------ | +| A | Security | +| B | Provisioning | +| C | Authorization | +| D | Local Authorization List Management | +| E | Transactions | +| F | Remote Control | +| G | Availability | +| H | Reservation | +| I | Tariff and Cost | +| J | Meter Values | +| K | [Smart Charging](#smart-charging-use-cases) | +| L | Firmware Management | +| M | ISO 15118 Certificate Management | +| N | Diagnostics | +| O | Display Message | +| P | Data Transfer | + +### Smart Charging Use Cases + +The use cases within the Smart Charging functional block are subdivided into the following three categories of use cases: + +1. General Smart Charging (Use Cases K01–K10) +2. External Charging Limit-based Smart Charging (K11–K14) +3. ISO 15118-based Smart Charging (K15–K17) + +Support for General and External Charging Limit-based Smart Charging is largely complete, with ISO 15118-based Smart Charging under active development. For an up-to-date overview of exactly which features are currently supported as well as design decisions that have been made to address optional or ambiguous functional requirements, please refer to the [OCPP 2.0.1 Status document](ocpp_201_status.md). + +#### K01 SetChargingProfile + +Allows the CSMS to influence the charging power or current drawn from a specific EVSE or the +entire Charging Station over a period of time. + +```mermaid +sequenceDiagram + CSMS->>+ChargePoint : SetChargingProfileRequest(call) + + ChargePoint->>+DeviceModel : SmartChargingCtrlrAvailable? + DeviceModel-->>-ChargePoint : Component + + rect Red + break SmartChargingCtrlrAvailable = false + ChargePoint-->>CSMS : Smart Charging NotSupported CallError + end + end + + ChargePoint->>+SmartCharging : validate_and_add_profile(call.msg.Profile, call.msg.EVSE ID) + + SmartCharging->>SmartCharging : validate_profile(Profile, EVSE ID) + + rect Red + break Invalid Profile + SmartCharging-->>ChargePoint : SetChargingProfileResponse: Rejected + ChargePoint-->>CSMS : SetChargingProfileResponse: Rejected + end + end + + SmartCharging->>+SmartCharging : add_profile(Profile, EVSE ID) + SmartCharging->>-EVerest : signal_set_charging_profiles_callback + + SmartCharging-->>-ChargePoint : SetChargingProfileResponse: Accepted + + ChargePoint-->>-CSMS : SetChargingProfileResponse: Accepted +``` + +Profile validation returns the following errors to the caller when a Profile +is `Rejected`: + +| Errors | Description | +| :------------------------------------------------------------ | :-------------------------------------------------------------- | +| `ChargingProfileFirstStartScheduleIsNotZero` | The `startPeriod` of the first `chargingSchedulePeriod` needs to be 0.
[K01.FR.31] | +| `ChargingProfileNoChargingSchedulePeriods` | Happens when the `ChargingProfile` doesn't have any Charging Schedule Periods. | +| `ChargingScheduleChargingRateUnitUnsupported` | Happens when a chargingRateUnit is passed in that is not configured in the `ChargingScheduleChargingRateUnit`. [K01.FR.26] | +| `ChargingSchedulePeriodInvalidPhaseToUse` | Happens when an invalid `phaseToUse` is passed in. [K01.FR.19] [K01.FR.48] | +| `ChargingSchedulePeriodPhaseToUseACPhaseSwitchingUnsupported` | Happens when phaseToUse is passed in and the EVSE does not have `ACPhaseSwitchingSupported` defined and set to true. [K01.FR.20] [K01.FR.48] | +| `ChargingSchedulePeriodsOutOfOrder` | `ChargingSchedulePeriod.startPeriod` elements need to be in increasing values. [K01.FR.35] | +| `ChargingStationMaxProfileCannotBeRelative` | Happens when a `ChargingStationMaxProfile.chargingProfileKind` is set to `Relative`. [K01.FR.38] | +| `ChargingStationMaxProfileEvseIdGreaterThanZero` | Happens when a `ChargingStationMaxProfile` is attempted to be set with an EvseID isn't `0`. [K01.FR.03] | +| `ChargingProfileMissingRequiredStartSchedule` | Happens when an `Absolute` or `Recurring` `ChargingProfile` doesn't have a `startSchedule`. [K01.FR.40] | +| `ChargingProfileExtraneousStartSchedule` | Happens when a Relative `ChargingProfile` has a `startSchedule`. [K01.FR.41] | +| `EvseDoesNotExist` | Happens when the `evseId`of a `SetChargingProfileRequest` does not exist. [K01.FR.28] | +| `ExistingChargingStationExternalConstraints` | Happens when a `SetChargingProfileRequest` Profile has a purpose of `ChargingStationExternalConstraints` and one already exists with the same `ChargingProfile.id` exists. [K01.FR.05] | +| `InvalidProfileType` | Happens when a `ChargingStationMaxProfile` is attempted to be set with a `ChargingProfile` that isn't a `ChargingStationMaxProfile`. | +| `TxProfileEvseHasNoActiveTransaction` | Happens when a `SetChargingProfileRequest` with a `TxProfile` is submitted and there is no transaction active on the specified EVSE. [K01.FR.09] | +| `TxProfileEvseIdNotGreaterThanZero` | `TxProfile` needs to have an `evseId` greater than 0. [K01.FR.16] | +| `TxProfileMissingTransactionId` | A `transactionId` is required for`SetChargingProfileRequest`s with a `TxProfile` in order to match the profile to a specific transation. [K01.FR.03] | +| `TxProfileTransactionNotOnEvse` | Happens when the provided `transactionId` is not known. [K01.FR.33] | +| `TxProfileConflictingStackLevel` | Happens when a TxProfile has a stackLevel and transactionId combination already exists in a TxProfile with a different id in order to ensure that no two charging profiles with same stack level and purpose can be valid at the same time. [K01.FR.39] | + + +#### K08 Get Composite Schedule + +The CSMS requests the Charging Station to report the Composite Charging +Schedule, as calculated by the Charging Station for a specific point of +time, and may change over time due to external causes such as local +balancing based on grid connection capacity and EVSE availablity. + +The Composite Schedule is the result of result of merging the time periods +set in the `ChargingStationMaxProfile`, `ChargingStationExternalConstraints`, +`TxDefaultProfile` and `TxProfile` type profiles. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: GetCompositeSchedule(call) + + ChargePoint->>+DeviceModel : ChargingScheduleChargingRateUnit? + DeviceModel-->>-ChargePoint : Component + + rect Red + break call.msg.chargingRateUnit is not supported + ChargePoint-->>CSMS : ChargingScheduleChargingRateUnitUnsupported CallError + end + end + + ChargePoint->>+EvseManager : does_evse_exist(call.msg.evseId) + EvseManager-->>-ChargePoint : bool + rect Red + break EVSE does not exist + ChargePoint-->>CSMS : EvseDoesNotExist CallError + end + end + + ChargePoint->>+SmartChargingHandler : get_valid_profiles(call.msg.evseId) + + SmartChargingHandler-->>-ChargePoint : vector + + ChargePoint->>+SmartChargingHandler : calculate_composite_schedule
(vector>+Profile: calculate_composite_schedule(profiles) + Profile-->>-SmartChargingHandler: composite_schedule + end + + note right of SmartChargingHandler: Create consolidated CompositeSchedule
from all 4 Profile types + + + SmartChargingHandler->>+Profile: calculate_composite_schedule(ExternalConstraints, Max, TxDefault, Tx) + Profile-->>-SmartChargingHandler: CompositeSchedule + + SmartChargingHandler-->>-ChargePoint: CompositeSchedule + + ChargePoint-->>-CSMS : GetCompositeScheduleResponse(CompositeSchedule) +``` + + +#### K09 Get Charging Profiles + +Returns to the CSMS the Charging Schedules/limits installed on a Charging Station based on the +passed in criteria. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: GetChargingProfiles(criteria) + + ChargePoint->>+SmartChargingHandler : get_reported_profiles(criteria) + + loop filter ChargingProfiles + SmartChargingHandler->>SmartChargingHandler: filter on ChargingProfile criteria + end + + SmartChargingHandler-->>-ChargePoint : Vector + + ChargePoint-->>CSMS : GetChargingProfilesResponse(profiles) + + alt no Profiles + rect Red + ChargePoint-->>CSMS : GetChargingProfilesResponse(NoProfiles) + ChargePoint->>CSMS : return + end + + else Profiles + ChargePoint-->>CSMS : GetChargingProfilesResponse(Accepted) + end + + ChargePoint->>ChargePoint : determine profiles_to_report + + ChargePoint-->>-CSMS : ReportChargingProfilesRequest(profiles_to_report) +``` + + +#### K10 Clear Charging Profile + +Clears Charging Profiles installed on a Charging Station based on the +passed in criteria. + +```mermaid +sequenceDiagram + + CSMS->>+ChargePoint: ClearChargingProfileRequest(criteria) + + alt no Profiles matching criteria + rect Red + ChargePoint-->>CSMS : ClearChargingProfileResponse(Unknown) + + end + + else found matching Profiles + ChargePoint-->>-CSMS : ClearChargingProfileResponse(Accepted) + end +``` From 31c5d4e819183a3570b06c2db32b1bd78ee9ecad Mon Sep 17 00:00:00 2001 From: Daniel Moore <9156191+drmrd@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:46:25 -0400 Subject: [PATCH 133/134] Update highlight color in use case diagrams Signed-off-by: Daniel Moore <9156191+drmrd@users.noreply.github.com> --- doc/ocpp_201_use_cases_in_depth.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/ocpp_201_use_cases_in_depth.md b/doc/ocpp_201_use_cases_in_depth.md index 255f8a1e1..dfccb01c1 100644 --- a/doc/ocpp_201_use_cases_in_depth.md +++ b/doc/ocpp_201_use_cases_in_depth.md @@ -50,7 +50,7 @@ sequenceDiagram ChargePoint->>+DeviceModel : SmartChargingCtrlrAvailable? DeviceModel-->>-ChargePoint : Component - rect Red + rect rgb(128,202,255) break SmartChargingCtrlrAvailable = false ChargePoint-->>CSMS : Smart Charging NotSupported CallError end @@ -60,7 +60,7 @@ sequenceDiagram SmartCharging->>SmartCharging : validate_profile(Profile, EVSE ID) - rect Red + rect rgb(128,202,255) break Invalid Profile SmartCharging-->>ChargePoint : SetChargingProfileResponse: Rejected ChargePoint-->>CSMS : SetChargingProfileResponse: Rejected @@ -119,7 +119,7 @@ sequenceDiagram ChargePoint->>+DeviceModel : ChargingScheduleChargingRateUnit? DeviceModel-->>-ChargePoint : Component - rect Red + rect rgb(128,202,255) break call.msg.chargingRateUnit is not supported ChargePoint-->>CSMS : ChargingScheduleChargingRateUnitUnsupported CallError end @@ -127,7 +127,7 @@ sequenceDiagram ChargePoint->>+EvseManager : does_evse_exist(call.msg.evseId) EvseManager-->>-ChargePoint : bool - rect Red + rect rgb(128,202,255) break EVSE does not exist ChargePoint-->>CSMS : EvseDoesNotExist CallError end @@ -177,7 +177,7 @@ sequenceDiagram ChargePoint-->>CSMS : GetChargingProfilesResponse(profiles) alt no Profiles - rect Red + rect rgb(128,202,255) ChargePoint-->>CSMS : GetChargingProfilesResponse(NoProfiles) ChargePoint->>CSMS : return end @@ -203,7 +203,7 @@ sequenceDiagram CSMS->>+ChargePoint: ClearChargingProfileRequest(criteria) alt no Profiles matching criteria - rect Red + rect rgb(128,202,255) ChargePoint-->>CSMS : ClearChargingProfileResponse(Unknown) end From b5f18ddaf81787e9494eeae2ba717b38095a14aa Mon Sep 17 00:00:00 2001 From: Daniel Moore <9156191+drmrd@users.noreply.github.com> Date: Tue, 15 Oct 2024 15:50:31 -0400 Subject: [PATCH 134/134] Update config.json path in 2.0.1 README Signed-off-by: Daniel Moore <9156191+drmrd@users.noreply.github.com> --- doc/ocpp_201_README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ocpp_201_README.md b/doc/ocpp_201_README.md index a157a8b01..2f69b1528 100644 --- a/doc/ocpp_201_README.md +++ b/doc/ocpp_201_README.md @@ -72,7 +72,7 @@ The ongoing development of OCPP 2.0.1 implementation is continuously tested agai EVerest provides a simplified OCPP 2.0.1 integration path through its `OCPP201` module. -When setting up a development environment (or building) EVerest through the [`everest-core`](https://github.com/EVerest/everest-core) project, a version of `libocpp` will be pulled down as a dependency. If you wish to use the `OCPP201` module, you will want to defined your charging station's Device Model in the [`config.json` file](config/v201/config.json) for the `libocpp` repository pulled in by `everest-core` as a dependency. This configuration will be incorporated into `everest-core` during the latter's build process. +When setting up a development environment (or building) EVerest through the [`everest-core`](https://github.com/EVerest/everest-core) project, a version of `libocpp` will be pulled down as a dependency. If you wish to use the `OCPP201` module, you will want to defined your charging station's Device Model in the [`config.json` file](/config/v201/config.json) for the `libocpp` repository pulled in by `everest-core` as a dependency. This configuration will be incorporated into `everest-core` during the latter's build process. Once `everest-core` has been built with your station-specific `libocpp` configuration, you can then specify and configure `OCPP201` as a module in the [runtime configuration](https://everest.github.io/nightly/general/04_detail_module_concept.html#wiring-it-all-together-the-run-configuration) of your EVerest deployment.