From 0c6181605a13ea211cf7b98197688b56b94fe280 Mon Sep 17 00:00:00 2001 From: Cornelius Claussen Date: Tue, 11 Jul 2023 17:33:00 +0200 Subject: [PATCH] refactor BSP interfaces - The new evse_board_support interface replaces the old board_support_AC interface both for AC and DC. - Move from abstract events (e.g. CarPluggedIn) to CP states A/B/C/D/E/F to simplify BSP drivers - This moves the complete IEC61851-1 state machine into EvseManager - create new interfaces for AC_RCD and connector_lock - Charging subsystem is now using the new error framework - Added most MREC error types that relate to charging - Yeti and umwc driver will need MCU firmware updates that will come soon - Added most MREC fault codes to NodeRed SIL UI Signed-off-by: Cornelius Claussen --- config/CMakeLists.txt | 1 - config/config-hil.yaml | 105 --- config/config-sil-dc-sae-v2g.yaml | 2 + config/config-sil-dc-sae-v2h.yaml | 2 + config/config-sil-dc.yaml | 3 +- config/config-sil-energy-management.yaml | 6 +- config/config-sil-ocpp-custom-extension.yaml | 6 +- config/config-sil-ocpp-pnc.yaml | 4 + config/config-sil-ocpp.yaml | 6 +- config/config-sil-ocpp201.yaml | 6 +- config/config-sil-two-evse-dc.yaml | 6 +- config/config-sil-two-evse.yaml | 6 +- config/config-sil.yaml | 10 +- config/nodered/config-sil-flow.json | 801 +++++++++++++++++- errors/ac_rcd.yaml | 25 + errors/connector_lock.yaml | 33 + errors/evse_board_support.yaml | 56 ++ errors/evse_manager.yaml | 11 + interfaces/ac_rcd.yaml | 19 + interfaces/board_support_AC.yaml | 98 --- interfaces/board_support_AC_debug.yaml | 40 - interfaces/connector_lock.yaml | 9 + interfaces/evse_board_support.yaml | 133 +++ interfaces/evse_manager.yaml | 6 +- interfaces/yeti_extras.yaml | 29 - modules/API/API.cpp | 4 +- modules/API/API.hpp | 10 +- modules/API/CMakeLists.txt | 5 +- modules/API/limit_decimal_places.cpp | 25 +- modules/API/limit_decimal_places.hpp | 4 +- modules/API/manifest.yaml | 25 +- modules/Auth/Auth.cpp | 6 +- modules/Auth/Auth.hpp | 1 + modules/Auth/include/AuthHandler.hpp | 3 +- modules/Auth/lib/AuthHandler.cpp | 17 +- modules/Auth/manifest.yaml | 14 + modules/Auth/tests/auth_tests.cpp | 3 +- modules/EvseManager/CMakeLists.txt | 2 + modules/EvseManager/Charger.cpp | 401 ++++----- modules/EvseManager/Charger.hpp | 51 +- modules/EvseManager/ErrorHandling.cpp | 338 ++++++++ modules/EvseManager/ErrorHandling.hpp | 141 +++ modules/EvseManager/EvseManager.cpp | 96 +-- modules/EvseManager/EvseManager.hpp | 33 +- modules/EvseManager/IECStateMachine.cpp | 402 +++++++++ modules/EvseManager/IECStateMachine.hpp | 128 +++ modules/EvseManager/Timeout.hpp | 89 +- .../EvseManager/energy_grid/energyImpl.hpp | 2 +- modules/EvseManager/evse/evse_managerImpl.cpp | 23 +- modules/EvseManager/manifest.yaml | 21 +- modules/MicroMegaWattBSP/CMakeLists.txt | 2 +- modules/MicroMegaWattBSP/MicroMegaWattBSP.hpp | 6 +- .../board_support/board_support_ACImpl.cpp | 123 --- .../board_support/evse_board_supportImpl.cpp | 126 +++ ..._ACImpl.hpp => evse_board_supportImpl.hpp} | 32 +- modules/MicroMegaWattBSP/manifest.yaml | 2 +- .../umwc_comms/CMakeLists.txt | 5 +- .../MicroMegaWattBSP/umwc_comms/config.h.in | 3 - .../MicroMegaWattBSP/umwc_comms/evSerial.cpp | 89 +- .../MicroMegaWattBSP/umwc_comms/evSerial.h | 18 +- .../umwc_comms/protobuf/generate_nanopb.sh | 2 +- .../umwc_comms/protobuf/hi2lo.options | 1 - .../umwc_comms/protobuf/hi2lo.pb.c | 39 - .../umwc_comms/protobuf/hi2lo.pb.h | 238 ------ .../umwc_comms/protobuf/hi2lo.proto | 55 -- .../umwc_comms/protobuf/lo2hi.pb.h | 194 ----- .../umwc_comms/protobuf/lo2hi.proto | 63 -- .../protobuf/{lo2hi.options => umwc.options} | 1 + .../umwc_comms/protobuf/umwc.pb.c | 40 + .../umwc_comms/protobuf/umwc.pb.h | 336 ++++++++ .../umwc_comms/protobuf/umwc.proto | 117 +++ .../umwc_fwupdate/CMakeLists.txt | 3 - .../umwc_fwupdate/config.h.in | 3 - .../MicroMegaWattBSP/umwc_fwupdate/main.cpp | 10 +- modules/YetiDriver/CMakeLists.txt | 6 +- modules/YetiDriver/YetiDriver.cpp | 235 +---- modules/YetiDriver/YetiDriver.hpp | 32 +- .../board_support/board_support_ACImpl.cpp | 179 ---- .../board_support/evse_board_supportImpl.cpp | 183 ++++ ..._ACImpl.hpp => evse_board_supportImpl.hpp} | 32 +- .../connector_lock/connector_lockImpl.cpp | 24 + .../connector_lockImpl.hpp} | 26 +- modules/YetiDriver/manifest.yaml | 17 +- modules/YetiDriver/rcd/ac_rcdImpl.cpp | 25 + .../ac_rcdImpl.hpp} | 23 +- modules/YetiDriver/yeti_comms/CMakeLists.txt | 8 +- modules/YetiDriver/yeti_comms/config.h.in | 3 - modules/YetiDriver/yeti_comms/evSerial.cpp | 201 +---- modules/YetiDriver/yeti_comms/evSerial.h | 54 +- .../yeti_comms/protobuf/common.pb.c | 10 - .../yeti_comms/protobuf/common.pb.h | 33 - .../yeti_comms/protobuf/common.proto | 8 - .../yeti_comms/protobuf/generate_nanopb.sh | 2 +- .../yeti_comms/protobuf/hi2lo.options | 3 - .../YetiDriver/yeti_comms/protobuf/hi2lo.pb.c | 78 -- .../YetiDriver/yeti_comms/protobuf/hi2lo.pb.h | 521 ------------ .../yeti_comms/protobuf/hi2lo.proto | 128 --- .../YetiDriver/yeti_comms/protobuf/lo2hi.pb.c | 43 - .../YetiDriver/yeti_comms/protobuf/lo2hi.pb.h | 472 ----------- .../yeti_comms/protobuf/lo2hi.proto | 169 ---- .../protobuf/{lo2hi.options => yeti.options} | 1 + .../yeti_comms/protobuf/yeti.pb.c} | 23 +- .../YetiDriver/yeti_comms/protobuf/yeti.pb.h | 380 +++++++++ .../YetiDriver/yeti_comms/protobuf/yeti.proto | 132 +++ .../yeti_extras/yeti_extrasImpl.cpp | 27 - .../YetiDriver/yeti_fwupdate/CMakeLists.txt | 5 +- modules/YetiDriver/yeti_fwupdate/config.h.in | 3 - modules/YetiDriver/yeti_fwupdate/main.cpp | 11 +- .../yeti_simulation_controlImpl.cpp | 65 -- modules/simulation/JsCarSimulator/index.js | 2 + modules/simulation/JsYetiSimulator/index.js | 759 +++++++++++++---- .../simulation/JsYetiSimulator/manifest.yaml | 27 +- types/board_support_common.yaml | 48 ++ ...d_support.yaml => evse_board_support.yaml} | 71 +- types/evse_manager.yaml | 30 +- 115 files changed, 4913 insertions(+), 3961 deletions(-) delete mode 100644 config/config-hil.yaml create mode 100644 errors/ac_rcd.yaml create mode 100644 errors/connector_lock.yaml create mode 100644 errors/evse_board_support.yaml create mode 100644 errors/evse_manager.yaml create mode 100644 interfaces/ac_rcd.yaml delete mode 100644 interfaces/board_support_AC.yaml delete mode 100644 interfaces/board_support_AC_debug.yaml create mode 100644 interfaces/connector_lock.yaml create mode 100644 interfaces/evse_board_support.yaml delete mode 100644 interfaces/yeti_extras.yaml create mode 100644 modules/EvseManager/ErrorHandling.cpp create mode 100644 modules/EvseManager/ErrorHandling.hpp create mode 100644 modules/EvseManager/IECStateMachine.cpp create mode 100644 modules/EvseManager/IECStateMachine.hpp delete mode 100644 modules/MicroMegaWattBSP/board_support/board_support_ACImpl.cpp create mode 100644 modules/MicroMegaWattBSP/board_support/evse_board_supportImpl.cpp rename modules/MicroMegaWattBSP/board_support/{board_support_ACImpl.hpp => evse_board_supportImpl.hpp} (58%) delete mode 100644 modules/MicroMegaWattBSP/umwc_comms/config.h.in delete mode 100644 modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.options delete mode 100644 modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.pb.c delete mode 100644 modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.pb.h delete mode 100644 modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.proto delete mode 100644 modules/MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.pb.h delete mode 100644 modules/MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.proto rename modules/MicroMegaWattBSP/umwc_comms/protobuf/{lo2hi.options => umwc.options} (51%) create mode 100644 modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.pb.c create mode 100644 modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.pb.h create mode 100644 modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.proto delete mode 100644 modules/MicroMegaWattBSP/umwc_fwupdate/config.h.in delete mode 100644 modules/YetiDriver/board_support/board_support_ACImpl.cpp create mode 100644 modules/YetiDriver/board_support/evse_board_supportImpl.cpp rename modules/YetiDriver/board_support/{board_support_ACImpl.hpp => evse_board_supportImpl.hpp} (58%) create mode 100644 modules/YetiDriver/connector_lock/connector_lockImpl.cpp rename modules/YetiDriver/{yeti_simulation_control/yeti_simulation_controlImpl.hpp => connector_lock/connector_lockImpl.hpp} (57%) create mode 100644 modules/YetiDriver/rcd/ac_rcdImpl.cpp rename modules/YetiDriver/{yeti_extras/yeti_extrasImpl.hpp => rcd/ac_rcdImpl.hpp} (66%) delete mode 100644 modules/YetiDriver/yeti_comms/config.h.in delete mode 100644 modules/YetiDriver/yeti_comms/protobuf/common.pb.c delete mode 100644 modules/YetiDriver/yeti_comms/protobuf/common.pb.h delete mode 100644 modules/YetiDriver/yeti_comms/protobuf/common.proto delete mode 100644 modules/YetiDriver/yeti_comms/protobuf/hi2lo.options delete mode 100644 modules/YetiDriver/yeti_comms/protobuf/hi2lo.pb.c delete mode 100644 modules/YetiDriver/yeti_comms/protobuf/hi2lo.pb.h delete mode 100644 modules/YetiDriver/yeti_comms/protobuf/hi2lo.proto delete mode 100644 modules/YetiDriver/yeti_comms/protobuf/lo2hi.pb.c delete mode 100644 modules/YetiDriver/yeti_comms/protobuf/lo2hi.pb.h delete mode 100644 modules/YetiDriver/yeti_comms/protobuf/lo2hi.proto rename modules/YetiDriver/yeti_comms/protobuf/{lo2hi.options => yeti.options} (51%) rename modules/{MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.pb.c => YetiDriver/yeti_comms/protobuf/yeti.pb.c} (54%) create mode 100644 modules/YetiDriver/yeti_comms/protobuf/yeti.pb.h create mode 100644 modules/YetiDriver/yeti_comms/protobuf/yeti.proto delete mode 100644 modules/YetiDriver/yeti_extras/yeti_extrasImpl.cpp delete mode 100644 modules/YetiDriver/yeti_fwupdate/config.h.in delete mode 100644 modules/YetiDriver/yeti_simulation_control/yeti_simulation_controlImpl.cpp create mode 100644 types/board_support_common.yaml rename types/{board_support.yaml => evse_board_support.yaml} (72%) diff --git a/config/CMakeLists.txt b/config/CMakeLists.txt index 3b600b1402..583f88282b 100644 --- a/config/CMakeLists.txt +++ b/config/CMakeLists.txt @@ -7,7 +7,6 @@ generate_config_run_script(CONFIG sil-dc-sae-v2g) generate_config_run_script(CONFIG sil-dc-sae-v2h) generate_config_run_script(CONFIG sil-two-evse-dc) generate_config_run_script(CONFIG sil-energy-management) -generate_config_run_script(CONFIG hil) generate_config_run_script(CONFIG sil-gen-pm) generate_config_run_script(CONFIG sil-ocpp) generate_config_run_script(CONFIG sil-ocpp-custom-extension) diff --git a/config/config-hil.yaml b/config/config-hil.yaml deleted file mode 100644 index 69368aec7a..0000000000 --- a/config/config-hil.yaml +++ /dev/null @@ -1,105 +0,0 @@ -active_modules: - emgr_logger: - module: JsEmgrLogger - config_implementation: - main: - file_path_prefix: emgr_data - connections: - emgr: - - module_id: energy_manager - implementation_id: main - pm_grid: - - module_id: sma_modbus_meter - implementation_id: main - pm_ev: - - module_id: yeti_driver - implementation_id: powermeter - energy_manager: - module: JsEnergyManager - config_implementation: - main: - pid_setpoint: 500 - pid_p_weight: 0.46 - pid_i_weight: 0.2 - pid_d_weight: 0.5 - pid_output_interval: 5000 - pid_i_limit: -1 - pid_min_output: 1380 - pid_max_output: 7360 - connections: - chargingdriver: - - module_id: evse_manager - implementation_id: evse - chargingdriverenergy: - - module_id: evse_manager - implementation_id: evse_energy_control - gridpowermeter: - - module_id: sma_modbus_meter - implementation_id: main - chargingdriverpowermeter: - - module_id: yeti_driver - implementation_id: powermeter - iso15118_charger: - module: EvseV2G - config_module: - device: auto - tls_security: allow - connections: - security: - - module_id: evse_security - implementation_id: main - evse_manager: - module: EvseManager - config_module: - three_phases: true - has_ventilation: true - country_code: DE - rcd_enabled: true - connections: - bsp: - - module_id: yeti_driver - implementation_id: board_support - powermeter: - - module_id: yeti_driver - implementation_id: powermeter - auth: - - module_id: auth - implementation_id: main - yeti_driver: - module: YetiDriver - config_module: - serial_port: /dev/ttyUSB0 - baud_rate: 115200 - car_simulator: - module: JsCarSimulator - connections: - simulation_control: - - module_id: yeti_driver - implementation_id: yeti_simulation_control - auth: - module: JsAuth - connections: - tokenProvider: - - module_id: token_provider_1 - implementation_id: main - tokenValidator: - - module_id: token_validator - implementation_id: main - evse_security: - module: EvseSecurity - config_module: - private_key_password: "123456" - token_provider_1: - module: DummyTokenProvider - connections: - evse: - - module_id: evse_manager - implementation_id: evse - token_validator: - module: DummyTokenValidator - config_implementation: - main: - validation_result: Accepted - validation_reason: Token seems valid - sleep: 0.25 -x-module-layout: {} diff --git a/config/config-sil-dc-sae-v2g.yaml b/config/config-sil-dc-sae-v2g.yaml index af94a72e04..0e56b1238e 100644 --- a/config/config-sil-dc-sae-v2g.yaml +++ b/config/config-sil-dc-sae-v2g.yaml @@ -52,6 +52,8 @@ active_modules: module: JsDCSupplySimulator yeti_driver: module: JsYetiSimulator + config_module: + connector_id: 1 slac: module: JsSlacSimulator imd: diff --git a/config/config-sil-dc-sae-v2h.yaml b/config/config-sil-dc-sae-v2h.yaml index 96c5d151e0..476a25a759 100644 --- a/config/config-sil-dc-sae-v2h.yaml +++ b/config/config-sil-dc-sae-v2h.yaml @@ -52,6 +52,8 @@ active_modules: module: JsDCSupplySimulator yeti_driver: module: JsYetiSimulator + config_module: + connector_id: 1 slac: module: JsSlacSimulator imd: diff --git a/config/config-sil-dc.yaml b/config/config-sil-dc.yaml index 9716ca77ff..07566523c7 100644 --- a/config/config-sil-dc.yaml +++ b/config/config-sil-dc.yaml @@ -19,7 +19,6 @@ active_modules: config_module: connector_id: 1 country_code: DE - rcd_enabled: true evse_id: DE*PNX*E12345*1 evse_id_din: 49A80737A45678 session_logging: true @@ -50,6 +49,8 @@ active_modules: module: JsDCSupplySimulator yeti_driver: module: JsYetiSimulator + config_module: + connector_id: 1 slac: module: JsSlacSimulator imd: diff --git a/config/config-sil-energy-management.yaml b/config/config-sil-energy-management.yaml index e6a2387017..5b382294a8 100644 --- a/config/config-sil-energy-management.yaml +++ b/config/config-sil-energy-management.yaml @@ -20,7 +20,6 @@ active_modules: three_phases: true has_ventilation: true country_code: DE - rcd_enabled: true evse_id: DE*PNX*E12345*1 session_logging: true session_logging_xml: false @@ -48,7 +47,6 @@ active_modules: three_phases: true has_ventilation: true country_code: DE - rcd_enabled: true evse_id: DE*PNX*E12345*2 session_logging: true session_logging_xml: false @@ -65,8 +63,12 @@ active_modules: implementation_id: powermeter yeti_driver_1: module: JsYetiSimulator + config_module: + connector_id: 1 yeti_driver_2: module: JsYetiSimulator + config_module: + connector_id: 2 slac: module: JsSlacSimulator car_simulator_1: diff --git a/config/config-sil-ocpp-custom-extension.yaml b/config/config-sil-ocpp-custom-extension.yaml index 81cf665c94..f8250729f9 100644 --- a/config/config-sil-ocpp-custom-extension.yaml +++ b/config/config-sil-ocpp-custom-extension.yaml @@ -20,7 +20,6 @@ active_modules: three_phases: true has_ventilation: true country_code: DE - rcd_enabled: true evse_id: "1" session_logging: true session_logging_xml: false @@ -48,7 +47,6 @@ active_modules: three_phases: true has_ventilation: true country_code: DE - rcd_enabled: true evse_id: "2" session_logging: true session_logging_xml: false @@ -71,8 +69,12 @@ active_modules: implementation_id: charger yeti_driver_1: module: JsYetiSimulator + config_module: + connector_id: 1 yeti_driver_2: module: JsYetiSimulator + config_module: + connector_id: 2 slac: module: JsSlacSimulator car_simulator_1: diff --git a/config/config-sil-ocpp-pnc.yaml b/config/config-sil-ocpp-pnc.yaml index f9c83bcd59..e576bb673c 100644 --- a/config/config-sil-ocpp-pnc.yaml +++ b/config/config-sil-ocpp-pnc.yaml @@ -74,8 +74,12 @@ active_modules: implementation_id: charger yeti_driver_1: module: JsYetiSimulator + config_module: + connector_id: 1 yeti_driver_2: module: JsYetiSimulator + config_module: + connector_id: 2 slac: module: JsSlacSimulator car_simulator_1: diff --git a/config/config-sil-ocpp.yaml b/config/config-sil-ocpp.yaml index bf3d22fe57..4067f3e954 100644 --- a/config/config-sil-ocpp.yaml +++ b/config/config-sil-ocpp.yaml @@ -20,7 +20,6 @@ active_modules: three_phases: true has_ventilation: true country_code: DE - rcd_enabled: true evse_id: "1" session_logging: true session_logging_xml: false @@ -49,7 +48,6 @@ active_modules: three_phases: true has_ventilation: true country_code: DE - rcd_enabled: true evse_id: "2" session_logging: true session_logging_xml: false @@ -73,8 +71,12 @@ active_modules: implementation_id: charger yeti_driver_1: module: JsYetiSimulator + config_module: + connector_id: 1 yeti_driver_2: module: JsYetiSimulator + config_module: + connector_id: 2 slac: module: JsSlacSimulator car_simulator_1: diff --git a/config/config-sil-ocpp201.yaml b/config/config-sil-ocpp201.yaml index 595497ba82..91c080d1a7 100644 --- a/config/config-sil-ocpp201.yaml +++ b/config/config-sil-ocpp201.yaml @@ -20,7 +20,6 @@ active_modules: three_phases: true has_ventilation: true country_code: DE - rcd_enabled: true evse_id: "1" session_logging: true session_logging_xml: false @@ -48,7 +47,6 @@ active_modules: three_phases: true has_ventilation: true country_code: DE - rcd_enabled: true evse_id: "2" session_logging: true session_logging_xml: false @@ -71,8 +69,12 @@ active_modules: implementation_id: charger yeti_driver_1: module: JsYetiSimulator + config_module: + connector_id: 1 yeti_driver_2: module: JsYetiSimulator + config_module: + connector_id: 2 slac: module: JsSlacSimulator car_simulator_1: diff --git a/config/config-sil-two-evse-dc.yaml b/config/config-sil-two-evse-dc.yaml index 73273bad60..90f2845908 100644 --- a/config/config-sil-two-evse-dc.yaml +++ b/config/config-sil-two-evse-dc.yaml @@ -19,7 +19,6 @@ active_modules: config_module: connector_id: 1 country_code: DE - rcd_enabled: true evse_id: DE*PNX*E12345*1 evse_id_din: 49A80737A45678 session_logging: true @@ -52,7 +51,6 @@ active_modules: three_phases: true has_ventilation: true country_code: DE - rcd_enabled: true evse_id: DE*PNX*E12345*2 session_logging: true session_logging_xml: false @@ -69,8 +67,12 @@ active_modules: implementation_id: powermeter yeti_driver_1: module: JsYetiSimulator + config_module: + connector_id: 1 yeti_driver_2: module: JsYetiSimulator + config_module: + connector_id: 2 slac_1: module: JsSlacSimulator powersupply_dc: diff --git a/config/config-sil-two-evse.yaml b/config/config-sil-two-evse.yaml index a6161a643c..c92e2cf503 100644 --- a/config/config-sil-two-evse.yaml +++ b/config/config-sil-two-evse.yaml @@ -20,7 +20,6 @@ active_modules: three_phases: true has_ventilation: true country_code: DE - rcd_enabled: true evse_id: DE*PNX*E12345*1 session_logging: true session_logging_xml: false @@ -48,7 +47,6 @@ active_modules: three_phases: true has_ventilation: true country_code: DE - rcd_enabled: true evse_id: DE*PNX*E12345*2 session_logging: true session_logging_xml: false @@ -65,8 +63,12 @@ active_modules: implementation_id: powermeter yeti_driver_1: module: JsYetiSimulator + config_module: + connector_id: 1 yeti_driver_2: module: JsYetiSimulator + config_module: + connector_id: 2 slac: module: JsSlacSimulator car_simulator_1: diff --git a/config/config-sil.yaml b/config/config-sil.yaml index 6591ec0044..7710c9d92d 100644 --- a/config/config-sil.yaml +++ b/config/config-sil.yaml @@ -12,6 +12,7 @@ active_modules: connection_timeout: 10 prioritize_authorization_over_stopping_transaction: true selection_algorithm: FindFirst + ignore_connector_faults: true connections: evse_manager: - implementation_id: evse @@ -62,7 +63,6 @@ active_modules: max_current_export_A: 32 payment_enable_contract: true payment_enable_eim: true - rcd_enabled: true session_logging: true session_logging_path: /tmp/everest-logs session_logging_xml: false @@ -80,6 +80,12 @@ active_modules: slac: - implementation_id: evse module_id: slac + ac_rcd: + - implementation_id: rcd + module_id: connector_1_powerpath + connector_lock: + - implementation_id: connector_lock + module_id: connector_1_powerpath module: EvseManager telemetry: id: 1 @@ -158,6 +164,8 @@ active_modules: connections: {} module: DummyTokenValidator connector_1_powerpath: + config_module: + connector_id: 1 connections: {} module: JsYetiSimulator telemetry: diff --git a/config/nodered/config-sil-flow.json b/config/nodered/config-sil-flow.json index 674bce4790..e743492e53 100644 --- a/config/nodered/config-sil-flow.json +++ b/config/nodered/config-sil-flow.json @@ -13,6 +13,14 @@ "disabled": false, "info": "" }, + { + "id": "cb7609df6138407d", + "type": "tab", + "label": "Errors", + "disabled": false, + "info": "", + "env": [] + }, { "id": "af1e1eeac9c4b704", "type": "group", @@ -331,6 +339,17 @@ "disabled": false, "hidden": false }, + { + "id": "18b792e585c4a82f", + "type": "ui_group", + "name": "Errors", + "tab": "d3ada9fa4cf6ac53", + "order": 1, + "disp": true, + "width": "6", + "collapse": false, + "className": "" + }, { "id": "c8955752ad17f297", "type": "mqtt in", @@ -1809,7 +1828,7 @@ }, { "label": "AC RCD Error", - "value": "sleep 1;rcd_current 10.3;sleep 10;rcd_current 0.1sleep 36000#unplug", + "value": "sleep 1;iec_wait_pwr_ready;sleep 1;draw_power_regulated 16,3;sleep 3;rcd_current 10.5;sleep 5;rcd_current 0.2;sleep 36000#unplug", "type": "str" }, { @@ -1949,5 +1968,785 @@ "620b0d248a89ece0" ] ] + }, + { + "id": "14a551bb80c5552d", + "type": "change", + "z": "cb7609df6138407d", + "name": "", + "rules": [ + { + "t": "set", + "p": "connector_number", + "pt": "flow", + "to": "1", + "tot": "str" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 440, + "y": 180, + "wires": [ + [] + ] + }, + { + "id": "2ffed6827d01d00d", + "type": "inject", + "z": "cb7609df6138407d", + "name": "", + "props": [ + { + "p": "payload" + }, + { + "p": "topic", + "vt": "str" + } + ], + "repeat": "", + "crontab": "", + "once": true, + "onceDelay": 0.1, + "topic": "", + "payloadType": "date", + "x": 190, + "y": 180, + "wires": [ + [ + "14a551bb80c5552d" + ] + ] + }, + { + "id": "ca7308d14419cbd2", + "type": "change", + "z": "cb7609df6138407d", + "name": "Insert Connector number", + "rules": [ + { + "t": "change", + "p": "topic", + "pt": "msg", + "from": "#", + "fromt": "str", + "to": "connector_number", + "tot": "flow" + } + ], + "action": "", + "property": "", + "from": "", + "to": "", + "reg": false, + "x": 770, + "y": 560, + "wires": [ + [ + "513a3b91748dc03c" + ] + ] + }, + { + "id": "513a3b91748dc03c", + "type": "mqtt out", + "z": "cb7609df6138407d", + "name": "", + "topic": "", + "qos": "1", + "retain": "false", + "respTopic": "", + "contentType": "", + "userProps": "", + "correl": "", + "expiry": "", + "broker": "fc8686af.48d178", + "x": 970, + "y": 560, + "wires": [] + }, + { + "id": "cf15f41427168f59", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "BrownOut", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"BrownOut\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"BrownOut\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 160, + "y": 280, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "b0c90949862e4acf", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "DiodeFault", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"DiodeFault\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"DiodeFault\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 170, + "y": 240, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "40c2bf363920110e", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "EnergyManagement", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"EnergyManagement\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"EnergyManagement\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 200, + "y": 320, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "94a8973cf4eb4963", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "PermanentFault", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"PermanentFault\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"PermanentFault\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 180, + "y": 360, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "db13aa747d6ffd3a", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC2GroundFailure", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC2GroundFailure\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC2GroundFailure\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 200, + "y": 400, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "a18a831e962fe2fb", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC4OverCurrentFailure", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC4OverCurrentFailure\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC4OverCurrentFailure\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 220, + "y": 440, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "2fc7fdfe4ae8b520", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC5OverVoltage", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC5OverVoltage\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC5OverVoltage\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 200, + "y": 480, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "9efbf3ce40d6881c", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC6UnderVoltage", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC6UnderVoltage\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC6UnderVoltage\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 200, + "y": 520, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "d6bbb4c57751877b", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC8EmergencyStop", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC8EmergencyStop\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC8EmergencyStop\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 210, + "y": 560, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "639a0db868e0ed18", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC10InvalidVehicleMode", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC10InvalidVehicleMode\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC10InvalidVehicleMode\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 220, + "y": 600, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "7b28a940fe45f635", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC14PilotFault", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC14PilotFault\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC14PilotFault\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 190, + "y": 640, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "0232fd01e1e02fe1", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC15PowerLoss", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC15PowerLoss\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC15PowerLoss\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 200, + "y": 680, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "202ebd4c388a5817", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC17EVSEContactorFault", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC17EVSEContactorFault\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC17EVSEContactorFault\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 230, + "y": 720, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "0a81c071b35d54d3", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC18CableOverTempDerate", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC18CableOverTempDerate\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC18CableOverTempDerate\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 230, + "y": 760, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "3eb9a5937aed34a7", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC19CableOverTempStop", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC19CableOverTempStop\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC19CableOverTempStop\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 230, + "y": 800, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "b6208cc76ab8ba93", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC20PartialInsertion", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC20PartialInsertion\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC20PartialInsertion\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 210, + "y": 840, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "1205c62ee631e717", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC23ProximityFault", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC23ProximityFault\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC23ProximityFault\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 210, + "y": 880, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "df7bf0f1e692028c", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC24ConnectorVoltageHigh", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC24ConnectorVoltageHigh\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC24ConnectorVoltageHigh\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 230, + "y": 920, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "5a669dee09d69d6c", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC25BrokenLatch", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC25BrokenLatch\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC25BrokenLatch\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 200, + "y": 960, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] + }, + { + "id": "25cadcb508c05cfc", + "type": "ui_switch", + "z": "cb7609df6138407d", + "name": "", + "label": "MREC26CutCable", + "tooltip": "", + "group": "18b792e585c4a82f", + "order": 1, + "width": 0, + "height": 0, + "passthru": true, + "decouple": "false", + "topic": "everest_external/nodered/#/carsim/error", + "topicType": "str", + "style": "", + "onvalue": "{\"error_type\":\"MREC26CutCable\",\"raise\":\"true\"}", + "onvalueType": "json", + "onicon": "", + "oncolor": "", + "offvalue": "{\"error_type\":\"MREC26CutCable\",\"raise\":\"false\"}", + "offvalueType": "json", + "officon": "", + "offcolor": "", + "animate": false, + "className": "", + "x": 190, + "y": 1000, + "wires": [ + [ + "ca7308d14419cbd2" + ] + ] } ] \ No newline at end of file diff --git a/errors/ac_rcd.yaml b/errors/ac_rcd.yaml new file mode 100644 index 0000000000..697ab5c6ae --- /dev/null +++ b/errors/ac_rcd.yaml @@ -0,0 +1,25 @@ +description: >- + Errors for AC RCD + + MREC error code should be triggered in parallel with the more fine grained non-standardized AC/DC errors. + + All error codes that begin with MREC needs to be implemented to fulfill the Minimum Required Error Codes defined by the ChargeX consortium: + + https://inl.gov/content/uploads/2023/07/ChargeX_MREC_Rev5_09.12.23.pdf +errors: + - name: Selftest + description: The Selftest failed, device permanently broken + - name: DC + description: RCD was triggered by a DC fault + - name: AC + description: RCD was triggered by an AC fault + - name: MREC2GroundFailure + description: >- + MREC compliant fault code + - name: VendorError + description: >- + Vendor specific error code. Will stop charging session. + - name: VendorWarning + description: >- + Vendor specific error code. Charging may continue. + \ No newline at end of file diff --git a/errors/connector_lock.yaml b/errors/connector_lock.yaml new file mode 100644 index 0000000000..db0f3bc621 --- /dev/null +++ b/errors/connector_lock.yaml @@ -0,0 +1,33 @@ +description: >- + Errors for Connector Lock + + The following error types give more details about connector lock errors. + You should consider setting a MREC_1_ConnectorLockFailure to indicate a generic lock failure with an MREC error code as well + as one of the more detailed but custom error codes to specify the reason: + + All error codes that begin with MREC needs to be implemented to fulfill the Minimum Required Error Codes defined by the ChargeX consortium: + + https://inl.gov/content/uploads/2023/07/ChargeX_MREC_Rev5_09.12.23.pdf +errors: + - name: ConnectorLockCapNotCharged + description: The capacitor for connector lock motor failed to charge within expected time + - name: ConnectorLockUnexpectedOpen + description: The connector lock feedback returns open while it should be closed + - name: ConnectorLockUnexpectedClose + description: The connector lock feedback returns closed while it should be open + - name: ConnectorLockFailedLock + description: The connector lock failed to lock (feedback still returns open) + - name: ConnectorLockFailedUnlock + description: The connector lock failed to unlock (feedback still returns closed) + - name: MREC1ConnectorLockFailure + description: >- + Failure to lock or unlock connector on the vehicle side as per MREC definition. + How should that be implemented? We can only find out about locking on the EVSE side, + so we will use this error to report EVSE side lock failures. It is probably a mistake in the MREC definition. + - name: VendorError + description: >- + Vendor specific error code. Will stop charging session. + - name: VendorWarning + description: >- + Vendor specific error code. Charging may continue. + \ No newline at end of file diff --git a/errors/evse_board_support.yaml b/errors/evse_board_support.yaml new file mode 100644 index 0000000000..c577ef2650 --- /dev/null +++ b/errors/evse_board_support.yaml @@ -0,0 +1,56 @@ +description: >- + Errors for the evse_board_support interface. + All error codes that begin with MREC needs to be implemented to fulfill the Minimum Required Error Codes defined by the ChargeX consortium: + + https://inl.gov/content/uploads/2023/07/ChargeX_MREC_Rev5_09.12.23.pdf +errors: + - name: DiodeFault + description: The CP diode in the EV is shorted. + - name: VentilationNotAvailable + description: EV requested state D but no ventilation is available. + - name: BrownOut + description: The hardware/MCU detected a brown out. + - name: EnergyManagement + description: Energy could not be delivered because an (external) energy management failed. + - name: PermanentFault + description: The EVSE is permanently broken and requires repair. + - name: MREC2GroundFailure + description: Ground fault circuit interrupter has been activated. + - name: MREC3HighTemperature + description: High temperature inside the EVSE is derating power delivery. + - name: MREC4OverCurrentFailure + description: Over current protection device has tripped. + - name: MREC5OverVoltage + description: Input voltage to the vehicle has risen above an acceptable level. + - name: MREC6UnderVoltage + description: Input voltage to the vehicle has dropped below an acceptable level. + - name: MREC8EmergencyStop + description: Emergency stop is pressed by the user (required if equipped). + - name: MREC10InvalidVehicleMode + description: The vehicle is in an invalid mode for charging (Reported by IEC stack) + - name: MREC14PilotFault + description: The control pilot voltage is out of range. + - name: MREC15PowerLoss + description: The EVSE is unable to supply any power due to mains failure + - name: MREC17EVSEContactorFault + description: Contactors fail to open or close on EVSE's side. May also include welding related errors. + - name: MREC18CableOverTempDerate + description: Temperature of charging cable or connector assembly is too high, resulting in reduced power operation. + - name: MREC19CableOverTempStop + description: Temperature of charging cable or connector assembly is too high, resulting in a stopped charging session. + - name: MREC20PartialInsertion + description: Cable latch is raised due to incomplete insertion into the vehicle charging port. + - name: MREC23ProximityFault + description: The proximity voltage is out of range. + - name: MREC24ConnectorVoltageHigh + description: The output voltage of EVSE is high before charging starts or after charging ends. + - name: MREC25BrokenLatch + description: The latch on the connector is broken. + - name: MREC26CutCable + description: The output cable has been severed from the EVSE. + - name: VendorError + description: >- + Vendor specific error code. Will stop charging session. + - name: VendorWarning + description: >- + Vendor specific error code. Charging may continue. diff --git a/errors/evse_manager.yaml b/errors/evse_manager.yaml new file mode 100644 index 0000000000..d3d3fce95c --- /dev/null +++ b/errors/evse_manager.yaml @@ -0,0 +1,11 @@ +description: >- + Errors for EvseManager + + All error codes that begin with MREC needs to be implemented to fulfill the Minimum Required Error Codes defined by the ChargeX consortium: + + https://inl.gov/content/uploads/2023/07/ChargeX_MREC_Rev5_09.12.23.pdf +errors: + - name: Internal + description: Internal error of the state machine + - name: MREC4OverCurrentFailure + description: Over current event \ No newline at end of file diff --git a/interfaces/ac_rcd.yaml b/interfaces/ac_rcd.yaml new file mode 100644 index 0000000000..a442385713 --- /dev/null +++ b/interfaces/ac_rcd.yaml @@ -0,0 +1,19 @@ +description: >- + This interface provides an AC Residual Current Monitor (RCD). Actual emergency switch off is done in HW directly, + but this interface allows some control and telemetry. +cmds: + self_test: + description: >- + Executes a self test of the RCD. If it fails, an error of type Selftest should be raised. + reset: + description: >- + Resets the RCD after a trigger. May not be supported by actual hardware. + result: + description: 'True: Reset successfull, False: Reset failed.' + type: boolean +vars: + rcd_current_mA: + description: Residual current in mA. Note that this does not trigger anything, it is merely for reporting. + type: number +errors: + - reference: /errors/ac_rcd diff --git a/interfaces/board_support_AC.yaml b/interfaces/board_support_AC.yaml deleted file mode 100644 index 76e09f0169..0000000000 --- a/interfaces/board_support_AC.yaml +++ /dev/null @@ -1,98 +0,0 @@ -description: >- - This interface defines the board support driver for AC power path: ControlPilot, - Relais, RCD and motor lock -cmds: - setup: - description: Setup config options - arguments: - three_phases: - description: 'true: Three phases enabled, false: only single phase' - type: boolean - has_ventilation: - description: 'true: Allow mode D charging, false: do not allow mode D charging' - type: boolean - country_code: - description: A two-letter country code in ISO 3166-1 alpha-2 format - type: string - rcd_enabled: - description: 'true: enable RCD, false: disable RCD' - type: boolean - get_hw_capabilities: - description: Get Hardware capability/limits - result: - description: Hardware capability/limits - type: object - $ref: /board_support#/HardwareCapabilities - enable: - description: >- - Enables or disables the EVSE. Typically disabled results in control - pilot state F. It must not accept cars for new charging sessions if disabled. - arguments: - value: - description: 'True: enabled, false: disabled.' - type: boolean - pwm_on: - description: Turns PWM on with duty cycle - arguments: - value: - description: PWM duty cycle (>0, <1) - type: number - minimum: 0 - maximum: 1 - pwm_off: - description: Turns PWM off (constant high voltage) - pwm_F: - description: Turns PWM off with Error F (constant negative voltage) - allow_power_on: - description: >- - Sets allow_power_on flag. If false, Relais must never be switched - on. - arguments: - value: - description: 'True: allow power on, false: do not allow power on.' - type: boolean - force_unlock: - description: Force unlock motor lock - result: - description: Returns true if unlocking sequence was successfully executed - type: boolean - switch_three_phases_while_charging: - description: >- - Special command to force switching between one and three phases while - charging is active. HW must go through some special sequence to ensure safe - operation. - arguments: - value: - description: 'True: switch to 3ph, False: switch to 1ph' - type: boolean - evse_replug: - description: >- - Special command initiate a virtual replug sequence without restarting - session. Emits a EvseReplugStarted event if supported and started. BSP will - take care to not emit other events such as CarPluggedIn/Out during that time. - Once finished it will emit a EvseReplugFinished. - arguments: - value: - description: Time in ms for the duration of the replug sequence - type: integer - read_pp_ampacity: - description: >- - Read the current carrying capacity of the connected cable in ampere. - In case of a fixed cable the configured maximum current the hardware can handle will be reported. - result: - description: Returns the current carrying capacity of the connected cable in ampere - type: number -vars: - event: - description: Event from ControlPilot signal/Relais/RCD - type: string - $ref: /board_support#/Event - nr_of_phases_available: - description: Instantaneous phase count available to car - type: integer - minimum: 1 - maximum: 3 - telemetry: - description: Other telemetry - type: object - $ref: /board_support#/Telemetry diff --git a/interfaces/board_support_AC_debug.yaml b/interfaces/board_support_AC_debug.yaml deleted file mode 100644 index 78b7c1d592..0000000000 --- a/interfaces/board_support_AC_debug.yaml +++ /dev/null @@ -1,40 +0,0 @@ -description: >- - This interface defines the board support debug information that is not - used for actual control -vars: - three_phases: - description: config option for three phase/single phase operation - type: boolean - three_phases_active: - description: True if three phases is enabled for current charging session - type: boolean - has_ventilation: - description: True if ventilated charging is allowed - type: boolean - pwm_running: - description: True if ventilated charging is allowed - type: boolean - simplified_mode: - description: True if car uses simplified mode of IEC61851 - type: boolean - rcd_reclosing_allowed: - description: True if RCD may reclose after fault according to local regulations - type: boolean - is_power_on: - description: True if Relais are currently closed (power on) - type: boolean - cp_hi_voltage: - description: Voltage of high part of PWM - type: number - cp_lo_voltage: - description: Voltage of low part of PWM - type: number - supply_12V_voltage: - description: Voltage of +12V supply - type: number - supply_N12V_voltage: - description: Voltage of -12V supply - type: number - rcd_current: - description: Residual current measurement - type: number diff --git a/interfaces/connector_lock.yaml b/interfaces/connector_lock.yaml new file mode 100644 index 0000000000..6043722423 --- /dev/null +++ b/interfaces/connector_lock.yaml @@ -0,0 +1,9 @@ +description: >- + This interface defines one connector locking motor (e.g. for AC sockets with no fixed attached cable) +cmds: + lock: + description: Lock connector lock + unlock: + description: Unlock connector lock (e.g. normal unlock or enforced by OCPP) +errors: + - reference: /errors/connector_lock diff --git a/interfaces/evse_board_support.yaml b/interfaces/evse_board_support.yaml new file mode 100644 index 0000000000..b968b14730 --- /dev/null +++ b/interfaces/evse_board_support.yaml @@ -0,0 +1,133 @@ +description: >- + This interface defines the board support driver for AC or DC minimal power path: ControlPilot, + output contactors. + Other components of the power path such as IMD(DC)/RCD(AC)/Connector Lock etc have their own interfaces. +cmds: + setup: + description: Setup config options + arguments: + three_phases: + description: 'true: Three phases enabled, false: only single phase' + type: boolean + has_ventilation: + description: 'true: Allow mode D charging, false: do not allow mode D charging' + type: boolean + country_code: + description: A two-letter country code in ISO 3166-1 alpha-2 format + type: string + get_hw_capabilities: + description: >- + Get Hardware capability/limits. For AC these are the limits of the power path (e.g. relais etc). + For DC, these are the limits for the AC input of the ACDC converter stack, i.e. the complete AC input. + Note that DC output limits are reported by the DC power supply itself. + result: + description: Hardware capability/limits + type: object + $ref: /evse_board_support#/HardwareCapabilities + enable: + description: >- + Enables or disables the charging port. Typically disabled results in control + pilot state F. It must not accept cars for new charging sessions if disabled. + arguments: + value: + description: 'True: enabled, false: disabled.' + type: boolean + pwm_on: + description: Turns PWM on with duty cycle (in percent) + arguments: + value: + description: PWM duty cycle (>0, <100) + type: number + minimum: 0 + maximum: 100 + pwm_off: + description: Turns PWM off (constant high voltage) + pwm_F: + description: Turns PWM off with Error F (constant negative voltage) + allow_power_on: + description: >- + Sets allow_power_on flag. If false, Relais must never be switched + on. + arguments: + value: + description: Flag and context + type: object + $ref: /evse_board_support#/PowerOnOff + ac_switch_three_phases_while_charging: + description: >- + Optional, in case of doubt do not implement. Report in hardware_capabilites if this command is supported. + This command switches between one and three phase operation during an active charging session. + Some cars can be permanently destroyed by that, so the bsp needs to implement a special sequence for the switching. + The exact sequence can be defined by the BSP, but one example would be a C2->C1->B1->F->B1->B2->C2 or similar. + Use with caution. + arguments: + value: + description: 'True: switch to 3ph, False: switch to 1ph' + type: boolean + evse_replug: + description: >- + Optional, in case of doubt do not implement. + Special command initiate a virtual replug sequence without restarting + session. Emits a EvseReplugStarted event if supported and started. BSP will + take care to not emit other events such as CarPluggedIn/Out during that time. + Once finished it will emit a EvseReplugFinished. This is mainly for testing purposes, + don't implement for production use. + arguments: + value: + description: Time in ms for the duration of the replug sequence + type: integer + ac_read_pp_ampacity: + description: >- + Read the current carrying capacity of the connected cable in ampere for AC charging + with a socket. This function will be used by EvseManager to get the PP value at + a distinct time. You should also publish the var pp_ampacity whenever the PP ampacity reading changes + to signal changes e.g. during the charging time. + This has no meaning for DC or AC charging with a fixed attached cable, it does not + need to be implemented and the returned value is not used in those cases. + result: + description: Returns the current carrying capacity of the connected cable + type: object + $ref: /board_support_common#/ProximityPilot + ac_set_overcurrent_limit_A: + description: >- + Many chargers implement a fast over current shutdown directly in the hardware that triggers if the EV draws more current than + the PWM allows. + If the hardware does not have this functionality, just ignore this command. Do not use it to set the PWM duty cycle. + Otherwise this command reports a value that should be used for the overcurrent detection. + A margin needs to be added to avoid false triggers. Do not use the PWM duty cycle to infer the current limit in the BSP, + as this will not work with HLC. + arguments: + value: + description: Ampere current limit value + type: number +vars: + event: + description: Event from ControlPilot signal/output relais + type: object + $ref: /board_support_common#/BspEvent + ac_nr_of_phases_available: + description: Instantaneous phase count available to car + type: integer + minimum: 1 + maximum: 3 + telemetry: + description: Other telemetry + type: object + $ref: /evse_board_support#/Telemetry + capabilities: + description: >- + Hardware capabilities/limits. Initially EvseManager will call get_hw_capabilities once to fetch the limits and caches the limits internally. + The BSP module does not have to publish this variable at all, then the initially fetched capabilities will be used. + The BSP may publish this variable to update limits in case they change during runtime, e.g. if the maximum current changes because the hardware gets too hot. + type: object + $ref: /evse_board_support#/HardwareCapabilities + ac_pp_ampacity: + description: >- + Current carrying capacity of the connected cable in ampere for AC charging + with a socket. Publish whenever it changes. + This has no meaning for DC or AC charging with a fixed attached cable, it does not + need to be implemented and the returned value is not used in those cases. + type: object + $ref: /board_support_common#/ProximityPilot +errors: + - reference: /errors/evse_board_support diff --git a/interfaces/evse_manager.yaml b/interfaces/evse_manager.yaml index c722753551..82225b19ff 100644 --- a/interfaces/evse_manager.yaml +++ b/interfaces/evse_manager.yaml @@ -163,7 +163,7 @@ vars: telemetry: description: Other telemetry type: object - $ref: /board_support#/Telemetry + $ref: /evse_board_support#/Telemetry powermeter: description: Measured dataset type: object @@ -174,7 +174,7 @@ vars: hw_capabilities: description: "Hardware capability/limits" type: object - $ref: /board_support#/HardwareCapabilities + $ref: /evse_board_support#/HardwareCapabilities iso15118_certificate_request: description: >- The vehicle requests the SECC to deliver the certificate that belong @@ -198,3 +198,5 @@ vars: description: >- Contains the selected protocol used for charging for informative purposes type: string +errors: + - reference: /errors/evse_manager \ No newline at end of file diff --git a/interfaces/yeti_extras.yaml b/interfaces/yeti_extras.yaml deleted file mode 100644 index d60b65098e..0000000000 --- a/interfaces/yeti_extras.yaml +++ /dev/null @@ -1,29 +0,0 @@ -description: >- - This interface defines Yeti extra funtionality not found in the generic - interfaces -cmds: - firmware_update: - description: This command reboots Yeti in firmware upgrade mode - arguments: - firmware_binary: - description: Path to firmware binary file that should be sent to Yeti Controller - type: string -vars: - time_stamp: - description: Provides the current time stamp - type: integer - hw_type: - description: Provides the hw_type - type: integer - hw_revision: - description: Provides the hw_revision - type: integer - protocol_version_major: - description: Provides the protocol_version_major - type: integer - protocol_version_minor: - description: Provides the protocol_version_minor - type: integer - sw_version_string: - description: Provides the sw_version_string - type: string diff --git a/modules/API/API.cpp b/modules/API/API.cpp index 18a0ef1881..02cb39b106 100644 --- a/modules/API/API.cpp +++ b/modules/API/API.cpp @@ -194,7 +194,7 @@ void API::init() { std::string var_hw_caps = var_base + "hardware_capabilities"; evse->subscribe_hw_capabilities( - [this, var_hw_caps, &hw_caps](types::board_support::HardwareCapabilities hw_capabilities) { + [this, var_hw_caps, &hw_caps](types::evse_board_support::HardwareCapabilities hw_capabilities) { hw_caps = this->limit_decimal_places->limit(hw_capabilities); this->mqtt.publish(var_hw_caps, hw_caps); }); @@ -217,7 +217,7 @@ void API::init() { }); std::string var_telemetry = var_base + "telemetry"; - evse->subscribe_telemetry([this, var_telemetry](types::board_support::Telemetry telemetry) { + evse->subscribe_telemetry([this, var_telemetry](types::evse_board_support::Telemetry telemetry) { this->mqtt.publish(var_telemetry, this->limit_decimal_places->limit(telemetry)); }); diff --git a/modules/API/API.hpp b/modules/API/API.hpp index 5ead0ed750..cb2fc1ece1 100644 --- a/modules/API/API.hpp +++ b/modules/API/API.hpp @@ -88,12 +88,13 @@ struct Conf { int hw_caps_max_current_import_decimal_places; int hw_caps_min_current_export_decimal_places; int hw_caps_min_current_import_decimal_places; + int hw_caps_max_plug_temperature_C_decimal_places; int limits_max_current_decimal_places; - int telemetry_temperature_decimal_places; + int telemetry_evse_temperature_C_decimal_places; int telemetry_fan_rpm_decimal_places; int telemetry_supply_voltage_12V_decimal_places; int telemetry_supply_voltage_minus_12V_decimal_places; - int telemetry_rcd_current_decimal_places; + int telemetry_plug_temperature_C_decimal_places; double powermeter_energy_import_round_to; double powermeter_energy_export_round_to; double powermeter_power_round_to; @@ -105,12 +106,13 @@ struct Conf { double hw_caps_max_current_import_round_to; double hw_caps_min_current_export_round_to; double hw_caps_min_current_import_round_to; + double hw_caps_max_plug_temperature_C_round_to; double limits_max_current_round_to; - double telemetry_temperature_round_to; + double telemetry_evse_temperature_C_round_to; double telemetry_fan_rpm_round_to; double telemetry_supply_voltage_12V_round_to; double telemetry_supply_voltage_minus_12V_round_to; - double telemetry_rcd_current_round_to; + double telemetry_plug_temperature_C_round_to; }; class API : public Everest::ModuleBase { diff --git a/modules/API/CMakeLists.txt b/modules/API/CMakeLists.txt index b8a5c91527..7146700eba 100644 --- a/modules/API/CMakeLists.txt +++ b/modules/API/CMakeLists.txt @@ -13,12 +13,15 @@ target_link_libraries(${MODULE_NAME} PRIVATE ryml::ryml ) +target_sources(${MODULE_NAME} + PRIVATE + "limit_decimal_places.cpp" +) # ev@bcc62523-e22b-41d7-ba2f-825b493a3c97:v1 target_sources(${MODULE_NAME} PRIVATE "main/emptyImpl.cpp" - "limit_decimal_places.cpp" ) # ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1 diff --git a/modules/API/limit_decimal_places.cpp b/modules/API/limit_decimal_places.cpp index 43607fe4bb..4ef7645499 100644 --- a/modules/API/limit_decimal_places.cpp +++ b/modules/API/limit_decimal_places.cpp @@ -205,7 +205,7 @@ std::string LimitDecimalPlaces::limit(const types::powermeter::Powermeter& power return power_meter_stream.str(); } -std::string LimitDecimalPlaces::limit(const types::board_support::HardwareCapabilities& hw_capabilities) { +std::string LimitDecimalPlaces::limit(const types::evse_board_support::HardwareCapabilities& hw_capabilities) { ryml::Tree tree; ryml::NodeRef root = tree.rootref(); root |= ryml::MAP; @@ -236,6 +236,14 @@ std::string LimitDecimalPlaces::limit(const types::board_support::HardwareCapabi this->round_to_nearest_step(hw_capabilities.min_current_A_export, this->config.hw_caps_min_current_export_round_to), this->config.hw_caps_min_current_export_decimal_places); + if (hw_capabilities.max_plug_temperature_C.has_value()) { + root["max_plug_temperature_C"] << ryml::fmt::real( + this->round_to_nearest_step(hw_capabilities.max_plug_temperature_C.value(), + this->config.hw_caps_max_plug_temperature_C_round_to), + this->config.hw_caps_max_plug_temperature_C_decimal_places); + } + + root["connector_type"] << types::evse_board_support::connector_type_to_string(hw_capabilities.connector_type); std::stringstream hardware_capabilities_stream; hardware_capabilities_stream << ryml::as_json(tree); @@ -263,7 +271,7 @@ std::string LimitDecimalPlaces::limit(const types::evse_manager::Limits& limits) return limits_stream.str(); } -std::string LimitDecimalPlaces::limit(const types::board_support::Telemetry& telemetry) { +std::string LimitDecimalPlaces::limit(const types::evse_board_support::Telemetry& telemetry) { ryml::Tree tree; ryml::NodeRef root = tree.rootref(); root |= ryml::MAP; @@ -272,8 +280,8 @@ std::string LimitDecimalPlaces::limit(const types::board_support::Telemetry& tel // limit decimal places root["temperature"] << ryml::fmt::real( - this->round_to_nearest_step(telemetry.temperature, this->config.telemetry_temperature_round_to), - this->config.telemetry_temperature_decimal_places); + this->round_to_nearest_step(telemetry.evse_temperature_C, this->config.telemetry_evse_temperature_C_round_to), + this->config.telemetry_evse_temperature_C_decimal_places); root["fan_rpm"] << ryml::fmt::real( this->round_to_nearest_step(telemetry.fan_rpm, this->config.telemetry_fan_rpm_round_to), this->config.telemetry_fan_rpm_decimal_places); @@ -284,9 +292,12 @@ std::string LimitDecimalPlaces::limit(const types::board_support::Telemetry& tel this->round_to_nearest_step(telemetry.supply_voltage_minus_12V, this->config.telemetry_supply_voltage_minus_12V_round_to), this->config.telemetry_supply_voltage_minus_12V_decimal_places); - root["rcd_current"] << ryml::fmt::real( - this->round_to_nearest_step(telemetry.rcd_current, this->config.telemetry_rcd_current_round_to), - this->config.telemetry_rcd_current_decimal_places); + if (telemetry.plug_temperature_C.has_value()) { + root["plug_temperature_C"] << ryml::fmt::real( + this->round_to_nearest_step(telemetry.plug_temperature_C.value(), + this->config.telemetry_plug_temperature_C_round_to), + this->config.telemetry_plug_temperature_C_decimal_places); + } std::stringstream telemetry_stream; telemetry_stream << ryml::as_json(tree); return telemetry_stream.str(); diff --git a/modules/API/limit_decimal_places.hpp b/modules/API/limit_decimal_places.hpp index f833f4fe2b..2971552c28 100644 --- a/modules/API/limit_decimal_places.hpp +++ b/modules/API/limit_decimal_places.hpp @@ -15,9 +15,9 @@ class LimitDecimalPlaces { public: LimitDecimalPlaces(const Conf& config) : config(config){}; std::string limit(const types::powermeter::Powermeter& powermeter); - std::string limit(const types::board_support::HardwareCapabilities& hw_capabilities); + std::string limit(const types::evse_board_support::HardwareCapabilities& hw_capabilities); std::string limit(const types::evse_manager::Limits& limits); - std::string limit(const types::board_support::Telemetry& telemetry); + std::string limit(const types::evse_board_support::Telemetry& telemetry); double round_to_nearest_step(double value, double step); private: diff --git a/modules/API/manifest.yaml b/modules/API/manifest.yaml index 956a2df5de..b246dc11f5 100644 --- a/modules/API/manifest.yaml +++ b/modules/API/manifest.yaml @@ -52,7 +52,7 @@ config: default: 2 minimum: 0 hw_caps_min_current_export_decimal_places: - description: Maximum number of decimal places for minimum import current in the hardware capabilities + description: Maximum number of decimal places for minimum export current in the hardware capabilities type: integer default: 2 minimum: 0 @@ -61,13 +61,18 @@ config: type: integer default: 2 minimum: 0 + hw_caps_max_plug_temperature_C_decimal_places: + description: Maximum number of decimal places for max_plug_temperature_C in the hardware capabilities + type: integer + default: 2 + minimum: 0 limits_max_current_decimal_places: description: Maximum number of decimal places for maximum current in the limits type: integer default: 2 minimum: 0 - telemetry_temperature_decimal_places: - description: Maximum number of decimal places for temperature in telemetry + telemetry_evse_temperature_C_decimal_places: + description: Maximum number of decimal places for evse_temperature_C in telemetry type: integer default: 2 minimum: 0 @@ -86,7 +91,7 @@ config: type: integer default: 2 minimum: 0 - telemetry_rcd_current_decimal_places: + telemetry_plug_temperature_C_decimal_places: description: Maximum number of decimal places for RCD current in telemetry type: integer default: 2 @@ -135,12 +140,16 @@ config: description: Round minimum import current in hardware limits to the nearest step. Ignored if value is 0 type: number default: 0 + hw_caps_max_plug_temperature_C_round_to: + description: Round max_plug_temperature_C in hardware limits to the nearest step. Ignored if value is 0 + type: number + default: 0 limits_max_current_round_to: description: Round maximum current in limits to the nearest step. Ignored if value is 0 type: number default: 0 - telemetry_temperature_round_to: - description: Round temperature in telemetry to the nearest step. Ignored if value is 0 + telemetry_evse_temperature_C_round_to: + description: Round evse_temperature_C in telemetry to the nearest step. Ignored if value is 0 type: number default: 0 telemetry_fan_rpm_round_to: @@ -155,8 +164,8 @@ config: description: Round supply voltage -12V in telemetry to the nearest step. Ignored if value is 0 type: number default: 0 - telemetry_rcd_current_round_to: - description: Round RCD current in telemetry to the nearest step. Ignored if value is 0 + telemetry_plug_temperature_C_round_to: + description: Round plug_temperature_C in telemetry to the nearest step. Ignored if value is 0 type: number default: 0 provides: diff --git a/modules/Auth/Auth.cpp b/modules/Auth/Auth.cpp index 49f35fc712..1f22b84393 100644 --- a/modules/Auth/Auth.cpp +++ b/modules/Auth/Auth.cpp @@ -12,9 +12,9 @@ void Auth::init() { invoke_init(*p_main); invoke_init(*p_reservation); - this->auth_handler = std::make_unique(string_to_selection_algorithm(this->config.selection_algorithm), - this->config.connection_timeout, - this->config.prioritize_authorization_over_stopping_transaction); + this->auth_handler = std::make_unique( + string_to_selection_algorithm(this->config.selection_algorithm), this->config.connection_timeout, + this->config.prioritize_authorization_over_stopping_transaction, this->config.ignore_connector_faults); for (const auto& token_provider : this->r_token_provider) { token_provider->subscribe_provided_token([this](ProvidedIdToken provided_token) { diff --git a/modules/Auth/Auth.hpp b/modules/Auth/Auth.hpp index 42349ec0df..3cfe76febf 100644 --- a/modules/Auth/Auth.hpp +++ b/modules/Auth/Auth.hpp @@ -34,6 +34,7 @@ struct Conf { std::string selection_algorithm; int connection_timeout; bool prioritize_authorization_over_stopping_transaction; + bool ignore_connector_faults; }; class Auth : public Everest::ModuleBase { diff --git a/modules/Auth/include/AuthHandler.hpp b/modules/Auth/include/AuthHandler.hpp index 8ac69e5953..5747bd973c 100644 --- a/modules/Auth/include/AuthHandler.hpp +++ b/modules/Auth/include/AuthHandler.hpp @@ -48,7 +48,7 @@ class AuthHandler { public: AuthHandler(const SelectionAlgorithm& selection_algorithm, const int connection_timeout, - bool prioritize_authorization_over_stopping_transaction); + bool prioritize_authorization_over_stopping_transaction, bool ignore_connector_faults); virtual ~AuthHandler(); /** @@ -181,6 +181,7 @@ class AuthHandler { SelectionAlgorithm selection_algorithm; int connection_timeout; bool prioritize_authorization_over_stopping_transaction; + bool ignore_faults; ReservationHandler reservation_handler; std::map> connectors; diff --git a/modules/Auth/lib/AuthHandler.cpp b/modules/Auth/lib/AuthHandler.cpp index 86e49a678f..ad1b04f95a 100644 --- a/modules/Auth/lib/AuthHandler.cpp +++ b/modules/Auth/lib/AuthHandler.cpp @@ -38,10 +38,11 @@ std::string token_handling_result_to_string(const TokenHandlingResult& result) { } // namespace conversions AuthHandler::AuthHandler(const SelectionAlgorithm& selection_algorithm, const int connection_timeout, - bool prioritize_authorization_over_stopping_transaction) : + bool prioritize_authorization_over_stopping_transaction, bool ignore_faults) : selection_algorithm(selection_algorithm), connection_timeout(connection_timeout), - prioritize_authorization_over_stopping_transaction(prioritize_authorization_over_stopping_transaction){}; + prioritize_authorization_over_stopping_transaction(prioritize_authorization_over_stopping_transaction), + ignore_faults(ignore_faults){}; AuthHandler::~AuthHandler() { } @@ -463,13 +464,19 @@ void AuthHandler::handle_session_event(const int connector_id, const SessionEven this->connectors.at(connector_id)->timeout_timer.stop(); break; case SessionEventEnum::AllErrorsCleared: - this->connectors.at(connector_id)->connector.submit_event(ConnectorEvent::ERROR_CLEARED); + if (not ignore_faults) { + this->connectors.at(connector_id)->connector.submit_event(ConnectorEvent::ERROR_CLEARED); + } break; case SessionEventEnum::PermanentFault: - this->connectors.at(connector_id)->connector.submit_event(ConnectorEvent::FAULTED); + if (not ignore_faults) { + this->connectors.at(connector_id)->connector.submit_event(ConnectorEvent::FAULTED); + } break; case SessionEventEnum::Error: - this->connectors.at(connector_id)->connector.submit_event(ConnectorEvent::FAULTED); + if (not ignore_faults) { + this->connectors.at(connector_id)->connector.submit_event(ConnectorEvent::FAULTED); + } break; case SessionEventEnum::Disabled: diff --git a/modules/Auth/manifest.yaml b/modules/Auth/manifest.yaml index 36f4fc8e86..f159c02b77 100644 --- a/modules/Auth/manifest.yaml +++ b/modules/Auth/manifest.yaml @@ -25,6 +25,20 @@ config: transaction can be stopped using the given parent_id_token type: boolean default: true + ignore_connector_faults: + description: >- + Boolean value to describe the handling of faults on connectors. + + If true, faults reported on connectors are ignored, i.e. they can still be authorized. This should be disabled in + most use cases, but e.g. in free charging applications it may be useful to allow a charging session in the following case: + A connector e.g. has an overtemperature fault that at some point will clear once it is cooled down. A car is plugged in before + the error is cleared. The user would expect that the charging starts once it is cooled down. When this option is set to false, + it will not be authorized on plug in as the connector is in fault state and it will never recover until the car is replugged. + If it is set to true, the authorization happens on the faulty connector and charging will start once the fault is cleared. + + If false, faulty connectors are treated as not available and will not be authorized. This is a good setting for e.g. public chargers. + type: boolean + default: false provides: main: description: This implements the auth interface for EVerest diff --git a/modules/Auth/tests/auth_tests.cpp b/modules/Auth/tests/auth_tests.cpp index e6d3473131..142f8d3906 100644 --- a/modules/Auth/tests/auth_tests.cpp +++ b/modules/Auth/tests/auth_tests.cpp @@ -61,7 +61,8 @@ class AuthTest : public ::testing::Test { std::vector evse_indices{0, 1}; this->auth_receiver = std::make_unique(evse_indices); - this->auth_handler = std::make_unique(SelectionAlgorithm::PlugEvents, CONNECTION_TIMEOUT, false); + this->auth_handler = + std::make_unique(SelectionAlgorithm::PlugEvents, CONNECTION_TIMEOUT, false, false); this->auth_handler->register_notify_evse_callback([this](const int evse_index, const ProvidedIdToken& provided_token, diff --git a/modules/EvseManager/CMakeLists.txt b/modules/EvseManager/CMakeLists.txt index d891c73599..ecf54561d6 100644 --- a/modules/EvseManager/CMakeLists.txt +++ b/modules/EvseManager/CMakeLists.txt @@ -15,6 +15,8 @@ target_sources(${MODULE_NAME} SessionLog.cpp v2gMessage.cpp CarManufacturer.cpp + IECStateMachine.cpp + ErrorHandling.cpp ) target_link_libraries(${MODULE_NAME} diff --git a/modules/EvseManager/Charger.cpp b/modules/EvseManager/Charger.cpp index 32afd1187b..be2279d8e6 100644 --- a/modules/EvseManager/Charger.cpp +++ b/modules/EvseManager/Charger.cpp @@ -17,13 +17,14 @@ namespace module { -Charger::Charger(const std::unique_ptr& r_bsp, const std::string& connector_type) : - r_bsp(r_bsp), connector_type(connector_type) { - +Charger::Charger(const std::unique_ptr& bsp, const std::unique_ptr& error_handling, + const types::evse_board_support::Connector_type& connector_type) : + bsp(bsp), error_handling(error_handling), connector_type(connector_type) { connectorEnabled = true; - maxCurrent = 6.0; - maxCurrentCable = r_bsp->call_read_pp_ampacity(); + if (connector_type == types::evse_board_support::Connector_type::IEC62196Type2Socket) { + maxCurrentCable = bsp->read_pp_ampacity(); + } authorized = false; update_pwm_last_dc = 0.; @@ -35,8 +36,8 @@ Charger::Charger(const std::unique_ptr& r_bsp, const std:: currentDrawnByVehicle[1] = 0.; currentDrawnByVehicle[2] = 0.; - t_step_EF_returnState = EvseState::Faulted; - t_step_X1_returnState = EvseState::Faulted; + t_step_EF_returnState = EvseState::Idle; + t_step_X1_returnState = EvseState::Idle; matching_started = false; @@ -44,40 +45,49 @@ Charger::Charger(const std::unique_ptr& r_bsp, const std:: session_active = false; hlc_use_5percent_current_session = false; + + // Register callbacks for errors/error clearings + error_handling->signal_error.connect([this]() { + std::scoped_lock lock(stateMutex); + signalEvent(types::evse_manager::SessionEventEnum::Error); + error_prevent_charging_flag = true; + }); + + error_handling->signal_all_errors_cleared.connect([this]() { + EVLOG_info << "All errors cleared"; + signalEvent(types::evse_manager::SessionEventEnum::AllErrorsCleared); + std::scoped_lock lock(stateMutex); + error_prevent_charging_flag = false; + }); } Charger::~Charger() { - r_bsp->call_pwm_F(); + pwm_F(); } void Charger::mainThread() { - // Enable CP output - r_bsp->call_enable(true); + bsp->enable(true); // publish initial values signalMaxCurrent(getMaxCurrent()); signalState(currentState); - signalError(errorState); while (true) { - if (mainThreadHandle.shouldExit()) { break; } std::this_thread::sleep_for(MAINLOOP_UPDATE_RATE); - stateMutex.lock(); - - // update power limits - powerAvailable(); - - // Run our own state machine update (i.e. run everything that needs - // to be done on regular intervals independent from events) - runStateMachine(); - - stateMutex.unlock(); + { + std::scoped_lock lock(stateMutex); + // update power limits + powerAvailable(); + // Run our own state machine update (i.e. run everything that needs + // to be done on regular intervals independent from events) + runStateMachine(); + } } } @@ -85,8 +95,11 @@ void Charger::runStateMachine() { // run over state machine loop until currentState does not change anymore do { - bool new_in_state = last_state_detect_state_change != currentState; - if (new_in_state) { + // If a state change happened or an error recovered during a state we reinitialize the state + bool initialize_state = (last_state_detect_state_change != currentState) || + (last_error_prevent_charging_flag != error_prevent_charging_flag); + + if (initialize_state) { session_log.evse(false, fmt::format("Charger state: {}->{}", evseStateToString(last_state_detect_state_change), evseStateToString(currentState))); @@ -94,6 +107,7 @@ void Charger::runStateMachine() { last_state = last_state_detect_state_change; last_state_detect_state_change = currentState; + last_error_prevent_charging_flag = error_prevent_charging_flag; auto now = std::chrono::system_clock::now(); @@ -104,12 +118,9 @@ void Charger::runStateMachine() { return; } - if (new_in_state) { + if (initialize_state) { currentStateStarted = now; signalState(currentState); - if (currentState == EvseState::Error) { - signalError(errorState); - } } auto timeInCurrentState = @@ -117,14 +128,14 @@ void Charger::runStateMachine() { switch (currentState) { case EvseState::Disabled: - if (new_in_state) { + if (initialize_state) { signalEvent(types::evse_manager::SessionEventEnum::Disabled); pwm_F(); } break; case EvseState::Replug: - if (new_in_state) { + if (initialize_state) { signalEvent(types::evse_manager::SessionEventEnum::ReplugStarted); // start timer in case we need to if (ac_with_soc_timeout) @@ -135,7 +146,7 @@ void Charger::runStateMachine() { case EvseState::Idle: // make sure we signal availability to potential new cars - if (new_in_state) { + if (initialize_state) { bcb_toggle_reset(); iec_allow_close_contactor = false; hlc_charging_active = false; @@ -153,8 +164,8 @@ void Charger::runStateMachine() { // Explicitly do not allow to be powered on. This is important // to make sure control_pilot does not switch on relais even if // we start PWM here - if (new_in_state) { - r_bsp->call_allow_power_on(false); + if (initialize_state) { + bsp->allow_power_on(false, types::evse_board_support::Reason::PowerOff); if (last_state == EvseState::Replug) { signalEvent(types::evse_manager::SessionEventEnum::ReplugFinished); @@ -177,8 +188,7 @@ void Charger::runStateMachine() { hlc_use_5percent_current_session = true; } else { // unsupported charging mode, give up here. - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::Internal; + error_handling->raise_internal_error("Unsupported charging mode."); } if (hlc_use_5percent_current_session) { @@ -190,8 +200,9 @@ void Charger::runStateMachine() { } // Read PP value in case of AC socket - if (connector_type == IEC62196Type2Socket && maxCurrentCable == 0) { - maxCurrentCable = r_bsp->call_read_pp_ampacity(); + if (connector_type == types::evse_board_support::Connector_type::IEC62196Type2Socket && + maxCurrentCable == 0) { + maxCurrentCable = bsp->read_pp_ampacity(); // retry if the value is not yet available. Some BSPs may take some time to measure the PP. if (maxCurrentCable == 0) { break; @@ -306,9 +317,7 @@ void Charger::runStateMachine() { currentState = targetState; } else { // unsupported charging mode, give up here. - EVLOG_error << "Unsupported charging mode."; - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::Internal; + error_handling->raise_internal_error("Unsupported charging mode."); } } else if (AuthorizedPnC()) { @@ -336,16 +345,14 @@ void Charger::runStateMachine() { currentState = targetState; } else { // unsupported charging mode, give up here. - EVLOG_error << "Unsupported charging mode."; - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::Internal; + error_handling->raise_internal_error("Unsupported charging mode."); } } break; case EvseState::T_step_EF: - if (new_in_state) { + if (initialize_state) { session_log.evse(false, "Enter T_step_EF"); pwm_F(); } @@ -360,7 +367,7 @@ void Charger::runStateMachine() { break; case EvseState::T_step_X1: - if (new_in_state) { + if (initialize_state) { session_log.evse(false, "Enter T_step_X1"); pwm_off(); } @@ -376,24 +383,27 @@ void Charger::runStateMachine() { case EvseState::PrepareCharging: - if (new_in_state) { + if (initialize_state) { signalEvent(types::evse_manager::SessionEventEnum::PrepareCharging); bcb_toggle_reset(); - - if (hlc_use_5percent_current_session) { - update_pwm_now_if_changed(PWM_5_PERCENT); - } } if (charge_mode == ChargeMode::DC) { if (hlc_allow_close_contactor && iec_allow_close_contactor) { - r_bsp->call_allow_power_on(true); + bsp->allow_power_on(true, types::evse_board_support::Reason::DCCableCheck); } } + // Wait here until all errors are cleared + if (errors_prevent_charging()) { + break; + } + // make sure we are enabling PWM if (!hlc_use_5percent_current_session) { update_pwm_now_if_changed(ampereToDutyCycle(getMaxCurrent())); + } else { + update_pwm_now_if_changed(PWM_5_PERCENT); } if (charge_mode == ChargeMode::AC) { @@ -434,10 +444,15 @@ void Charger::runStateMachine() { break; case EvseState::Charging: - if (new_in_state) { + if (initialize_state) { hlc_charging_terminate_pause = HlcTerminatePause::Unknown; } + // Wait here until all errors are cleared + if (errors_prevent_charging()) { + break; + } + if (charge_mode == ChargeMode::DC) { // FIXME: handle DC pause/resume here // FIXME: handle DC no power available from Energy management @@ -446,15 +461,19 @@ void Charger::runStateMachine() { if (!powerAvailable()) { pauseChargingWaitForPower(); + // FIXME new in state breaks break; } - if (new_in_state) { + if (initialize_state) { if (last_state != EvseState::PrepareCharging) { signalEvent(types::evse_manager::SessionEventEnum::ChargingResumed); } - r_bsp->call_allow_power_on(true); + // Allow another wake-up sequence + legacy_wakeup_done = false; + + bsp->allow_power_on(true, types::evse_board_support::Reason::FullPowerCharging); // make sure we are enabling PWM if (hlc_use_5percent_current_session) update_pwm_now_if_changed(PWM_5_PERCENT); @@ -486,9 +505,9 @@ void Charger::runStateMachine() { if (hlc_charging_active) { // This is for HLC charging (both AC and DC) - if (new_in_state) { + if (initialize_state) { bcb_toggle_reset(); - r_bsp->call_allow_power_on(false); + bsp->allow_power_on(false, types::evse_board_support::Reason::PowerOff); if (charge_mode == ChargeMode::DC) { signal_DC_supply_off(); } @@ -524,18 +543,14 @@ void Charger::runStateMachine() { break; } - if (new_in_state) { + if (initialize_state) { signalEvent(types::evse_manager::SessionEventEnum::ChargingPausedEV); - r_bsp->call_allow_power_on(true); - // make sure we are enabling PWM - if (hlc_use_5percent_current_session) { - update_pwm_now(PWM_5_PERCENT); - } else { - update_pwm_now(ampereToDutyCycle(getMaxCurrent())); - } + // bsp->allow_power_on(true, types::evse_board_support::Reason::FullPowerCharging); + // make sure we are enabling PWM + // update_pwm_now(ampereToDutyCycle(getMaxCurrent())); } else { // update PWM if it has changed and 5 seconds have passed since last update - if (!hlc_use_5percent_current_session) { + if (!errors_prevent_charging()) { update_pwm_max_every_5seconds(ampereToDutyCycle(getMaxCurrent())); } } @@ -543,7 +558,7 @@ void Charger::runStateMachine() { break; case EvseState::ChargingPausedEVSE: - if (new_in_state) { + if (initialize_state) { signalEvent(types::evse_manager::SessionEventEnum::ChargingPausedEVSE); if (hlc_charging_active) { // currentState = EvseState::StoppingCharging; @@ -558,7 +573,7 @@ void Charger::runStateMachine() { break; case EvseState::WaitingForEnergy: - if (new_in_state) { + if (initialize_state) { signalEvent(types::evse_manager::SessionEventEnum::WaitingForEnergy); if (!hlc_use_5percent_current_session) pwm_off(); @@ -566,7 +581,7 @@ void Charger::runStateMachine() { break; case EvseState::StoppingCharging: - if (new_in_state) { + if (initialize_state) { bcb_toggle_reset(); if (transactionActive() || sessionActive()) { signalEvent(types::evse_manager::SessionEventEnum::StoppingCharging); @@ -605,7 +620,7 @@ void Charger::runStateMachine() { case EvseState::Finished: - if (new_in_state) { + if (initialize_state) { // Transaction may already be stopped when it was cancelled earlier. // In that case, do not sent a second transactionFinished event. if (transactionActive()) @@ -622,57 +637,30 @@ void Charger::runStateMachine() { restart(); break; - - case EvseState::Error: - if (new_in_state) { - signalEvent(types::evse_manager::SessionEventEnum::Error); - pwm_off(); - } - // Do not set F here, as F cannot detect unplugging of car! - break; - - case EvseState::Faulted: - if (new_in_state) { - signalEvent(types::evse_manager::SessionEventEnum::PermanentFault); - pwm_F(); - } - break; } } while (last_state_detect_state_change != currentState); } -void Charger::processEvent(types::board_support::Event cp_event) { - +void Charger::processEvent(CPEvent cp_event) { switch (cp_event) { - case ControlPilotEvent::CarPluggedIn: - case ControlPilotEvent::CarRequestedPower: - case ControlPilotEvent::CarRequestedStopPower: - case ControlPilotEvent::CarUnplugged: - case ControlPilotEvent::ErrorDF: - case ControlPilotEvent::ErrorE: - case ControlPilotEvent::BCDtoEF: - case ControlPilotEvent::EFtoBCD: - session_log.car(false, fmt::format("Event {}", types::board_support::event_to_string(cp_event))); + case CPEvent::CarPluggedIn: + case CPEvent::CarRequestedPower: + case CPEvent::CarRequestedStopPower: + case CPEvent::CarUnplugged: + case CPEvent::BCDtoEF: + case CPEvent::EFtoBCD: + session_log.car(false, fmt::format("Event {}", cpevent_to_string(cp_event))); break; - case ControlPilotEvent::ErrorOverCurrent: - case ControlPilotEvent::ErrorRCD: - case ControlPilotEvent::ErrorRelais: - case ControlPilotEvent::ErrorVentilationNotAvailable: - case ControlPilotEvent::PermanentFault: - case ControlPilotEvent::PowerOff: - case ControlPilotEvent::PowerOn: - case ControlPilotEvent::EvseReplugStarted: - case ControlPilotEvent::EvseReplugFinished: - default: - session_log.evse(false, fmt::format("Event {}", types::board_support::event_to_string(cp_event))); + session_log.evse(false, fmt::format("Event {}", cpevent_to_string(cp_event))); break; } std::lock_guard lock(stateMutex); - if (cp_event == ControlPilotEvent::PowerOn) { + + if (cp_event == CPEvent::PowerOn) { contactors_closed = true; - } else if (cp_event == ControlPilotEvent::PowerOff) { + } else if (cp_event == CPEvent::PowerOff) { contactors_closed = false; } @@ -689,43 +677,43 @@ void Charger::processEvent(types::board_support::Event cp_event) { runStateMachine(); } -void Charger::processCPEventsState(ControlPilotEvent cp_event) { +void Charger::processCPEventsState(CPEvent cp_event) { switch (currentState) { case EvseState::Idle: - if (cp_event == ControlPilotEvent::CarPluggedIn) { + if (cp_event == CPEvent::CarPluggedIn) { currentState = EvseState::WaitingForAuthentication; } break; case EvseState::WaitingForAuthentication: - if (cp_event == ControlPilotEvent::CarRequestedPower) { + if (cp_event == CPEvent::CarRequestedPower) { session_log.car(false, "B->C transition before PWM is enabled at this stage violates IEC61851-1"); iec_allow_close_contactor = true; - } else if (cp_event == ControlPilotEvent::CarRequestedStopPower) { + } else if (cp_event == CPEvent::CarRequestedStopPower) { session_log.car(false, "C->B transition at this stage violates IEC61851-1"); iec_allow_close_contactor = false; } break; case EvseState::PrepareCharging: - if (cp_event == ControlPilotEvent::CarRequestedPower) { + if (cp_event == CPEvent::CarRequestedPower) { iec_allow_close_contactor = true; - } else if (cp_event == ControlPilotEvent::CarRequestedStopPower) { + } else if (cp_event == CPEvent::CarRequestedStopPower) { iec_allow_close_contactor = false; // currentState = EvseState::StoppingCharging; } break; case EvseState::Charging: - if (cp_event == ControlPilotEvent::CarRequestedStopPower) { + if (cp_event == CPEvent::CarRequestedStopPower) { iec_allow_close_contactor = false; currentState = EvseState::ChargingPausedEV; } break; case EvseState::ChargingPausedEV: - if (cp_event == ControlPilotEvent::CarRequestedPower) { + if (cp_event == CPEvent::CarRequestedPower) { iec_allow_close_contactor = true; // For BASIC charging we can simply switch back to Charging if (charge_mode == ChargeMode::AC && !hlc_charging_active) { @@ -735,7 +723,7 @@ void Charger::processCPEventsState(ControlPilotEvent cp_event) { } } - if (cp_event == ControlPilotEvent::CarRequestedStopPower && !pwm_running && hlc_charging_active) { + if (cp_event == CPEvent::CarRequestedStopPower && !pwm_running && hlc_charging_active) { bcb_toggle_detect_stop_pulse(); } break; @@ -743,9 +731,9 @@ void Charger::processCPEventsState(ControlPilotEvent cp_event) { case EvseState::StoppingCharging: // Allow session restart from EV after SessionStop.terminate with BCB toggle if (hlc_charging_active && !pwm_running) { - if (cp_event == ControlPilotEvent::CarRequestedPower) { + if (cp_event == CPEvent::CarRequestedPower) { bcb_toggle_detect_start_pulse(); - } else if (cp_event == ControlPilotEvent::CarRequestedStopPower) { + } else if (cp_event == CPEvent::CarRequestedStopPower) { bcb_toggle_detect_stop_pulse(); } } @@ -756,88 +744,21 @@ void Charger::processCPEventsState(ControlPilotEvent cp_event) { } } -void Charger::processCPEventsIndependent(ControlPilotEvent cp_event) { - +void Charger::processCPEventsIndependent(CPEvent cp_event) { switch (cp_event) { - case ControlPilotEvent::EvseReplugStarted: + case CPEvent::EvseReplugStarted: currentState = EvseState::Replug; break; - case ControlPilotEvent::EvseReplugFinished: + case CPEvent::EvseReplugFinished: currentState = EvseState::WaitingForAuthentication; break; - case ControlPilotEvent::CarUnplugged: - if (currentState == EvseState::Error) - signalEvent(types::evse_manager::SessionEventEnum::AllErrorsCleared); + case CPEvent::CarUnplugged: if (!hlc_charging_active) { currentState = EvseState::StoppingCharging; } else { currentState = EvseState::Finished; } break; - case ControlPilotEvent::ErrorE: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::Car; - break; - case ControlPilotEvent::ErrorDF: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::CarDiodeFault; - break; - case ControlPilotEvent::ErrorRelais: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::Relais; - break; - case ControlPilotEvent::ErrorRCD: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::RCD; - break; - case ControlPilotEvent::ErrorVentilationNotAvailable: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::VentilationNotAvailable; - break; - case ControlPilotEvent::ErrorOverCurrent: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::OverCurrent; - break; - case ControlPilotEvent::ErrorRCD_DC: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::RCDDC; - break; - case ControlPilotEvent::ErrorOverVoltage: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::OverVoltage; - break; - case ControlPilotEvent::ErrorUnderVoltage: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::UnderVoltage; - break; - case ControlPilotEvent::ErrorMotorLock: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::MotorLock; - break; - case ControlPilotEvent::ErrorOverTemperature: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::OverTemperature; - break; - case ControlPilotEvent::ErrorBrownOut: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::BrownOut; - break; - case ControlPilotEvent::ErrorCablePP: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::CablePP; - break; - case ControlPilotEvent::ErrorEnergyManagement: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::EnergyManagement; - break; - case ControlPilotEvent::ErrorNeutralPEN: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::NeutralPEN; - break; - case ControlPilotEvent::ErrorCpDriver: - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::CpDriver; - break; default: break; } @@ -857,7 +778,7 @@ void Charger::update_pwm_now(float dc) { auto start = date::utc_clock::now(); update_pwm_last_dc = dc; pwm_running = true; - r_bsp->call_pwm_on(dc); + bsp->set_pwm(dc); session_log.evse( false, @@ -876,14 +797,14 @@ void Charger::pwm_off() { session_log.evse(false, "Set PWM Off"); pwm_running = false; update_pwm_last_dc = 1.; - r_bsp->call_pwm_off(); + bsp->set_pwm_off(); } void Charger::pwm_F() { session_log.evse(false, "Set PWM F"); pwm_running = false; update_pwm_last_dc = 0.; - r_bsp->call_pwm_F(); + bsp->set_pwm_F(); } void Charger::run() { @@ -923,19 +844,7 @@ bool Charger::setMaxCurrent(float c, std::chrono::time_point va if (validUntil > date::utc_clock::now()) { maxCurrent = c; maxCurrentValidUntil = validUntil; - signalMaxCurrent(c); - return true; - } - } - return false; -} - -bool Charger::setMaxCurrent(float c) { - if (c >= 0.0 && c <= CHARGER_ABSOLUTE_MAX_CURRENT) { - std::lock_guard lock(configMutex); - // is it still valid? - if (maxCurrentValidUntil > date::utc_clock::now()) { - maxCurrent = c; + bsp->set_overcurrent_limit(c); signalMaxCurrent(c); return true; } @@ -999,7 +908,7 @@ bool Charger::evseReplug() { // If BSP never executes the replug, we also never change state and nothing happens. // After replugging finishes, BSP will emit EvseReplugFinished event and we will go back to WaitingForAuth EVLOG_info << fmt::format("Calling evse_replug({})...", t_replug_ms); - r_bsp->call_evse_replug(t_replug_ms); + bsp->evse_replug(t_replug_ms); return true; } @@ -1085,17 +994,18 @@ types::evse_manager::StartSessionReason Charger::getSessionStartedReason() { } bool Charger::switchThreePhasesWhileCharging(bool n) { - r_bsp->call_switch_three_phases_while_charging(n); + bsp->switch_three_phases_while_charging(n); return false; // FIXME: implement real return value when protobuf has sync calls } -void Charger::setup(bool three_phases, bool has_ventilation, const std::string& country_code, bool rcd_enabled, +void Charger::setup(bool three_phases, bool has_ventilation, const std::string& country_code, const ChargeMode _charge_mode, bool _ac_hlc_enabled, bool _ac_hlc_use_5percent, bool _ac_enforce_hlc, bool _ac_with_soc_timeout, float _soft_over_current_tolerance_percent, float _soft_over_current_measurement_noise_A) { std::lock_guard lock(configMutex); // set up board support package - r_bsp->call_setup(three_phases, has_ventilation, country_code, rcd_enabled); + bsp->setup(three_phases, has_ventilation, country_code); + // cache our config variables charge_mode = _charge_mode; ac_hlc_enabled_current_session = ac_hlc_enabled = _ac_hlc_enabled; @@ -1186,12 +1096,10 @@ bool Charger::AuthorizedPnC() { } bool Charger::DeAuthorize() { - if (sessionActive()) { auto s = getCurrentState(); - if (s == EvseState::Disabled || s == EvseState::Idle || s == EvseState::WaitingForAuthentication || - s == EvseState::Error || s == EvseState::Faulted) { + if (s == EvseState::Disabled || s == EvseState::Idle || s == EvseState::WaitingForAuthentication) { // We can safely remove auth as it is not in use right now std::lock_guard lock(configMutex); @@ -1207,11 +1115,6 @@ bool Charger::DeAuthorize() { return false; } -types::evse_manager::ErrorEnum Charger::getErrorState() { - std::lock_guard lock(stateMutex); - return errorState; -} - bool Charger::disable(int connector_id) { std::lock_guard lock(stateMutex); if (connector_id != 0) { @@ -1240,8 +1143,7 @@ bool Charger::enable(int connector_id) { void Charger::set_faulted() { std::lock_guard lock(stateMutex); - currentState = EvseState::Faulted; - signalEvent(types::evse_manager::SessionEventEnum::PermanentFault); + error_prevent_charging_flag = true; } bool Charger::restart() { @@ -1280,12 +1182,6 @@ std::string Charger::evseStateToString(EvseState s) { case EvseState::Finished: return ("Finished"); break; - case EvseState::Error: - return ("Error"); - break; - case EvseState::Faulted: - return ("Faulted"); - break; case EvseState::T_step_EF: return ("T_step_EF"); break; @@ -1309,17 +1205,14 @@ float Charger::getMaxCurrent() { std::lock_guard lock(configMutex); auto maxc = maxCurrent; - if (connector_type == IEC62196Type2Socket && maxCurrentCable < maxc && currentState != EvseState::Idle) { + if (connector_type == types::evse_board_support::Connector_type::IEC62196Type2Socket && maxCurrentCable < maxc && + currentState != EvseState::Idle) { maxc = maxCurrentCable; } return maxc; } -bool Charger::forceUnlock() { - return r_bsp->call_force_unlock(); -} - void Charger::setCurrentDrawnByVehicle(float l1, float l2, float l3) { std::lock_guard lock(configMutex); currentDrawnByVehicle[0] = l1; @@ -1349,11 +1242,11 @@ void Charger::checkSoftOverCurrent() { auto timeSinceOverCurrentStarted = std::chrono::duration_cast(now - lastOverCurrentEvent).count(); if (overCurrent && timeSinceOverCurrentStarted >= softOverCurrentTimeout) { - session_log.evse(false, fmt::format("Soft overcurrent event (L1:{}, L2:{}, L3:{}, limit {}) triggered", - currentDrawnByVehicle[0], currentDrawnByVehicle[1], - currentDrawnByVehicle[2], limit)); - currentState = EvseState::Error; - errorState = types::evse_manager::ErrorEnum::OverCurrent; + auto errstr = fmt::format("Soft overcurrent event (L1:{}, L2:{}, L3:{}, limit {}) triggered", + currentDrawnByVehicle[0], currentDrawnByVehicle[1], currentDrawnByVehicle[2], limit); + session_log.evse(false, errstr); + // raise the OC error + error_handling->raise_overcurrent_error(errstr); } } @@ -1485,8 +1378,7 @@ void Charger::set_hlc_allow_close_contactor(bool on) { void Charger::set_hlc_error(types::evse_manager::ErrorEnum e) { std::lock_guard lock(stateMutex); - currentState = EvseState::Error; - errorState = e; + error_prevent_charging_flag = true; } // this resets the BCB sequence (which may contain 1-3 toggle pulses) @@ -1509,6 +1401,9 @@ void Charger::bcb_toggle_detect_start_pulse() { // call this on C->B transitions void Charger::bcb_toggle_detect_stop_pulse() { + if (!hlc_bcb_sequence_started) + return; + // This is probably and end of BCB toggle, verify it was not too long or too short auto pulse_length = std::chrono::steady_clock::now() - hlc_ev_pause_start_of_bcb; @@ -1541,4 +1436,34 @@ bool Charger::bcb_toggle_detected() { return false; } +void Charger::set_rcd_error() { + std::lock_guard lock(stateMutex); + error_prevent_charging_flag = true; +} + +bool Charger::errors_prevent_charging() { + if (error_prevent_charging_flag) { + graceful_stop_charging(); + return true; + } + return false; +} + +void Charger::graceful_stop_charging() { + + if (pwm_running) { + pwm_off(); + } + + // Shutdown DC power supplies + if (charge_mode == ChargeMode::DC) { + signal_DC_supply_off(); + } + + // open contactors + if (contactors_closed) { + bsp->allow_power_on(false, types::evse_board_support::Reason::PowerOff); + } +} + } // namespace module diff --git a/modules/EvseManager/Charger.hpp b/modules/EvseManager/Charger.hpp index 86231ba21d..6175d180eb 100644 --- a/modules/EvseManager/Charger.hpp +++ b/modules/EvseManager/Charger.hpp @@ -30,23 +30,24 @@ #include #include #include -#include #include #include #include #include #include +#include "ErrorHandling.hpp" +#include "IECStateMachine.hpp" + namespace module { const std::string IEC62196Type2Cable = "IEC62196Type2Cable"; const std::string IEC62196Type2Socket = "IEC62196Type2Socket"; -using ControlPilotEvent = types::board_support::Event; - class Charger { public: - Charger(const std::unique_ptr& r_bsp, const std::string& connector_type); + Charger(const std::unique_ptr& bsp, const std::unique_ptr& error_handling, + const types::evse_board_support::Connector_type& connector_type); ~Charger(); // Public interface to configure Charger @@ -57,8 +58,7 @@ class Charger { // external input to charger: update max_current and new validUntil bool setMaxCurrent(float ampere, std::chrono::time_point validUntil); - // update only max_current but keep the current validUntil - bool setMaxCurrent(float ampere); + float getMaxCurrent(); sigslot::signal signalMaxCurrent; @@ -67,15 +67,15 @@ class Charger { DC }; - void setup(bool three_phases, bool has_ventilation, const std::string& country_code, bool rcd_enabled, - const ChargeMode charge_mode, bool ac_hlc_enabled, bool ac_hlc_use_5percent, bool ac_enforce_hlc, - bool ac_with_soc_timeout, float soft_over_current_tolerance_percent, - float soft_over_current_measurement_noise_A); + void setup(bool three_phases, bool has_ventilation, const std::string& country_code, const ChargeMode charge_mode, + bool ac_hlc_enabled, bool ac_hlc_use_5percent, bool ac_enforce_hlc, bool ac_with_soc_timeout, + float soft_over_current_tolerance_percent, float soft_over_current_measurement_noise_A); bool enable(int connector_id); bool disable(int connector_id); void set_faulted(); void set_hlc_error(types::evse_manager::ErrorEnum e); + void set_rcd_error(); // switch to next charging session after Finished bool restart(); @@ -131,10 +131,7 @@ class Charger { sigslot::signal<> signal_hlc_stop_charging; - // Request more details about the error that happend - types::evse_manager::ErrorEnum getErrorState(); - - void processEvent(types::board_support::Event event); + void processEvent(CPEvent event); void run(); @@ -161,8 +158,6 @@ class Charger { ChargingPausedEVSE, StoppingCharging, Finished, - Error, - Faulted, T_step_EF, T_step_X1, Replug @@ -178,8 +173,8 @@ class Charger { EvseState getCurrentState(); sigslot::signal signalState; - sigslot::signal signalError; - // /Deprecated + // sigslot::signal signalError; + // /Deprecated void inform_new_evse_max_hlc_limits(const types::iso15118_charger::DC_EVSEMaximumLimits& l); types::iso15118_charger::DC_EVSEMaximumLimits get_evse_max_hlc_limits(); @@ -191,6 +186,8 @@ class Charger { void set_hlc_charging_active(); void set_hlc_allow_close_contactor(bool on); + bool errors_prevent_charging(); + private: void bcb_toggle_reset(); void bcb_toggle_detect_start_pulse(); @@ -200,14 +197,15 @@ class Charger { // main Charger thread Everest::Thread mainThreadHandle; - const std::unique_ptr& r_bsp; - const std::string& connector_type; + const std::unique_ptr& bsp; + const std::unique_ptr& error_handling; + const types::evse_board_support::Connector_type& connector_type; void mainThread(); float maxCurrent; std::chrono::time_point maxCurrentValidUntil; - float maxCurrentCable; + float maxCurrentCable{0.}; bool powerAvailable(); @@ -236,11 +234,16 @@ class Charger { EvseState currentState; EvseState last_state; EvseState last_state_detect_state_change; + types::evse_manager::ErrorEnum errorState{types::evse_manager::ErrorEnum::Internal}; std::chrono::system_clock::time_point currentStateStarted; bool connectorEnabled; + bool error_prevent_charging_flag{false}; + bool last_error_prevent_charging_flag{false}; + void graceful_stop_charging(); + float ampereToDutyCycle(float ampere); void checkSoftOverCurrent(); @@ -265,10 +268,8 @@ class Charger { bool matching_started; - ControlPilotEvent string_to_control_pilot_event(const types::board_support::Event& event); - - void processCPEventsIndependent(ControlPilotEvent cp_event); - void processCPEventsState(ControlPilotEvent cp_event); + void processCPEventsIndependent(CPEvent cp_event); + void processCPEventsState(CPEvent cp_event); void runStateMachine(); bool authorized; diff --git a/modules/EvseManager/ErrorHandling.cpp b/modules/EvseManager/ErrorHandling.cpp new file mode 100644 index 0000000000..e913d970a6 --- /dev/null +++ b/modules/EvseManager/ErrorHandling.cpp @@ -0,0 +1,338 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Pionix GmbH and Contributors to EVerest + +#include "ErrorHandling.hpp" + +namespace module { + +ErrorHandling::ErrorHandling(const std::unique_ptr& _r_bsp, + const std::vector>& _r_hlc, + const std::vector>& _r_connector_lock, + const std::vector>& _r_ac_rcd, + const std::unique_ptr& _p_evse) : + r_bsp(_r_bsp), r_hlc(_r_hlc), r_connector_lock(_r_connector_lock), r_ac_rcd(_r_ac_rcd), p_evse(_p_evse) { + + if (r_hlc.size() > 0) { + hlc = true; + } + + // Subscribe to bsp driver to receive Errors from the bsp hardware + r_bsp->subscribe_all_errors( + [this](const Everest::error::Error& error) { + if (modify_error_bsp(error, true)) { + // signal to charger a new error has been set + signal_error(); + }; + }, + [this](const Everest::error::Error& error) { + modify_error_bsp(error, false); + + if (active_errors.all_cleared()) { + // signal to charger that all errors are cleared now + signal_all_errors_cleared(); + // clear errors with HLC stack + if (hlc) { + r_hlc[0]->call_reset_error(); + } + } + }); + + // Subscribe to connector lock to receive errors from connector lock hardware + if (r_connector_lock.size() > 0) { + r_connector_lock[0]->subscribe_all_errors( + [this](const Everest::error::Error& error) { + if (modify_error_connector_lock(error, true)) { + // signal to charger a new error has been set + signal_error(); + }; + }, + [this](const Everest::error::Error& error) { + modify_error_connector_lock(error, false); + + if (active_errors.all_cleared()) { + // signal to charger that all errors are cleared now + signal_all_errors_cleared(); + // clear errors with HLC stack + if (hlc) { + r_hlc[0]->call_reset_error(); + } + } + }); + } + + // Subscribe to ac_rcd to receive errors from AC RCD hardware + if (r_ac_rcd.size() > 0) { + r_ac_rcd[0]->subscribe_all_errors( + [this](const Everest::error::Error& error) { + if (modify_error_ac_rcd(error, true)) { + // signal to charger a new error has been set + signal_error(); + }; + }, + [this](const Everest::error::Error& error) { + modify_error_ac_rcd(error, false); + + if (active_errors.all_cleared()) { + // signal to charger that all errors are cleared now + signal_all_errors_cleared(); + // clear errors with HLC stack + if (hlc) { + r_hlc[0]->call_reset_error(); + } + } + }); + } +} + +void ErrorHandling::raise_overcurrent_error(const std::string& description) { + // raise externally + p_evse->raise_evse_manager_MREC4OverCurrentFailure("Slow overcurrent detected", Everest::error::Severity::High); + + if (modify_error_evse_manager("evse_manager/MREC4OverCurrentFailure", true)) { + // signal to charger a new error has been set + signal_error(); + }; +} + +void ErrorHandling::clear_overcurrent_error() { + // clear externally + p_evse->request_clear_all_evse_manager_MREC4OverCurrentFailure(); + + modify_error_evse_manager("evse_manager/MREC4OverCurrentFailure", false); + + if (active_errors.all_cleared()) { + // signal to charger that all errors are cleared now + signal_all_errors_cleared(); + // clear errors with HLC stack + if (hlc) { + r_hlc[0]->call_reset_error(); + } + } +} + +void ErrorHandling::raise_internal_error(const std::string& description) { + // raise externally + // FIXME raise_evse_manager_MREC4OverCurrentFailure(description); + + if (modify_error_evse_manager("evse_manager/Internal", true)) { + // signal to charger a new error has been set + signal_error(); + }; +} + +void ErrorHandling::clear_internal_error() { + // clear externally + // FIXME clear_evse_manager_MREC4OverCurrentFailure(); + + modify_error_evse_manager("evse_manager/Internal", false); + + if (active_errors.all_cleared()) { + // signal to charger that all errors are cleared now + signal_all_errors_cleared(); + // clear errors with HLC stack + if (hlc) { + r_hlc[0]->call_reset_error(); + } + } +} + +bool ErrorHandling::modify_error_bsp(const Everest::error::Error& error, bool active) { + const std::string& error_type = error.type; + + if (active) { + EVLOG_error << "Raised error " << error_type << ": " << error.description << " (" << error.message << ")"; + } else { + EVLOG_info << "Cleared error " << error_type << ": " << error.description << " (" << error.message << ")"; + } + + if (error_type == "evse_board_support/DiodeFault") { + active_errors.bsp.DiodeFault = active; + } else if (error_type == "evse_board_support/VentilationNotAvailable") { + active_errors.bsp.VentilationNotAvailable = active; + } else if (error_type == "evse_board_support/BrownOut") { + active_errors.bsp.BrownOut = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/EnergyManagement") { + active_errors.bsp.EnergyManagement = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/PermanentFault") { + active_errors.bsp.PermanentFault = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/MREC2GroundFailure") { + active_errors.bsp.MREC2GroundFailure = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/MREC4OverCurrentFailure") { + active_errors.bsp.MREC4OverCurrentFailure = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/MREC5OverVoltage") { + active_errors.bsp.MREC5OverVoltage = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/MREC6UnderVoltage") { + active_errors.bsp.MREC6UnderVoltage = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/MREC8EmergencyStop") { + active_errors.bsp.MREC8EmergencyStop = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_EmergencyShutdown); + } + } else if (error_type == "evse_board_support/MREC10InvalidVehicleMode") { + active_errors.bsp.MREC10InvalidVehicleMode = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/MREC14PilotFault") { + active_errors.bsp.MREC14PilotFault = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/MREC15PowerLoss") { + active_errors.bsp.MREC15PowerLoss = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/MREC17EVSEContactorFault") { + active_errors.bsp.MREC17EVSEContactorFault = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Contactor); + } + } else if (error_type == "evse_board_support/MREC19CableOverTempStop") { + active_errors.bsp.MREC19CableOverTempStop = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/MREC20PartialInsertion") { + active_errors.bsp.MREC20PartialInsertion = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/MREC23ProximityFault") { + active_errors.bsp.MREC23ProximityFault = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/MREC24ConnectorVoltageHigh") { + active_errors.bsp.MREC24ConnectorVoltageHigh = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/MREC25BrokenLatch") { + active_errors.bsp.MREC25BrokenLatch = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/MREC26CutCable") { + active_errors.bsp.MREC26CutCable = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "evse_board_support/VendorError") { + active_errors.bsp.VendorError = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else { + return false; // Error does not stop charging, ignored here + } + return true; // Error stops charging +}; + +bool ErrorHandling::modify_error_connector_lock(const Everest::error::Error& error, bool active) { + const std::string& error_type = error.type; + + if (active) { + EVLOG_error << "Raised error " << error_type << ": " << error.description << " (" << error.message << ")"; + } else { + EVLOG_info << "Cleared error " << error_type << ": " << error.description << " (" << error.message << ")"; + } + + if (error_type == "connector_lock/ConnectorLockCapNotCharged") { + active_errors.connector_lock.ConnectorLockCapNotCharged = active; + } else if (error_type == "connector_lock/ConnectorLockUnexpectedClose") { + active_errors.connector_lock.ConnectorLockUnexpectedClose = active; + } else if (error_type == "connector_lock/ConnectorLockUnexpectedOpen") { + active_errors.connector_lock.ConnectorLockUnexpectedOpen = active; + } else if (error_type == "connector_lock/ConnectorLockFailedLock") { + active_errors.connector_lock.ConnectorLockFailedLock = active; + } else if (error_type == "connector_lock/ConnectorLockFailedUnlock") { + active_errors.connector_lock.ConnectorLockFailedUnlock = active; + } else if (error_type == "connector_lock/MREC1ConnectorLockFailure") { + active_errors.connector_lock.MREC1ConnectorLockFailure = active; + } else if (error_type == "connector_lock/VendorError") { + active_errors.connector_lock.VendorError = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else { + return false; // Error does not stop charging, ignored here + } + return true; // Error stops charging +}; + +bool ErrorHandling::modify_error_ac_rcd(const Everest::error::Error& error, bool active) { + const std::string& error_type = error.type; + + if (active) { + EVLOG_error << "Raised error " << error_type << ": " << error.description << " (" << error.message << ")"; + } else { + EVLOG_info << "Cleared error " << error_type << ": " << error.description << " (" << error.message << ")"; + } + + if (error_type == "ac_rcd/MREC2GroundFailure") { + active_errors.ac_rcd.MREC2GroundFailure = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_RCD); + } + } else if (error_type == "ac_rcd/VendorError") { + active_errors.ac_rcd.VendorError = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "ac_rcd/Selftest") { + active_errors.ac_rcd.Selftest = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + } else if (error_type == "ac_rcd/AC") { + active_errors.ac_rcd.AC = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_RCD); + } + } else if (error_type == "ac_rcd/DC") { + active_errors.ac_rcd.DC = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_RCD); + } + } else { + return false; // Error does not stop charging, ignored here + } + return true; // Error stops charging +}; + +bool ErrorHandling::modify_error_evse_manager(const std::string& error_type, bool active) { + if (error_type == "evse_manager/MREC4OverCurrentFailure") { + active_errors.bsp.MREC4OverCurrentFailure = active; + if (hlc && active) { + r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); + } + + } else { + return false; // Error does not stop charging, ignored here + } + return true; // Error stops charging +}; + +} // namespace module diff --git a/modules/EvseManager/ErrorHandling.hpp b/modules/EvseManager/ErrorHandling.hpp new file mode 100644 index 0000000000..aca051bfb6 --- /dev/null +++ b/modules/EvseManager/ErrorHandling.hpp @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2020 - 2021 Pionix GmbH and Contributors to EVerest + +/* + The ErrorHandling class handles all errors from BSP/ConnectorLock etc + and classifies them for charging: + + If we can continue charging despite the error, we treat them as warnings and do not track them here. If e.g. the BSP + raises a high temperature error it needs to limit the output power by itself. + + The decision whether an error requires a replug or not to clear depends on the reporting module. It will need to clear + them at the appropriate time. +*/ + +#ifndef SRC_ERROR_HANDLING_H_ +#define SRC_ERROR_HANDLING_H_ + +#include "ld-ev.hpp" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "Timeout.hpp" +#include "utils/thread.hpp" + +namespace module { + +// bit field to track which errors are active at the moment. Only tracks errors that stop charging. +struct ActiveErrors { + + struct bsp_errors { + std::atomic_bool DiodeFault{false}; + std::atomic_bool VentilationNotAvailable{false}; + std::atomic_bool BrownOut{false}; + std::atomic_bool EnergyManagement{false}; + std::atomic_bool PermanentFault{false}; + std::atomic_bool MREC2GroundFailure{false}; + std::atomic_bool MREC4OverCurrentFailure{false}; + std::atomic_bool MREC5OverVoltage{false}; + std::atomic_bool MREC6UnderVoltage{false}; + std::atomic_bool MREC8EmergencyStop{false}; + std::atomic_bool MREC10InvalidVehicleMode{false}; + std::atomic_bool MREC14PilotFault{false}; + std::atomic_bool MREC15PowerLoss{false}; + std::atomic_bool MREC17EVSEContactorFault{false}; + std::atomic_bool MREC19CableOverTempStop{false}; + std::atomic_bool MREC20PartialInsertion{false}; + std::atomic_bool MREC23ProximityFault{false}; + std::atomic_bool MREC24ConnectorVoltageHigh{false}; + std::atomic_bool MREC25BrokenLatch{false}; + std::atomic_bool MREC26CutCable{false}; + std::atomic_bool VendorError{false}; + } bsp; + + struct evse_manager_errors { + std::atomic_bool MREC4OverCurrentFailure{false}; + std::atomic_bool Internal{false}; + } evse_manager; + + struct ac_rcd_errors { + std::atomic_bool MREC2GroundFailure{false}; + std::atomic_bool VendorError{false}; + std::atomic_bool Selftest{false}; + std::atomic_bool AC{false}; + std::atomic_bool DC{false}; + } ac_rcd; + + struct connector_lock_errors { + std::atomic_bool ConnectorLockCapNotCharged{false}; + std::atomic_bool ConnectorLockUnexpectedOpen{false}; + std::atomic_bool ConnectorLockUnexpectedClose{false}; + std::atomic_bool ConnectorLockFailedLock{false}; + std::atomic_bool ConnectorLockFailedUnlock{false}; + std::atomic_bool MREC1ConnectorLockFailure{false}; + std::atomic_bool VendorError{false}; + } connector_lock; + + bool all_cleared() { + return not(bsp.DiodeFault or bsp.VentilationNotAvailable or bsp.BrownOut or bsp.EnergyManagement or + bsp.PermanentFault or bsp.MREC2GroundFailure or bsp.MREC4OverCurrentFailure or + bsp.MREC5OverVoltage or bsp.MREC6UnderVoltage or bsp.MREC8EmergencyStop or + bsp.MREC10InvalidVehicleMode or bsp.MREC14PilotFault or bsp.MREC15PowerLoss or + bsp.MREC17EVSEContactorFault or bsp.MREC19CableOverTempStop or bsp.MREC20PartialInsertion or + bsp.MREC23ProximityFault or bsp.MREC24ConnectorVoltageHigh or bsp.MREC25BrokenLatch or + bsp.MREC26CutCable or evse_manager.MREC4OverCurrentFailure or evse_manager.Internal or + ac_rcd.MREC2GroundFailure or ac_rcd.VendorError or ac_rcd.Selftest or ac_rcd.AC or ac_rcd.DC or + connector_lock.ConnectorLockCapNotCharged or connector_lock.ConnectorLockUnexpectedOpen or + connector_lock.ConnectorLockUnexpectedClose or connector_lock.ConnectorLockFailedLock or + connector_lock.ConnectorLockFailedUnlock or connector_lock.MREC1ConnectorLockFailure or + connector_lock.VendorError); + } +}; + +class ErrorHandling { +public: + // We need the r_bsp reference to be able to talk to the bsp driver module + explicit ErrorHandling(const std::unique_ptr& r_bsp, + const std::vector>& r_hlc, + const std::vector>& r_connector_lock, + const std::vector>& r_ac_rcd, + const std::unique_ptr& _p_evse); + + // Signal for internal events type + sigslot::signal<> signal_error; + sigslot::signal<> signal_all_errors_cleared; + + void raise_overcurrent_error(const std::string& description); + void clear_overcurrent_error(); + + void raise_internal_error(const std::string& description); + void clear_internal_error(); + +private: + const std::unique_ptr& r_bsp; + const std::vector>& r_hlc; + const std::vector>& r_connector_lock; + const std::vector>& r_ac_rcd; + const std::unique_ptr& p_evse; + + bool modify_error_bsp(const Everest::error::Error& error, bool active); + bool modify_error_connector_lock(const Everest::error::Error& error, bool active); + bool modify_error_ac_rcd(const Everest::error::Error& error, bool active); + + bool modify_error_evse_manager(const std::string& error_type, bool active); + bool hlc{false}; + + ActiveErrors active_errors; +}; + +} // namespace module + +#endif // SRC_BSP_STATE_MACHINE_H_ diff --git a/modules/EvseManager/EvseManager.cpp b/modules/EvseManager/EvseManager.cpp index d65428d23f..8a04541c1f 100644 --- a/modules/EvseManager/EvseManager.cpp +++ b/modules/EvseManager/EvseManager.cpp @@ -1,10 +1,13 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright Pionix GmbH and Contributors to EVerest #include "EvseManager.hpp" -#include "SessionLog.hpp" -#include "Timeout.hpp" + #include #include + +#include "IECStateMachine.hpp" +#include "SessionLog.hpp" +#include "Timeout.hpp" using namespace std::literals::chrono_literals; namespace module { @@ -79,7 +82,18 @@ void EvseManager::init() { } void EvseManager::ready() { - charger = std::unique_ptr(new Charger(r_bsp, config.connector_type)); + bsp = std::unique_ptr(new IECStateMachine(r_bsp)); + error_handling = + std::unique_ptr(new ErrorHandling(r_bsp, r_hlc, r_connector_lock, r_ac_rcd, p_evse)); + + hw_capabilities = r_bsp->call_get_hw_capabilities(); + + charger = std::unique_ptr(new Charger(bsp, error_handling, hw_capabilities.connector_type)); + + if (r_connector_lock.size() > 0) { + bsp->signal_lock.connect([this]() { r_connector_lock[0]->call_lock(); }); + bsp->signal_unlock.connect([this]() { r_connector_lock[0]->call_unlock(); }); + } if (get_hlc_enabled()) { @@ -485,8 +499,8 @@ void EvseManager::ready() { // switch to DC mode for first session for AC with SoC if (config.ac_with_soc) { - r_bsp->subscribe_event([this](const types::board_support::Event& event) { - if (event == types::board_support::Event::CarUnplugged) { + bsp->signal_event.connect([this](const CPEvent event) { + if (event == CPEvent::CarUnplugged) { // configure for DC again for next session. Will reset to AC when SoC is received switch_DC_mode(); } @@ -505,8 +519,6 @@ void EvseManager::ready() { }); } - hw_capabilities = r_bsp->call_get_hw_capabilities(); - // Maybe override with user setting for this EVSE if (config.max_current_import_A < hw_capabilities.max_current_A_import) { hw_capabilities.max_current_A_import = config.max_current_import_A; @@ -535,15 +547,15 @@ void EvseManager::ready() { hw_capabilities.max_phase_count_import); } - r_bsp->subscribe_event([this](const types::board_support::Event event) { + bsp->signal_event.connect([this](const CPEvent event) { // Forward events from BSP to SLAC module before we process the events in the charger if (slac_enabled) { - if (event == types::board_support::Event::EFtoBCD) { + if (event == CPEvent::EFtoBCD) { // this means entering BCD from E|F r_slac[0]->call_enter_bcd(); - } else if (event == types::board_support::Event::BCDtoEF) { + } else if (event == CPEvent::BCDtoEF) { r_slac[0]->call_leave_bcd(); - } else if (event == types::board_support::Event::CarPluggedIn) { + } else if (event == CPEvent::CarPluggedIn) { // CC: right now we dont support energy saving mode, so no need to reset slac here. // It is more important to start slac as early as possible to avoid unneccesary retries // e.g. by Tesla cars which send the first SLAC_PARM_REQ directly after plugin. @@ -553,7 +565,7 @@ void EvseManager::ready() { // This is entering BCD from state A car_manufacturer = types::evse_manager::CarManufacturer::Unknown; r_slac[0]->call_enter_bcd(); - } else if (event == types::board_support::Event::CarUnplugged) { + } else if (event == CPEvent::CarUnplugged) { r_slac[0]->call_leave_bcd(); r_slac[0]->call_reset(false); } @@ -564,7 +576,7 @@ void EvseManager::ready() { // Forward some events to HLC if (get_hlc_enabled()) { // Reset HLC auth waiting flags on new session - if (event == types::board_support::Event::CarPluggedIn) { + if (event == CPEvent::CarPluggedIn) { r_hlc[0]->call_reset_error(); r_hlc[0]->call_ac_contactor_closed(false); r_hlc[0]->call_stop_charging(false); @@ -577,32 +589,12 @@ void EvseManager::ready() { } } - if (event == types::board_support::Event::ErrorRelais) { - session_log.evse(false, "Error Relais"); - r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Contactor); - } - - if (event == types::board_support::Event::ErrorRCD) { - session_log.evse(false, "Error RCD"); - r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_RCD); - } - - if (event == types::board_support::Event::PermanentFault) { - session_log.evse(false, "Error Permanent Fault"); - r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_Malfunction); - } - - if (event == types::board_support::Event::ErrorOverCurrent) { - session_log.evse(false, "Error Over Current"); - r_hlc[0]->call_send_error(types::iso15118_charger::EvseError::Error_EmergencyShutdown); - } - - if (event == types::board_support::Event::PowerOn) { + if (event == CPEvent::PowerOn) { contactor_open = false; r_hlc[0]->call_ac_contactor_closed(true); } - if (event == types::board_support::Event::PowerOff) { + if (event == CPEvent::PowerOff) { contactor_open = true; latest_target_voltage = 0; latest_target_current = 0; @@ -617,7 +609,7 @@ void EvseManager::ready() { }); }); - r_bsp->subscribe_nr_of_phases_available([this](int n) { signalNrOfPhasesAvailable(n); }); + r_bsp->subscribe_ac_nr_of_phases_available([this](int n) { signalNrOfPhasesAvailable(n); }); if (r_powermeter_billing().size() > 0) { r_powermeter_billing()[0]->subscribe_powermeter([this](types::powermeter::Powermeter p) { @@ -662,7 +654,6 @@ void EvseManager::ready() { } if (slac_enabled) { - // Reset once on startup and disable modem r_slac[0]->call_reset(false); @@ -734,7 +725,7 @@ void EvseManager::ready() { if (config.ac_with_soc) { setup_fake_DC_mode(); } else { - charger->setup(local_three_phases, config.has_ventilation, config.country_code, config.rcd_enabled, + charger->setup(local_three_phases, config.has_ventilation, config.country_code, (config.charge_mode == "DC" ? Charger::ChargeMode::DC : Charger::ChargeMode::AC), hlc_enabled, config.ac_hlc_use_5percent, config.ac_enforce_hlc, false, config.soft_over_current_tolerance_percent, config.soft_over_current_measurement_noise_A); @@ -867,7 +858,7 @@ types::powermeter::Powermeter EvseManager::get_latest_powermeter_data_billing() return latest_powermeter_data_billing; } -types::board_support::HardwareCapabilities EvseManager::get_hw_capabilities() { +types::evse_board_support::HardwareCapabilities EvseManager::get_hw_capabilities() { return hw_capabilities; } @@ -889,8 +880,8 @@ void EvseManager::switch_AC_mode() { // This sets up a fake DC mode that is just supposed to work until we get the SoC. // It is only used for AC<>DC<>AC<>DC mode to get AC charging with SoC. void EvseManager::setup_fake_DC_mode() { - charger->setup(local_three_phases, config.has_ventilation, config.country_code, config.rcd_enabled, - Charger::ChargeMode::DC, hlc_enabled, config.ac_hlc_use_5percent, config.ac_enforce_hlc, false, + charger->setup(local_three_phases, config.has_ventilation, config.country_code, Charger::ChargeMode::DC, + hlc_enabled, config.ac_hlc_use_5percent, config.ac_enforce_hlc, false, config.soft_over_current_tolerance_percent, config.soft_over_current_measurement_noise_A); types::iso15118_charger::EVSEID evseid = {config.evse_id, config.evse_id_din}; @@ -933,8 +924,8 @@ void EvseManager::setup_fake_DC_mode() { } void EvseManager::setup_AC_mode() { - charger->setup(local_three_phases, config.has_ventilation, config.country_code, config.rcd_enabled, - Charger::ChargeMode::AC, hlc_enabled, config.ac_hlc_use_5percent, config.ac_enforce_hlc, true, + charger->setup(local_three_phases, config.has_ventilation, config.country_code, Charger::ChargeMode::AC, + hlc_enabled, config.ac_hlc_use_5percent, config.ac_enforce_hlc, true, config.soft_over_current_tolerance_percent, config.soft_over_current_measurement_noise_A); types::iso15118_charger::EVSEID evseid = {config.evse_id, config.evse_id_din}; @@ -1072,7 +1063,7 @@ bool EvseManager::reserve(int32_t id) { } // is the evse faulted? - if (charger->getCurrentState() == Charger::EvseState::Faulted) { + if (charger->errors_prevent_charging()) { return false; } @@ -1193,7 +1184,8 @@ void EvseManager::cable_check() { session_log.car(true, "DC HLC Close contactor (in CableCheck)"); charger->set_hlc_allow_close_contactor(true); - Timeout timeout(CABLECHECK_CONTACTORS_CLOSE_TIMEOUT); + Timeout timeout; + timeout.start(CABLECHECK_CONTACTORS_CLOSE_TIMEOUT); while (!timeout.reached()) { if (!contactor_open) @@ -1398,14 +1390,17 @@ bool EvseManager::powersupply_DC_set(double _voltage, double _current) { } void EvseManager::powersupply_DC_off() { - session_log.evse(false, "DC power supply OFF"); - r_powersupply_DC[0]->call_setMode(types::power_supply_DC::Mode::Off); - powersupply_dc_is_on = false; + if (powersupply_dc_is_on) { + session_log.evse(false, "DC power supply OFF"); + r_powersupply_DC[0]->call_setMode(types::power_supply_DC::Mode::Off); + powersupply_dc_is_on = false; + } } bool EvseManager::wait_powersupply_DC_voltage_reached(double target_voltage) { // wait until the voltage has rised to the target value - Timeout timeout(30s); + Timeout timeout; + timeout.start(30s); bool voltage_ok = false; while (!timeout.reached()) { types::power_supply_DC::VoltageCurrent m; @@ -1425,7 +1420,8 @@ bool EvseManager::wait_powersupply_DC_voltage_reached(double target_voltage) { bool EvseManager::wait_powersupply_DC_below_voltage(double target_voltage) { // wait until the voltage is below the target voltage - Timeout timeout(30s); + Timeout timeout; + timeout.start(30s); bool voltage_ok = false; while (!timeout.reached()) { types::power_supply_DC::VoltageCurrent m; diff --git a/modules/EvseManager/EvseManager.hpp b/modules/EvseManager/EvseManager.hpp index 0206ac09cd..8408036305 100644 --- a/modules/EvseManager/EvseManager.hpp +++ b/modules/EvseManager/EvseManager.hpp @@ -17,7 +17,9 @@ // headers for required interface implementations #include -#include +#include +#include +#include #include #include #include @@ -25,10 +27,6 @@ // ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1 // insert your custom include headers here -#include "CarManufacturer.hpp" -#include "Charger.hpp" -#include "SessionLog.hpp" -#include "VarContainer.hpp" #include #include #include @@ -38,6 +36,12 @@ #include #include #include + +#include "CarManufacturer.hpp" +#include "Charger.hpp" +#include "ErrorHandling.hpp" +#include "SessionLog.hpp" +#include "VarContainer.hpp" // ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1 namespace module { @@ -56,7 +60,6 @@ struct Conf { bool three_phases; bool has_ventilation; std::string country_code; - bool rcd_enabled; double max_current_import_A; double max_current_export_A; std::string charge_mode; @@ -71,7 +74,6 @@ struct Conf { bool switch_to_minimum_voltage_after_cable_check; bool hack_skoda_enyaq; int hack_present_current_offset; - std::string connector_type; bool hack_pause_imd_during_precharge; bool hack_allow_bpt_with_iso2; bool autocharge_use_slac_instead_of_hlc; @@ -92,7 +94,8 @@ class EvseManager : public Everest::ModuleBase { EvseManager(const ModuleInfo& info, Everest::MqttProvider& mqtt_provider, Everest::TelemetryProvider& telemetry, std::unique_ptr p_evse, std::unique_ptr p_energy_grid, std::unique_ptr p_token_provider, - std::unique_ptr r_bsp, + std::unique_ptr r_bsp, std::vector> r_ac_rcd, + std::vector> r_connector_lock, std::vector> r_powermeter_grid_side, std::vector> r_powermeter_car_side, std::vector> r_slac, std::vector> r_hlc, @@ -105,6 +108,8 @@ class EvseManager : public Everest::ModuleBase { p_energy_grid(std::move(p_energy_grid)), p_token_provider(std::move(p_token_provider)), r_bsp(std::move(r_bsp)), + r_ac_rcd(std::move(r_ac_rcd)), + r_connector_lock(std::move(r_connector_lock)), r_powermeter_grid_side(std::move(r_powermeter_grid_side)), r_powermeter_car_side(std::move(r_powermeter_car_side)), r_slac(std::move(r_slac)), @@ -118,7 +123,9 @@ class EvseManager : public Everest::ModuleBase { const std::unique_ptr p_evse; const std::unique_ptr p_energy_grid; const std::unique_ptr p_token_provider; - const std::unique_ptr r_bsp; + const std::unique_ptr r_bsp; + const std::vector> r_ac_rcd; + const std::vector> r_connector_lock; const std::vector> r_powermeter_grid_side; const std::vector> r_powermeter_car_side; const std::vector> r_slac; @@ -132,7 +139,7 @@ class EvseManager : public Everest::ModuleBase { std::unique_ptr charger; sigslot::signal signalNrOfPhasesAvailable; types::powermeter::Powermeter get_latest_powermeter_data_billing(); - types::board_support::HardwareCapabilities get_hw_capabilities(); + types::evse_board_support::HardwareCapabilities get_hw_capabilities(); bool updateLocalMaxCurrentLimit(float max_current); // deprecated bool updateLocalMaxWattLimit(float max_watt); // deprecated bool updateLocalEnergyLimit(types::energy::ExternalLimits l); @@ -166,6 +173,8 @@ class EvseManager : public Everest::ModuleBase { std::atomic_bool sae_bidi_active{false}; void ready_to_start_charging(); + + std::unique_ptr bsp; // ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1 protected: @@ -184,7 +193,7 @@ class EvseManager : public Everest::ModuleBase { types::powermeter::Powermeter latest_powermeter_data_billing; Everest::Thread energyThreadHandle; - types::board_support::HardwareCapabilities hw_capabilities; + types::evse_board_support::HardwareCapabilities hw_capabilities; bool local_three_phases; types::energy::ExternalLimits local_energy_limits; const float EVSE_ABSOLUTE_MAX_CURRENT = 80.0; @@ -248,6 +257,8 @@ class EvseManager : public Everest::ModuleBase { static constexpr auto CABLECHECK_CONTACTORS_CLOSE_TIMEOUT{std::chrono::seconds(5)}; std::atomic_bool current_demand_active{false}; + + std::unique_ptr error_handling; // ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1 }; diff --git a/modules/EvseManager/IECStateMachine.cpp b/modules/EvseManager/IECStateMachine.cpp new file mode 100644 index 0000000000..494dfd7c6c --- /dev/null +++ b/modules/EvseManager/IECStateMachine.cpp @@ -0,0 +1,402 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Pionix GmbH and Contributors to EVerest + +#include "IECStateMachine.hpp" + +#include +#include + +namespace module { + +// helper type for visitor +template struct overloaded : Ts... { + using Ts::operator()...; +}; +template overloaded(Ts...) -> overloaded; + +static std::variant from_bsp_event(types::board_support_common::Event e) { + switch (e) { + case types::board_support_common::Event::A: + return RawCPState::A; + case types::board_support_common::Event::B: + return RawCPState::B; + case types::board_support_common::Event::C: + return RawCPState::C; + case types::board_support_common::Event::D: + return RawCPState::D; + case types::board_support_common::Event::E: + return RawCPState::E; + case types::board_support_common::Event::F: + return RawCPState::F; + case types::board_support_common::Event::PowerOn: + return CPEvent::PowerOn; + case types::board_support_common::Event::PowerOff: + return CPEvent::PowerOff; + case types::board_support_common::Event::EvseReplugStarted: + return CPEvent::EvseReplugStarted; + case types::board_support_common::Event::EvseReplugFinished: + return CPEvent::EvseReplugFinished; + default: + return RawCPState::Disabled; + } +} + +/// \brief Converts the given Event \p e to human readable string +/// \returns a string representation of the Event +const std::string cpevent_to_string(CPEvent e) { + switch (e) { + case CPEvent::CarPluggedIn: + return "CarPluggedIn"; + case CPEvent::CarRequestedPower: + return "CarRequestedPower"; + case CPEvent::PowerOn: + return "PowerOn"; + case CPEvent::PowerOff: + return "PowerOff"; + case CPEvent::CarRequestedStopPower: + return "CarRequestedStopPower"; + case CPEvent::CarUnplugged: + return "CarUnplugged"; + case CPEvent::EFtoBCD: + return "EFtoBCD"; + case CPEvent::BCDtoEF: + return "BCDtoEF"; + case CPEvent::EvseReplugStarted: + return "EvseReplugStarted"; + case CPEvent::EvseReplugFinished: + return "EvseReplugFinished"; + } + throw std::out_of_range("No known string conversion for provided enum of type CPEvent"); +} + +IECStateMachine::IECStateMachine(const std::unique_ptr& r_bsp) : r_bsp(r_bsp) { + // feed the state machine whenever the timer expires + timeout_state_c1.signal_reached.connect(&IECStateMachine::feed_state_machine, this); + + // Subscribe to bsp driver to receive BspEvents from the hardware + r_bsp->subscribe_event([this](const types::board_support_common::BspEvent event) { + if (enabled) { + // feed into state machine + process_bsp_event(event); + } else { + EVLOG_info << "Ignoring BSP Event, BSP is not enabled yet."; + } + }); +} + +void IECStateMachine::process_bsp_event(const types::board_support_common::BspEvent bsp_event) { + auto event = from_bsp_event(bsp_event.event); + std::visit(overloaded{[this](RawCPState& raw_state) { + // If it is a raw CP state, run it through the state machine + { + std::lock_guard l(state_machine_mutex); + cp_state = raw_state; + } + feed_state_machine(); + }, + // If it is another CP event, pass through + [this](CPEvent& event) { signal_event(event); }}, + event); +} + +void IECStateMachine::feed_state_machine() { + auto events = state_machine(); + + // Process all events + while (not events.empty()) { + signal_event(events.front()); + events.pop(); + } +} + +// Main IEC state machine. Needs to be called whenever: +// - CP state changes (both events from hardware as well as duty cycle changes) +// - Allow power on changes +// - The C1 6s timer expires +std::queue IECStateMachine::state_machine() { + + std::queue events; + std::lock_guard lock(state_machine_mutex); + + switch (cp_state) { + + case RawCPState::Disabled: + if (last_cp_state != RawCPState::Disabled) { + pwm_running = false; + r_bsp->call_pwm_off(); + ev_simplified_mode = false; + timeout_state_c1.stop(); + call_allow_power_on_bsp(false); + connector_unlock(); + } + break; + + case RawCPState::A: + if (last_cp_state != RawCPState::A) { + pwm_running = false; + r_bsp->call_pwm_off(); + ev_simplified_mode = false; + car_plugged_in = false; + call_allow_power_on_bsp(false); + timeout_state_c1.stop(); + connector_unlock(); + } + + // Table A.6: Sequence 2.1 Unplug at state Bx (or any other + // state) Table A.6: Sequence 2.2 Unplug at state Cx, Dx + if (last_cp_state != RawCPState::A && last_cp_state != RawCPState::Disabled) { + events.push(CPEvent::CarUnplugged); + } + break; + + case RawCPState::B: + // Table A.6: Sequence 7 EV stops charging + // Table A.6: Sequence 8.2 EV supply equipment + // responds to EV opens S2 (w/o PWM) + connector_lock(); + + if (last_cp_state != RawCPState::A && last_cp_state != RawCPState::B) { + + events.push(CPEvent::CarRequestedStopPower); + // Need to switch off according to Table A.6 Sequence 8.1 + // within 100ms + call_allow_power_on_bsp(false); + timeout_state_c1.stop(); + } + + // Table A.6: Sequence 1.1 Plug-in + if (last_cp_state == RawCPState::A || last_cp_state == RawCPState::Disabled || + (!car_plugged_in && last_cp_state == RawCPState::F)) { + events.push(CPEvent::CarPluggedIn); + ev_simplified_mode = false; + } + + if (last_cp_state == RawCPState::E || last_cp_state == RawCPState::F) { + // Triggers SLAC start + events.push(CPEvent::EFtoBCD); + } + break; + + case RawCPState::D: + connector_lock(); + // If state D is not supported switch off. + if (not has_ventilation) { + call_allow_power_on_bsp(false); + timeout_state_c1.stop(); + break; + } + // no break, intended fall through: If we support state D it is handled the same way as state C + [[fallthrough]]; + + case RawCPState::C: + connector_lock(); + // Table A.6: Sequence 1.2 Plug-in + if (last_cp_state == RawCPState::A || last_cp_state == RawCPState::Disabled || + (!car_plugged_in && last_cp_state == RawCPState::F)) { + events.push(CPEvent::CarPluggedIn); + EVLOG_info << "Detected simplified mode."; + ev_simplified_mode = true; + } else if (last_cp_state == RawCPState::B) { + events.push(CPEvent::CarRequestedPower); + } + + if (!pwm_running && last_pwm_running) { // X2->C1 + // Table A.6 Sequence 10.2: EV does not stop drawing power + // even if PWM stops. Stop within 6 seconds (E.g. Kona1!) + timeout_state_c1.start(std::chrono::seconds(6)); + } + + // PWM switches on while in state C + if (pwm_running && !last_pwm_running) { + // when resuming after a pause before the EV goes to state B, stop the timer. + timeout_state_c1.stop(); + + // If we resume charging and the EV never left state C during pause we allow non-compliant EVs to switch + // on again. + if (power_on_allowed) { + call_allow_power_on_bsp(true); + } + } + + if (timeout_state_c1.reached()) { + EVLOG_warning << "Timeout of 6 seconds reached, EV did not go back to state B after PWM was switch off. " + "Power off under load."; + // We are still in state C, but the 6 seconds timeout has been reached. Now force power off under load. + call_allow_power_on_bsp(false); + } + + if (pwm_running) { // C2 + // 1) When we come from state B: switch on if we are allowed to + // 2) When we are in C2 for a while now and finally get a delayed power_on_allowed: also switch on + if (power_on_allowed && (!last_power_on_allowed || last_cp_state == RawCPState::B)) { + // Table A.6: Sequence 4 EV ready to charge. + // Must enable power within 3 seconds. + call_allow_power_on_bsp(true); + } + + // Simulate Request power Event here for simplified mode + // to ensure that this mode behaves similar for higher + // layers. Note this does not work with 5% mode + // correctly, but simplified mode does not support HLC + // anyway. + if (!last_pwm_running && ev_simplified_mode) { + events.push(CPEvent::CarRequestedPower); + } + } + break; + + case RawCPState::E: + connector_unlock(); + if (last_cp_state != RawCPState::E) { + timeout_state_c1.stop(); + call_allow_power_on_bsp(false); + } + break; + + case RawCPState::F: + connector_unlock(); + timeout_state_c1.stop(); + call_allow_power_on_bsp(false); + break; + } + + last_cp_state = cp_state; + last_pwm_running = pwm_running; + last_power_on_allowed = power_on_allowed; + + return events; +} + +// High level state machine sets PWM duty cycle +void IECStateMachine::set_pwm(double value) { + { + std::scoped_lock lock(state_machine_mutex); + if (value > 0 && value < 1) { + pwm_running = true; + } else { + pwm_running = false; + } + } + + r_bsp->call_pwm_on(value * 100); + feed_state_machine(); +} + +// High level state machine sets state X1 +void IECStateMachine::set_pwm_off() { + { + std::scoped_lock lock(state_machine_mutex); + pwm_running = false; + } + r_bsp->call_pwm_off(); + feed_state_machine(); +} + +// High level state machine sets state F +void IECStateMachine::set_pwm_F() { + { + std::scoped_lock lock(state_machine_mutex); + pwm_running = false; + } + r_bsp->call_pwm_F(); + feed_state_machine(); +} + +// The higher level state machine in Charger.cpp calls this to indicate it allows contactors to be switched on +void IECStateMachine::allow_power_on(bool value, types::evse_board_support::Reason reason) { + { + std::scoped_lock lock(state_machine_mutex); + // Only set the flags here in case of power on. + power_on_allowed = value; + power_on_reason = reason; + // In case of power off, we can directly forward this to the BSP driver here + if (not power_on_allowed) { + call_allow_power_on_bsp(false); + } + } + // The actual power on will be handled in the state machine to verify it is in the correct CP state etc. + feed_state_machine(); +} + +// Private member function used to actually call the BSP driver's allow_power_on +// No need to lock mutex as this will be called from state machine or locked context only +void IECStateMachine::call_allow_power_on_bsp(bool value) { + if (not value) { + power_on_allowed = false; + power_on_reason = types::evse_board_support::Reason::PowerOff; + } + r_bsp->call_allow_power_on({value, power_on_reason}); +} + +// High level state machine requests reading PP ampacity value. +// We forward this request to the BSP driver. The high level state machine will never call this if it is not used +// (e.g. in DC or AC tethered charging) +double IECStateMachine::read_pp_ampacity() { + auto a = r_bsp->call_ac_read_pp_ampacity(); + switch (a.ampacity) { + case types::board_support_common::Ampacity::A_13: + return 13.; + case types::board_support_common::Ampacity::A_20: + return 20.; + case types::board_support_common::Ampacity::A_32: + return 32.; + case types::board_support_common::Ampacity::A_63_3ph_70_1ph: + if (three_phases) { + return 63.; + } else { + return 70.; + } + default: + return 0.; + } +} + +// Forward special replug request. Only for testing setups. +void IECStateMachine::evse_replug(int ms) { + r_bsp->call_evse_replug(ms); +} + +// Forward special request to switch the number of phases during charging. BSP will need to implement a special +// sequence to not destroy cars. +void IECStateMachine::switch_three_phases_while_charging(bool n) { + r_bsp->call_ac_switch_three_phases_while_charging(n); +} + +// Forwards config parameters from EvseManager module config to BSP +void IECStateMachine::setup(bool three_phases, bool has_ventilation, std::string country_code) { + r_bsp->call_setup(three_phases, has_ventilation, country_code); + this->has_ventilation = has_ventilation; + this->three_phases = three_phases; +} + +// enable/disable the charging port and CP signal +void IECStateMachine::enable(bool en) { + enabled = en; + r_bsp->call_enable(en); +} + +// Forward the over current detection limit to the BSP. Many BSP MCUs monitor the charge current and trigger a fault +// in case of over current. This sets the target charging current value to be used in OC detection. It cannot be +// derived from the PWM duty cycle, use this value instead. +void IECStateMachine::set_overcurrent_limit(double amps) { + if (amps != last_amps) { + r_bsp->call_ac_set_overcurrent_limit_A(amps); + last_amps = amps; + } +} + +void IECStateMachine::connector_lock() { + if (not locked) { + signal_lock(); + locked = true; + } +} + +void IECStateMachine::connector_unlock() { + if (locked) { + signal_unlock(); + locked = false; + } +} + +} // namespace module diff --git a/modules/EvseManager/IECStateMachine.hpp b/modules/EvseManager/IECStateMachine.hpp new file mode 100644 index 0000000000..83e8a8c3cd --- /dev/null +++ b/modules/EvseManager/IECStateMachine.hpp @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2023 Pionix GmbH and Contributors to EVerest + +/* + The IECStateMachine class provides an adapter between the board support package driver (in a seperate module) and the + high level state machine in Charger.cpp. + + Typically the CP signal generation/reading and control of contactors/RCD etc is handled by a dedicated MCU. This MCU + and/or the HW is responsible for the basic electrical safety of the system (such as safely shut down in case of RCD + trigger or Linux crashing). The BSP driver is just a simple HW abstraction layer that translates the commands for + setting PWM duty cycle/allow contactors on as well as the CP signal readings/error conditions into the everest world. + It should not need to implement any logic or understanding of the IEC61851-1 or any higher protocol. + + This IECStateMachine is the low level state machine translating the IEC61851-1 CP states ABCDEF into more useful + abstract events such as "CarPluggedIn/CarRequestedPower" etc. These events drive the high level state machine in + Charger.cpp which handles the actual charging session and coordinates IEC/ISO/SLAC. + +*/ + +#ifndef SRC_BSP_STATE_MACHINE_H_ +#define SRC_BSP_STATE_MACHINE_H_ + +#include "ld-ev.hpp" + +#include +#include +#include + +#include +#include + +#include "Timeout.hpp" +#include "utils/thread.hpp" + +namespace module { + +// Abstract events that drive the higher level state machine in Charger.cpp +enum class CPEvent { + CarPluggedIn, + CarRequestedPower, + PowerOn, + PowerOff, + CarRequestedStopPower, + CarUnplugged, + EFtoBCD, + BCDtoEF, + EvseReplugStarted, + EvseReplugFinished, +}; + +// Just a helper for log printing +const std::string cpevent_to_string(CPEvent e); + +// Raw (valid) CP states for the IECStateMachine +enum class RawCPState { + Disabled, + A, + B, + C, + D, + E, + F +}; + +class IECStateMachine { +public: + // We need the r_bsp reference to be able to talk to the bsp driver module + explicit IECStateMachine(const std::unique_ptr& r_bsp); + + // Call when new events from BSP requirement come in. Will signal internal events + void process_bsp_event(const types::board_support_common::BspEvent bsp_event); + // Allow power on from Charger state machine + void allow_power_on(bool value, types::evse_board_support::Reason reason); + + double read_pp_ampacity(); + void evse_replug(int ms); + void switch_three_phases_while_charging(bool n); + void setup(bool three_phases, bool has_ventilation, std::string country_code); + + void set_overcurrent_limit(double amps); + + void set_pwm(double value); + void set_pwm_off(); + void set_pwm_F(); + + void enable(bool en); + + void connector_lock(); + void connector_unlock(); + + // Signal for internal events type + sigslot::signal signal_event; + sigslot::signal<> signal_lock; + sigslot::signal<> signal_unlock; + +private: + const std::unique_ptr& r_bsp; + + bool pwm_running{false}; + bool last_pwm_running{false}; + + bool ev_simplified_mode{false}; + bool has_ventilation{false}; + bool power_on_allowed{false}; + bool last_power_on_allowed{false}; + std::atomic last_amps{-1}; + + bool car_plugged_in{false}; + + RawCPState cp_state{RawCPState::Disabled}, last_cp_state{RawCPState::Disabled}; + AsyncTimeout timeout_state_c1; + + std::mutex state_machine_mutex; + void feed_state_machine(); + std::queue state_machine(); + + types::evse_board_support::Reason power_on_reason{types::evse_board_support::Reason::PowerOff}; + void call_allow_power_on_bsp(bool value); + + std::atomic_bool three_phases{true}; + std::atomic_bool locked{false}; + + std::atomic_bool enabled{false}; +}; + +} // namespace module + +#endif // SRC_BSP_STATE_MACHINE_H_ diff --git a/modules/EvseManager/Timeout.hpp b/modules/EvseManager/Timeout.hpp index 77d5d36a39..0e98972378 100644 --- a/modules/EvseManager/Timeout.hpp +++ b/modules/EvseManager/Timeout.hpp @@ -4,27 +4,106 @@ #define TIMEOUT_HPP #include +#include + +#include "utils/thread.hpp" + using namespace std::chrono; /* - Simple helper class for a timeout + Simple helper class for a polling timeout */ class Timeout { public: - explicit Timeout(milliseconds _t) : t(_t), start(steady_clock::now()) { + void start(milliseconds _t) { + t = _t; + start_time = steady_clock::now(); + running = true; + } + + void stop() { + running = false; + } + + bool is_running() { + return running; } bool reached() { - if ((steady_clock::now() - start) > t) + if (!running) + return false; + if ((steady_clock::now() - start_time) > t) { + running = false; return true; - else + } else { return false; + } } private: milliseconds t; - time_point start; + time_point start_time; + bool running{false}; +}; + +/* Simple helper class for a timeout with internal thread */ +class AsyncTimeout { +public: + void start(milliseconds _t) { + if (running) { + stop(); + } + t = _t; + start_time = steady_clock::now(); + running = true; + // start waiting thread + wait_thread = std::thread([this]() { + while (not wait_thread.shouldExit()) { + std::this_thread::sleep_for(resolution); + if (reached()) { + // Note the order is important here. + // We first signal reached which will call all callbacks. + // The timer is still running in this in those callbacks, so they can also call reached() and get a + // true as return value. + signal_reached(); + // After all signal handlers are called, we stop the timer. + running = false; + return; + } + } + }); + } + + // Note that stopping the timer may take up to "resolution" amount of time to return + void stop() { + wait_thread.stop(); + running = false; + } + + bool is_running() { + return running; + } + + bool reached() { + if (!running) { + return false; + } + if ((steady_clock::now() - start_time) > t) { + return true; + } else { + return false; + } + } + + sigslot::signal<> signal_reached; + +private: + constexpr static auto resolution = 500ms; + milliseconds t; + time_point start_time; + std::atomic_bool running{false}; + Everest::Thread wait_thread; }; #endif diff --git a/modules/EvseManager/energy_grid/energyImpl.hpp b/modules/EvseManager/energy_grid/energyImpl.hpp index 95928d6e52..d0e2101269 100644 --- a/modules/EvseManager/energy_grid/energyImpl.hpp +++ b/modules/EvseManager/energy_grid/energyImpl.hpp @@ -58,7 +58,7 @@ class energyImpl : public energyImplBase { void clear_export_request_schedule(); void clear_request_schedules(); void request_energy_from_energy_manager(); - types::board_support::HardwareCapabilities hw_caps; + types::evse_board_support::HardwareCapabilities hw_caps; // ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1 }; diff --git a/modules/EvseManager/evse/evse_managerImpl.cpp b/modules/EvseManager/evse/evse_managerImpl.cpp index 8da41e77e9..84efbe2338 100644 --- a/modules/EvseManager/evse/evse_managerImpl.cpp +++ b/modules/EvseManager/evse/evse_managerImpl.cpp @@ -106,10 +106,10 @@ void evse_managerImpl::ready() { } }); - mod->r_bsp->subscribe_telemetry([this](types::board_support::Telemetry telemetry) { + mod->r_bsp->subscribe_telemetry([this](types::evse_board_support::Telemetry telemetry) { // external Nodered interface mod->mqtt.publish(fmt::format("everest_external/nodered/{}/state/temperature", mod->config.connector_id), - telemetry.temperature); + telemetry.evse_temperature_C); // /external Nodered interface publish_telemetry(telemetry); }); @@ -245,7 +245,8 @@ void evse_managerImpl::ready() { se.transaction_finished.emplace(transaction_finished); } else if (e == types::evse_manager::SessionEventEnum::Error) { types::evse_manager::Error error; - error.error_code = mod->charger->getErrorState(); + // FIXME this should report something useful instead! + error.error_code = types::evse_manager::ErrorEnum::Other; se.error = error; } else if (e == types::evse_manager::SessionEventEnum::Enabled or e == types::evse_manager::SessionEventEnum::Disabled) { @@ -281,13 +282,6 @@ void evse_managerImpl::ready() { mod->mqtt.publish(fmt::format("everest_external/nodered/{}/state/state", mod->config.connector_id), static_cast(s)); }); - - mod->charger->signalError.connect([this](types::evse_manager::ErrorEnum s) { - mod->mqtt.publish(fmt::format("everest_external/nodered/{}/state/error_type", mod->config.connector_id), - static_cast(s)); - mod->mqtt.publish(fmt::format("everest_external/nodered/{}/state/error_string", mod->config.connector_id), - types::evse_manager::error_enum_to_string(s)); - }); // /Deprecated } @@ -364,10 +358,6 @@ bool evse_managerImpl::handle_stop_transaction(types::evse_manager::StopTransact return mod->charger->cancelTransaction(request); }; -bool evse_managerImpl::handle_force_unlock(int& connector_id) { - return mod->charger->forceUnlock(); -}; - std::string evse_managerImpl::generate_session_uuid() { return boost::uuids::to_string(boost::uuids::random_generator()()); } @@ -405,5 +395,10 @@ bool evse_managerImpl::handle_external_ready_to_start_charging() { return false; } +bool evse_managerImpl::handle_force_unlock(int& connector_id) { + mod->bsp->connector_unlock(); + return true; +}; + } // namespace evse } // namespace module diff --git a/modules/EvseManager/manifest.yaml b/modules/EvseManager/manifest.yaml index b694eceaf6..d014e53868 100644 --- a/modules/EvseManager/manifest.yaml +++ b/modules/EvseManager/manifest.yaml @@ -54,10 +54,6 @@ config: description: Country Code type: string default: DE - rcd_enabled: - description: Enable or disable RCD - type: boolean - default: true max_current_import_A: description: User configurable current limit for this EVSE in Ampere type: number @@ -133,13 +129,6 @@ config: Set to 0 unless you really know what you are doing. type: integer default: 0 - connector_type: - description: Type of charging connector available at this EVSE - type: string - enum: - - IEC62196Type2Cable - - IEC62196Type2Socket - default: IEC62196Type2Cable hack_pause_imd_during_precharge: description: >- Disable IMD at the end of CableCheck and re-enable when current is flowing in CurrentDemand. @@ -218,7 +207,15 @@ provides: interface: auth_token_provider requires: bsp: - interface: board_support_AC + interface: evse_board_support + ac_rcd: + interface: ac_rcd + min_connections: 0 + max_connections: 1 + connector_lock: + interface: connector_lock + min_connections: 0 + max_connections: 1 powermeter_grid_side: interface: powermeter min_connections: 0 diff --git a/modules/MicroMegaWattBSP/CMakeLists.txt b/modules/MicroMegaWattBSP/CMakeLists.txt index 16bcfbecae..bd4c41b3ef 100644 --- a/modules/MicroMegaWattBSP/CMakeLists.txt +++ b/modules/MicroMegaWattBSP/CMakeLists.txt @@ -28,7 +28,7 @@ target_sources(${MODULE_NAME} PRIVATE "dc_supply/power_supply_DCImpl.cpp" "powermeter/powermeterImpl.cpp" - "board_support/board_support_ACImpl.cpp" + "board_support/evse_board_supportImpl.cpp" ) # ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1 diff --git a/modules/MicroMegaWattBSP/MicroMegaWattBSP.hpp b/modules/MicroMegaWattBSP/MicroMegaWattBSP.hpp index c8f5b61c2f..d6ea3c4cf5 100644 --- a/modules/MicroMegaWattBSP/MicroMegaWattBSP.hpp +++ b/modules/MicroMegaWattBSP/MicroMegaWattBSP.hpp @@ -11,7 +11,7 @@ #include "ld-ev.hpp" // headers for provided interface implementations -#include +#include #include #include @@ -35,7 +35,7 @@ class MicroMegaWattBSP : public Everest::ModuleBase { MicroMegaWattBSP(const ModuleInfo& info, Everest::MqttProvider& mqtt_provider, std::unique_ptr p_dc_supply, std::unique_ptr p_powermeter, - std::unique_ptr p_board_support, Conf& config) : + std::unique_ptr p_board_support, Conf& config) : ModuleBase(info), mqtt(mqtt_provider), p_dc_supply(std::move(p_dc_supply)), @@ -46,7 +46,7 @@ class MicroMegaWattBSP : public Everest::ModuleBase { Everest::MqttProvider& mqtt; const std::unique_ptr p_dc_supply; const std::unique_ptr p_powermeter; - const std::unique_ptr p_board_support; + const std::unique_ptr p_board_support; const Conf& config; // ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1 diff --git a/modules/MicroMegaWattBSP/board_support/board_support_ACImpl.cpp b/modules/MicroMegaWattBSP/board_support/board_support_ACImpl.cpp deleted file mode 100644 index 9524a6963b..0000000000 --- a/modules/MicroMegaWattBSP/board_support/board_support_ACImpl.cpp +++ /dev/null @@ -1,123 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright Pionix GmbH and Contributors to EVerest - -#include "board_support_ACImpl.hpp" - -namespace module { -namespace board_support { - -static types::board_support::Event cast_event_type(const Event& e) { - switch (e.type) { - case Event_InterfaceEvent_CAR_PLUGGED_IN: - return types::board_support::Event::CarPluggedIn; - case Event_InterfaceEvent_CAR_REQUESTED_POWER: - return types::board_support::Event::CarRequestedPower; - case Event_InterfaceEvent_POWER_ON: - return types::board_support::Event::PowerOn; - case Event_InterfaceEvent_POWER_OFF: - return types::board_support::Event::PowerOff; - case Event_InterfaceEvent_CAR_REQUESTED_STOP_POWER: - return types::board_support::Event::CarRequestedStopPower; - case Event_InterfaceEvent_CAR_UNPLUGGED: - return types::board_support::Event::CarUnplugged; - case Event_InterfaceEvent_ERROR_E: - return types::board_support::Event::ErrorE; - case Event_InterfaceEvent_ERROR_DF: - return types::board_support::Event::ErrorDF; - case Event_InterfaceEvent_ERROR_RELAIS: - return types::board_support::Event::ErrorRelais; - case Event_InterfaceEvent_ERROR_RCD: - return types::board_support::Event::ErrorRCD; - case Event_InterfaceEvent_ERROR_VENTILATION_NOT_AVAILABLE: - return types::board_support::Event::ErrorVentilationNotAvailable; - case Event_InterfaceEvent_ERROR_OVER_CURRENT: - return types::board_support::Event::ErrorOverCurrent; - case Event_InterfaceEvent_ENTER_BCD: - return types::board_support::Event::EFtoBCD; - case Event_InterfaceEvent_LEAVE_BCD: - return types::board_support::Event::BCDtoEF; - case Event_InterfaceEvent_PERMANENT_FAULT: - return types::board_support::Event::PermanentFault; - case Event_InterfaceEvent_EVSE_REPLUG_STARTED: - return types::board_support::Event::EvseReplugStarted; - case Event_InterfaceEvent_EVSE_REPLUG_FINISHED: - return types::board_support::Event::EvseReplugFinished; - } - - EVLOG_error << "Received an unknown interface event from uMWC: " << (int)e.type; - return types::board_support::Event::ErrorVentilationNotAvailable; -} - -void board_support_ACImpl::init() { - { - std::lock_guard lock(capsMutex); - - caps.min_current_A_import = 0; - caps.max_current_A_import = 6; - caps.min_phase_count_import = 1; - caps.max_phase_count_import = 3; - caps.supports_changing_phases_during_charging = false; - - caps.min_current_A_export = 0; - caps.max_current_A_export = 6; - caps.min_phase_count_export = 1; - caps.max_phase_count_export = 3; - } - - mod->serial.signalEvent.connect([this](Event e) { - EVLOG_info << "CP EVENT: " << types::board_support::event_to_string(cast_event_type(e)); - publish_event(cast_event_type(e)); - }); -} - -void board_support_ACImpl::ready() { -} - -void board_support_ACImpl::handle_setup(bool& three_phases, bool& has_ventilation, std::string& country_code, - bool& rcd_enabled){}; - -types::board_support::HardwareCapabilities board_support_ACImpl::handle_get_hw_capabilities() { - std::lock_guard lock(capsMutex); - return caps; -}; - -void board_support_ACImpl::handle_enable(bool& value) { - if (value) - mod->serial.enable(); - else - mod->serial.disable(); -}; - -void board_support_ACImpl::handle_pwm_on(double& value) { - mod->serial.setPWM(1, value); -}; - -void board_support_ACImpl::handle_pwm_off() { - mod->serial.setPWM(0, 0.); -}; - -void board_support_ACImpl::handle_pwm_F() { - mod->serial.setPWM(2, 0.); -}; - -void board_support_ACImpl::handle_allow_power_on(bool& value) { - mod->serial.allowPowerOn(value); -}; - -bool board_support_ACImpl::handle_force_unlock() { - return true; -}; - -void board_support_ACImpl::handle_switch_three_phases_while_charging(bool& value){}; - -void board_support_ACImpl::handle_evse_replug(int& value) { - mod->serial.replug(value); -}; - -double board_support_ACImpl::handle_read_pp_ampacity() { - std::lock_guard lock(capsMutex); - return caps.max_current_A_import; -}; - -} // namespace board_support -} // namespace module diff --git a/modules/MicroMegaWattBSP/board_support/evse_board_supportImpl.cpp b/modules/MicroMegaWattBSP/board_support/evse_board_supportImpl.cpp new file mode 100644 index 0000000000..f1a3949015 --- /dev/null +++ b/modules/MicroMegaWattBSP/board_support/evse_board_supportImpl.cpp @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest + +#include "evse_board_supportImpl.hpp" + +namespace module { +namespace board_support { + +/* + + +static types::board_support::Event cast_event_type(const Event& e) { +switch (e.type) { +case Event_InterfaceEvent_CAR_PLUGGED_IN: + return types::board_support::Event::CarPluggedIn; +case Event_InterfaceEvent_CAR_REQUESTED_POWER: + return types::board_support::Event::CarRequestedPower; +case Event_InterfaceEvent_POWER_ON: + return types::board_support::Event::PowerOn; +case Event_InterfaceEvent_POWER_OFF: + return types::board_support::Event::PowerOff; +case Event_InterfaceEvent_CAR_REQUESTED_STOP_POWER: + return types::board_support::Event::CarRequestedStopPower; +case Event_InterfaceEvent_CAR_UNPLUGGED: + return types::board_support::Event::CarUnplugged; +case Event_InterfaceEvent_ERROR_E: + return types::board_support::Event::ErrorE; +case Event_InterfaceEvent_ERROR_DF: + return types::board_support::Event::ErrorDF; +case Event_InterfaceEvent_ERROR_RELAIS: + return types::board_support::Event::ErrorRelais; +case Event_InterfaceEvent_ERROR_RCD: + return types::board_support::Event::ErrorRCD; +case Event_InterfaceEvent_ERROR_VENTILATION_NOT_AVAILABLE: + return types::board_support::Event::ErrorVentilationNotAvailable; +case Event_InterfaceEvent_ERROR_OVER_CURRENT: + return types::board_support::Event::ErrorOverCurrent; +case Event_InterfaceEvent_ENTER_BCD: + return types::board_support::Event::EFtoBCD; +case Event_InterfaceEvent_LEAVE_BCD: + return types::board_support::Event::BCDtoEF; +case Event_InterfaceEvent_PERMANENT_FAULT: + return types::board_support::Event::PermanentFault; +case Event_InterfaceEvent_EVSE_REPLUG_STARTED: + return types::board_support::Event::EvseReplugStarted; +case Event_InterfaceEvent_EVSE_REPLUG_FINISHED: + return types::board_support::Event::EvseReplugFinished; +} + +EVLOG_error << "Received an unknown interface event from uMWC: " << (int)e.type; +return types::board_support::Event::ErrorVentilationNotAvailable; +} +*/ + +void evse_board_supportImpl::init() { + { + std::lock_guard lock(capsMutex); + + caps.min_current_A_import = 0; + caps.max_current_A_import = 6; + caps.min_phase_count_import = 1; + caps.max_phase_count_import = 3; + caps.supports_changing_phases_during_charging = false; + + caps.min_current_A_export = 0; + caps.max_current_A_export = 6; + caps.min_phase_count_export = 1; + caps.max_phase_count_export = 3; + } + + /* mod->serial.signalEvent.connect([this](Event e) { + EVLOG_info << "CP EVENT: " << types::board_support::event_to_string(cast_event_type(e)); + publish_event(cast_event_type(e)); + });*/ +} + +void evse_board_supportImpl::ready() { +} + +void evse_board_supportImpl::handle_setup(bool& three_phases, bool& has_ventilation, std::string& country_code) { + // your code for cmd setup goes here +} + +types::evse_board_support::HardwareCapabilities evse_board_supportImpl::handle_get_hw_capabilities() { + std::lock_guard lock(capsMutex); + return caps; +} + +void evse_board_supportImpl::handle_enable(bool& value) { + mod->serial.enable(value); +} + +void evse_board_supportImpl::handle_pwm_on(double& value) { + mod->serial.setPWM(value * 100); +} + +void evse_board_supportImpl::handle_pwm_off() { + mod->serial.setPWM(10001.); +} + +void evse_board_supportImpl::handle_pwm_F() { + mod->serial.setPWM(0); +} + +void evse_board_supportImpl::handle_allow_power_on(types::evse_board_support::PowerOnOff& value) { + mod->serial.allowPowerOn(value.allow_power_on); +} + +void evse_board_supportImpl::handle_ac_switch_three_phases_while_charging(bool& value) { + // your code for cmd ac_switch_three_phases_while_charging goes here +} + +void evse_board_supportImpl::handle_evse_replug(int& value) { + mod->serial.replug(); +} + +types::board_support_common::ProximityPilot evse_board_supportImpl::handle_ac_read_pp_ampacity() { + return {types::board_support_common::Ampacity::A_13}; +} + +void evse_board_supportImpl::handle_ac_set_overcurrent_limit_A(double& value) { + // your code for cmd ac_set_overcurrent_limit_A goes here +} + +} // namespace board_support +} // namespace module diff --git a/modules/MicroMegaWattBSP/board_support/board_support_ACImpl.hpp b/modules/MicroMegaWattBSP/board_support/evse_board_supportImpl.hpp similarity index 58% rename from modules/MicroMegaWattBSP/board_support/board_support_ACImpl.hpp rename to modules/MicroMegaWattBSP/board_support/evse_board_supportImpl.hpp index 8e89dc0823..c149ac48e3 100644 --- a/modules/MicroMegaWattBSP/board_support/board_support_ACImpl.hpp +++ b/modules/MicroMegaWattBSP/board_support/evse_board_supportImpl.hpp @@ -1,14 +1,14 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright Pionix GmbH and Contributors to EVerest -#ifndef BOARD_SUPPORT_BOARD_SUPPORT_AC_IMPL_HPP -#define BOARD_SUPPORT_BOARD_SUPPORT_AC_IMPL_HPP +#ifndef BOARD_SUPPORT_EVSE_BOARD_SUPPORT_IMPL_HPP +#define BOARD_SUPPORT_EVSE_BOARD_SUPPORT_IMPL_HPP // // AUTO GENERATED - MARKED REGIONS WILL BE KEPT // template version 3 // -#include +#include #include "../MicroMegaWattBSP.hpp" @@ -21,11 +21,12 @@ namespace board_support { struct Conf {}; -class board_support_ACImpl : public board_support_ACImplBase { +class evse_board_supportImpl : public evse_board_supportImplBase { public: - board_support_ACImpl() = delete; - board_support_ACImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer& mod, Conf& config) : - board_support_ACImplBase(ev, "board_support"), mod(mod), config(config){}; + evse_board_supportImpl() = delete; + evse_board_supportImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer& mod, + Conf& config) : + evse_board_supportImplBase(ev, "board_support"), mod(mod), config(config){}; // ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1 // insert your public definitions here @@ -33,18 +34,17 @@ class board_support_ACImpl : public board_support_ACImplBase { protected: // command handler functions (virtual) - virtual void handle_setup(bool& three_phases, bool& has_ventilation, std::string& country_code, - bool& rcd_enabled) override; - virtual types::board_support::HardwareCapabilities handle_get_hw_capabilities() override; + virtual void handle_setup(bool& three_phases, bool& has_ventilation, std::string& country_code) override; + virtual types::evse_board_support::HardwareCapabilities handle_get_hw_capabilities() override; virtual void handle_enable(bool& value) override; virtual void handle_pwm_on(double& value) override; virtual void handle_pwm_off() override; virtual void handle_pwm_F() override; - virtual void handle_allow_power_on(bool& value) override; - virtual bool handle_force_unlock() override; - virtual void handle_switch_three_phases_while_charging(bool& value) override; + virtual void handle_allow_power_on(types::evse_board_support::PowerOnOff& value) override; + virtual void handle_ac_switch_three_phases_while_charging(bool& value) override; virtual void handle_evse_replug(int& value) override; - virtual double handle_read_pp_ampacity() override; + virtual types::board_support_common::ProximityPilot handle_ac_read_pp_ampacity() override; + virtual void handle_ac_set_overcurrent_limit_A(double& value) override; // ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1 // insert your protected definitions here @@ -59,7 +59,7 @@ class board_support_ACImpl : public board_support_ACImplBase { // ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1 // insert your private definitions here - types::board_support::HardwareCapabilities caps; + types::evse_board_support::HardwareCapabilities caps; std::mutex capsMutex; // ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1 }; @@ -71,4 +71,4 @@ class board_support_ACImpl : public board_support_ACImplBase { } // namespace board_support } // namespace module -#endif // BOARD_SUPPORT_BOARD_SUPPORT_AC_IMPL_HPP +#endif // BOARD_SUPPORT_EVSE_BOARD_SUPPORT_IMPL_HPP diff --git a/modules/MicroMegaWattBSP/manifest.yaml b/modules/MicroMegaWattBSP/manifest.yaml index 5ddfb65f6f..b32d4d542e 100644 --- a/modules/MicroMegaWattBSP/manifest.yaml +++ b/modules/MicroMegaWattBSP/manifest.yaml @@ -30,7 +30,7 @@ provides: interface: powermeter description: provides the Yeti Internal Power Meter board_support: - interface: board_support_AC + interface: evse_board_support description: provides the board support Interface to low level control control pilot, relais, rcd, motor lock enable_external_mqtt: true metadata: diff --git a/modules/MicroMegaWattBSP/umwc_comms/CMakeLists.txt b/modules/MicroMegaWattBSP/umwc_comms/CMakeLists.txt index 4146174df8..395eda75ea 100644 --- a/modules/MicroMegaWattBSP/umwc_comms/CMakeLists.txt +++ b/modules/MicroMegaWattBSP/umwc_comms/CMakeLists.txt @@ -6,8 +6,6 @@ project(umwc_comms VERSION 0.1) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED True) - -configure_file(config.h.in config.h) set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) @@ -16,8 +14,7 @@ add_library(umwc_comms STATIC) target_sources(umwc_comms PRIVATE evSerial.cpp - protobuf/hi2lo.pb.c - protobuf/lo2hi.pb.c + protobuf/umwc.pb.c ) target_include_directories(umwc_comms diff --git a/modules/MicroMegaWattBSP/umwc_comms/config.h.in b/modules/MicroMegaWattBSP/umwc_comms/config.h.in deleted file mode 100644 index 4b96d6dfff..0000000000 --- a/modules/MicroMegaWattBSP/umwc_comms/config.h.in +++ /dev/null @@ -1,3 +0,0 @@ -// the configured options and settings for YetiDriver -#define YetiComms_VERSION_MAJOR @YetiComms_VERSION_MAJOR@ -#define YetiComms_VERSION_MINOR @YetiComms_VERSION_MINOR@ diff --git a/modules/MicroMegaWattBSP/umwc_comms/evSerial.cpp b/modules/MicroMegaWattBSP/umwc_comms/evSerial.cpp index 56ded825cb..d758200a1c 100644 --- a/modules/MicroMegaWattBSP/umwc_comms/evSerial.cpp +++ b/modules/MicroMegaWattBSP/umwc_comms/evSerial.cpp @@ -18,8 +18,7 @@ #include #include -#include "hi2lo.pb.h" -#include "lo2hi.pb.h" +#include "umwc.pb.h" evSerial::evSerial() { fd = 0; @@ -133,7 +132,6 @@ void evSerial::handlePacket(uint8_t* buf, int len) { // printf ("packet received len %u\n", len); // Check CRC32 (last 4 bytes) - // uint32_t crc = calculateCrc(rx_packet_buf, rx_packet_len); if (crc32(buf, len)) { printf("CRC mismatch\n"); return; @@ -141,33 +139,41 @@ void evSerial::handlePacket(uint8_t* buf, int len) { len -= 4; - LoToHi msg_in; + McuToEverest msg_in; pb_istream_t istream = pb_istream_from_buffer(buf, len); - if (pb_decode(&istream, LoToHi_fields, &msg_in)) + if (pb_decode(&istream, McuToEverest_fields, &msg_in)) switch (msg_in.which_payload) { - case LoToHi_keep_alive_tag: + case McuToEverest_keep_alive_tag: // printf("Received keep_alive_lo\n"); signalKeepAliveLo(msg_in.payload.keep_alive); // detect connection timeout if keep_alive packets stop coming... last_keep_alive_lo_timestamp = date::utc_clock::now(); break; - case LoToHi_power_meter_tag: + case McuToEverest_power_meter_tag: // printf("Received power_meter %i\n", (int)(msg_in.payload.power_meter.voltage)); signalPowerMeter(msg_in.payload.power_meter); break; - case LoToHi_event_tag: - // printf("Received event %i\n", msg_in.payload.event); - signalEvent(msg_in.payload.event); - break; - case LoToHi_telemetry_tag: + case McuToEverest_telemetry_tag: /*printf("Received telemetry cp_hi %f cp_lo %f relais_on %i pwm_dc %f\n", msg_in.payload.telemetry.cp_hi, msg_in.payload.telemetry.cp_lo, (int)msg_in.payload.telemetry.relais_on, msg_in.payload.telemetry.pwm_dc);*/ signalTelemetry(msg_in.payload.telemetry); break; - case LoToHi_reset_done_tag: + case McuToEverest_cp_state_tag: + signalCPState(msg_in.payload.cp_state); + break; + case McuToEverest_pp_state_tag: + signalPPState(msg_in.payload.pp_state); + break; + case McuToEverest_relais_state_tag: + signalRelaisState(msg_in.payload.relais_state); + break; + case McuToEverest_error_flags_tag: + signalErrorFlags(msg_in.payload.error_flags); + break; + case McuToEverest_reset_tag: // printf("Received reset_done\n"); reset_done_flag = true; if (!forced_reset) @@ -248,11 +254,11 @@ void evSerial::readThread() { } } -bool evSerial::linkWrite(HiToLo* m) { +bool evSerial::linkWrite(EverestToMcu* m) { uint8_t tx_packet_buf[1024]; uint8_t encode_buf[1500]; pb_ostream_t ostream = pb_ostream_from_buffer(tx_packet_buf, sizeof(tx_packet_buf) - 4); - bool status = pb_encode(&ostream, HiToLo_fields, m); + bool status = pb_encode(&ostream, EverestToMcu_fields, m); if (!status) { // couldn't encode @@ -309,50 +315,43 @@ bool evSerial::serial_timed_out() { return false; } -void evSerial::setPWM(uint32_t mode, float dc) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_set_pwm_tag; - msg_out.payload.set_pwm.mode = mode; - msg_out.payload.set_pwm.duty_cycle = dc; +void evSerial::setPWM(uint32_t dc) { + EverestToMcu msg_out = EverestToMcu_init_default; + msg_out.which_payload = EverestToMcu_pwm_duty_cycle_tag; + msg_out.payload.pwm_duty_cycle = dc; linkWrite(&msg_out); } void evSerial::allowPowerOn(bool p) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_allow_power_on_tag; - msg_out.payload.allow_power_on.p = p; - linkWrite(&msg_out); -} - -void evSerial::enable() { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_enable_tag; + EverestToMcu msg_out = EverestToMcu_init_default; + msg_out.which_payload = EverestToMcu_allow_power_on_tag; + msg_out.payload.allow_power_on = p; linkWrite(&msg_out); } -void evSerial::disable() { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_disable_tag; +void evSerial::enable(bool en) { + EverestToMcu msg_out = EverestToMcu_init_default; + msg_out.which_payload = EverestToMcu_enable_tag; + msg_out.payload.enable = en; linkWrite(&msg_out); } -void evSerial::replug(int t) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_replug_tag; - msg_out.payload.replug.time = t; +void evSerial::replug() { + EverestToMcu msg_out = EverestToMcu_init_default; + msg_out.which_payload = EverestToMcu_replug_tag; linkWrite(&msg_out); } void evSerial::firmwareUpdate(bool rom) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_firmware_update_tag; + EverestToMcu msg_out = EverestToMcu_init_default; + msg_out.which_payload = EverestToMcu_firmware_update_tag; msg_out.payload.firmware_update.invoke_rom_bootloader = rom; linkWrite(&msg_out); } void evSerial::setOutputVoltageCurrent(float v, float c) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_set_output_voltage_current_tag; + EverestToMcu msg_out = EverestToMcu_init_default; + msg_out.which_payload = EverestToMcu_set_output_voltage_current_tag; msg_out.payload.set_output_voltage_current.voltage = v; msg_out.payload.set_output_voltage_current.current = c; linkWrite(&msg_out); @@ -376,8 +375,8 @@ bool evSerial::reset(const int reset_pin) { system(cmd); } else { // Try to soft reset Yeti controller to be in a known state - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_reset_tag; + EverestToMcu msg_out = EverestToMcu_init_default; + msg_out.which_payload = EverestToMcu_reset_tag; linkWrite(&msg_out); } @@ -405,13 +404,11 @@ bool evSerial::reset(const int reset_pin) { } void evSerial::keepAlive() { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_keep_alive_tag; + EverestToMcu msg_out = EverestToMcu_init_default; + msg_out.which_payload = EverestToMcu_keep_alive_tag; msg_out.payload.keep_alive.time_stamp = 0; msg_out.payload.keep_alive.hw_type = 0; msg_out.payload.keep_alive.hw_revision = 0; - msg_out.payload.keep_alive.protocol_version_major = 0; - msg_out.payload.keep_alive.protocol_version_minor = 1; strcpy(msg_out.payload.keep_alive.sw_version_string, "n/a"); linkWrite(&msg_out); } diff --git a/modules/MicroMegaWattBSP/umwc_comms/evSerial.h b/modules/MicroMegaWattBSP/umwc_comms/evSerial.h index 84ad3078bd..befa7d3926 100644 --- a/modules/MicroMegaWattBSP/umwc_comms/evSerial.h +++ b/modules/MicroMegaWattBSP/umwc_comms/evSerial.h @@ -3,8 +3,7 @@ #ifndef YETI_SERIAL #define YETI_SERIAL -#include "hi2lo.pb.h" -#include "lo2hi.pb.h" +#include "umwc.pb.h" #include #include #include @@ -23,22 +22,27 @@ class evSerial { void readThread(); void run(); - void enable(); + void enable(bool en); void disable(); - void replug(int t); + void replug(); bool reset(const int reset_pin); void firmwareUpdate(bool rom); void keepAlive(); - void setPWM(uint32_t mode, float dc); + void setPWM(uint32_t dc); void allowPowerOn(bool p); void setOutputVoltageCurrent(float v, float c); sigslot::signal signalKeepAliveLo; sigslot::signal signalPowerMeter; - sigslot::signal signalEvent; sigslot::signal signalTelemetry; + + sigslot::signal signalCPState; + sigslot::signal signalPPState; + sigslot::signal signalErrorFlags; + sigslot::signal signalRelaisState; + sigslot::signal<> signalSpuriousReset; sigslot::signal<> signalConnectionTimeout; @@ -64,7 +68,7 @@ class evSerial { Everest::Thread readThreadHandle; Everest::Thread timeoutDetectionThreadHandle; - bool linkWrite(HiToLo* m); + bool linkWrite(EverestToMcu* m); volatile bool reset_done_flag; volatile bool forced_reset; diff --git a/modules/MicroMegaWattBSP/umwc_comms/protobuf/generate_nanopb.sh b/modules/MicroMegaWattBSP/umwc_comms/protobuf/generate_nanopb.sh index 2a5aceeba0..9d075a727c 100755 --- a/modules/MicroMegaWattBSP/umwc_comms/protobuf/generate_nanopb.sh +++ b/modules/MicroMegaWattBSP/umwc_comms/protobuf/generate_nanopb.sh @@ -1,2 +1,2 @@ #!/bin/sh -nanopb_generator.py -L "#include " -I . -D . lo2hi.proto hi2lo.proto +nanopb_generator.py -L "#include " -I . -D . umwc.proto diff --git a/modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.options b/modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.options deleted file mode 100644 index 4cee617af8..0000000000 --- a/modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.options +++ /dev/null @@ -1 +0,0 @@ -KeepAliveHi.sw_version_string max_length:50 diff --git a/modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.pb.c b/modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.pb.c deleted file mode 100644 index fccf7fb4ce..0000000000 --- a/modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.pb.c +++ /dev/null @@ -1,39 +0,0 @@ -/* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5 */ - -#include "hi2lo.pb.h" -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -PB_BIND(HiToLo, HiToLo, AUTO) - - -PB_BIND(AllowPowerOn, AllowPowerOn, AUTO) - - -PB_BIND(SetOutputVoltageCurrent, SetOutputVoltageCurrent, AUTO) - - -PB_BIND(SetPWM, SetPWM, AUTO) - - -PB_BIND(FirmwareUpdate, FirmwareUpdate, AUTO) - - -PB_BIND(KeepAliveHi, KeepAliveHi, AUTO) - - -PB_BIND(Replug, Replug, AUTO) - - -PB_BIND(Enable, Enable, AUTO) - - -PB_BIND(Disable, Disable, AUTO) - - -PB_BIND(Reset, Reset, AUTO) - - - diff --git a/modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.pb.h b/modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.pb.h deleted file mode 100644 index 3133cf6e15..0000000000 --- a/modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.pb.h +++ /dev/null @@ -1,238 +0,0 @@ -/* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5 */ - -#ifndef PB_HI2LO_PB_H_INCLUDED -#define PB_HI2LO_PB_H_INCLUDED -#include - -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -/* Struct definitions */ -typedef struct _Disable { - char dummy_field; -} Disable; - -typedef struct _Enable { - char dummy_field; -} Enable; - -typedef struct _Reset { - char dummy_field; -} Reset; - -typedef struct _AllowPowerOn { - bool p; -} AllowPowerOn; - -typedef struct _FirmwareUpdate { - bool invoke_rom_bootloader; -} FirmwareUpdate; - -typedef struct _KeepAliveHi { - uint32_t time_stamp; - uint32_t hw_type; - uint32_t hw_revision; - uint32_t protocol_version_major; - uint32_t protocol_version_minor; - char sw_version_string[51]; -} KeepAliveHi; - -typedef struct _Replug { - uint32_t time; -} Replug; - -typedef struct _SetOutputVoltageCurrent { - float voltage; - float current; -} SetOutputVoltageCurrent; - -typedef struct _SetPWM { - int32_t mode; /* 0: OFF, 1: ON, 2: F */ - float duty_cycle; -} SetPWM; - -/* This container message is send from Hi Level to Low level and may contain any allowed message in that direction. */ -typedef struct _HiToLo { - /* Common/configuration messages */ - pb_size_t which_payload; - union { - Enable enable; - Disable disable; - KeepAliveHi keep_alive; - FirmwareUpdate firmware_update; - SetPWM set_pwm; - AllowPowerOn allow_power_on; - Reset reset; - Replug replug; - SetOutputVoltageCurrent set_output_voltage_current; - } payload; -} HiToLo; - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Initializer values for message structs */ -#define HiToLo_init_default {0, {Enable_init_default}} -#define AllowPowerOn_init_default {0} -#define SetOutputVoltageCurrent_init_default {0, 0} -#define SetPWM_init_default {0, 0} -#define FirmwareUpdate_init_default {0} -#define KeepAliveHi_init_default {0, 0, 0, 0, 0, ""} -#define Replug_init_default {0} -#define Enable_init_default {0} -#define Disable_init_default {0} -#define Reset_init_default {0} -#define HiToLo_init_zero {0, {Enable_init_zero}} -#define AllowPowerOn_init_zero {0} -#define SetOutputVoltageCurrent_init_zero {0, 0} -#define SetPWM_init_zero {0, 0} -#define FirmwareUpdate_init_zero {0} -#define KeepAliveHi_init_zero {0, 0, 0, 0, 0, ""} -#define Replug_init_zero {0} -#define Enable_init_zero {0} -#define Disable_init_zero {0} -#define Reset_init_zero {0} - -/* Field tags (for use in manual encoding/decoding) */ -#define AllowPowerOn_p_tag 1 -#define FirmwareUpdate_invoke_rom_bootloader_tag 1 -#define KeepAliveHi_time_stamp_tag 1 -#define KeepAliveHi_hw_type_tag 2 -#define KeepAliveHi_hw_revision_tag 3 -#define KeepAliveHi_protocol_version_major_tag 4 -#define KeepAliveHi_protocol_version_minor_tag 5 -#define KeepAliveHi_sw_version_string_tag 6 -#define Replug_time_tag 1 -#define SetOutputVoltageCurrent_voltage_tag 1 -#define SetOutputVoltageCurrent_current_tag 2 -#define SetPWM_mode_tag 1 -#define SetPWM_duty_cycle_tag 2 -#define HiToLo_enable_tag 6 -#define HiToLo_disable_tag 7 -#define HiToLo_keep_alive_tag 13 -#define HiToLo_firmware_update_tag 16 -#define HiToLo_set_pwm_tag 20 -#define HiToLo_allow_power_on_tag 21 -#define HiToLo_reset_tag 23 -#define HiToLo_replug_tag 24 -#define HiToLo_set_output_voltage_current_tag 50 - -/* Struct field encoding specification for nanopb */ -#define HiToLo_FIELDLIST(X, a) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,enable,payload.enable), 6) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,disable,payload.disable), 7) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,keep_alive,payload.keep_alive), 13) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,firmware_update,payload.firmware_update), 16) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,set_pwm,payload.set_pwm), 20) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,allow_power_on,payload.allow_power_on), 21) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,reset,payload.reset), 23) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,replug,payload.replug), 24) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,set_output_voltage_current,payload.set_output_voltage_current), 50) -#define HiToLo_CALLBACK NULL -#define HiToLo_DEFAULT NULL -#define HiToLo_payload_enable_MSGTYPE Enable -#define HiToLo_payload_disable_MSGTYPE Disable -#define HiToLo_payload_keep_alive_MSGTYPE KeepAliveHi -#define HiToLo_payload_firmware_update_MSGTYPE FirmwareUpdate -#define HiToLo_payload_set_pwm_MSGTYPE SetPWM -#define HiToLo_payload_allow_power_on_MSGTYPE AllowPowerOn -#define HiToLo_payload_reset_MSGTYPE Reset -#define HiToLo_payload_replug_MSGTYPE Replug -#define HiToLo_payload_set_output_voltage_current_MSGTYPE SetOutputVoltageCurrent - -#define AllowPowerOn_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, p, 1) -#define AllowPowerOn_CALLBACK NULL -#define AllowPowerOn_DEFAULT NULL - -#define SetOutputVoltageCurrent_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, FLOAT, voltage, 1) \ -X(a, STATIC, SINGULAR, FLOAT, current, 2) -#define SetOutputVoltageCurrent_CALLBACK NULL -#define SetOutputVoltageCurrent_DEFAULT NULL - -#define SetPWM_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, INT32, mode, 1) \ -X(a, STATIC, SINGULAR, FLOAT, duty_cycle, 2) -#define SetPWM_CALLBACK NULL -#define SetPWM_DEFAULT NULL - -#define FirmwareUpdate_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, invoke_rom_bootloader, 1) -#define FirmwareUpdate_CALLBACK NULL -#define FirmwareUpdate_DEFAULT NULL - -#define KeepAliveHi_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, time_stamp, 1) \ -X(a, STATIC, SINGULAR, UINT32, hw_type, 2) \ -X(a, STATIC, SINGULAR, UINT32, hw_revision, 3) \ -X(a, STATIC, SINGULAR, UINT32, protocol_version_major, 4) \ -X(a, STATIC, SINGULAR, UINT32, protocol_version_minor, 5) \ -X(a, STATIC, SINGULAR, STRING, sw_version_string, 6) -#define KeepAliveHi_CALLBACK NULL -#define KeepAliveHi_DEFAULT NULL - -#define Replug_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, time, 1) -#define Replug_CALLBACK NULL -#define Replug_DEFAULT NULL - -#define Enable_FIELDLIST(X, a) \ - -#define Enable_CALLBACK NULL -#define Enable_DEFAULT NULL - -#define Disable_FIELDLIST(X, a) \ - -#define Disable_CALLBACK NULL -#define Disable_DEFAULT NULL - -#define Reset_FIELDLIST(X, a) \ - -#define Reset_CALLBACK NULL -#define Reset_DEFAULT NULL - -extern const pb_msgdesc_t HiToLo_msg; -extern const pb_msgdesc_t AllowPowerOn_msg; -extern const pb_msgdesc_t SetOutputVoltageCurrent_msg; -extern const pb_msgdesc_t SetPWM_msg; -extern const pb_msgdesc_t FirmwareUpdate_msg; -extern const pb_msgdesc_t KeepAliveHi_msg; -extern const pb_msgdesc_t Replug_msg; -extern const pb_msgdesc_t Enable_msg; -extern const pb_msgdesc_t Disable_msg; -extern const pb_msgdesc_t Reset_msg; - -/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define HiToLo_fields &HiToLo_msg -#define AllowPowerOn_fields &AllowPowerOn_msg -#define SetOutputVoltageCurrent_fields &SetOutputVoltageCurrent_msg -#define SetPWM_fields &SetPWM_msg -#define FirmwareUpdate_fields &FirmwareUpdate_msg -#define KeepAliveHi_fields &KeepAliveHi_msg -#define Replug_fields &Replug_msg -#define Enable_fields &Enable_msg -#define Disable_fields &Disable_msg -#define Reset_fields &Reset_msg - -/* Maximum encoded size of messages (where known) */ -#define AllowPowerOn_size 2 -#define Disable_size 0 -#define Enable_size 0 -#define FirmwareUpdate_size 2 -#define HiToLo_size 84 -#define KeepAliveHi_size 82 -#define Replug_size 6 -#define Reset_size 0 -#define SetOutputVoltageCurrent_size 10 -#define SetPWM_size 16 - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.proto b/modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.proto deleted file mode 100644 index 29f71a54bc..0000000000 --- a/modules/MicroMegaWattBSP/umwc_comms/protobuf/hi2lo.proto +++ /dev/null @@ -1,55 +0,0 @@ -syntax = "proto3"; - -/* - This container message is send from Hi Level to Low level and may contain any allowed message in that direction. -*/ -message HiToLo { - oneof payload { - // Common/configuration messages - Enable enable = 6; - Disable disable = 7; - KeepAliveHi keep_alive = 13; - FirmwareUpdate firmware_update = 16; - SetPWM set_pwm = 20; - AllowPowerOn allow_power_on = 21; - SetOutputVoltageCurrent set_output_voltage_current = 50; - Reset reset = 23; - Replug replug = 24; - } -} - -message AllowPowerOn { - bool p = 1; -} - -message SetOutputVoltageCurrent { - float voltage = 1; - float current = 2; -} - -message SetPWM { - int32 mode = 1; // 0: OFF, 1: ON, 2: F - float duty_cycle = 2; -} - -message FirmwareUpdate { - bool invoke_rom_bootloader = 1; -} - -message KeepAliveHi { - uint32 time_stamp = 1; - uint32 hw_type = 2; - uint32 hw_revision = 3; - uint32 protocol_version_major = 4; - uint32 protocol_version_minor = 5; - string sw_version_string = 6; - -} - -message Replug { - uint32 time = 1; -} - -message Enable { } -message Disable { } -message Reset { } \ No newline at end of file diff --git a/modules/MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.pb.h b/modules/MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.pb.h deleted file mode 100644 index 7773af8ab4..0000000000 --- a/modules/MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.pb.h +++ /dev/null @@ -1,194 +0,0 @@ -/* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5 */ - -#ifndef PB_LO2HI_PB_H_INCLUDED -#define PB_LO2HI_PB_H_INCLUDED -#include - -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -/* Enum definitions */ -typedef enum _Event_InterfaceEvent { - Event_InterfaceEvent_CAR_PLUGGED_IN = 0, - Event_InterfaceEvent_CAR_REQUESTED_POWER = 1, - Event_InterfaceEvent_POWER_ON = 2, - Event_InterfaceEvent_POWER_OFF = 3, - Event_InterfaceEvent_CAR_REQUESTED_STOP_POWER = 4, - Event_InterfaceEvent_CAR_UNPLUGGED = 5, - Event_InterfaceEvent_ERROR_E = 6, - Event_InterfaceEvent_ERROR_DF = 7, - Event_InterfaceEvent_ERROR_RELAIS = 8, - Event_InterfaceEvent_ERROR_RCD = 9, - Event_InterfaceEvent_ERROR_VENTILATION_NOT_AVAILABLE = 10, - Event_InterfaceEvent_ERROR_OVER_CURRENT = 11, - Event_InterfaceEvent_ENTER_BCD = 12, - Event_InterfaceEvent_LEAVE_BCD = 13, - Event_InterfaceEvent_PERMANENT_FAULT = 14, - Event_InterfaceEvent_EVSE_REPLUG_STARTED = 15, - Event_InterfaceEvent_EVSE_REPLUG_FINISHED = 16 -} Event_InterfaceEvent; - -/* Struct definitions */ -typedef struct _ResetDone { - char dummy_field; -} ResetDone; - -typedef struct _Event { - Event_InterfaceEvent type; -} Event; - -typedef struct _KeepAliveLo { - uint32_t time_stamp; - uint32_t hw_type; - uint32_t hw_revision; - uint32_t protocol_version_major; - uint32_t protocol_version_minor; - char sw_version_string[51]; -} KeepAliveLo; - -typedef struct _PowerMeter { - float voltage; -} PowerMeter; - -typedef struct _Telemetry { - float cp_hi; - float cp_lo; - float pwm_dc; - float relais_on; -} Telemetry; - -/* This container message is send from Lo Level to Hi level and may contain any allowed message in that direction. */ -typedef struct _LoToHi { - /* Common Packets */ - pb_size_t which_payload; - union { - KeepAliveLo keep_alive; - PowerMeter power_meter; - Event event; - ResetDone reset_done; - Telemetry telemetry; - } payload; -} LoToHi; - - -/* Helper constants for enums */ -#define _Event_InterfaceEvent_MIN Event_InterfaceEvent_CAR_PLUGGED_IN -#define _Event_InterfaceEvent_MAX Event_InterfaceEvent_EVSE_REPLUG_FINISHED -#define _Event_InterfaceEvent_ARRAYSIZE ((Event_InterfaceEvent)(Event_InterfaceEvent_EVSE_REPLUG_FINISHED+1)) - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Initializer values for message structs */ -#define LoToHi_init_default {0, {KeepAliveLo_init_default}} -#define Event_init_default {_Event_InterfaceEvent_MIN} -#define PowerMeter_init_default {0} -#define Telemetry_init_default {0, 0, 0, 0} -#define KeepAliveLo_init_default {0, 0, 0, 0, 0, ""} -#define ResetDone_init_default {0} -#define LoToHi_init_zero {0, {KeepAliveLo_init_zero}} -#define Event_init_zero {_Event_InterfaceEvent_MIN} -#define PowerMeter_init_zero {0} -#define Telemetry_init_zero {0, 0, 0, 0} -#define KeepAliveLo_init_zero {0, 0, 0, 0, 0, ""} -#define ResetDone_init_zero {0} - -/* Field tags (for use in manual encoding/decoding) */ -#define Event_type_tag 1 -#define KeepAliveLo_time_stamp_tag 1 -#define KeepAliveLo_hw_type_tag 2 -#define KeepAliveLo_hw_revision_tag 3 -#define KeepAliveLo_protocol_version_major_tag 4 -#define KeepAliveLo_protocol_version_minor_tag 5 -#define KeepAliveLo_sw_version_string_tag 6 -#define PowerMeter_voltage_tag 2 -#define Telemetry_cp_hi_tag 1 -#define Telemetry_cp_lo_tag 2 -#define Telemetry_pwm_dc_tag 3 -#define Telemetry_relais_on_tag 4 -#define LoToHi_keep_alive_tag 3 -#define LoToHi_power_meter_tag 4 -#define LoToHi_event_tag 6 -#define LoToHi_reset_done_tag 7 -#define LoToHi_telemetry_tag 8 - -/* Struct field encoding specification for nanopb */ -#define LoToHi_FIELDLIST(X, a) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,keep_alive,payload.keep_alive), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,power_meter,payload.power_meter), 4) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,event,payload.event), 6) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,reset_done,payload.reset_done), 7) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,telemetry,payload.telemetry), 8) -#define LoToHi_CALLBACK NULL -#define LoToHi_DEFAULT NULL -#define LoToHi_payload_keep_alive_MSGTYPE KeepAliveLo -#define LoToHi_payload_power_meter_MSGTYPE PowerMeter -#define LoToHi_payload_event_MSGTYPE Event -#define LoToHi_payload_reset_done_MSGTYPE ResetDone -#define LoToHi_payload_telemetry_MSGTYPE Telemetry - -#define Event_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UENUM, type, 1) -#define Event_CALLBACK NULL -#define Event_DEFAULT NULL - -#define PowerMeter_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, FLOAT, voltage, 2) -#define PowerMeter_CALLBACK NULL -#define PowerMeter_DEFAULT NULL - -#define Telemetry_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, FLOAT, cp_hi, 1) \ -X(a, STATIC, SINGULAR, FLOAT, cp_lo, 2) \ -X(a, STATIC, SINGULAR, FLOAT, pwm_dc, 3) \ -X(a, STATIC, SINGULAR, FLOAT, relais_on, 4) -#define Telemetry_CALLBACK NULL -#define Telemetry_DEFAULT NULL - -#define KeepAliveLo_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, time_stamp, 1) \ -X(a, STATIC, SINGULAR, UINT32, hw_type, 2) \ -X(a, STATIC, SINGULAR, UINT32, hw_revision, 3) \ -X(a, STATIC, SINGULAR, UINT32, protocol_version_major, 4) \ -X(a, STATIC, SINGULAR, UINT32, protocol_version_minor, 5) \ -X(a, STATIC, SINGULAR, STRING, sw_version_string, 6) -#define KeepAliveLo_CALLBACK NULL -#define KeepAliveLo_DEFAULT NULL - -#define ResetDone_FIELDLIST(X, a) \ - -#define ResetDone_CALLBACK NULL -#define ResetDone_DEFAULT NULL - -extern const pb_msgdesc_t LoToHi_msg; -extern const pb_msgdesc_t Event_msg; -extern const pb_msgdesc_t PowerMeter_msg; -extern const pb_msgdesc_t Telemetry_msg; -extern const pb_msgdesc_t KeepAliveLo_msg; -extern const pb_msgdesc_t ResetDone_msg; - -/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define LoToHi_fields &LoToHi_msg -#define Event_fields &Event_msg -#define PowerMeter_fields &PowerMeter_msg -#define Telemetry_fields &Telemetry_msg -#define KeepAliveLo_fields &KeepAliveLo_msg -#define ResetDone_fields &ResetDone_msg - -/* Maximum encoded size of messages (where known) */ -#define Event_size 2 -#define KeepAliveLo_size 82 -#define LoToHi_size 84 -#define PowerMeter_size 5 -#define ResetDone_size 0 -#define Telemetry_size 20 - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/modules/MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.proto b/modules/MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.proto deleted file mode 100644 index 26e0626a8a..0000000000 --- a/modules/MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.proto +++ /dev/null @@ -1,63 +0,0 @@ -syntax = "proto3"; - -/* - This container message is send from Lo Level to Hi level and may contain any allowed message in that direction. -*/ -message LoToHi { - oneof payload { - // Common Packets - KeepAliveLo keep_alive = 3; - PowerMeter power_meter = 4; - ResetDone reset_done = 7; - // Packets only available in control_mode = 2 (low level control) - Event event = 6; - Telemetry telemetry = 8; - } -} - -message Event { - enum InterfaceEvent { - CAR_PLUGGED_IN = 0; - CAR_REQUESTED_POWER = 1; - POWER_ON = 2; - POWER_OFF = 3; - CAR_REQUESTED_STOP_POWER = 4; - CAR_UNPLUGGED = 5; - ERROR_E = 6; - ERROR_DF = 7; - ERROR_RELAIS = 8; - ERROR_RCD = 9; - ERROR_VENTILATION_NOT_AVAILABLE = 10; - ERROR_OVER_CURRENT = 11; - ENTER_BCD = 12; - LEAVE_BCD = 13; - PERMANENT_FAULT = 14; - EVSE_REPLUG_STARTED = 15; - EVSE_REPLUG_FINISHED = 16; - } - InterfaceEvent type = 1; -} - -message PowerMeter { - float voltage = 2; -} - -message Telemetry { - float cp_hi = 1; - float cp_lo = 2; - float pwm_dc = 3; - float relais_on = 4; -} - -message KeepAliveLo { - uint32 time_stamp = 1; - uint32 hw_type = 2; - uint32 hw_revision = 3; - uint32 protocol_version_major = 4; - uint32 protocol_version_minor = 5; - string sw_version_string = 6; -} - -message ResetDone { -} - diff --git a/modules/MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.options b/modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.options similarity index 51% rename from modules/MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.options rename to modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.options index 9cba6786c2..8242b29aa8 100644 --- a/modules/MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.options +++ b/modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.options @@ -1 +1,2 @@ +KeepAlive.sw_version_string max_length:50 KeepAliveLo.sw_version_string max_length:50 diff --git a/modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.pb.c b/modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.pb.c new file mode 100644 index 0000000000..74b0f0260a --- /dev/null +++ b/modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.pb.c @@ -0,0 +1,40 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.6 */ + +#include "umwc.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(EverestToMcu, EverestToMcu, 2) + + +PB_BIND(McuToEverest, McuToEverest, 2) + + +PB_BIND(SetOutputVoltageCurrent, SetOutputVoltageCurrent, AUTO) + + +PB_BIND(ErrorFlags, ErrorFlags, AUTO) + + +PB_BIND(KeepAliveLo, KeepAliveLo, AUTO) + + +PB_BIND(KeepAlive, KeepAlive, AUTO) + + +PB_BIND(Telemetry, Telemetry, AUTO) + + +PB_BIND(PowerMeter, PowerMeter, AUTO) + + +PB_BIND(FirmwareUpdate, FirmwareUpdate, AUTO) + + + + + + + diff --git a/modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.pb.h b/modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.pb.h new file mode 100644 index 0000000000..edd5e9e786 --- /dev/null +++ b/modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.pb.h @@ -0,0 +1,336 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.6 */ + +#ifndef PB_UMWC_PB_H_INCLUDED +#define PB_UMWC_PB_H_INCLUDED +#include + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Enum definitions */ +typedef enum _CpState { + CpState_STATE_A = 0, + CpState_STATE_B = 1, + CpState_STATE_C = 2, + CpState_STATE_D = 3, + CpState_STATE_E = 4, + CpState_STATE_F = 5 +} CpState; + +typedef enum _ResetReason { + ResetReason_USER = 0, + ResetReason_WATCHDOG = 1 +} ResetReason; + +typedef enum _PpState { + PpState_STATE_NC = 0, + PpState_STATE_13A = 1, + PpState_STATE_20A = 2, + PpState_STATE_32A = 3, + PpState_STATE_70A = 4, + PpState_STATE_FAULT = 5 +} PpState; + +typedef enum _LockState { + LockState_UNDEFINED = 0, + LockState_UNLOCKED = 1, + LockState_LOCKED = 2 +} LockState; + +/* Struct definitions */ +typedef struct _ErrorFlags { + bool diode_fault; + bool cp_signal_fault; +} ErrorFlags; + +typedef struct _FirmwareUpdate { + bool invoke_rom_bootloader; +} FirmwareUpdate; + +typedef struct _KeepAlive { + uint32_t time_stamp; + uint32_t hw_type; + uint32_t hw_revision; + char sw_version_string[51]; +} KeepAlive; + +typedef struct _KeepAliveLo { + uint32_t time_stamp; + uint32_t hw_type; + uint32_t hw_revision; + uint32_t protocol_version_major; + uint32_t protocol_version_minor; + char sw_version_string[51]; + float hwcap_max_current; + float hwcap_min_current; + uint32_t hwcap_max_phase_count; + uint32_t hwcap_min_phase_count; + bool supports_changing_phases_during_charging; +} KeepAliveLo; + +typedef struct _PowerMeter { + float voltage; +} PowerMeter; + +typedef struct _SetOutputVoltageCurrent { + float voltage; + float current; +} SetOutputVoltageCurrent; + +typedef struct _Telemetry { + float cp_hi; + float cp_lo; + float pwm_dc; + float relais_on; +} Telemetry; + +/* This container message is send from EVerest to MCU and may contain any allowed message in that direction. */ +typedef struct _EverestToMcu { + pb_size_t which_payload; + union { + /* Needs to remain the same to allow firmware updates of older versions */ + FirmwareUpdate firmware_update; + SetOutputVoltageCurrent set_output_voltage_current; + /* Other IDs are 100+ to avoid compatibility issues with older firmware versions */ + KeepAlive keep_alive; + bool connector_lock; /* false: unlock, true: lock */ + uint32_t pwm_duty_cycle; /* in 0.01 %, 0 = State F, 10000 = X1 */ + bool allow_power_on; + bool reset; + bool enable; + bool replug; + } payload; +} EverestToMcu; + +/* This container message is send from MCU to EVerest and may contain any allowed message in that direction. */ +typedef struct _McuToEverest { + pb_size_t which_payload; + union { + /* Needs to remain the same to allow firmware updates of older versions */ + KeepAliveLo keep_alive; + /* Other IDs are 100+ to avoid compatibility issues with older firmware versions */ + ResetReason reset; + CpState cp_state; + bool relais_state; /* false: relais are off, true: relais are on */ + ErrorFlags error_flags; + Telemetry telemetry; + PpState pp_state; + LockState lock_state; + PowerMeter power_meter; + } payload; +} McuToEverest; + + +/* Helper constants for enums */ +#define _CpState_MIN CpState_STATE_A +#define _CpState_MAX CpState_STATE_F +#define _CpState_ARRAYSIZE ((CpState)(CpState_STATE_F+1)) + +#define _ResetReason_MIN ResetReason_USER +#define _ResetReason_MAX ResetReason_WATCHDOG +#define _ResetReason_ARRAYSIZE ((ResetReason)(ResetReason_WATCHDOG+1)) + +#define _PpState_MIN PpState_STATE_NC +#define _PpState_MAX PpState_STATE_FAULT +#define _PpState_ARRAYSIZE ((PpState)(PpState_STATE_FAULT+1)) + +#define _LockState_MIN LockState_UNDEFINED +#define _LockState_MAX LockState_LOCKED +#define _LockState_ARRAYSIZE ((LockState)(LockState_LOCKED+1)) + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define EverestToMcu_init_default {0, {FirmwareUpdate_init_default}} +#define McuToEverest_init_default {0, {KeepAliveLo_init_default}} +#define SetOutputVoltageCurrent_init_default {0, 0} +#define ErrorFlags_init_default {0, 0} +#define KeepAliveLo_init_default {0, 0, 0, 0, 0, "", 0, 0, 0, 0, 0} +#define KeepAlive_init_default {0, 0, 0, ""} +#define Telemetry_init_default {0, 0, 0, 0} +#define PowerMeter_init_default {0} +#define FirmwareUpdate_init_default {0} +#define EverestToMcu_init_zero {0, {FirmwareUpdate_init_zero}} +#define McuToEverest_init_zero {0, {KeepAliveLo_init_zero}} +#define SetOutputVoltageCurrent_init_zero {0, 0} +#define ErrorFlags_init_zero {0, 0} +#define KeepAliveLo_init_zero {0, 0, 0, 0, 0, "", 0, 0, 0, 0, 0} +#define KeepAlive_init_zero {0, 0, 0, ""} +#define Telemetry_init_zero {0, 0, 0, 0} +#define PowerMeter_init_zero {0} +#define FirmwareUpdate_init_zero {0} + +/* Field tags (for use in manual encoding/decoding) */ +#define ErrorFlags_diode_fault_tag 1 +#define ErrorFlags_cp_signal_fault_tag 6 +#define FirmwareUpdate_invoke_rom_bootloader_tag 1 +#define KeepAlive_time_stamp_tag 1 +#define KeepAlive_hw_type_tag 2 +#define KeepAlive_hw_revision_tag 3 +#define KeepAlive_sw_version_string_tag 6 +#define KeepAliveLo_time_stamp_tag 1 +#define KeepAliveLo_hw_type_tag 2 +#define KeepAliveLo_hw_revision_tag 3 +#define KeepAliveLo_protocol_version_major_tag 4 +#define KeepAliveLo_protocol_version_minor_tag 5 +#define KeepAliveLo_sw_version_string_tag 6 +#define KeepAliveLo_hwcap_max_current_tag 7 +#define KeepAliveLo_hwcap_min_current_tag 8 +#define KeepAliveLo_hwcap_max_phase_count_tag 9 +#define KeepAliveLo_hwcap_min_phase_count_tag 10 +#define KeepAliveLo_supports_changing_phases_during_charging_tag 11 +#define PowerMeter_voltage_tag 2 +#define SetOutputVoltageCurrent_voltage_tag 1 +#define SetOutputVoltageCurrent_current_tag 2 +#define Telemetry_cp_hi_tag 1 +#define Telemetry_cp_lo_tag 2 +#define Telemetry_pwm_dc_tag 3 +#define Telemetry_relais_on_tag 4 +#define EverestToMcu_firmware_update_tag 16 +#define EverestToMcu_set_output_voltage_current_tag 50 +#define EverestToMcu_keep_alive_tag 100 +#define EverestToMcu_connector_lock_tag 102 +#define EverestToMcu_pwm_duty_cycle_tag 103 +#define EverestToMcu_allow_power_on_tag 104 +#define EverestToMcu_reset_tag 105 +#define EverestToMcu_enable_tag 106 +#define EverestToMcu_replug_tag 107 +#define McuToEverest_keep_alive_tag 3 +#define McuToEverest_reset_tag 101 +#define McuToEverest_cp_state_tag 102 +#define McuToEverest_relais_state_tag 103 +#define McuToEverest_error_flags_tag 104 +#define McuToEverest_telemetry_tag 105 +#define McuToEverest_pp_state_tag 106 +#define McuToEverest_lock_state_tag 107 +#define McuToEverest_power_meter_tag 108 + +/* Struct field encoding specification for nanopb */ +#define EverestToMcu_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,firmware_update,payload.firmware_update), 16) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,set_output_voltage_current,payload.set_output_voltage_current), 50) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,keep_alive,payload.keep_alive), 100) \ +X(a, STATIC, ONEOF, BOOL, (payload,connector_lock,payload.connector_lock), 102) \ +X(a, STATIC, ONEOF, UINT32, (payload,pwm_duty_cycle,payload.pwm_duty_cycle), 103) \ +X(a, STATIC, ONEOF, BOOL, (payload,allow_power_on,payload.allow_power_on), 104) \ +X(a, STATIC, ONEOF, BOOL, (payload,reset,payload.reset), 105) \ +X(a, STATIC, ONEOF, BOOL, (payload,enable,payload.enable), 106) \ +X(a, STATIC, ONEOF, BOOL, (payload,replug,payload.replug), 107) +#define EverestToMcu_CALLBACK NULL +#define EverestToMcu_DEFAULT NULL +#define EverestToMcu_payload_firmware_update_MSGTYPE FirmwareUpdate +#define EverestToMcu_payload_set_output_voltage_current_MSGTYPE SetOutputVoltageCurrent +#define EverestToMcu_payload_keep_alive_MSGTYPE KeepAlive + +#define McuToEverest_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,keep_alive,payload.keep_alive), 3) \ +X(a, STATIC, ONEOF, UENUM, (payload,reset,payload.reset), 101) \ +X(a, STATIC, ONEOF, UENUM, (payload,cp_state,payload.cp_state), 102) \ +X(a, STATIC, ONEOF, BOOL, (payload,relais_state,payload.relais_state), 103) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,error_flags,payload.error_flags), 104) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,telemetry,payload.telemetry), 105) \ +X(a, STATIC, ONEOF, UENUM, (payload,pp_state,payload.pp_state), 106) \ +X(a, STATIC, ONEOF, UENUM, (payload,lock_state,payload.lock_state), 107) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,power_meter,payload.power_meter), 108) +#define McuToEverest_CALLBACK NULL +#define McuToEverest_DEFAULT NULL +#define McuToEverest_payload_keep_alive_MSGTYPE KeepAliveLo +#define McuToEverest_payload_error_flags_MSGTYPE ErrorFlags +#define McuToEverest_payload_telemetry_MSGTYPE Telemetry +#define McuToEverest_payload_power_meter_MSGTYPE PowerMeter + +#define SetOutputVoltageCurrent_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, FLOAT, voltage, 1) \ +X(a, STATIC, SINGULAR, FLOAT, current, 2) +#define SetOutputVoltageCurrent_CALLBACK NULL +#define SetOutputVoltageCurrent_DEFAULT NULL + +#define ErrorFlags_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, BOOL, diode_fault, 1) \ +X(a, STATIC, SINGULAR, BOOL, cp_signal_fault, 6) +#define ErrorFlags_CALLBACK NULL +#define ErrorFlags_DEFAULT NULL + +#define KeepAliveLo_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, time_stamp, 1) \ +X(a, STATIC, SINGULAR, UINT32, hw_type, 2) \ +X(a, STATIC, SINGULAR, UINT32, hw_revision, 3) \ +X(a, STATIC, SINGULAR, UINT32, protocol_version_major, 4) \ +X(a, STATIC, SINGULAR, UINT32, protocol_version_minor, 5) \ +X(a, STATIC, SINGULAR, STRING, sw_version_string, 6) \ +X(a, STATIC, SINGULAR, FLOAT, hwcap_max_current, 7) \ +X(a, STATIC, SINGULAR, FLOAT, hwcap_min_current, 8) \ +X(a, STATIC, SINGULAR, UINT32, hwcap_max_phase_count, 9) \ +X(a, STATIC, SINGULAR, UINT32, hwcap_min_phase_count, 10) \ +X(a, STATIC, SINGULAR, BOOL, supports_changing_phases_during_charging, 11) +#define KeepAliveLo_CALLBACK NULL +#define KeepAliveLo_DEFAULT NULL + +#define KeepAlive_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, time_stamp, 1) \ +X(a, STATIC, SINGULAR, UINT32, hw_type, 2) \ +X(a, STATIC, SINGULAR, UINT32, hw_revision, 3) \ +X(a, STATIC, SINGULAR, STRING, sw_version_string, 6) +#define KeepAlive_CALLBACK NULL +#define KeepAlive_DEFAULT NULL + +#define Telemetry_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, FLOAT, cp_hi, 1) \ +X(a, STATIC, SINGULAR, FLOAT, cp_lo, 2) \ +X(a, STATIC, SINGULAR, FLOAT, pwm_dc, 3) \ +X(a, STATIC, SINGULAR, FLOAT, relais_on, 4) +#define Telemetry_CALLBACK NULL +#define Telemetry_DEFAULT NULL + +#define PowerMeter_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, FLOAT, voltage, 2) +#define PowerMeter_CALLBACK NULL +#define PowerMeter_DEFAULT NULL + +#define FirmwareUpdate_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, BOOL, invoke_rom_bootloader, 1) +#define FirmwareUpdate_CALLBACK NULL +#define FirmwareUpdate_DEFAULT NULL + +extern const pb_msgdesc_t EverestToMcu_msg; +extern const pb_msgdesc_t McuToEverest_msg; +extern const pb_msgdesc_t SetOutputVoltageCurrent_msg; +extern const pb_msgdesc_t ErrorFlags_msg; +extern const pb_msgdesc_t KeepAliveLo_msg; +extern const pb_msgdesc_t KeepAlive_msg; +extern const pb_msgdesc_t Telemetry_msg; +extern const pb_msgdesc_t PowerMeter_msg; +extern const pb_msgdesc_t FirmwareUpdate_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define EverestToMcu_fields &EverestToMcu_msg +#define McuToEverest_fields &McuToEverest_msg +#define SetOutputVoltageCurrent_fields &SetOutputVoltageCurrent_msg +#define ErrorFlags_fields &ErrorFlags_msg +#define KeepAliveLo_fields &KeepAliveLo_msg +#define KeepAlive_fields &KeepAlive_msg +#define Telemetry_fields &Telemetry_msg +#define PowerMeter_fields &PowerMeter_msg +#define FirmwareUpdate_fields &FirmwareUpdate_msg + +/* Maximum encoded size of messages (where known) */ +#define ErrorFlags_size 4 +#define EverestToMcu_size 73 +#define FirmwareUpdate_size 2 +#define KeepAliveLo_size 106 +#define KeepAlive_size 70 +#define McuToEverest_size 108 +#define PowerMeter_size 5 +#define SetOutputVoltageCurrent_size 10 +#define Telemetry_size 20 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.proto b/modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.proto new file mode 100644 index 0000000000..d757e449a3 --- /dev/null +++ b/modules/MicroMegaWattBSP/umwc_comms/protobuf/umwc.proto @@ -0,0 +1,117 @@ +syntax = "proto3"; + +/* + This container message is send from EVerest to MCU and may contain any allowed message in that direction. +*/ +message EverestToMcu { + oneof payload { + // Needs to remain the same to allow firmware updates of older versions + FirmwareUpdate firmware_update = 16; + + SetOutputVoltageCurrent set_output_voltage_current = 50; + + // Other IDs are 100+ to avoid compatibility issues with older firmware versions + KeepAlive keep_alive = 100; + bool connector_lock = 102; // false: unlock, true: lock + uint32 pwm_duty_cycle = 103; // in 0.01 %, 0 = State F, 10000 = X1 + bool allow_power_on = 104; + bool reset = 105; + bool enable = 106; + bool replug = 107; + } +} + +/* + This container message is send from MCU to EVerest and may contain any allowed message in that direction. +*/ +message McuToEverest { + oneof payload { + // Needs to remain the same to allow firmware updates of older versions + KeepAliveLo keep_alive = 3; + + // Other IDs are 100+ to avoid compatibility issues with older firmware versions + ResetReason reset = 101; + CpState cp_state = 102; + bool relais_state = 103; // false: relais are off, true: relais are on + ErrorFlags error_flags = 104; + Telemetry telemetry = 105; + PpState pp_state = 106; + LockState lock_state = 107; + PowerMeter power_meter = 108; + } +} + +enum CpState { + STATE_A = 0; + STATE_B = 1; + STATE_C = 2; + STATE_D = 3; + STATE_E = 4; + STATE_F = 5; +} + +message SetOutputVoltageCurrent { + float voltage = 1; + float current = 2; +} + +message ErrorFlags { + bool diode_fault = 1; + bool cp_signal_fault = 6; +} + +enum ResetReason { + USER = 0; + WATCHDOG = 1; +} + +message KeepAliveLo { + uint32 time_stamp = 1; + uint32 hw_type = 2; + uint32 hw_revision = 3; + uint32 protocol_version_major = 4; + uint32 protocol_version_minor = 5; + string sw_version_string = 6; + float hwcap_max_current = 7; + float hwcap_min_current = 8; + uint32 hwcap_max_phase_count = 9; + uint32 hwcap_min_phase_count = 10; + bool supports_changing_phases_during_charging = 11; +} + +message KeepAlive { + uint32 time_stamp = 1; + uint32 hw_type = 2; + uint32 hw_revision = 3; + string sw_version_string = 6; +} + +message Telemetry { + float cp_hi = 1; + float cp_lo = 2; + float pwm_dc = 3; + float relais_on = 4; +} + +enum PpState { + STATE_NC = 0; + STATE_13A = 1; + STATE_20A = 2; + STATE_32A = 3; + STATE_70A = 4; + STATE_FAULT = 5; +} + +enum LockState { + UNDEFINED = 0; + UNLOCKED = 1; + LOCKED = 2; +} + +message PowerMeter { + float voltage = 2; +} + +message FirmwareUpdate { + bool invoke_rom_bootloader = 1; +} \ No newline at end of file diff --git a/modules/MicroMegaWattBSP/umwc_fwupdate/CMakeLists.txt b/modules/MicroMegaWattBSP/umwc_fwupdate/CMakeLists.txt index f3c718ccfe..e4e1f20644 100644 --- a/modules/MicroMegaWattBSP/umwc_fwupdate/CMakeLists.txt +++ b/modules/MicroMegaWattBSP/umwc_fwupdate/CMakeLists.txt @@ -6,9 +6,6 @@ project(umwc_fwupdate VERSION 0.1) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) - -configure_file(config.h.in config.h) - # add the executable add_executable(umwc_fwupdate main.cpp) target_include_directories(umwc_fwupdate PUBLIC "${PROJECT_BINARY_DIR}" PUBLIC "../umwc_comms/nanopb" PUBLIC "../umwc_comms/protobuf" PUBLIC "../umwc_comms") diff --git a/modules/MicroMegaWattBSP/umwc_fwupdate/config.h.in b/modules/MicroMegaWattBSP/umwc_fwupdate/config.h.in deleted file mode 100644 index e4ebf2da0f..0000000000 --- a/modules/MicroMegaWattBSP/umwc_fwupdate/config.h.in +++ /dev/null @@ -1,3 +0,0 @@ -// the configured options and settings for umwcDriver -#define umwc_fwupdate_VERSION_MAJOR @umwc_fwupdate_VERSION_MAJOR@ -#define umwc_fwupdate_VERSION_MINOR @umwc_fwupdate_VERSION_MINOR@ diff --git a/modules/MicroMegaWattBSP/umwc_fwupdate/main.cpp b/modules/MicroMegaWattBSP/umwc_fwupdate/main.cpp index 1c82a1ef4e..ca7a71b74c 100644 --- a/modules/MicroMegaWattBSP/umwc_fwupdate/main.cpp +++ b/modules/MicroMegaWattBSP/umwc_fwupdate/main.cpp @@ -9,9 +9,7 @@ #include -#include "config.h" -#include "hi2lo.pb.h" -#include "lo2hi.pb.h" +#include "umwc.pb.h" using namespace std::chrono_literals; @@ -29,7 +27,7 @@ void help() { } int main(int argc, char* argv[]) { - printf("uMWC ROM Bootloader Firmware Updater %i.%i\n", umwc_fwupdate_VERSION_MAJOR, umwc_fwupdate_VERSION_MINOR); + printf("uMWC ROM Bootloader Firmware Updater\n"); if (argc != 3) { help(); exit(0); @@ -50,8 +48,8 @@ int main(int argc, char* argv[]) { } printf("\nRebooting uMWC in ROM Bootloader mode...\n"); // send some dummy commands to make sure protocol is in sync - p->disable(); - p->disable(); + p->enable(false); + p->enable(false); // now reboot uC in boot loader mode p->firmwareUpdate(true); sleep(1); diff --git a/modules/YetiDriver/CMakeLists.txt b/modules/YetiDriver/CMakeLists.txt index 16df973d9a..f7a826a2f0 100644 --- a/modules/YetiDriver/CMakeLists.txt +++ b/modules/YetiDriver/CMakeLists.txt @@ -29,9 +29,9 @@ target_link_libraries(${MODULE_NAME} target_sources(${MODULE_NAME} PRIVATE "powermeter/powermeterImpl.cpp" - "board_support/board_support_ACImpl.cpp" - "yeti_extras/yeti_extrasImpl.cpp" - "yeti_simulation_control/yeti_simulation_controlImpl.cpp" + "board_support/evse_board_supportImpl.cpp" + "rcd/ac_rcdImpl.cpp" + "connector_lock/connector_lockImpl.cpp" ) # ev@c55432ab-152c-45a9-9d2e-7281d50c69c3:v1 diff --git a/modules/YetiDriver/YetiDriver.cpp b/modules/YetiDriver/YetiDriver.cpp index 0456893418..435611dfa2 100644 --- a/modules/YetiDriver/YetiDriver.cpp +++ b/modules/YetiDriver/YetiDriver.cpp @@ -6,30 +6,6 @@ namespace module { -std::string lowlevelstate_to_string(const DebugUpdate_LoLevelState s, bool pwm_on) { - const std::string pwm = (pwm_on ? "2" : "1"); - switch (s) { - case DebugUpdate_LoLevelState_DISABLED: - return "Disabled"; - case DebugUpdate_LoLevelState_A: - return "A" + pwm; - case DebugUpdate_LoLevelState_B: - return "B" + pwm; - case DebugUpdate_LoLevelState_C: - return "C" + pwm; - case DebugUpdate_LoLevelState_D: - return "D" + pwm; - case DebugUpdate_LoLevelState_E: - return "E"; - case DebugUpdate_LoLevelState_F: - return "F"; - case DebugUpdate_LoLevelState_DF: - return "DF"; - default: - return "Unknown"; - } -} - void YetiDriver::init() { // initialize serial driver @@ -84,9 +60,9 @@ void YetiDriver::init() { {"error", false}}; // invoke_init(*p_powermeter); - invoke_init(*p_yeti_extras); - invoke_init(*p_yeti_simulation_control); invoke_init(*p_board_support); + invoke_init(*p_connector_lock); + invoke_init(*p_rcd); } void YetiDriver::ready() { @@ -101,17 +77,10 @@ void YetiDriver::ready() { serial.signalConnectionTimeout.connect( [this]() { EVLOG_AND_THROW(EVEXCEPTION(Everest::EverestInternalError, "Yeti UART timeout!")); }); - serial.setControlMode(str_to_control_mode(config.control_mode)); - invoke_ready(*p_powermeter); - invoke_ready(*p_yeti_extras); - invoke_ready(*p_yeti_simulation_control); invoke_ready(*p_board_support); - - serial.signalKeepAliveLo.connect([this](const KeepAliveLo& k) { - auto k_json = keep_alive_lo_to_json(k); - mqtt.publish("/external/keepalive_json", k_json.dump()); - }); + invoke_ready(*p_connector_lock); + invoke_ready(*p_rcd); telemetryThreadHandle = std::thread([this]() { while (!telemetryThreadHandle.shouldExit()) { @@ -126,179 +95,57 @@ void YetiDriver::ready() { } }); - serial.signalDebugUpdate.connect([this](const DebugUpdate& d) { - static bool relay_was_on = true; - auto d_json = debug_update_to_json(d); - mqtt.publish("/external/debug_json", d_json.dump()); - { - std::scoped_lock lock(telemetry_mutex); - // update external telemetry data - telemetry_power_path_controller.at("timestamp") = Everest::Date::to_rfc3339(date::utc_clock::now()); - telemetry_power_path_controller.at("cp_voltage_high") = d.evse_pwm_voltage_hi; - telemetry_power_path_controller.at("cp_voltage_low") = d.evse_pwm_voltage_lo; - telemetry_power_path_controller.at("cp_pwm_duty_cycle") = 0.; // FIXME this should be included - telemetry_power_path_controller.at("cp_state") = - lowlevelstate_to_string(d.lowlevel_state, d.evse_pwm_running); - telemetry_power_path_controller.at("pp_ohm") = 0.; // FIXME this should be included - telemetry_power_path_controller.at("supply_voltage_12V") = d.supply_voltage_12V; - telemetry_power_path_controller.at("supply_voltage_minus_12V") = d.supply_voltage_N12V; - telemetry_power_path_controller.at("temperature_controller") = d.cpu_temperature; - telemetry_power_path_controller.at("temperature_car_connector") = 0.; - telemetry_power_path_controller.at("watchdog_reset_count") = d.watchdog_reset_count; - - telemetry_rcd.at("timestamp") = Everest::Date::to_rfc3339(date::utc_clock::now()); - telemetry_rcd.at("current_mA") = d.rcd_current; - telemetry_rcd.at("enabled") = d.rcd_enabled; - - telemetry_power_switch.at("timestamp") = Everest::Date::to_rfc3339(date::utc_clock::now()); - telemetry_power_switch.at("is_on") = d.relais_on; - if (relay_was_on != d.relais_on) { - publish_external_telemetry_livedata("power_switch", telemetry_power_switch); - } - relay_was_on = d.relais_on; - } - }); -} - -Everest::json power_meter_data_to_json(const PowerMeter& p) { - Everest::json j; - j["time_stamp"] = p.time_stamp; - j["vrmsL1"] = p.vrmsL1; - j["vrmsL2"] = p.vrmsL2; - j["vrmsL3"] = p.vrmsL3; - - j["irmsL1"] = p.irmsL1; - j["irmsL2"] = p.irmsL2; - j["irmsL3"] = p.irmsL3; - j["irmsN"] = p.irmsN; - j["wattHrL1"] = p.wattHrL1; - j["wattHrL2"] = p.wattHrL2; - j["wattHrL3"] = p.wattHrL3; - j["totalWattHr_Out"] = p.totalWattHr; - j["tempL1"] = p.tempL1; - j["tempL2"] = p.tempL2; - j["tempL3"] = p.tempL3; - j["wattL1"] = p.wattL1; - j["wattL2"] = p.wattL2; - j["wattL3"] = p.wattL3; - j["freqL1"] = p.freqL1; - j["freqL2"] = p.freqL2; - j["freqL3"] = p.freqL3; - j["phaseSeqError"] = p.phaseSeqError; - return j; + serial.signalErrorFlags.connect([this](ErrorFlags e) { error_handling(e); }); } -std::string state_to_string(const StateUpdate& s) { - switch (s.state) { - case StateUpdate_State_DISABLED: - return "Disabled"; - case StateUpdate_State_IDLE: - return "Idle"; - case StateUpdate_State_WAITING_FOR_AUTHENTICATION: - return "Waiting for Auth"; - case StateUpdate_State_CHARGING: - return "Charging"; - case StateUpdate_State_CHARGING_PAUSED_EV: - return "Car Paused"; - case StateUpdate_State_CHARGING_PAUSED_EVSE: - return "EVSE Paused"; - case StateUpdate_State_CHARGING_FINSIHED: - return "Finished"; - case StateUpdate_State_ERROR: - return "Error"; - case StateUpdate_State_FAULTED: - return "Faulted"; - default: - return "Unknown"; +void YetiDriver::publish_external_telemetry_livedata(const std::string& topic, const Everest::TelemetryMap& data) { + if (info.telemetry_enabled) { + telemetry.publish("livedata", topic, data); } } -std::string error_type_to_string(ErrorFlags s) { - switch (s.type) { - case ErrorFlags_ErrorType_ERROR_F: - return "EVSE Fault"; - case ErrorFlags_ErrorType_ERROR_E: - return "Car Fault"; - case ErrorFlags_ErrorType_ERROR_DF: - return "Diode Fault"; - case ErrorFlags_ErrorType_ERROR_RELAIS: - return "Relais Fault"; - case ErrorFlags_ErrorType_ERROR_VENTILATION_NOT_AVAILABLE: - return "Ventilation n/a"; - case ErrorFlags_ErrorType_ERROR_RCD: - return "RCD Fault"; - default: - return "Unknown"; - } -} +bool rcd_selftest_failed; -Everest::json state_update_to_json(const StateUpdate& s) { - Everest::json j; - j["time_stamp"] = (int)s.time_stamp; +bool connector_lock_failed; +bool cp_signal_fault; - j["state"] = s.state; - j["state_string"] = state_to_string(s); +void YetiDriver::clear_errors_on_unplug() { + p_board_support->request_clear_all_evse_board_support_MREC2GroundFailure(); + p_connector_lock->request_clear_all_connector_lock_MREC1ConnectorLockFailure(); +} - if (s.which_state_flags == StateUpdate_error_type_tag) { - j["error_type"] = static_cast(s.state_flags.error_type.type); - j["error_string"] = error_type_to_string(s.state_flags.error_type); - } +void YetiDriver::error_handling(ErrorFlags e) { - return j; -} + if (e.diode_fault and not last_error_flags.diode_fault) { + p_board_support->raise_evse_board_support_DiodeFault("Diode Fault", Everest::error::Severity::High); + } else if (not e.diode_fault and last_error_flags.diode_fault) { + p_board_support->request_clear_all_evse_board_support_DiodeFault(); + } -Everest::json debug_update_to_json(const DebugUpdate& d) { - Everest::json j; - j["time_stamp"] = static_cast(d.time_stamp); - j["evse_pwm_voltage_hi"] = d.evse_pwm_voltage_hi; - j["evse_pwm_voltage_lo"] = d.evse_pwm_voltage_lo; - j["supply_voltage_12V"] = d.supply_voltage_12V; - j["supply_voltage_N12V"] = d.supply_voltage_N12V; - j["lowlevel_state"] = d.lowlevel_state; - j["evse_pwm_running"] = d.evse_pwm_running; - j["ev_simplified_mode"] = d.ev_simplified_mode; - j["has_ventilation"] = d.has_ventilation; - j["ventilated_charging_active"] = d.ventilated_charging_active; - j["rcd_reclosing_allowed"] = d.rcd_reclosing_allowed; - j["control_mode"] = d.control_mode; - j["authorized"] = d.authorized; - j["cpu_temperature"] = d.cpu_temperature; - j["rcd_enabled"] = d.rcd_enabled; - j["evse_pp_voltage"] = d.evse_pp_voltage; - j["max_current_cable"] = d.max_current_cable; - j["watchdog_reset_count"] = d.watchdog_reset_count; - j["simulation"] = d.simulation; - j["max_current"] = d.max_current; - j["use_three_phases"] = d.use_three_phases; - j["rcd_current"] = d.rcd_current; - j["relais_on"] = d.relais_on; - return j; -} + if (e.rcd_triggered and not last_error_flags.rcd_triggered) { + p_board_support->raise_evse_board_support_MREC2GroundFailure("Onboard RCD triggered", + Everest::error::Severity::High); + } -Everest::json keep_alive_lo_to_json(const KeepAliveLo& k) { - Everest::json j; - j["time_stamp"] = static_cast(k.time_stamp); - j["hw_type"] = static_cast(k.hw_type); - j["hw_revision"] = static_cast(k.hw_revision); - j["protocol_version_major"] = static_cast(k.protocol_version_major); - j["protocol_version_minor"] = static_cast(k.protocol_version_minor); - j["sw_version_string"] = std::string(k.sw_version_string); - return j; -} + if (e.ventilation_not_available and not last_error_flags.ventilation_not_available) { + p_board_support->raise_evse_board_support_VentilationNotAvailable("State D is not supported", + Everest::error::Severity::High); + } else if (not e.ventilation_not_available and last_error_flags.ventilation_not_available) { + p_board_support->request_clear_all_evse_board_support_VentilationNotAvailable(); + } -InterfaceControlMode str_to_control_mode(std::string data) { - if (data == "low") - return InterfaceControlMode_LOW; - else if (data == "high") - return InterfaceControlMode_HIGH; - else - return InterfaceControlMode_NONE; -} + if (e.connector_lock_failed and not last_error_flags.connector_lock_failed) { + p_connector_lock->raise_connector_lock_MREC1ConnectorLockFailure("Lock motor failure", + Everest::error::Severity::High); + } -void YetiDriver::publish_external_telemetry_livedata(const std::string& topic, const Everest::TelemetryMap& data) { - if (info.telemetry_enabled) { - telemetry.publish("livedata", topic, data); + if (e.cp_signal_fault and not last_error_flags.cp_signal_fault) { + p_board_support->raise_evse_board_support_MREC14PilotFault("CP error", Everest::error::Severity::High); + } else if (not e.cp_signal_fault and last_error_flags.cp_signal_fault) { + p_board_support->request_clear_all_evse_board_support_MREC14PilotFault(); } + + last_error_flags = e; } } // namespace module diff --git a/modules/YetiDriver/YetiDriver.hpp b/modules/YetiDriver/YetiDriver.hpp index 1ad6706a2a..b30f172008 100644 --- a/modules/YetiDriver/YetiDriver.hpp +++ b/modules/YetiDriver/YetiDriver.hpp @@ -11,10 +11,10 @@ #include "ld-ev.hpp" // headers for provided interface implementations -#include +#include +#include +#include #include -#include -#include // ev@4bf81b14-a215-475c-a1d3-0a484ae48918:v1 #include "yeti_comms/evSerial.h" @@ -33,31 +33,29 @@ struct Conf { class YetiDriver : public Everest::ModuleBase { public: YetiDriver() = delete; - YetiDriver(const ModuleInfo& info, Everest::MqttProvider& mqtt_provider, Everest::TelemetryProvider& telemetry, + YetiDriver(const ModuleInfo& info, Everest::TelemetryProvider& telemetry, std::unique_ptr p_powermeter, - std::unique_ptr p_board_support, - std::unique_ptr p_yeti_extras, - std::unique_ptr p_yeti_simulation_control, Conf& config) : + std::unique_ptr p_board_support, std::unique_ptr p_rcd, + std::unique_ptr p_connector_lock, Conf& config) : ModuleBase(info), - mqtt(mqtt_provider), telemetry(telemetry), p_powermeter(std::move(p_powermeter)), p_board_support(std::move(p_board_support)), - p_yeti_extras(std::move(p_yeti_extras)), - p_yeti_simulation_control(std::move(p_yeti_simulation_control)), + p_rcd(std::move(p_rcd)), + p_connector_lock(std::move(p_connector_lock)), config(config){}; - Everest::MqttProvider& mqtt; Everest::TelemetryProvider& telemetry; const std::unique_ptr p_powermeter; - const std::unique_ptr p_board_support; - const std::unique_ptr p_yeti_extras; - const std::unique_ptr p_yeti_simulation_control; + const std::unique_ptr p_board_support; + const std::unique_ptr p_rcd; + const std::unique_ptr p_connector_lock; const Conf& config; // ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1 void publish_external_telemetry_livedata(const std::string& topic, const Everest::TelemetryMap& data); evSerial serial; + void clear_errors_on_unplug(); // ev@1fce4c5e-0ab8-41bb-90f7-14277703d2ac:v1 protected: @@ -78,17 +76,15 @@ class YetiDriver : public Everest::ModuleBase { Everest::TelemetryMap telemetry_rcd; std::mutex telemetry_mutex; Everest::Thread telemetryThreadHandle; + void error_handling(ErrorFlags e); + ErrorFlags last_error_flags; // ev@211cfdbe-f69a-4cd6-a4ec-f8aaa3d1b6c8:v1 }; // ev@087e516b-124c-48df-94fb-109508c7cda9:v1 Everest::json power_meter_data_to_json(const PowerMeter& p); -Everest::json debug_update_to_json(const DebugUpdate& d); -Everest::json state_update_to_json(const StateUpdate& s); Everest::json keep_alive_lo_to_json(const KeepAliveLo& k); std::string error_type_to_string(ErrorFlags s); -std::string state_to_string(const StateUpdate& s); -InterfaceControlMode str_to_control_mode(std::string data); // ev@087e516b-124c-48df-94fb-109508c7cda9:v1 } // namespace module diff --git a/modules/YetiDriver/board_support/board_support_ACImpl.cpp b/modules/YetiDriver/board_support/board_support_ACImpl.cpp deleted file mode 100644 index c79cbff5a9..0000000000 --- a/modules/YetiDriver/board_support/board_support_ACImpl.cpp +++ /dev/null @@ -1,179 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 - 2021 Pionix GmbH and Contributors to EVerest -#include "board_support_ACImpl.hpp" - -using namespace std::chrono_literals; - -namespace module { -namespace board_support { - -types::board_support::Event cast_event_type(const Event& e) { - switch (e.type) { - case Event_InterfaceEvent_CAR_PLUGGED_IN: - return types::board_support::Event::CarPluggedIn; - case Event_InterfaceEvent_CAR_REQUESTED_POWER: - return types::board_support::Event::CarRequestedPower; - case Event_InterfaceEvent_POWER_ON: - return types::board_support::Event::PowerOn; - case Event_InterfaceEvent_POWER_OFF: - return types::board_support::Event::PowerOff; - case Event_InterfaceEvent_CAR_REQUESTED_STOP_POWER: - return types::board_support::Event::CarRequestedStopPower; - case Event_InterfaceEvent_CAR_UNPLUGGED: - return types::board_support::Event::CarUnplugged; - case Event_InterfaceEvent_ERROR_E: - return types::board_support::Event::ErrorE; - case Event_InterfaceEvent_ERROR_DF: - return types::board_support::Event::ErrorDF; - case Event_InterfaceEvent_ERROR_RELAIS: - return types::board_support::Event::ErrorRelais; - case Event_InterfaceEvent_ERROR_RCD: - return types::board_support::Event::ErrorRCD; - case Event_InterfaceEvent_ERROR_VENTILATION_NOT_AVAILABLE: - return types::board_support::Event::ErrorVentilationNotAvailable; - case Event_InterfaceEvent_ERROR_OVER_CURRENT: - return types::board_support::Event::ErrorOverCurrent; - case Event_InterfaceEvent_ENTER_BCD: - return types::board_support::Event::EFtoBCD; - case Event_InterfaceEvent_LEAVE_BCD: - return types::board_support::Event::BCDtoEF; - case Event_InterfaceEvent_PERMANENT_FAULT: - return types::board_support::Event::PermanentFault; - case Event_InterfaceEvent_EVSE_REPLUG_STARTED: - return types::board_support::Event::EvseReplugStarted; - case Event_InterfaceEvent_EVSE_REPLUG_FINISHED: - return types::board_support::Event::EvseReplugFinished; - } - - EVLOG_AND_THROW(Everest::EverestConfigError("Received an unknown interface event from Yeti")); -} - -void board_support_ACImpl::init() { - { - std::lock_guard lock(capsMutex); - - caps.min_current_A_import = mod->config.caps_min_current_A; - caps.max_current_A_import = 6; - caps.min_phase_count_import = 1; - caps.max_phase_count_import = 3; - caps.supports_changing_phases_during_charging = false; - - caps.min_current_A_export = mod->config.caps_min_current_A; - caps.max_current_A_export = 6; - caps.min_phase_count_export = 1; - caps.max_phase_count_export = 3; - caps.supports_changing_phases_during_charging = false; - } - - mod->serial.signalEvent.connect([this](Event e) { publish_event(cast_event_type(e)); }); - - // FIXME - // Everything used here should be moved out of debug update in protobuf - mod->serial.signalDebugUpdate.connect([this](DebugUpdate d) { - publish_nr_of_phases_available((d.use_three_phases ? 3 : 1)); - - types::board_support::Telemetry telemetry; - telemetry.temperature = d.cpu_temperature; - telemetry.fan_rpm = 0.; - telemetry.supply_voltage_12V = d.supply_voltage_12V; - telemetry.supply_voltage_minus_12V = d.supply_voltage_N12V; - telemetry.rcd_current = d.rcd_current; - telemetry.relais_on = d.relais_on; - - publish_telemetry(telemetry); - }); - - mod->serial.signalKeepAliveLo.connect([this](KeepAliveLo l) { - std::lock_guard lock(capsMutex); - - caps.min_current_A_import = - (mod->config.caps_min_current_A >= 0 ? mod->config.caps_min_current_A : l.hwcap_min_current); - caps.max_current_A_import = l.hwcap_max_current; - caps.min_phase_count_import = l.hwcap_min_phase_count; - caps.max_phase_count_import = l.hwcap_max_phase_count; - - caps.min_current_A_export = - (mod->config.caps_min_current_A >= 0 ? mod->config.caps_min_current_A : l.hwcap_min_current); - caps.max_current_A_export = l.hwcap_max_current; - caps.min_phase_count_export = l.hwcap_min_phase_count; - caps.max_phase_count_export = l.hwcap_max_phase_count; - - caps.supports_changing_phases_during_charging = l.supports_changing_phases_during_charging; - caps_received = true; - }); -} // namespace board_support - -void board_support_ACImpl::ready() { - // Wait for caps to be received at least once - int i; - for (i = 0; i < 50; i++) { - { - std::lock_guard lock(capsMutex); - if (caps_received) - break; - } - - std::this_thread::sleep_for(100ms); - } - if (i == 49) { - EVLOG_AND_THROW( - Everest::EverestTimeoutError("Did not receive hardware capabilities from Yeti hardware, exiting.")); - } -} - -void board_support_ACImpl::handle_setup(bool& three_phases, bool& has_ventilation, std::string& country_code, - bool& rcd_enabled) { - mod->serial.setCountryCode(country_code.c_str()); - mod->serial.setHasVentilation(has_ventilation); - mod->serial.setThreePhases(three_phases); - mod->serial.enableRCD(rcd_enabled); -}; - -void board_support_ACImpl::handle_enable(bool& value) { - if (value) - mod->serial.enable(); - else - mod->serial.disable(); -}; - -void board_support_ACImpl::handle_pwm_on(double& value) { - mod->serial.setPWM(1, value); -}; - -void board_support_ACImpl::handle_pwm_off() { - mod->serial.setPWM(0, 0.); -}; - -void board_support_ACImpl::handle_pwm_F() { - mod->serial.setPWM(2, 0.); -}; - -void board_support_ACImpl::handle_allow_power_on(bool& value) { - mod->serial.allowPowerOn(value); -}; - -bool board_support_ACImpl::handle_force_unlock() { - return mod->serial.forceUnlock(); -}; - -void board_support_ACImpl::handle_switch_three_phases_while_charging(bool& value) { - mod->serial.switchThreePhasesWhileCharging(value); -}; - -void board_support_ACImpl::handle_evse_replug(int& value) { - mod->serial.replug(value); -}; - -double board_support_ACImpl::handle_read_pp_ampacity() { - // FIXME: read PP ampacity from yeti, report back maximum current the hardware can handle for now - std::lock_guard lock(capsMutex); - return caps.max_current_A_import; -} - -types::board_support::HardwareCapabilities board_support_ACImpl::handle_get_hw_capabilities() { - std::lock_guard lock(capsMutex); - return caps; -}; - -} // namespace board_support -} // namespace module diff --git a/modules/YetiDriver/board_support/evse_board_supportImpl.cpp b/modules/YetiDriver/board_support/evse_board_supportImpl.cpp new file mode 100644 index 0000000000..bcf12ed44f --- /dev/null +++ b/modules/YetiDriver/board_support/evse_board_supportImpl.cpp @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest + +#include "evse_board_supportImpl.hpp" + +namespace module { +namespace board_support { + +static types::board_support_common::BspEvent cast_event_type(CpState cp_state) { + types::board_support_common::BspEvent event; + switch (cp_state) { + case CpState_STATE_A: + event.event = types::board_support_common::Event::A; + break; + case CpState_STATE_B: + event.event = types::board_support_common::Event::B; + break; + case CpState_STATE_C: + event.event = types::board_support_common::Event::C; + break; + case CpState_STATE_D: + event.event = types::board_support_common::Event::D; + break; + case CpState_STATE_E: + event.event = types::board_support_common::Event::E; + break; + case CpState_STATE_F: + event.event = types::board_support_common::Event::F; + break; + } + return event; +} + +static types::board_support_common::BspEvent cast_event_type(bool relais_state) { + types::board_support_common::BspEvent event; + if (relais_state) { + event.event = types::board_support_common::Event::PowerOn; + } else { + event.event = types::board_support_common::Event::PowerOff; + } + return event; +} + +static types::board_support_common::ProximityPilot cast_pp_type(PpState pp_state) { + types::board_support_common::ProximityPilot pp; + switch (pp_state) { + case PpState_STATE_13A: + pp.ampacity = types::board_support_common::Ampacity::A_13; + break; + case PpState_STATE_20A: + pp.ampacity = types::board_support_common::Ampacity::A_20; + break; + case PpState_STATE_32A: + pp.ampacity = types::board_support_common::Ampacity::A_32; + break; + case PpState_STATE_70A: + pp.ampacity = types::board_support_common::Ampacity::A_63_3ph_70_1ph; + break; + case PpState_STATE_FAULT: + pp.ampacity = types::board_support_common::Ampacity::None; + break; + case PpState_STATE_NC: + pp.ampacity = types::board_support_common::Ampacity::None; + break; + } + return pp; +} + +void evse_board_supportImpl::init() { + { + std::lock_guard lock(capsMutex); + + caps.min_current_A_import = mod->config.caps_min_current_A; + caps.max_current_A_import = 6; + caps.min_phase_count_import = 1; + caps.max_phase_count_import = 3; + caps.supports_changing_phases_during_charging = false; + + caps.min_current_A_export = mod->config.caps_min_current_A; + caps.max_current_A_export = 6; + caps.min_phase_count_export = 1; + caps.max_phase_count_export = 3; + caps.supports_changing_phases_during_charging = false; + } + + mod->serial.signalCPState.connect([this](CpState cp_state) { + publish_event(cast_event_type(cp_state)); + + if (cp_state == CpState_STATE_A) { + mod->clear_errors_on_unplug(); + } + }); + mod->serial.signalRelaisState.connect([this](bool relais_state) { publish_event(cast_event_type(relais_state)); }); + mod->serial.signalPPState.connect([this](PpState pp_state) { + std::lock_guard lock(capsMutex); + last_pp = cast_pp_type(pp_state); + publish_ac_pp_ampacity(last_pp); + }); + + mod->serial.signalKeepAliveLo.connect([this](KeepAliveLo l) { + std::lock_guard lock(capsMutex); + + caps.min_current_A_import = + (mod->config.caps_min_current_A >= 0 ? mod->config.caps_min_current_A : l.hwcap_min_current); + caps.max_current_A_import = l.hwcap_max_current; + caps.min_phase_count_import = l.hwcap_min_phase_count; + caps.max_phase_count_import = l.hwcap_max_phase_count; + + caps.min_current_A_export = + (mod->config.caps_min_current_A >= 0 ? mod->config.caps_min_current_A : l.hwcap_min_current); + caps.max_current_A_export = l.hwcap_max_current; + caps.min_phase_count_export = l.hwcap_min_phase_count; + caps.max_phase_count_export = l.hwcap_max_phase_count; + + caps.supports_changing_phases_during_charging = l.supports_changing_phases_during_charging; + caps_received = true; + }); +} + +void evse_board_supportImpl::ready() { + // Wait for caps to be received at least once + int i; + for (i = 0; i < 50; i++) { + { + std::lock_guard lock(capsMutex); + if (caps_received) + break; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } + if (i == 49) { + EVLOG_AND_THROW( + Everest::EverestTimeoutError("Did not receive hardware capabilities from Yeti hardware, exiting.")); + } +} + +types::evse_board_support::HardwareCapabilities evse_board_supportImpl::handle_get_hw_capabilities() { + std::lock_guard lock(capsMutex); + return caps; +} + +void evse_board_supportImpl::handle_pwm_on(double& value) { + mod->serial.setPWM(value * 100); +} + +void evse_board_supportImpl::handle_pwm_off() { + mod->serial.setPWM(10001); +} + +void evse_board_supportImpl::handle_pwm_F() { + mod->serial.setPWM(0); +} + +void evse_board_supportImpl::handle_allow_power_on(types::evse_board_support::PowerOnOff& value) { + mod->serial.allowPowerOn(value.allow_power_on); +} + +types::board_support_common::ProximityPilot evse_board_supportImpl::handle_ac_read_pp_ampacity() { + // FIXME: read PP ampacity from yeti, report back maximum current the hardware can handle for now + std::lock_guard lock(capsMutex); + return last_pp; +} + +void evse_board_supportImpl::handle_ac_set_overcurrent_limit_A(double& value) { + // your code for cmd ac_set_overcurrent_limit_A goes here +} + +void evse_board_supportImpl::handle_ac_switch_three_phases_while_charging(bool& value) { +} + +void evse_board_supportImpl::handle_evse_replug(int& value) { +} + +void evse_board_supportImpl::handle_enable(bool& value) { + // Query CP state once and publish +} + +void evse_board_supportImpl::handle_setup(bool& three_phases, bool& has_ventilation, std::string& country_code) { +} + +} // namespace board_support +} // namespace module diff --git a/modules/YetiDriver/board_support/board_support_ACImpl.hpp b/modules/YetiDriver/board_support/evse_board_supportImpl.hpp similarity index 58% rename from modules/YetiDriver/board_support/board_support_ACImpl.hpp rename to modules/YetiDriver/board_support/evse_board_supportImpl.hpp index 0141988b2e..636a4bd1d5 100644 --- a/modules/YetiDriver/board_support/board_support_ACImpl.hpp +++ b/modules/YetiDriver/board_support/evse_board_supportImpl.hpp @@ -1,14 +1,14 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright Pionix GmbH and Contributors to EVerest -#ifndef BOARD_SUPPORT_BOARD_SUPPORT_AC_IMPL_HPP -#define BOARD_SUPPORT_BOARD_SUPPORT_AC_IMPL_HPP +#ifndef BOARD_SUPPORT_EVSE_BOARD_SUPPORT_IMPL_HPP +#define BOARD_SUPPORT_EVSE_BOARD_SUPPORT_IMPL_HPP // // AUTO GENERATED - MARKED REGIONS WILL BE KEPT // template version 3 // -#include +#include #include "../YetiDriver.hpp" @@ -21,11 +21,11 @@ namespace board_support { struct Conf {}; -class board_support_ACImpl : public board_support_ACImplBase { +class evse_board_supportImpl : public evse_board_supportImplBase { public: - board_support_ACImpl() = delete; - board_support_ACImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer& mod, Conf& config) : - board_support_ACImplBase(ev, "board_support"), mod(mod), config(config){}; + evse_board_supportImpl() = delete; + evse_board_supportImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer& mod, Conf& config) : + evse_board_supportImplBase(ev, "board_support"), mod(mod), config(config){}; // ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1 // insert your public definitions here @@ -33,18 +33,17 @@ class board_support_ACImpl : public board_support_ACImplBase { protected: // command handler functions (virtual) - virtual void handle_setup(bool& three_phases, bool& has_ventilation, std::string& country_code, - bool& rcd_enabled) override; - virtual types::board_support::HardwareCapabilities handle_get_hw_capabilities() override; + virtual void handle_setup(bool& three_phases, bool& has_ventilation, std::string& country_code) override; + virtual types::evse_board_support::HardwareCapabilities handle_get_hw_capabilities() override; virtual void handle_enable(bool& value) override; virtual void handle_pwm_on(double& value) override; virtual void handle_pwm_off() override; virtual void handle_pwm_F() override; - virtual void handle_allow_power_on(bool& value) override; - virtual bool handle_force_unlock() override; - virtual void handle_switch_three_phases_while_charging(bool& value) override; + virtual void handle_allow_power_on(types::evse_board_support::PowerOnOff& value) override; + virtual void handle_ac_switch_three_phases_while_charging(bool& value) override; virtual void handle_evse_replug(int& value) override; - virtual double handle_read_pp_ampacity() override; + virtual types::board_support_common::ProximityPilot handle_ac_read_pp_ampacity() override; + virtual void handle_ac_set_overcurrent_limit_A(double& value) override; // ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1 // insert your protected definitions here @@ -59,9 +58,10 @@ class board_support_ACImpl : public board_support_ACImplBase { // ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1 // insert your private definitions here - types::board_support::HardwareCapabilities caps; + types::evse_board_support::HardwareCapabilities caps; bool caps_received{false}; std::mutex capsMutex; + types::board_support_common::ProximityPilot last_pp; // ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1 }; @@ -72,4 +72,4 @@ class board_support_ACImpl : public board_support_ACImplBase { } // namespace board_support } // namespace module -#endif // BOARD_SUPPORT_BOARD_SUPPORT_AC_IMPL_HPP +#endif // BOARD_SUPPORT_EVSE_BOARD_SUPPORT_IMPL_HPP diff --git a/modules/YetiDriver/connector_lock/connector_lockImpl.cpp b/modules/YetiDriver/connector_lock/connector_lockImpl.cpp new file mode 100644 index 0000000000..fb9f887fad --- /dev/null +++ b/modules/YetiDriver/connector_lock/connector_lockImpl.cpp @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest + +#include "connector_lockImpl.hpp" + +namespace module { +namespace connector_lock { + +void connector_lockImpl::init() { + mod->serial.signalLockState.connect([this](bool l) { lock_state = l; }); +} + +void connector_lockImpl::ready() { +} + +void connector_lockImpl::handle_lock() { +} + +void connector_lockImpl::handle_unlock() { + mod->serial.forceUnlock(); +} + +} // namespace connector_lock +} // namespace module diff --git a/modules/YetiDriver/yeti_simulation_control/yeti_simulation_controlImpl.hpp b/modules/YetiDriver/connector_lock/connector_lockImpl.hpp similarity index 57% rename from modules/YetiDriver/yeti_simulation_control/yeti_simulation_controlImpl.hpp rename to modules/YetiDriver/connector_lock/connector_lockImpl.hpp index 51ba8db8ab..b1d0b159e6 100644 --- a/modules/YetiDriver/yeti_simulation_control/yeti_simulation_controlImpl.hpp +++ b/modules/YetiDriver/connector_lock/connector_lockImpl.hpp @@ -1,14 +1,14 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright Pionix GmbH and Contributors to EVerest -#ifndef YETI_SIMULATION_CONTROL_YETI_SIMULATION_CONTROL_IMPL_HPP -#define YETI_SIMULATION_CONTROL_YETI_SIMULATION_CONTROL_IMPL_HPP +#ifndef CONNECTOR_LOCK_CONNECTOR_LOCK_IMPL_HPP +#define CONNECTOR_LOCK_CONNECTOR_LOCK_IMPL_HPP // // AUTO GENERATED - MARKED REGIONS WILL BE KEPT // template version 3 // -#include +#include #include "../YetiDriver.hpp" @@ -17,16 +17,15 @@ // ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1 namespace module { -namespace yeti_simulation_control { +namespace connector_lock { struct Conf {}; -class yeti_simulation_controlImpl : public yeti_simulation_controlImplBase { +class connector_lockImpl : public connector_lockImplBase { public: - yeti_simulation_controlImpl() = delete; - yeti_simulation_controlImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer& mod, - Conf& config) : - yeti_simulation_controlImplBase(ev, "yeti_simulation_control"), mod(mod), config(config){}; + connector_lockImpl() = delete; + connector_lockImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer& mod, Conf& config) : + connector_lockImplBase(ev, "connector_lock"), mod(mod), config(config){}; // ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1 // insert your public definitions here @@ -34,8 +33,8 @@ class yeti_simulation_controlImpl : public yeti_simulation_controlImplBase { protected: // command handler functions (virtual) - virtual void handle_enable(bool& value) override; - virtual void handle_setSimulationData(types::yeti::SimulationData& value) override; + virtual void handle_lock() override; + virtual void handle_unlock() override; // ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1 // insert your protected definitions here @@ -50,6 +49,7 @@ class yeti_simulation_controlImpl : public yeti_simulation_controlImplBase { // ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1 // insert your private definitions here + std::atomic_bool lock_state{false}; // ev@3370e4dd-95f4-47a9-aaec-ea76f34a66c9:v1 }; @@ -57,7 +57,7 @@ class yeti_simulation_controlImpl : public yeti_simulation_controlImplBase { // insert other definitions here // ev@3d7da0ad-02c2-493d-9920-0bbbd56b9876:v1 -} // namespace yeti_simulation_control +} // namespace connector_lock } // namespace module -#endif // YETI_SIMULATION_CONTROL_YETI_SIMULATION_CONTROL_IMPL_HPP +#endif // CONNECTOR_LOCK_CONNECTOR_LOCK_IMPL_HPP diff --git a/modules/YetiDriver/manifest.yaml b/modules/YetiDriver/manifest.yaml index 42a4e5e666..d4b53adf85 100644 --- a/modules/YetiDriver/manifest.yaml +++ b/modules/YetiDriver/manifest.yaml @@ -33,15 +33,14 @@ provides: interface: powermeter description: provides the Yeti Internal Power Meter board_support: - interface: board_support_AC - description: provides the board support Interface to low level control control pilot, relais, rcd, motor lock - yeti_extras: - interface: yeti_extras - description: extra functionality special for Yeti - yeti_simulation_control: - interface: yeti_simulation_control - description: Interface for the Yeti HIL simulator -enable_external_mqtt: true + interface: evse_board_support + description: provides the board support Interface to low level control control pilot, relais, motor lock + rcd: + interface: ac_rcd + description: RCD interface of the onboard RCD + connector_lock: + interface: connector_lock + description: Interface for the motor lock enable_telemetry: true metadata: license: https://opensource.org/licenses/Apache-2.0 diff --git a/modules/YetiDriver/rcd/ac_rcdImpl.cpp b/modules/YetiDriver/rcd/ac_rcdImpl.cpp new file mode 100644 index 0000000000..a1c868f27a --- /dev/null +++ b/modules/YetiDriver/rcd/ac_rcdImpl.cpp @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright Pionix GmbH and Contributors to EVerest + +#include "ac_rcdImpl.hpp" + +namespace module { +namespace rcd { + +void ac_rcdImpl::init() { +} + +void ac_rcdImpl::ready() { +} + +void ac_rcdImpl::handle_self_test() { + // your code for cmd self_test goes here +} + +bool ac_rcdImpl::handle_reset() { + // your code for cmd reset goes here + return true; +} + +} // namespace rcd +} // namespace module diff --git a/modules/YetiDriver/yeti_extras/yeti_extrasImpl.hpp b/modules/YetiDriver/rcd/ac_rcdImpl.hpp similarity index 66% rename from modules/YetiDriver/yeti_extras/yeti_extrasImpl.hpp rename to modules/YetiDriver/rcd/ac_rcdImpl.hpp index 2500653dd6..19cfe20aaa 100644 --- a/modules/YetiDriver/yeti_extras/yeti_extrasImpl.hpp +++ b/modules/YetiDriver/rcd/ac_rcdImpl.hpp @@ -1,14 +1,14 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright Pionix GmbH and Contributors to EVerest -#ifndef YETI_EXTRAS_YETI_EXTRAS_IMPL_HPP -#define YETI_EXTRAS_YETI_EXTRAS_IMPL_HPP +#ifndef RCD_AC_RCD_IMPL_HPP +#define RCD_AC_RCD_IMPL_HPP // // AUTO GENERATED - MARKED REGIONS WILL BE KEPT // template version 3 // -#include +#include #include "../YetiDriver.hpp" @@ -17,15 +17,15 @@ // ev@75ac1216-19eb-4182-a85c-820f1fc2c091:v1 namespace module { -namespace yeti_extras { +namespace rcd { struct Conf {}; -class yeti_extrasImpl : public yeti_extrasImplBase { +class ac_rcdImpl : public ac_rcdImplBase { public: - yeti_extrasImpl() = delete; - yeti_extrasImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer& mod, Conf& config) : - yeti_extrasImplBase(ev, "yeti_extras"), mod(mod), config(config){}; + ac_rcdImpl() = delete; + ac_rcdImpl(Everest::ModuleAdapter* ev, const Everest::PtrContainer& mod, Conf& config) : + ac_rcdImplBase(ev, "rcd"), mod(mod), config(config){}; // ev@8ea32d28-373f-4c90-ae5e-b4fcc74e2a61:v1 // insert your public definitions here @@ -33,7 +33,8 @@ class yeti_extrasImpl : public yeti_extrasImplBase { protected: // command handler functions (virtual) - virtual void handle_firmware_update(std::string& firmware_binary) override; + virtual void handle_self_test() override; + virtual bool handle_reset() override; // ev@d2d1847a-7b88-41dd-ad07-92785f06f5c4:v1 // insert your protected definitions here @@ -55,7 +56,7 @@ class yeti_extrasImpl : public yeti_extrasImplBase { // insert other definitions here // ev@3d7da0ad-02c2-493d-9920-0bbbd56b9876:v1 -} // namespace yeti_extras +} // namespace rcd } // namespace module -#endif // YETI_EXTRAS_YETI_EXTRAS_IMPL_HPP +#endif // RCD_AC_RCD_IMPL_HPP diff --git a/modules/YetiDriver/yeti_comms/CMakeLists.txt b/modules/YetiDriver/yeti_comms/CMakeLists.txt index 554ecb836d..15d4ed5a08 100644 --- a/modules/YetiDriver/yeti_comms/CMakeLists.txt +++ b/modules/YetiDriver/yeti_comms/CMakeLists.txt @@ -3,19 +3,15 @@ cmake_minimum_required(VERSION 3.10) # set the project name project(yeti_comms VERSION 0.1) # specify the C++ standard -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) - -configure_file(config.h.in config.h) - # add the executable add_library(yeti_comms STATIC) target_sources(yeti_comms PRIVATE evSerial.cpp - protobuf/hi2lo.pb.c - protobuf/lo2hi.pb.c + protobuf/yeti.pb.c ) target_include_directories(yeti_comms diff --git a/modules/YetiDriver/yeti_comms/config.h.in b/modules/YetiDriver/yeti_comms/config.h.in deleted file mode 100644 index 4b96d6dfff..0000000000 --- a/modules/YetiDriver/yeti_comms/config.h.in +++ /dev/null @@ -1,3 +0,0 @@ -// the configured options and settings for YetiDriver -#define YetiComms_VERSION_MAJOR @YetiComms_VERSION_MAJOR@ -#define YetiComms_VERSION_MINOR @YetiComms_VERSION_MINOR@ diff --git a/modules/YetiDriver/yeti_comms/evSerial.cpp b/modules/YetiDriver/yeti_comms/evSerial.cpp index 41b3c4e999..7fc01c0702 100644 --- a/modules/YetiDriver/yeti_comms/evSerial.cpp +++ b/modules/YetiDriver/yeti_comms/evSerial.cpp @@ -18,9 +18,7 @@ #include #include -#include "common.pb.h" -#include "hi2lo.pb.h" -#include "lo2hi.pb.h" +#include "yeti.pb.h" evSerial::evSerial() { fd = 0; @@ -142,44 +140,39 @@ void evSerial::handlePacket(uint8_t* buf, int len) { len -= 4; - LoToHi msg_in; + McuToEverest msg_in; pb_istream_t istream = pb_istream_from_buffer(buf, len); - if (pb_decode(&istream, LoToHi_fields, &msg_in)) + if (pb_decode(&istream, McuToEverest_fields, &msg_in)) switch (msg_in.which_payload) { - case LoToHi_state_update_tag: - // printf("Received state_update\n"); - signalStateUpdate(msg_in.payload.state_update); - break; - case LoToHi_debug_update_tag: - // printf("Received debug_update\n"); - signalDebugUpdate(msg_in.payload.debug_update); - break; - case LoToHi_keep_alive_tag: + case McuToEverest_keep_alive_tag: // printf("Received keep_alive_lo\n"); signalKeepAliveLo(msg_in.payload.keep_alive); // detect connection timeout if keep_alive packets stop coming... last_keep_alive_lo_timestamp = date::utc_clock::now(); break; - case LoToHi_power_meter_tag: - // printf("Received power_meter\n"); - // FIXME: in the long run we could set the clock in the uC. But for now we just fix the timestamp here... - { - auto unix_timestamp = std::chrono::seconds(std::time(NULL)); - msg_in.payload.power_meter.time_stamp = unix_timestamp.count(); - } + case McuToEverest_power_meter_tag: { + auto unix_timestamp = std::chrono::seconds(std::time(NULL)); + msg_in.payload.power_meter.time_stamp = unix_timestamp.count(); signalPowerMeter(msg_in.payload.power_meter); + } break; + case McuToEverest_cp_state_tag: + signalCPState(msg_in.payload.cp_state); + break; + case McuToEverest_pp_state_tag: + signalPPState(msg_in.payload.pp_state); break; - case LoToHi_simulation_feedback_tag: - // printf("Received power_meter\n"); - signalSimulationFeedback(msg_in.payload.simulation_feedback); + case McuToEverest_relais_state_tag: + signalRelaisState(msg_in.payload.relais_state); break; - case LoToHi_event_tag: - // printf("Received event %i\n",msg_in.payload.event); - signalEvent(msg_in.payload.event); + case McuToEverest_lock_state_tag: + signalLockState(msg_in.payload.lock_state); break; - case LoToHi_reset_done_tag: + case McuToEverest_error_flags_tag: + signalErrorFlags(msg_in.payload.error_flags); + break; + case McuToEverest_reset_tag: // printf("Received reset_done\n"); reset_done_flag = true; if (!forced_reset) @@ -259,11 +252,11 @@ void evSerial::readThread() { } } -bool evSerial::linkWrite(HiToLo* m) { +bool evSerial::linkWrite(EverestToMcu* m) { uint8_t tx_packet_buf[1024]; uint8_t encode_buf[1500]; pb_ostream_t ostream = pb_ostream_from_buffer(tx_packet_buf, sizeof(tx_packet_buf) - 4); - bool status = pb_encode(&ostream, HiToLo_fields, m); + bool status = pb_encode(&ostream, McuToEverest_fields, m); if (!status) { // couldn't encode @@ -320,122 +313,24 @@ bool evSerial::serial_timed_out() { return false; } -void evSerial::setMaxCurrent(float c) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_set_max_current_tag; - msg_out.payload.set_max_current.ampere = c; - linkWrite(&msg_out); -} - -void evSerial::setThreePhases(bool n) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_set_three_phases_tag; - msg_out.payload.set_three_phases.n = n; - linkWrite(&msg_out); -} - -void evSerial::enableRCD(bool e) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_enable_rcd_tag; - msg_out.payload.enable_rcd.e = e; - linkWrite(&msg_out); -} - -void evSerial::setHasVentilation(bool v) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_set_has_ventilation_tag; - msg_out.payload.set_has_ventilation.v = v; - linkWrite(&msg_out); -} - -void evSerial::setCountryCode(const char* iso3166_alpha2_code) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_set_country_code_tag; - if (strlen(iso3166_alpha2_code) < 10) { - strcpy(msg_out.payload.set_country_code.iso3166_alpha2_code, iso3166_alpha2_code); - linkWrite(&msg_out); - } -} - -void evSerial::setControlMode(InterfaceControlMode c) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_set_control_mode_tag; - msg_out.payload.set_control_mode.control_mode = c; - linkWrite(&msg_out); -} - -void evSerial::setAuth(const char* userid) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_set_auth_tag; - if (strlen(userid) < 50) { - strcpy(msg_out.payload.set_auth.userid, userid); - linkWrite(&msg_out); - } -} - -void evSerial::setPWM(uint32_t mode, float dc) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_set_pwm_tag; - msg_out.payload.set_pwm.mode = mode; - msg_out.payload.set_pwm.duty_cycle = dc; +void evSerial::setPWM(uint32_t dc) { + EverestToMcu msg_out = EverestToMcu_init_default; + msg_out.which_payload = EverestToMcu_pwm_duty_cycle_tag; + msg_out.payload.pwm_duty_cycle = dc; linkWrite(&msg_out); } void evSerial::allowPowerOn(bool p) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_allow_power_on_tag; - msg_out.payload.allow_power_on.p = p; + EverestToMcu msg_out = EverestToMcu_init_default; + msg_out.which_payload = EverestToMcu_allow_power_on_tag; + msg_out.payload.allow_power_on = p; linkWrite(&msg_out); } -bool evSerial::forceUnlock() { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_force_unlock_tag; - linkWrite(&msg_out); - return true; // FIXME: actuall return success value from uC -} - -void evSerial::enable() { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_enable_tag; - linkWrite(&msg_out); -} - -void evSerial::disable() { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_disable_tag; - linkWrite(&msg_out); -} - -void evSerial::switchThreePhasesWhileCharging(bool n) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_switch_three_phases_while_charging_tag; - msg_out.payload.switch_three_phases_while_charging.n = n; - linkWrite(&msg_out); -} - -void evSerial::replug(int t) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_replug_tag; - msg_out.payload.replug.time = t; - linkWrite(&msg_out); -} - -void evSerial::pauseCharging() { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_pause_charging_tag; - linkWrite(&msg_out); -} - -void evSerial::resumeCharging() { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_resume_charging_tag; - linkWrite(&msg_out); -} - -void evSerial::restart() { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_restart_tag; +void evSerial::forceUnlock() { + EverestToMcu msg_out = EverestToMcu_init_default; + msg_out.which_payload = EverestToMcu_connector_lock_tag; + msg_out.payload.connector_lock = false; linkWrite(&msg_out); } @@ -457,8 +352,8 @@ bool evSerial::reset(const int reset_pin) { system(cmd); } else { // Try to soft reset Yeti controller to be in a known state - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_reset_tag; + EverestToMcu msg_out = EverestToMcu_init_default; + msg_out.which_payload = EverestToMcu_reset_tag; linkWrite(&msg_out); } @@ -486,34 +381,18 @@ bool evSerial::reset(const int reset_pin) { } void evSerial::firmwareUpdate(bool rom) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_firmware_update_tag; + EverestToMcu msg_out = EverestToMcu_init_default; + msg_out.which_payload = EverestToMcu_firmware_update_tag; msg_out.payload.firmware_update.invoke_rom_bootloader = rom; linkWrite(&msg_out); } -void evSerial::enableSimulation(bool s) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_enable_simulation_tag; - msg_out.payload.enable_simulation.s = s; - linkWrite(&msg_out); -} - -void evSerial::setSimulationData(SimulationData s) { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_simulation_data_tag; - msg_out.payload.simulation_data = s; - linkWrite(&msg_out); -} - void evSerial::keepAlive() { - HiToLo msg_out = HiToLo_init_default; - msg_out.which_payload = HiToLo_keep_alive_tag; + EverestToMcu msg_out = EverestToMcu_init_default; + msg_out.which_payload = EverestToMcu_keep_alive_tag; msg_out.payload.keep_alive.time_stamp = 0; msg_out.payload.keep_alive.hw_type = 0; msg_out.payload.keep_alive.hw_revision = 0; - msg_out.payload.keep_alive.protocol_version_major = 0; - msg_out.payload.keep_alive.protocol_version_minor = 1; strcpy(msg_out.payload.keep_alive.sw_version_string, "n/a"); linkWrite(&msg_out); } diff --git a/modules/YetiDriver/yeti_comms/evSerial.h b/modules/YetiDriver/yeti_comms/evSerial.h index 9f45d27f7f..e6716e6a2b 100644 --- a/modules/YetiDriver/yeti_comms/evSerial.h +++ b/modules/YetiDriver/yeti_comms/evSerial.h @@ -3,18 +3,17 @@ #ifndef YETI_SERIAL #define YETI_SERIAL +#include "yeti.pb.h" +#include +#include +#include #include #include #include -#include -#include "lo2hi.pb.h" -#include "hi2lo.pb.h" -#include -#include class evSerial { - public: +public: evSerial(); ~evSerial(); @@ -23,43 +22,26 @@ class evSerial { void readThread(); void run(); - void setMaxCurrent(float c); - void setThreePhases(bool n); - void enableRCD(bool e); - void setHasVentilation(bool v); - void setCountryCode(const char* iso3166_alpha2_code); - void setControlMode(InterfaceControlMode s); - void setAuth(const char* userid); - void enable(); - void disable(); - void switchThreePhasesWhileCharging(bool n); - void replug(int t); - void pauseCharging(); - void resumeCharging(); - void restart(); bool reset(const int reset_pin); void firmwareUpdate(bool rom); void keepAlive(); - void setPWM(uint32_t mode, float dc); + void setPWM(uint32_t dc); void allowPowerOn(bool p); - bool forceUnlock(); - - void enableSimulation(bool s); - void setSimulationData(SimulationData s); - + void forceUnlock(); - sigslot::signal signalStateUpdate; - sigslot::signal signalDebugUpdate; sigslot::signal signalKeepAliveLo; sigslot::signal signalPowerMeter; - sigslot::signal signalSimulationFeedback; - sigslot::signal signalEvent; + sigslot::signal signalCPState; + sigslot::signal signalPPState; + sigslot::signal signalErrorFlags; + sigslot::signal signalRelaisState; + sigslot::signal signalLockState; + sigslot::signal<> signalSpuriousReset; sigslot::signal<> signalConnectionTimeout; - private: - +private: // Serial interface bool setSerialAttributes(); int fd; @@ -70,18 +52,18 @@ class evSerial { void handlePacket(uint8_t* buf, int len); void cobsDecode(uint8_t* buf, int len); void cobsDecodeByte(uint8_t byte); - size_t cobsEncode(const void *data, size_t length, uint8_t *buffer); + size_t cobsEncode(const void* data, size_t length, uint8_t* buffer); uint8_t msg[2048]; uint8_t code; uint8_t block; - uint8_t *decode; - uint32_t crc32(uint8_t *buf, int len); + uint8_t* decode; + uint32_t crc32(uint8_t* buf, int len); // Read thread for serial port Everest::Thread readThreadHandle; Everest::Thread timeoutDetectionThreadHandle; - bool linkWrite(HiToLo *m); + bool linkWrite(EverestToMcu* m); volatile bool reset_done_flag; volatile bool forced_reset; diff --git a/modules/YetiDriver/yeti_comms/protobuf/common.pb.c b/modules/YetiDriver/yeti_comms/protobuf/common.pb.c deleted file mode 100644 index 02eb54a203..0000000000 --- a/modules/YetiDriver/yeti_comms/protobuf/common.pb.c +++ /dev/null @@ -1,10 +0,0 @@ -/* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5 */ - -#include "common.pb.h" -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - - - diff --git a/modules/YetiDriver/yeti_comms/protobuf/common.pb.h b/modules/YetiDriver/yeti_comms/protobuf/common.pb.h deleted file mode 100644 index d221666ce8..0000000000 --- a/modules/YetiDriver/yeti_comms/protobuf/common.pb.h +++ /dev/null @@ -1,33 +0,0 @@ -/* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5 */ - -#ifndef PB_COMMON_PB_H_INCLUDED -#define PB_COMMON_PB_H_INCLUDED -#include - -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -/* Enum definitions */ -typedef enum _InterfaceControlMode { - InterfaceControlMode_NONE = 0, - InterfaceControlMode_HIGH = 1, - InterfaceControlMode_LOW = 2 -} InterfaceControlMode; - -/* Helper constants for enums */ -#define _InterfaceControlMode_MIN InterfaceControlMode_NONE -#define _InterfaceControlMode_MAX InterfaceControlMode_LOW -#define _InterfaceControlMode_ARRAYSIZE ((InterfaceControlMode)(InterfaceControlMode_LOW+1)) - - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/modules/YetiDriver/yeti_comms/protobuf/common.proto b/modules/YetiDriver/yeti_comms/protobuf/common.proto deleted file mode 100644 index 1a0c8d515f..0000000000 --- a/modules/YetiDriver/yeti_comms/protobuf/common.proto +++ /dev/null @@ -1,8 +0,0 @@ -syntax = "proto3"; - -enum InterfaceControlMode { - NONE = 0; - HIGH = 1; - LOW = 2; -} - diff --git a/modules/YetiDriver/yeti_comms/protobuf/generate_nanopb.sh b/modules/YetiDriver/yeti_comms/protobuf/generate_nanopb.sh index e48d551f3c..5467437308 100755 --- a/modules/YetiDriver/yeti_comms/protobuf/generate_nanopb.sh +++ b/modules/YetiDriver/yeti_comms/protobuf/generate_nanopb.sh @@ -1,2 +1,2 @@ #!/bin/sh -nanopb_generator.py -L "#include " -I . -D . common.proto lo2hi.proto hi2lo.proto +nanopb_generator.py -L "#include " -I . -D . yeti.proto diff --git a/modules/YetiDriver/yeti_comms/protobuf/hi2lo.options b/modules/YetiDriver/yeti_comms/protobuf/hi2lo.options deleted file mode 100644 index 3069dbb9b7..0000000000 --- a/modules/YetiDriver/yeti_comms/protobuf/hi2lo.options +++ /dev/null @@ -1,3 +0,0 @@ -SetAuth.userid max_length:50 -KeepAliveHi.sw_version_string max_length:50 -SetCountryCode.iso3166_alpha2_code max_length:10 diff --git a/modules/YetiDriver/yeti_comms/protobuf/hi2lo.pb.c b/modules/YetiDriver/yeti_comms/protobuf/hi2lo.pb.c deleted file mode 100644 index 1c3ca4e2bc..0000000000 --- a/modules/YetiDriver/yeti_comms/protobuf/hi2lo.pb.c +++ /dev/null @@ -1,78 +0,0 @@ -/* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5 */ - -#include "hi2lo.pb.h" -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -PB_BIND(HiToLo, HiToLo, AUTO) - - -PB_BIND(AllowPowerOn, AllowPowerOn, AUTO) - - -PB_BIND(SetPWM, SetPWM, AUTO) - - -PB_BIND(FirmwareUpdate, FirmwareUpdate, AUTO) - - -PB_BIND(EnableSimulation, EnableSimulation, AUTO) - - -PB_BIND(SimulationData, SimulationData, AUTO) - - -PB_BIND(KeepAliveHi, KeepAliveHi, AUTO) - - -PB_BIND(SetMaxCurrent, SetMaxCurrent, AUTO) - - -PB_BIND(Replug, Replug, AUTO) - - -PB_BIND(SetThreePhases, SetThreePhases, AUTO) - - -PB_BIND(EnableRCD, EnableRCD, AUTO) - - -PB_BIND(SetHasVentilation, SetHasVentilation, AUTO) - - -PB_BIND(SetCountryCode, SetCountryCode, AUTO) - - -PB_BIND(SetControlMode, SetControlMode, AUTO) - - -PB_BIND(SetAuth, SetAuth, AUTO) - - -PB_BIND(Enable, Enable, AUTO) - - -PB_BIND(Disable, Disable, AUTO) - - -PB_BIND(Reset, Reset, AUTO) - - -PB_BIND(SwitchThreePhasesWhileCharging, SwitchThreePhasesWhileCharging, AUTO) - - -PB_BIND(PauseCharging, PauseCharging, AUTO) - - -PB_BIND(ResumeCharging, ResumeCharging, AUTO) - - -PB_BIND(Restart, Restart, AUTO) - - -PB_BIND(ForceUnlock, ForceUnlock, AUTO) - - - diff --git a/modules/YetiDriver/yeti_comms/protobuf/hi2lo.pb.h b/modules/YetiDriver/yeti_comms/protobuf/hi2lo.pb.h deleted file mode 100644 index d86bebc18d..0000000000 --- a/modules/YetiDriver/yeti_comms/protobuf/hi2lo.pb.h +++ /dev/null @@ -1,521 +0,0 @@ -/* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5 */ - -#ifndef PB_HI2LO_PB_H_INCLUDED -#define PB_HI2LO_PB_H_INCLUDED -#include -#include "common.pb.h" - -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -/* Struct definitions */ -typedef struct _Disable { - char dummy_field; -} Disable; - -typedef struct _Enable { - char dummy_field; -} Enable; - -typedef struct _ForceUnlock { - char dummy_field; -} ForceUnlock; - -typedef struct _PauseCharging { - char dummy_field; -} PauseCharging; - -typedef struct _Reset { - char dummy_field; -} Reset; - -typedef struct _Restart { - char dummy_field; -} Restart; - -typedef struct _ResumeCharging { - char dummy_field; -} ResumeCharging; - -typedef struct _AllowPowerOn { - bool p; -} AllowPowerOn; - -typedef struct _EnableRCD { - bool e; -} EnableRCD; - -typedef struct _EnableSimulation { - bool s; -} EnableSimulation; - -typedef struct _FirmwareUpdate { - bool invoke_rom_bootloader; -} FirmwareUpdate; - -typedef struct _KeepAliveHi { - uint32_t time_stamp; - uint32_t hw_type; - uint32_t hw_revision; - uint32_t protocol_version_major; - uint32_t protocol_version_minor; - char sw_version_string[51]; -} KeepAliveHi; - -typedef struct _Replug { - uint32_t time; -} Replug; - -typedef struct _SetAuth { - char userid[51]; -} SetAuth; - -typedef struct _SetControlMode { - InterfaceControlMode control_mode; -} SetControlMode; - -typedef struct _SetCountryCode { - char iso3166_alpha2_code[11]; -} SetCountryCode; - -typedef struct _SetHasVentilation { - bool v; -} SetHasVentilation; - -typedef struct _SetMaxCurrent { - float ampere; -} SetMaxCurrent; - -typedef struct _SetPWM { - int32_t mode; /* 0: OFF, 1: ON, 2: F */ - float duty_cycle; -} SetPWM; - -typedef struct _SetThreePhases { - bool n; -} SetThreePhases; - -typedef struct _SimulationData { - float cp_voltage; - float pp_resistor; - float currentL1; - float currentL2; - float currentL3; - float currentN; - float voltageL1; - float voltageL2; - float voltageL3; - float freqL1; - float freqL2; - float freqL3; - float rcd_current; - bool diode_fail; - bool error_e; -} SimulationData; - -typedef struct _SwitchThreePhasesWhileCharging { - bool n; -} SwitchThreePhasesWhileCharging; - -/* This container message is send from Hi Level to Low level and may contain any allowed message in that direction. */ -typedef struct _HiToLo { - /* Common/configuration messages */ - pb_size_t which_payload; - union { - SetMaxCurrent set_max_current; - SetThreePhases set_three_phases; - SetHasVentilation set_has_ventilation; - SetCountryCode set_country_code; - Enable enable; - Disable disable; - SetAuth set_auth; - SwitchThreePhasesWhileCharging switch_three_phases_while_charging; - PauseCharging pause_charging; - ResumeCharging resume_charging; - EnableRCD enable_rcd; - KeepAliveHi keep_alive; - Restart restart; - FirmwareUpdate firmware_update; - EnableSimulation enable_simulation; - SimulationData simulation_data; - SetControlMode set_control_mode; - SetPWM set_pwm; - AllowPowerOn allow_power_on; - ForceUnlock force_unlock; - Reset reset; - Replug replug; - } payload; -} HiToLo; - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Initializer values for message structs */ -#define HiToLo_init_default {0, {SetMaxCurrent_init_default}} -#define AllowPowerOn_init_default {0} -#define SetPWM_init_default {0, 0} -#define FirmwareUpdate_init_default {0} -#define EnableSimulation_init_default {0} -#define SimulationData_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define KeepAliveHi_init_default {0, 0, 0, 0, 0, ""} -#define SetMaxCurrent_init_default {0} -#define Replug_init_default {0} -#define SetThreePhases_init_default {0} -#define EnableRCD_init_default {0} -#define SetHasVentilation_init_default {0} -#define SetCountryCode_init_default {""} -#define SetControlMode_init_default {_InterfaceControlMode_MIN} -#define SetAuth_init_default {""} -#define Enable_init_default {0} -#define Disable_init_default {0} -#define Reset_init_default {0} -#define SwitchThreePhasesWhileCharging_init_default {0} -#define PauseCharging_init_default {0} -#define ResumeCharging_init_default {0} -#define Restart_init_default {0} -#define ForceUnlock_init_default {0} -#define HiToLo_init_zero {0, {SetMaxCurrent_init_zero}} -#define AllowPowerOn_init_zero {0} -#define SetPWM_init_zero {0, 0} -#define FirmwareUpdate_init_zero {0} -#define EnableSimulation_init_zero {0} -#define SimulationData_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define KeepAliveHi_init_zero {0, 0, 0, 0, 0, ""} -#define SetMaxCurrent_init_zero {0} -#define Replug_init_zero {0} -#define SetThreePhases_init_zero {0} -#define EnableRCD_init_zero {0} -#define SetHasVentilation_init_zero {0} -#define SetCountryCode_init_zero {""} -#define SetControlMode_init_zero {_InterfaceControlMode_MIN} -#define SetAuth_init_zero {""} -#define Enable_init_zero {0} -#define Disable_init_zero {0} -#define Reset_init_zero {0} -#define SwitchThreePhasesWhileCharging_init_zero {0} -#define PauseCharging_init_zero {0} -#define ResumeCharging_init_zero {0} -#define Restart_init_zero {0} -#define ForceUnlock_init_zero {0} - -/* Field tags (for use in manual encoding/decoding) */ -#define AllowPowerOn_p_tag 1 -#define EnableRCD_e_tag 1 -#define EnableSimulation_s_tag 1 -#define FirmwareUpdate_invoke_rom_bootloader_tag 1 -#define KeepAliveHi_time_stamp_tag 1 -#define KeepAliveHi_hw_type_tag 2 -#define KeepAliveHi_hw_revision_tag 3 -#define KeepAliveHi_protocol_version_major_tag 4 -#define KeepAliveHi_protocol_version_minor_tag 5 -#define KeepAliveHi_sw_version_string_tag 6 -#define Replug_time_tag 1 -#define SetAuth_userid_tag 1 -#define SetControlMode_control_mode_tag 1 -#define SetCountryCode_iso3166_alpha2_code_tag 1 -#define SetHasVentilation_v_tag 1 -#define SetMaxCurrent_ampere_tag 1 -#define SetPWM_mode_tag 1 -#define SetPWM_duty_cycle_tag 2 -#define SetThreePhases_n_tag 1 -#define SimulationData_cp_voltage_tag 1 -#define SimulationData_pp_resistor_tag 2 -#define SimulationData_currentL1_tag 3 -#define SimulationData_currentL2_tag 4 -#define SimulationData_currentL3_tag 5 -#define SimulationData_currentN_tag 6 -#define SimulationData_voltageL1_tag 7 -#define SimulationData_voltageL2_tag 8 -#define SimulationData_voltageL3_tag 9 -#define SimulationData_freqL1_tag 10 -#define SimulationData_freqL2_tag 11 -#define SimulationData_freqL3_tag 12 -#define SimulationData_rcd_current_tag 13 -#define SimulationData_diode_fail_tag 14 -#define SimulationData_error_e_tag 15 -#define SwitchThreePhasesWhileCharging_n_tag 1 -#define HiToLo_set_max_current_tag 1 -#define HiToLo_set_three_phases_tag 2 -#define HiToLo_set_has_ventilation_tag 3 -#define HiToLo_set_country_code_tag 4 -#define HiToLo_enable_tag 6 -#define HiToLo_disable_tag 7 -#define HiToLo_set_auth_tag 8 -#define HiToLo_switch_three_phases_while_charging_tag 9 -#define HiToLo_pause_charging_tag 10 -#define HiToLo_resume_charging_tag 11 -#define HiToLo_enable_rcd_tag 12 -#define HiToLo_keep_alive_tag 13 -#define HiToLo_restart_tag 14 -#define HiToLo_firmware_update_tag 16 -#define HiToLo_enable_simulation_tag 17 -#define HiToLo_simulation_data_tag 18 -#define HiToLo_set_control_mode_tag 19 -#define HiToLo_set_pwm_tag 20 -#define HiToLo_allow_power_on_tag 21 -#define HiToLo_force_unlock_tag 22 -#define HiToLo_reset_tag 23 -#define HiToLo_replug_tag 24 - -/* Struct field encoding specification for nanopb */ -#define HiToLo_FIELDLIST(X, a) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,set_max_current,payload.set_max_current), 1) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,set_three_phases,payload.set_three_phases), 2) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,set_has_ventilation,payload.set_has_ventilation), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,set_country_code,payload.set_country_code), 4) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,enable,payload.enable), 6) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,disable,payload.disable), 7) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,set_auth,payload.set_auth), 8) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,switch_three_phases_while_charging,payload.switch_three_phases_while_charging), 9) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,pause_charging,payload.pause_charging), 10) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,resume_charging,payload.resume_charging), 11) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,enable_rcd,payload.enable_rcd), 12) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,keep_alive,payload.keep_alive), 13) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,restart,payload.restart), 14) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,firmware_update,payload.firmware_update), 16) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,enable_simulation,payload.enable_simulation), 17) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,simulation_data,payload.simulation_data), 18) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,set_control_mode,payload.set_control_mode), 19) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,set_pwm,payload.set_pwm), 20) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,allow_power_on,payload.allow_power_on), 21) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,force_unlock,payload.force_unlock), 22) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,reset,payload.reset), 23) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,replug,payload.replug), 24) -#define HiToLo_CALLBACK NULL -#define HiToLo_DEFAULT NULL -#define HiToLo_payload_set_max_current_MSGTYPE SetMaxCurrent -#define HiToLo_payload_set_three_phases_MSGTYPE SetThreePhases -#define HiToLo_payload_set_has_ventilation_MSGTYPE SetHasVentilation -#define HiToLo_payload_set_country_code_MSGTYPE SetCountryCode -#define HiToLo_payload_enable_MSGTYPE Enable -#define HiToLo_payload_disable_MSGTYPE Disable -#define HiToLo_payload_set_auth_MSGTYPE SetAuth -#define HiToLo_payload_switch_three_phases_while_charging_MSGTYPE SwitchThreePhasesWhileCharging -#define HiToLo_payload_pause_charging_MSGTYPE PauseCharging -#define HiToLo_payload_resume_charging_MSGTYPE ResumeCharging -#define HiToLo_payload_enable_rcd_MSGTYPE EnableRCD -#define HiToLo_payload_keep_alive_MSGTYPE KeepAliveHi -#define HiToLo_payload_restart_MSGTYPE Restart -#define HiToLo_payload_firmware_update_MSGTYPE FirmwareUpdate -#define HiToLo_payload_enable_simulation_MSGTYPE EnableSimulation -#define HiToLo_payload_simulation_data_MSGTYPE SimulationData -#define HiToLo_payload_set_control_mode_MSGTYPE SetControlMode -#define HiToLo_payload_set_pwm_MSGTYPE SetPWM -#define HiToLo_payload_allow_power_on_MSGTYPE AllowPowerOn -#define HiToLo_payload_force_unlock_MSGTYPE ForceUnlock -#define HiToLo_payload_reset_MSGTYPE Reset -#define HiToLo_payload_replug_MSGTYPE Replug - -#define AllowPowerOn_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, p, 1) -#define AllowPowerOn_CALLBACK NULL -#define AllowPowerOn_DEFAULT NULL - -#define SetPWM_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, INT32, mode, 1) \ -X(a, STATIC, SINGULAR, FLOAT, duty_cycle, 2) -#define SetPWM_CALLBACK NULL -#define SetPWM_DEFAULT NULL - -#define FirmwareUpdate_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, invoke_rom_bootloader, 1) -#define FirmwareUpdate_CALLBACK NULL -#define FirmwareUpdate_DEFAULT NULL - -#define EnableSimulation_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, s, 1) -#define EnableSimulation_CALLBACK NULL -#define EnableSimulation_DEFAULT NULL - -#define SimulationData_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, FLOAT, cp_voltage, 1) \ -X(a, STATIC, SINGULAR, FLOAT, pp_resistor, 2) \ -X(a, STATIC, SINGULAR, FLOAT, currentL1, 3) \ -X(a, STATIC, SINGULAR, FLOAT, currentL2, 4) \ -X(a, STATIC, SINGULAR, FLOAT, currentL3, 5) \ -X(a, STATIC, SINGULAR, FLOAT, currentN, 6) \ -X(a, STATIC, SINGULAR, FLOAT, voltageL1, 7) \ -X(a, STATIC, SINGULAR, FLOAT, voltageL2, 8) \ -X(a, STATIC, SINGULAR, FLOAT, voltageL3, 9) \ -X(a, STATIC, SINGULAR, FLOAT, freqL1, 10) \ -X(a, STATIC, SINGULAR, FLOAT, freqL2, 11) \ -X(a, STATIC, SINGULAR, FLOAT, freqL3, 12) \ -X(a, STATIC, SINGULAR, FLOAT, rcd_current, 13) \ -X(a, STATIC, SINGULAR, BOOL, diode_fail, 14) \ -X(a, STATIC, SINGULAR, BOOL, error_e, 15) -#define SimulationData_CALLBACK NULL -#define SimulationData_DEFAULT NULL - -#define KeepAliveHi_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, time_stamp, 1) \ -X(a, STATIC, SINGULAR, UINT32, hw_type, 2) \ -X(a, STATIC, SINGULAR, UINT32, hw_revision, 3) \ -X(a, STATIC, SINGULAR, UINT32, protocol_version_major, 4) \ -X(a, STATIC, SINGULAR, UINT32, protocol_version_minor, 5) \ -X(a, STATIC, SINGULAR, STRING, sw_version_string, 6) -#define KeepAliveHi_CALLBACK NULL -#define KeepAliveHi_DEFAULT NULL - -#define SetMaxCurrent_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, FLOAT, ampere, 1) -#define SetMaxCurrent_CALLBACK NULL -#define SetMaxCurrent_DEFAULT NULL - -#define Replug_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, time, 1) -#define Replug_CALLBACK NULL -#define Replug_DEFAULT NULL - -#define SetThreePhases_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, n, 1) -#define SetThreePhases_CALLBACK NULL -#define SetThreePhases_DEFAULT NULL - -#define EnableRCD_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, e, 1) -#define EnableRCD_CALLBACK NULL -#define EnableRCD_DEFAULT NULL - -#define SetHasVentilation_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, v, 1) -#define SetHasVentilation_CALLBACK NULL -#define SetHasVentilation_DEFAULT NULL - -#define SetCountryCode_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, STRING, iso3166_alpha2_code, 1) -#define SetCountryCode_CALLBACK NULL -#define SetCountryCode_DEFAULT NULL - -#define SetControlMode_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UENUM, control_mode, 1) -#define SetControlMode_CALLBACK NULL -#define SetControlMode_DEFAULT NULL - -#define SetAuth_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, STRING, userid, 1) -#define SetAuth_CALLBACK NULL -#define SetAuth_DEFAULT NULL - -#define Enable_FIELDLIST(X, a) \ - -#define Enable_CALLBACK NULL -#define Enable_DEFAULT NULL - -#define Disable_FIELDLIST(X, a) \ - -#define Disable_CALLBACK NULL -#define Disable_DEFAULT NULL - -#define Reset_FIELDLIST(X, a) \ - -#define Reset_CALLBACK NULL -#define Reset_DEFAULT NULL - -#define SwitchThreePhasesWhileCharging_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, n, 1) -#define SwitchThreePhasesWhileCharging_CALLBACK NULL -#define SwitchThreePhasesWhileCharging_DEFAULT NULL - -#define PauseCharging_FIELDLIST(X, a) \ - -#define PauseCharging_CALLBACK NULL -#define PauseCharging_DEFAULT NULL - -#define ResumeCharging_FIELDLIST(X, a) \ - -#define ResumeCharging_CALLBACK NULL -#define ResumeCharging_DEFAULT NULL - -#define Restart_FIELDLIST(X, a) \ - -#define Restart_CALLBACK NULL -#define Restart_DEFAULT NULL - -#define ForceUnlock_FIELDLIST(X, a) \ - -#define ForceUnlock_CALLBACK NULL -#define ForceUnlock_DEFAULT NULL - -extern const pb_msgdesc_t HiToLo_msg; -extern const pb_msgdesc_t AllowPowerOn_msg; -extern const pb_msgdesc_t SetPWM_msg; -extern const pb_msgdesc_t FirmwareUpdate_msg; -extern const pb_msgdesc_t EnableSimulation_msg; -extern const pb_msgdesc_t SimulationData_msg; -extern const pb_msgdesc_t KeepAliveHi_msg; -extern const pb_msgdesc_t SetMaxCurrent_msg; -extern const pb_msgdesc_t Replug_msg; -extern const pb_msgdesc_t SetThreePhases_msg; -extern const pb_msgdesc_t EnableRCD_msg; -extern const pb_msgdesc_t SetHasVentilation_msg; -extern const pb_msgdesc_t SetCountryCode_msg; -extern const pb_msgdesc_t SetControlMode_msg; -extern const pb_msgdesc_t SetAuth_msg; -extern const pb_msgdesc_t Enable_msg; -extern const pb_msgdesc_t Disable_msg; -extern const pb_msgdesc_t Reset_msg; -extern const pb_msgdesc_t SwitchThreePhasesWhileCharging_msg; -extern const pb_msgdesc_t PauseCharging_msg; -extern const pb_msgdesc_t ResumeCharging_msg; -extern const pb_msgdesc_t Restart_msg; -extern const pb_msgdesc_t ForceUnlock_msg; - -/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define HiToLo_fields &HiToLo_msg -#define AllowPowerOn_fields &AllowPowerOn_msg -#define SetPWM_fields &SetPWM_msg -#define FirmwareUpdate_fields &FirmwareUpdate_msg -#define EnableSimulation_fields &EnableSimulation_msg -#define SimulationData_fields &SimulationData_msg -#define KeepAliveHi_fields &KeepAliveHi_msg -#define SetMaxCurrent_fields &SetMaxCurrent_msg -#define Replug_fields &Replug_msg -#define SetThreePhases_fields &SetThreePhases_msg -#define EnableRCD_fields &EnableRCD_msg -#define SetHasVentilation_fields &SetHasVentilation_msg -#define SetCountryCode_fields &SetCountryCode_msg -#define SetControlMode_fields &SetControlMode_msg -#define SetAuth_fields &SetAuth_msg -#define Enable_fields &Enable_msg -#define Disable_fields &Disable_msg -#define Reset_fields &Reset_msg -#define SwitchThreePhasesWhileCharging_fields &SwitchThreePhasesWhileCharging_msg -#define PauseCharging_fields &PauseCharging_msg -#define ResumeCharging_fields &ResumeCharging_msg -#define Restart_fields &Restart_msg -#define ForceUnlock_fields &ForceUnlock_msg - -/* Maximum encoded size of messages (where known) */ -#define AllowPowerOn_size 2 -#define Disable_size 0 -#define EnableRCD_size 2 -#define EnableSimulation_size 2 -#define Enable_size 0 -#define FirmwareUpdate_size 2 -#define ForceUnlock_size 0 -#define HiToLo_size 84 -#define KeepAliveHi_size 82 -#define PauseCharging_size 0 -#define Replug_size 6 -#define Reset_size 0 -#define Restart_size 0 -#define ResumeCharging_size 0 -#define SetAuth_size 52 -#define SetControlMode_size 2 -#define SetCountryCode_size 12 -#define SetHasVentilation_size 2 -#define SetMaxCurrent_size 5 -#define SetPWM_size 16 -#define SetThreePhases_size 2 -#define SimulationData_size 69 -#define SwitchThreePhasesWhileCharging_size 2 - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/modules/YetiDriver/yeti_comms/protobuf/hi2lo.proto b/modules/YetiDriver/yeti_comms/protobuf/hi2lo.proto deleted file mode 100644 index 1f94453a2a..0000000000 --- a/modules/YetiDriver/yeti_comms/protobuf/hi2lo.proto +++ /dev/null @@ -1,128 +0,0 @@ -syntax = "proto3"; -import "common.proto"; - -/* - This container message is send from Hi Level to Low level and may contain any allowed message in that direction. -*/ -message HiToLo { - oneof payload { - // Common/configuration messages - SetControlMode set_control_mode = 19; - SetThreePhases set_three_phases = 2; - SetHasVentilation set_has_ventilation = 3; - SetCountryCode set_country_code = 4; - Enable enable = 6; - Disable disable = 7; - SetAuth set_auth = 8; // available also in low level control to allow for signed meter values - SwitchThreePhasesWhileCharging switch_three_phases_while_charging = 9; - EnableRCD enable_rcd = 12; - KeepAliveHi keep_alive = 13; - FirmwareUpdate firmware_update = 16; - ForceUnlock force_unlock = 22; - // Commands only available in control_mode = 1 (high level control) - SetMaxCurrent set_max_current = 1; - PauseCharging pause_charging = 10; - ResumeCharging resume_charging = 11; - Restart restart = 14; - // Commands only available in control_mode = 2 (direct low level control) - SetPWM set_pwm = 20; - AllowPowerOn allow_power_on = 21; - // Commands for HIL simulator - EnableSimulation enable_simulation = 17; - SimulationData simulation_data = 18; - Reset reset = 23; - Replug replug = 24; - } -} - -message AllowPowerOn { - bool p = 1; -} - -message SetPWM { - int32 mode = 1; // 0: OFF, 1: ON, 2: F - float duty_cycle = 2; -} - -message FirmwareUpdate { - bool invoke_rom_bootloader = 1; -} - -message EnableSimulation { - bool s = 1; -} - -message SimulationData { - float cp_voltage = 1; - float pp_resistor = 2; - float currentL1 = 3; - float currentL2 = 4; - float currentL3 = 5; - float currentN = 6; - float voltageL1 = 7; - float voltageL2 = 8; - float voltageL3 = 9; - float freqL1 = 10; - float freqL2 = 11; - float freqL3 = 12; - float rcd_current = 13; - bool diode_fail = 14; - bool error_e = 15; -} - - -message KeepAliveHi { - uint32 time_stamp = 1; - uint32 hw_type = 2; - uint32 hw_revision = 3; - uint32 protocol_version_major = 4; - uint32 protocol_version_minor = 5; - string sw_version_string = 6; - -} - -message SetMaxCurrent { - float ampere = 1; -} - -message Replug { - uint32 time = 1; -} - -message SetThreePhases { - bool n = 1; -} - -message EnableRCD { - bool e = 1; -} - -message SetHasVentilation { - bool v = 1; -} - -message SetCountryCode { - string iso3166_alpha2_code = 1; -} - -message SetControlMode { - InterfaceControlMode control_mode = 1; -} - -message SetAuth { - string userid = 1; -} - -message Enable { } -message Disable { } -message Reset { } - -message SwitchThreePhasesWhileCharging { - bool n = 1; -} - -message PauseCharging { } -message ResumeCharging { } -message Restart { } - -message ForceUnlock { } diff --git a/modules/YetiDriver/yeti_comms/protobuf/lo2hi.pb.c b/modules/YetiDriver/yeti_comms/protobuf/lo2hi.pb.c deleted file mode 100644 index 0b46ad0776..0000000000 --- a/modules/YetiDriver/yeti_comms/protobuf/lo2hi.pb.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5 */ - -#include "lo2hi.pb.h" -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -PB_BIND(LoToHi, LoToHi, AUTO) - - -PB_BIND(Event, Event, AUTO) - - -PB_BIND(SimulationFeedback, SimulationFeedback, AUTO) - - -PB_BIND(PowerMeter, PowerMeter, AUTO) - - -PB_BIND(KeepAliveLo, KeepAliveLo, AUTO) - - -PB_BIND(StateUpdate, StateUpdate, AUTO) - - -PB_BIND(ErrorFlags, ErrorFlags, AUTO) - - -PB_BIND(ChargingFlags, ChargingFlags, AUTO) - - -PB_BIND(ResetDone, ResetDone, AUTO) - - -PB_BIND(DebugUpdate, DebugUpdate, AUTO) - - - - - - - diff --git a/modules/YetiDriver/yeti_comms/protobuf/lo2hi.pb.h b/modules/YetiDriver/yeti_comms/protobuf/lo2hi.pb.h deleted file mode 100644 index 4e09f0b18b..0000000000 --- a/modules/YetiDriver/yeti_comms/protobuf/lo2hi.pb.h +++ /dev/null @@ -1,472 +0,0 @@ -/* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5 */ - -#ifndef PB_LO2HI_PB_H_INCLUDED -#define PB_LO2HI_PB_H_INCLUDED -#include -#include "common.pb.h" - -#if PB_PROTO_HEADER_VERSION != 40 -#error Regenerate this file with the current version of nanopb generator. -#endif - -/* Enum definitions */ -typedef enum _Event_InterfaceEvent { - Event_InterfaceEvent_CAR_PLUGGED_IN = 0, - Event_InterfaceEvent_CAR_REQUESTED_POWER = 1, - Event_InterfaceEvent_POWER_ON = 2, - Event_InterfaceEvent_POWER_OFF = 3, - Event_InterfaceEvent_CAR_REQUESTED_STOP_POWER = 4, - Event_InterfaceEvent_CAR_UNPLUGGED = 5, - Event_InterfaceEvent_ERROR_E = 6, - Event_InterfaceEvent_ERROR_DF = 7, - Event_InterfaceEvent_ERROR_RELAIS = 8, - Event_InterfaceEvent_ERROR_RCD = 9, - Event_InterfaceEvent_ERROR_VENTILATION_NOT_AVAILABLE = 10, - Event_InterfaceEvent_ERROR_OVER_CURRENT = 11, - Event_InterfaceEvent_ENTER_BCD = 12, - Event_InterfaceEvent_LEAVE_BCD = 13, - Event_InterfaceEvent_PERMANENT_FAULT = 14, - Event_InterfaceEvent_EVSE_REPLUG_STARTED = 15, - Event_InterfaceEvent_EVSE_REPLUG_FINISHED = 16 -} Event_InterfaceEvent; - -typedef enum _StateUpdate_State { - StateUpdate_State_DISABLED = 0, - StateUpdate_State_IDLE = 1, - StateUpdate_State_WAITING_FOR_AUTHENTICATION = 2, - StateUpdate_State_CHARGING = 3, - StateUpdate_State_CHARGING_PAUSED_EV = 4, - StateUpdate_State_CHARGING_PAUSED_EVSE = 5, - StateUpdate_State_CHARGING_FINSIHED = 6, - StateUpdate_State_ERROR = 7, - StateUpdate_State_FAULTED = 8 -} StateUpdate_State; - -typedef enum _ErrorFlags_ErrorType { - ErrorFlags_ErrorType_ERROR_F = 0, - ErrorFlags_ErrorType_ERROR_E = 1, - ErrorFlags_ErrorType_ERROR_DF = 2, - ErrorFlags_ErrorType_ERROR_RELAIS = 3, - ErrorFlags_ErrorType_ERROR_VENTILATION_NOT_AVAILABLE = 4, - ErrorFlags_ErrorType_ERROR_RCD = 5, - ErrorFlags_ErrorType_ERROR_OVER_CURRENT = 6 -} ErrorFlags_ErrorType; - -typedef enum _DebugUpdate_LoLevelState { - DebugUpdate_LoLevelState_DISABLED = 0, - DebugUpdate_LoLevelState_A = 1, - DebugUpdate_LoLevelState_B = 2, - DebugUpdate_LoLevelState_C = 3, - DebugUpdate_LoLevelState_D = 4, - DebugUpdate_LoLevelState_E = 5, - DebugUpdate_LoLevelState_F = 6, - DebugUpdate_LoLevelState_DF = 7 -} DebugUpdate_LoLevelState; - -/* Struct definitions */ -typedef struct _ResetDone { - char dummy_field; -} ResetDone; - -typedef struct _ChargingFlags { - bool ventilation; -} ChargingFlags; - -typedef struct _DebugUpdate { - uint32_t time_stamp; - float evse_pwm_voltage_hi; - float evse_pwm_voltage_lo; - float supply_voltage_12V; - float supply_voltage_N12V; - DebugUpdate_LoLevelState lowlevel_state; - bool evse_pwm_running; - bool ev_simplified_mode; - bool has_ventilation; - bool ventilated_charging_active; - bool rcd_reclosing_allowed; - bool authorized; - float cpu_temperature; - bool rcd_enabled; - float evse_pp_voltage; - float max_current_cable; - uint32_t watchdog_reset_count; - bool simulation; - InterfaceControlMode control_mode; - float max_current; - bool use_three_phases; - float rcd_current; - bool relais_on; -} DebugUpdate; - -typedef struct _ErrorFlags { - ErrorFlags_ErrorType type; -} ErrorFlags; - -typedef struct _Event { - Event_InterfaceEvent type; -} Event; - -typedef struct _KeepAliveLo { - uint32_t time_stamp; - uint32_t hw_type; - uint32_t hw_revision; - uint32_t protocol_version_major; - uint32_t protocol_version_minor; - char sw_version_string[51]; - float hwcap_max_current; - float hwcap_min_current; - uint32_t hwcap_max_phase_count; - uint32_t hwcap_min_phase_count; - bool supports_changing_phases_during_charging; -} KeepAliveLo; - -typedef struct _PowerMeter { - uint32_t time_stamp; - float vrmsL1; - float vrmsL2; - float vrmsL3; - float irmsL1; - float irmsL2; - float irmsL3; - float irmsN; - float wattHrL1; - float wattHrL2; - float wattHrL3; - float totalWattHr; - float tempL1; - float tempL2; - float tempL3; - float tempN; - float wattL1; - float wattL2; - float wattL3; - float freqL1; - float freqL2; - float freqL3; - bool phaseSeqError; -} PowerMeter; - -typedef struct _SimulationFeedback { - float pwmDutyCycle; - float evse_pwm_voltage_hi; - float evse_pwm_voltage_lo; - bool evse_pwm_running; - uint32_t relais_on; -} SimulationFeedback; - -typedef struct _StateUpdate { - uint32_t time_stamp; - StateUpdate_State state; - pb_size_t which_state_flags; - union { - ErrorFlags error_type; - ChargingFlags charging_flags; - } state_flags; -} StateUpdate; - -/* This container message is send from Lo Level to Hi level and may contain any allowed message in that direction. */ -typedef struct _LoToHi { - /* Common Packets */ - pb_size_t which_payload; - union { - StateUpdate state_update; - DebugUpdate debug_update; - KeepAliveLo keep_alive; - PowerMeter power_meter; - SimulationFeedback simulation_feedback; - Event event; - ResetDone reset_done; - } payload; -} LoToHi; - - -/* Helper constants for enums */ -#define _Event_InterfaceEvent_MIN Event_InterfaceEvent_CAR_PLUGGED_IN -#define _Event_InterfaceEvent_MAX Event_InterfaceEvent_EVSE_REPLUG_FINISHED -#define _Event_InterfaceEvent_ARRAYSIZE ((Event_InterfaceEvent)(Event_InterfaceEvent_EVSE_REPLUG_FINISHED+1)) - -#define _StateUpdate_State_MIN StateUpdate_State_DISABLED -#define _StateUpdate_State_MAX StateUpdate_State_FAULTED -#define _StateUpdate_State_ARRAYSIZE ((StateUpdate_State)(StateUpdate_State_FAULTED+1)) - -#define _ErrorFlags_ErrorType_MIN ErrorFlags_ErrorType_ERROR_F -#define _ErrorFlags_ErrorType_MAX ErrorFlags_ErrorType_ERROR_OVER_CURRENT -#define _ErrorFlags_ErrorType_ARRAYSIZE ((ErrorFlags_ErrorType)(ErrorFlags_ErrorType_ERROR_OVER_CURRENT+1)) - -#define _DebugUpdate_LoLevelState_MIN DebugUpdate_LoLevelState_DISABLED -#define _DebugUpdate_LoLevelState_MAX DebugUpdate_LoLevelState_DF -#define _DebugUpdate_LoLevelState_ARRAYSIZE ((DebugUpdate_LoLevelState)(DebugUpdate_LoLevelState_DF+1)) - - -#ifdef __cplusplus -extern "C" { -#endif - -/* Initializer values for message structs */ -#define LoToHi_init_default {0, {StateUpdate_init_default}} -#define Event_init_default {_Event_InterfaceEvent_MIN} -#define SimulationFeedback_init_default {0, 0, 0, 0, 0} -#define PowerMeter_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define KeepAliveLo_init_default {0, 0, 0, 0, 0, "", 0, 0, 0, 0, 0} -#define StateUpdate_init_default {0, _StateUpdate_State_MIN, 0, {ErrorFlags_init_default}} -#define ErrorFlags_init_default {_ErrorFlags_ErrorType_MIN} -#define ChargingFlags_init_default {0} -#define ResetDone_init_default {0} -#define DebugUpdate_init_default {0, 0, 0, 0, 0, _DebugUpdate_LoLevelState_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _InterfaceControlMode_MIN, 0, 0, 0, 0} -#define LoToHi_init_zero {0, {StateUpdate_init_zero}} -#define Event_init_zero {_Event_InterfaceEvent_MIN} -#define SimulationFeedback_init_zero {0, 0, 0, 0, 0} -#define PowerMeter_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} -#define KeepAliveLo_init_zero {0, 0, 0, 0, 0, "", 0, 0, 0, 0, 0} -#define StateUpdate_init_zero {0, _StateUpdate_State_MIN, 0, {ErrorFlags_init_zero}} -#define ErrorFlags_init_zero {_ErrorFlags_ErrorType_MIN} -#define ChargingFlags_init_zero {0} -#define ResetDone_init_zero {0} -#define DebugUpdate_init_zero {0, 0, 0, 0, 0, _DebugUpdate_LoLevelState_MIN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _InterfaceControlMode_MIN, 0, 0, 0, 0} - -/* Field tags (for use in manual encoding/decoding) */ -#define ChargingFlags_ventilation_tag 1 -#define DebugUpdate_time_stamp_tag 1 -#define DebugUpdate_evse_pwm_voltage_hi_tag 2 -#define DebugUpdate_evse_pwm_voltage_lo_tag 3 -#define DebugUpdate_supply_voltage_12V_tag 4 -#define DebugUpdate_supply_voltage_N12V_tag 5 -#define DebugUpdate_lowlevel_state_tag 6 -#define DebugUpdate_evse_pwm_running_tag 7 -#define DebugUpdate_ev_simplified_mode_tag 8 -#define DebugUpdate_has_ventilation_tag 9 -#define DebugUpdate_ventilated_charging_active_tag 10 -#define DebugUpdate_rcd_reclosing_allowed_tag 12 -#define DebugUpdate_authorized_tag 15 -#define DebugUpdate_cpu_temperature_tag 17 -#define DebugUpdate_rcd_enabled_tag 18 -#define DebugUpdate_evse_pp_voltage_tag 21 -#define DebugUpdate_max_current_cable_tag 22 -#define DebugUpdate_watchdog_reset_count_tag 23 -#define DebugUpdate_simulation_tag 24 -#define DebugUpdate_control_mode_tag 25 -#define DebugUpdate_max_current_tag 26 -#define DebugUpdate_use_three_phases_tag 27 -#define DebugUpdate_rcd_current_tag 28 -#define DebugUpdate_relais_on_tag 29 -#define ErrorFlags_type_tag 1 -#define Event_type_tag 1 -#define KeepAliveLo_time_stamp_tag 1 -#define KeepAliveLo_hw_type_tag 2 -#define KeepAliveLo_hw_revision_tag 3 -#define KeepAliveLo_protocol_version_major_tag 4 -#define KeepAliveLo_protocol_version_minor_tag 5 -#define KeepAliveLo_sw_version_string_tag 6 -#define KeepAliveLo_hwcap_max_current_tag 7 -#define KeepAliveLo_hwcap_min_current_tag 8 -#define KeepAliveLo_hwcap_max_phase_count_tag 9 -#define KeepAliveLo_hwcap_min_phase_count_tag 10 -#define KeepAliveLo_supports_changing_phases_during_charging_tag 11 -#define PowerMeter_time_stamp_tag 1 -#define PowerMeter_vrmsL1_tag 2 -#define PowerMeter_vrmsL2_tag 3 -#define PowerMeter_vrmsL3_tag 4 -#define PowerMeter_irmsL1_tag 5 -#define PowerMeter_irmsL2_tag 6 -#define PowerMeter_irmsL3_tag 7 -#define PowerMeter_irmsN_tag 8 -#define PowerMeter_wattHrL1_tag 9 -#define PowerMeter_wattHrL2_tag 10 -#define PowerMeter_wattHrL3_tag 11 -#define PowerMeter_totalWattHr_tag 12 -#define PowerMeter_tempL1_tag 13 -#define PowerMeter_tempL2_tag 14 -#define PowerMeter_tempL3_tag 15 -#define PowerMeter_tempN_tag 16 -#define PowerMeter_wattL1_tag 17 -#define PowerMeter_wattL2_tag 18 -#define PowerMeter_wattL3_tag 19 -#define PowerMeter_freqL1_tag 20 -#define PowerMeter_freqL2_tag 21 -#define PowerMeter_freqL3_tag 22 -#define PowerMeter_phaseSeqError_tag 23 -#define SimulationFeedback_pwmDutyCycle_tag 1 -#define SimulationFeedback_evse_pwm_voltage_hi_tag 2 -#define SimulationFeedback_evse_pwm_voltage_lo_tag 3 -#define SimulationFeedback_evse_pwm_running_tag 4 -#define SimulationFeedback_relais_on_tag 5 -#define StateUpdate_time_stamp_tag 1 -#define StateUpdate_state_tag 2 -#define StateUpdate_error_type_tag 3 -#define StateUpdate_charging_flags_tag 4 -#define LoToHi_state_update_tag 1 -#define LoToHi_debug_update_tag 2 -#define LoToHi_keep_alive_tag 3 -#define LoToHi_power_meter_tag 4 -#define LoToHi_simulation_feedback_tag 5 -#define LoToHi_event_tag 6 -#define LoToHi_reset_done_tag 7 - -/* Struct field encoding specification for nanopb */ -#define LoToHi_FIELDLIST(X, a) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,state_update,payload.state_update), 1) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,debug_update,payload.debug_update), 2) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,keep_alive,payload.keep_alive), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,power_meter,payload.power_meter), 4) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,simulation_feedback,payload.simulation_feedback), 5) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,event,payload.event), 6) \ -X(a, STATIC, ONEOF, MESSAGE, (payload,reset_done,payload.reset_done), 7) -#define LoToHi_CALLBACK NULL -#define LoToHi_DEFAULT NULL -#define LoToHi_payload_state_update_MSGTYPE StateUpdate -#define LoToHi_payload_debug_update_MSGTYPE DebugUpdate -#define LoToHi_payload_keep_alive_MSGTYPE KeepAliveLo -#define LoToHi_payload_power_meter_MSGTYPE PowerMeter -#define LoToHi_payload_simulation_feedback_MSGTYPE SimulationFeedback -#define LoToHi_payload_event_MSGTYPE Event -#define LoToHi_payload_reset_done_MSGTYPE ResetDone - -#define Event_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UENUM, type, 1) -#define Event_CALLBACK NULL -#define Event_DEFAULT NULL - -#define SimulationFeedback_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, FLOAT, pwmDutyCycle, 1) \ -X(a, STATIC, SINGULAR, FLOAT, evse_pwm_voltage_hi, 2) \ -X(a, STATIC, SINGULAR, FLOAT, evse_pwm_voltage_lo, 3) \ -X(a, STATIC, SINGULAR, BOOL, evse_pwm_running, 4) \ -X(a, STATIC, SINGULAR, UINT32, relais_on, 5) -#define SimulationFeedback_CALLBACK NULL -#define SimulationFeedback_DEFAULT NULL - -#define PowerMeter_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, time_stamp, 1) \ -X(a, STATIC, SINGULAR, FLOAT, vrmsL1, 2) \ -X(a, STATIC, SINGULAR, FLOAT, vrmsL2, 3) \ -X(a, STATIC, SINGULAR, FLOAT, vrmsL3, 4) \ -X(a, STATIC, SINGULAR, FLOAT, irmsL1, 5) \ -X(a, STATIC, SINGULAR, FLOAT, irmsL2, 6) \ -X(a, STATIC, SINGULAR, FLOAT, irmsL3, 7) \ -X(a, STATIC, SINGULAR, FLOAT, irmsN, 8) \ -X(a, STATIC, SINGULAR, FLOAT, wattHrL1, 9) \ -X(a, STATIC, SINGULAR, FLOAT, wattHrL2, 10) \ -X(a, STATIC, SINGULAR, FLOAT, wattHrL3, 11) \ -X(a, STATIC, SINGULAR, FLOAT, totalWattHr, 12) \ -X(a, STATIC, SINGULAR, FLOAT, tempL1, 13) \ -X(a, STATIC, SINGULAR, FLOAT, tempL2, 14) \ -X(a, STATIC, SINGULAR, FLOAT, tempL3, 15) \ -X(a, STATIC, SINGULAR, FLOAT, tempN, 16) \ -X(a, STATIC, SINGULAR, FLOAT, wattL1, 17) \ -X(a, STATIC, SINGULAR, FLOAT, wattL2, 18) \ -X(a, STATIC, SINGULAR, FLOAT, wattL3, 19) \ -X(a, STATIC, SINGULAR, FLOAT, freqL1, 20) \ -X(a, STATIC, SINGULAR, FLOAT, freqL2, 21) \ -X(a, STATIC, SINGULAR, FLOAT, freqL3, 22) \ -X(a, STATIC, SINGULAR, BOOL, phaseSeqError, 23) -#define PowerMeter_CALLBACK NULL -#define PowerMeter_DEFAULT NULL - -#define KeepAliveLo_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, time_stamp, 1) \ -X(a, STATIC, SINGULAR, UINT32, hw_type, 2) \ -X(a, STATIC, SINGULAR, UINT32, hw_revision, 3) \ -X(a, STATIC, SINGULAR, UINT32, protocol_version_major, 4) \ -X(a, STATIC, SINGULAR, UINT32, protocol_version_minor, 5) \ -X(a, STATIC, SINGULAR, STRING, sw_version_string, 6) \ -X(a, STATIC, SINGULAR, FLOAT, hwcap_max_current, 7) \ -X(a, STATIC, SINGULAR, FLOAT, hwcap_min_current, 8) \ -X(a, STATIC, SINGULAR, UINT32, hwcap_max_phase_count, 9) \ -X(a, STATIC, SINGULAR, UINT32, hwcap_min_phase_count, 10) \ -X(a, STATIC, SINGULAR, BOOL, supports_changing_phases_during_charging, 11) -#define KeepAliveLo_CALLBACK NULL -#define KeepAliveLo_DEFAULT NULL - -#define StateUpdate_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, time_stamp, 1) \ -X(a, STATIC, SINGULAR, UENUM, state, 2) \ -X(a, STATIC, ONEOF, MESSAGE, (state_flags,error_type,state_flags.error_type), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (state_flags,charging_flags,state_flags.charging_flags), 4) -#define StateUpdate_CALLBACK NULL -#define StateUpdate_DEFAULT NULL -#define StateUpdate_state_flags_error_type_MSGTYPE ErrorFlags -#define StateUpdate_state_flags_charging_flags_MSGTYPE ChargingFlags - -#define ErrorFlags_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UENUM, type, 1) -#define ErrorFlags_CALLBACK NULL -#define ErrorFlags_DEFAULT NULL - -#define ChargingFlags_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, ventilation, 1) -#define ChargingFlags_CALLBACK NULL -#define ChargingFlags_DEFAULT NULL - -#define ResetDone_FIELDLIST(X, a) \ - -#define ResetDone_CALLBACK NULL -#define ResetDone_DEFAULT NULL - -#define DebugUpdate_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, time_stamp, 1) \ -X(a, STATIC, SINGULAR, FLOAT, evse_pwm_voltage_hi, 2) \ -X(a, STATIC, SINGULAR, FLOAT, evse_pwm_voltage_lo, 3) \ -X(a, STATIC, SINGULAR, FLOAT, supply_voltage_12V, 4) \ -X(a, STATIC, SINGULAR, FLOAT, supply_voltage_N12V, 5) \ -X(a, STATIC, SINGULAR, UENUM, lowlevel_state, 6) \ -X(a, STATIC, SINGULAR, BOOL, evse_pwm_running, 7) \ -X(a, STATIC, SINGULAR, BOOL, ev_simplified_mode, 8) \ -X(a, STATIC, SINGULAR, BOOL, has_ventilation, 9) \ -X(a, STATIC, SINGULAR, BOOL, ventilated_charging_active, 10) \ -X(a, STATIC, SINGULAR, BOOL, rcd_reclosing_allowed, 12) \ -X(a, STATIC, SINGULAR, BOOL, authorized, 15) \ -X(a, STATIC, SINGULAR, FLOAT, cpu_temperature, 17) \ -X(a, STATIC, SINGULAR, BOOL, rcd_enabled, 18) \ -X(a, STATIC, SINGULAR, FLOAT, evse_pp_voltage, 21) \ -X(a, STATIC, SINGULAR, FLOAT, max_current_cable, 22) \ -X(a, STATIC, SINGULAR, UINT32, watchdog_reset_count, 23) \ -X(a, STATIC, SINGULAR, BOOL, simulation, 24) \ -X(a, STATIC, SINGULAR, UENUM, control_mode, 25) \ -X(a, STATIC, SINGULAR, FLOAT, max_current, 26) \ -X(a, STATIC, SINGULAR, BOOL, use_three_phases, 27) \ -X(a, STATIC, SINGULAR, FLOAT, rcd_current, 28) \ -X(a, STATIC, SINGULAR, BOOL, relais_on, 29) -#define DebugUpdate_CALLBACK NULL -#define DebugUpdate_DEFAULT NULL - -extern const pb_msgdesc_t LoToHi_msg; -extern const pb_msgdesc_t Event_msg; -extern const pb_msgdesc_t SimulationFeedback_msg; -extern const pb_msgdesc_t PowerMeter_msg; -extern const pb_msgdesc_t KeepAliveLo_msg; -extern const pb_msgdesc_t StateUpdate_msg; -extern const pb_msgdesc_t ErrorFlags_msg; -extern const pb_msgdesc_t ChargingFlags_msg; -extern const pb_msgdesc_t ResetDone_msg; -extern const pb_msgdesc_t DebugUpdate_msg; - -/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define LoToHi_fields &LoToHi_msg -#define Event_fields &Event_msg -#define SimulationFeedback_fields &SimulationFeedback_msg -#define PowerMeter_fields &PowerMeter_msg -#define KeepAliveLo_fields &KeepAliveLo_msg -#define StateUpdate_fields &StateUpdate_msg -#define ErrorFlags_fields &ErrorFlags_msg -#define ChargingFlags_fields &ChargingFlags_msg -#define ResetDone_fields &ResetDone_msg -#define DebugUpdate_fields &DebugUpdate_msg - -/* Maximum encoded size of messages (where known) */ -#define ChargingFlags_size 2 -#define DebugUpdate_size 92 -#define ErrorFlags_size 2 -#define Event_size 2 -#define KeepAliveLo_size 106 -#define LoToHi_size 123 -#define PowerMeter_size 121 -#define ResetDone_size 0 -#define SimulationFeedback_size 23 -#define StateUpdate_size 12 - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif diff --git a/modules/YetiDriver/yeti_comms/protobuf/lo2hi.proto b/modules/YetiDriver/yeti_comms/protobuf/lo2hi.proto deleted file mode 100644 index f1850a5faa..0000000000 --- a/modules/YetiDriver/yeti_comms/protobuf/lo2hi.proto +++ /dev/null @@ -1,169 +0,0 @@ -syntax = "proto3"; -import "common.proto"; - -/* - This container message is send from Lo Level to Hi level and may contain any allowed message in that direction. -*/ -message LoToHi { - oneof payload { - // Common Packets - KeepAliveLo keep_alive = 3; - PowerMeter power_meter = 4; - DebugUpdate debug_update = 2; - ResetDone reset_done = 7; - // Packets only available in control_mode = 1 (high level control) - StateUpdate state_update = 1; - // Packets only available in control_mode = 2 (low level control) - Event event = 6; - // HIL packets - SimulationFeedback simulation_feedback = 5; - } -} - -message Event { - enum InterfaceEvent { - CAR_PLUGGED_IN = 0; - CAR_REQUESTED_POWER = 1; - POWER_ON = 2; - POWER_OFF = 3; - CAR_REQUESTED_STOP_POWER = 4; - CAR_UNPLUGGED = 5; - ERROR_E = 6; - ERROR_DF = 7; - ERROR_RELAIS = 8; - ERROR_RCD = 9; - ERROR_VENTILATION_NOT_AVAILABLE = 10; - ERROR_OVER_CURRENT = 11; - ENTER_BCD = 12; - LEAVE_BCD = 13; - PERMANENT_FAULT = 14; - EVSE_REPLUG_STARTED = 15; - EVSE_REPLUG_FINISHED = 16; - } - InterfaceEvent type = 1; -} - -message SimulationFeedback { - float pwmDutyCycle = 1; - float evse_pwm_voltage_hi = 2; - float evse_pwm_voltage_lo = 3; - bool evse_pwm_running = 4; - uint32 relais_on = 5; -} - -message PowerMeter { - uint32 time_stamp = 1; - float vrmsL1 = 2; - float vrmsL2 = 3; - float vrmsL3 = 4; - float irmsL1 = 5; - float irmsL2 = 6; - float irmsL3 = 7; - float irmsN = 8; - float wattHrL1 = 9; - float wattHrL2 = 10; - float wattHrL3 = 11; - float totalWattHr = 12; - float tempL1 = 13; - float tempL2 = 14; - float tempL3 = 15; - float tempN = 16; - float wattL1 = 17; - float wattL2 = 18; - float wattL3 = 19; - float freqL1 = 20; - float freqL2 = 21; - float freqL3 = 22; - bool phaseSeqError = 23; -} - -message KeepAliveLo { - uint32 time_stamp = 1; - uint32 hw_type = 2; - uint32 hw_revision = 3; - uint32 protocol_version_major = 4; - uint32 protocol_version_minor = 5; - string sw_version_string = 6; - float hwcap_max_current = 7; - float hwcap_min_current = 8; - uint32 hwcap_max_phase_count = 9; - uint32 hwcap_min_phase_count = 10; - bool supports_changing_phases_during_charging = 11; -} - -message StateUpdate { - uint32 time_stamp = 1; - enum State { - DISABLED = 0; - IDLE = 1; - WAITING_FOR_AUTHENTICATION = 2; - CHARGING = 3; - CHARGING_PAUSED_EV = 4; - CHARGING_PAUSED_EVSE = 5; - CHARGING_FINSIHED = 6; - ERROR = 7; - FAULTED = 8; - } - State state = 2; - oneof state_flags { - ErrorFlags error_type = 3; - ChargingFlags charging_flags = 4; - } -} - -message ErrorFlags { - enum ErrorType { - ERROR_F = 0; - ERROR_E = 1; - ERROR_DF = 2; - ERROR_RELAIS = 3; - ERROR_VENTILATION_NOT_AVAILABLE = 4; - ERROR_RCD = 5; - ERROR_OVER_CURRENT = 6; - } - ErrorType type = 1; -} - -message ChargingFlags { - bool ventilation = 1; -} - -message ResetDone { -} - -message DebugUpdate { - uint32 time_stamp = 1; - float evse_pwm_voltage_hi = 2; - float evse_pwm_voltage_lo = 3; - float supply_voltage_12V = 4; - float supply_voltage_N12V = 5; - enum LoLevelState { - DISABLED = 0; - A = 1; - B = 2; - C = 3; - D = 4; - E = 5; - F = 6; - DF = 7; - } - LoLevelState lowlevel_state = 6; - bool evse_pwm_running = 7; - bool ev_simplified_mode = 8; - bool has_ventilation = 9; - bool ventilated_charging_active = 10; - bool rcd_reclosing_allowed = 12; - InterfaceControlMode control_mode = 25; - bool authorized = 15; - float cpu_temperature = 17; - bool rcd_enabled = 18; - float evse_pp_voltage = 21; - float max_current_cable = 22; - uint32 watchdog_reset_count = 23; - bool simulation = 24; - float max_current = 26; - bool use_three_phases = 27; - float rcd_current = 28; - bool relais_on = 29; -} - diff --git a/modules/YetiDriver/yeti_comms/protobuf/lo2hi.options b/modules/YetiDriver/yeti_comms/protobuf/yeti.options similarity index 51% rename from modules/YetiDriver/yeti_comms/protobuf/lo2hi.options rename to modules/YetiDriver/yeti_comms/protobuf/yeti.options index 9cba6786c2..8242b29aa8 100644 --- a/modules/YetiDriver/yeti_comms/protobuf/lo2hi.options +++ b/modules/YetiDriver/yeti_comms/protobuf/yeti.options @@ -1 +1,2 @@ +KeepAlive.sw_version_string max_length:50 KeepAliveLo.sw_version_string max_length:50 diff --git a/modules/MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.pb.c b/modules/YetiDriver/yeti_comms/protobuf/yeti.pb.c similarity index 54% rename from modules/MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.pb.c rename to modules/YetiDriver/yeti_comms/protobuf/yeti.pb.c index f58e830f99..fb59877bb3 100644 --- a/modules/MicroMegaWattBSP/umwc_comms/protobuf/lo2hi.pb.c +++ b/modules/YetiDriver/yeti_comms/protobuf/yeti.pb.c @@ -1,27 +1,36 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5 */ +/* Generated by nanopb-0.4.6 */ -#include "lo2hi.pb.h" +#include "yeti.pb.h" #if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. #endif -PB_BIND(LoToHi, LoToHi, AUTO) +PB_BIND(EverestToMcu, EverestToMcu, 2) -PB_BIND(Event, Event, AUTO) +PB_BIND(McuToEverest, McuToEverest, 2) -PB_BIND(PowerMeter, PowerMeter, AUTO) +PB_BIND(ErrorFlags, ErrorFlags, AUTO) + + +PB_BIND(KeepAliveLo, KeepAliveLo, AUTO) + + +PB_BIND(KeepAlive, KeepAlive, AUTO) PB_BIND(Telemetry, Telemetry, AUTO) -PB_BIND(KeepAliveLo, KeepAliveLo, AUTO) +PB_BIND(PowerMeter, PowerMeter, AUTO) + + +PB_BIND(FirmwareUpdate, FirmwareUpdate, AUTO) + -PB_BIND(ResetDone, ResetDone, AUTO) diff --git a/modules/YetiDriver/yeti_comms/protobuf/yeti.pb.h b/modules/YetiDriver/yeti_comms/protobuf/yeti.pb.h new file mode 100644 index 0000000000..15e41dda38 --- /dev/null +++ b/modules/YetiDriver/yeti_comms/protobuf/yeti.pb.h @@ -0,0 +1,380 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.6 */ + +#ifndef PB_YETI_PB_H_INCLUDED +#define PB_YETI_PB_H_INCLUDED +#include + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Enum definitions */ +typedef enum _CpState { + CpState_STATE_A = 0, + CpState_STATE_B = 1, + CpState_STATE_C = 2, + CpState_STATE_D = 3, + CpState_STATE_E = 4, + CpState_STATE_F = 5 +} CpState; + +typedef enum _ResetReason { + ResetReason_USER = 0, + ResetReason_WATCHDOG = 1 +} ResetReason; + +typedef enum _PpState { + PpState_STATE_NC = 0, + PpState_STATE_13A = 1, + PpState_STATE_20A = 2, + PpState_STATE_32A = 3, + PpState_STATE_70A = 4, + PpState_STATE_FAULT = 5 +} PpState; + +typedef enum _LockState { + LockState_UNDEFINED = 0, + LockState_UNLOCKED = 1, + LockState_LOCKED = 2 +} LockState; + +/* Struct definitions */ +typedef struct _ErrorFlags { + bool diode_fault; + bool rcd_selftest_failed; + bool rcd_triggered; + bool ventilation_not_available; + bool connector_lock_failed; + bool cp_signal_fault; +} ErrorFlags; + +typedef struct _FirmwareUpdate { + bool invoke_rom_bootloader; +} FirmwareUpdate; + +typedef struct _KeepAlive { + uint32_t time_stamp; + uint32_t hw_type; + uint32_t hw_revision; + char sw_version_string[51]; +} KeepAlive; + +typedef struct _KeepAliveLo { + uint32_t time_stamp; + uint32_t hw_type; + uint32_t hw_revision; + uint32_t protocol_version_major; + uint32_t protocol_version_minor; + char sw_version_string[51]; + float hwcap_max_current; + float hwcap_min_current; + uint32_t hwcap_max_phase_count; + uint32_t hwcap_min_phase_count; + bool supports_changing_phases_during_charging; +} KeepAliveLo; + +typedef struct _PowerMeter { + uint32_t time_stamp; + float vrmsL1; + float vrmsL2; + float vrmsL3; + float irmsL1; + float irmsL2; + float irmsL3; + float irmsN; + float wattHrL1; + float wattHrL2; + float wattHrL3; + float totalWattHr; + float tempL1; + float tempL2; + float tempL3; + float tempN; + float wattL1; + float wattL2; + float wattL3; + float freqL1; + float freqL2; + float freqL3; + bool phaseSeqError; +} PowerMeter; + +typedef struct _Telemetry { + uint32_t cp_voltage_hi; + uint32_t cp_voltage_lo; +} Telemetry; + +/* This container message is send from EVerest to MCU and may contain any allowed message in that direction. */ +typedef struct _EverestToMcu { + pb_size_t which_payload; + union { + /* Needs to remain the same to allow firmware updates of older versions */ + FirmwareUpdate firmware_update; + /* Other IDs are 100+ to avoid compatibility issues with older firmware versions */ + KeepAlive keep_alive; + bool connector_lock; /* false: unlock, true: lock */ + uint32_t pwm_duty_cycle; /* in 0.01 %, 0 = State F, 10000 = X1 */ + bool allow_power_on; + bool reset; + } payload; +} EverestToMcu; + +/* This container message is send from MCU to EVerest and may contain any allowed message in that direction. */ +typedef struct _McuToEverest { + pb_size_t which_payload; + union { + /* Needs to remain the same to allow firmware updates of older versions */ + KeepAliveLo keep_alive; + /* Other IDs are 100+ to avoid compatibility issues with older firmware versions */ + ResetReason reset; + CpState cp_state; + bool relais_state; /* false: relais are off, true: relais are on */ + ErrorFlags error_flags; + Telemetry telemetry; + PpState pp_state; + LockState lock_state; + PowerMeter power_meter; + } payload; +} McuToEverest; + + +/* Helper constants for enums */ +#define _CpState_MIN CpState_STATE_A +#define _CpState_MAX CpState_STATE_F +#define _CpState_ARRAYSIZE ((CpState)(CpState_STATE_F+1)) + +#define _ResetReason_MIN ResetReason_USER +#define _ResetReason_MAX ResetReason_WATCHDOG +#define _ResetReason_ARRAYSIZE ((ResetReason)(ResetReason_WATCHDOG+1)) + +#define _PpState_MIN PpState_STATE_NC +#define _PpState_MAX PpState_STATE_FAULT +#define _PpState_ARRAYSIZE ((PpState)(PpState_STATE_FAULT+1)) + +#define _LockState_MIN LockState_UNDEFINED +#define _LockState_MAX LockState_LOCKED +#define _LockState_ARRAYSIZE ((LockState)(LockState_LOCKED+1)) + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define EverestToMcu_init_default {0, {FirmwareUpdate_init_default}} +#define McuToEverest_init_default {0, {KeepAliveLo_init_default}} +#define ErrorFlags_init_default {0, 0, 0, 0, 0, 0} +#define KeepAliveLo_init_default {0, 0, 0, 0, 0, "", 0, 0, 0, 0, 0} +#define KeepAlive_init_default {0, 0, 0, ""} +#define Telemetry_init_default {0, 0} +#define PowerMeter_init_default {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define FirmwareUpdate_init_default {0} +#define EverestToMcu_init_zero {0, {FirmwareUpdate_init_zero}} +#define McuToEverest_init_zero {0, {KeepAliveLo_init_zero}} +#define ErrorFlags_init_zero {0, 0, 0, 0, 0, 0} +#define KeepAliveLo_init_zero {0, 0, 0, 0, 0, "", 0, 0, 0, 0, 0} +#define KeepAlive_init_zero {0, 0, 0, ""} +#define Telemetry_init_zero {0, 0} +#define PowerMeter_init_zero {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +#define FirmwareUpdate_init_zero {0} + +/* Field tags (for use in manual encoding/decoding) */ +#define ErrorFlags_diode_fault_tag 1 +#define ErrorFlags_rcd_selftest_failed_tag 2 +#define ErrorFlags_rcd_triggered_tag 3 +#define ErrorFlags_ventilation_not_available_tag 4 +#define ErrorFlags_connector_lock_failed_tag 5 +#define ErrorFlags_cp_signal_fault_tag 6 +#define FirmwareUpdate_invoke_rom_bootloader_tag 1 +#define KeepAlive_time_stamp_tag 1 +#define KeepAlive_hw_type_tag 2 +#define KeepAlive_hw_revision_tag 3 +#define KeepAlive_sw_version_string_tag 6 +#define KeepAliveLo_time_stamp_tag 1 +#define KeepAliveLo_hw_type_tag 2 +#define KeepAliveLo_hw_revision_tag 3 +#define KeepAliveLo_protocol_version_major_tag 4 +#define KeepAliveLo_protocol_version_minor_tag 5 +#define KeepAliveLo_sw_version_string_tag 6 +#define KeepAliveLo_hwcap_max_current_tag 7 +#define KeepAliveLo_hwcap_min_current_tag 8 +#define KeepAliveLo_hwcap_max_phase_count_tag 9 +#define KeepAliveLo_hwcap_min_phase_count_tag 10 +#define KeepAliveLo_supports_changing_phases_during_charging_tag 11 +#define PowerMeter_time_stamp_tag 1 +#define PowerMeter_vrmsL1_tag 2 +#define PowerMeter_vrmsL2_tag 3 +#define PowerMeter_vrmsL3_tag 4 +#define PowerMeter_irmsL1_tag 5 +#define PowerMeter_irmsL2_tag 6 +#define PowerMeter_irmsL3_tag 7 +#define PowerMeter_irmsN_tag 8 +#define PowerMeter_wattHrL1_tag 9 +#define PowerMeter_wattHrL2_tag 10 +#define PowerMeter_wattHrL3_tag 11 +#define PowerMeter_totalWattHr_tag 12 +#define PowerMeter_tempL1_tag 13 +#define PowerMeter_tempL2_tag 14 +#define PowerMeter_tempL3_tag 15 +#define PowerMeter_tempN_tag 16 +#define PowerMeter_wattL1_tag 17 +#define PowerMeter_wattL2_tag 18 +#define PowerMeter_wattL3_tag 19 +#define PowerMeter_freqL1_tag 20 +#define PowerMeter_freqL2_tag 21 +#define PowerMeter_freqL3_tag 22 +#define PowerMeter_phaseSeqError_tag 23 +#define Telemetry_cp_voltage_hi_tag 1 +#define Telemetry_cp_voltage_lo_tag 2 +#define EverestToMcu_firmware_update_tag 16 +#define EverestToMcu_keep_alive_tag 100 +#define EverestToMcu_connector_lock_tag 102 +#define EverestToMcu_pwm_duty_cycle_tag 103 +#define EverestToMcu_allow_power_on_tag 104 +#define EverestToMcu_reset_tag 105 +#define McuToEverest_keep_alive_tag 3 +#define McuToEverest_reset_tag 101 +#define McuToEverest_cp_state_tag 102 +#define McuToEverest_relais_state_tag 103 +#define McuToEverest_error_flags_tag 104 +#define McuToEverest_telemetry_tag 105 +#define McuToEverest_pp_state_tag 106 +#define McuToEverest_lock_state_tag 107 +#define McuToEverest_power_meter_tag 108 + +/* Struct field encoding specification for nanopb */ +#define EverestToMcu_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,firmware_update,payload.firmware_update), 16) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,keep_alive,payload.keep_alive), 100) \ +X(a, STATIC, ONEOF, BOOL, (payload,connector_lock,payload.connector_lock), 102) \ +X(a, STATIC, ONEOF, UINT32, (payload,pwm_duty_cycle,payload.pwm_duty_cycle), 103) \ +X(a, STATIC, ONEOF, BOOL, (payload,allow_power_on,payload.allow_power_on), 104) \ +X(a, STATIC, ONEOF, BOOL, (payload,reset,payload.reset), 105) +#define EverestToMcu_CALLBACK NULL +#define EverestToMcu_DEFAULT NULL +#define EverestToMcu_payload_firmware_update_MSGTYPE FirmwareUpdate +#define EverestToMcu_payload_keep_alive_MSGTYPE KeepAlive + +#define McuToEverest_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,keep_alive,payload.keep_alive), 3) \ +X(a, STATIC, ONEOF, UENUM, (payload,reset,payload.reset), 101) \ +X(a, STATIC, ONEOF, UENUM, (payload,cp_state,payload.cp_state), 102) \ +X(a, STATIC, ONEOF, BOOL, (payload,relais_state,payload.relais_state), 103) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,error_flags,payload.error_flags), 104) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,telemetry,payload.telemetry), 105) \ +X(a, STATIC, ONEOF, UENUM, (payload,pp_state,payload.pp_state), 106) \ +X(a, STATIC, ONEOF, UENUM, (payload,lock_state,payload.lock_state), 107) \ +X(a, STATIC, ONEOF, MESSAGE, (payload,power_meter,payload.power_meter), 108) +#define McuToEverest_CALLBACK NULL +#define McuToEverest_DEFAULT NULL +#define McuToEverest_payload_keep_alive_MSGTYPE KeepAliveLo +#define McuToEverest_payload_error_flags_MSGTYPE ErrorFlags +#define McuToEverest_payload_telemetry_MSGTYPE Telemetry +#define McuToEverest_payload_power_meter_MSGTYPE PowerMeter + +#define ErrorFlags_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, BOOL, diode_fault, 1) \ +X(a, STATIC, SINGULAR, BOOL, rcd_selftest_failed, 2) \ +X(a, STATIC, SINGULAR, BOOL, rcd_triggered, 3) \ +X(a, STATIC, SINGULAR, BOOL, ventilation_not_available, 4) \ +X(a, STATIC, SINGULAR, BOOL, connector_lock_failed, 5) \ +X(a, STATIC, SINGULAR, BOOL, cp_signal_fault, 6) +#define ErrorFlags_CALLBACK NULL +#define ErrorFlags_DEFAULT NULL + +#define KeepAliveLo_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, time_stamp, 1) \ +X(a, STATIC, SINGULAR, UINT32, hw_type, 2) \ +X(a, STATIC, SINGULAR, UINT32, hw_revision, 3) \ +X(a, STATIC, SINGULAR, UINT32, protocol_version_major, 4) \ +X(a, STATIC, SINGULAR, UINT32, protocol_version_minor, 5) \ +X(a, STATIC, SINGULAR, STRING, sw_version_string, 6) \ +X(a, STATIC, SINGULAR, FLOAT, hwcap_max_current, 7) \ +X(a, STATIC, SINGULAR, FLOAT, hwcap_min_current, 8) \ +X(a, STATIC, SINGULAR, UINT32, hwcap_max_phase_count, 9) \ +X(a, STATIC, SINGULAR, UINT32, hwcap_min_phase_count, 10) \ +X(a, STATIC, SINGULAR, BOOL, supports_changing_phases_during_charging, 11) +#define KeepAliveLo_CALLBACK NULL +#define KeepAliveLo_DEFAULT NULL + +#define KeepAlive_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, time_stamp, 1) \ +X(a, STATIC, SINGULAR, UINT32, hw_type, 2) \ +X(a, STATIC, SINGULAR, UINT32, hw_revision, 3) \ +X(a, STATIC, SINGULAR, STRING, sw_version_string, 6) +#define KeepAlive_CALLBACK NULL +#define KeepAlive_DEFAULT NULL + +#define Telemetry_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, cp_voltage_hi, 1) \ +X(a, STATIC, SINGULAR, UINT32, cp_voltage_lo, 2) +#define Telemetry_CALLBACK NULL +#define Telemetry_DEFAULT NULL + +#define PowerMeter_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, time_stamp, 1) \ +X(a, STATIC, SINGULAR, FLOAT, vrmsL1, 2) \ +X(a, STATIC, SINGULAR, FLOAT, vrmsL2, 3) \ +X(a, STATIC, SINGULAR, FLOAT, vrmsL3, 4) \ +X(a, STATIC, SINGULAR, FLOAT, irmsL1, 5) \ +X(a, STATIC, SINGULAR, FLOAT, irmsL2, 6) \ +X(a, STATIC, SINGULAR, FLOAT, irmsL3, 7) \ +X(a, STATIC, SINGULAR, FLOAT, irmsN, 8) \ +X(a, STATIC, SINGULAR, FLOAT, wattHrL1, 9) \ +X(a, STATIC, SINGULAR, FLOAT, wattHrL2, 10) \ +X(a, STATIC, SINGULAR, FLOAT, wattHrL3, 11) \ +X(a, STATIC, SINGULAR, FLOAT, totalWattHr, 12) \ +X(a, STATIC, SINGULAR, FLOAT, tempL1, 13) \ +X(a, STATIC, SINGULAR, FLOAT, tempL2, 14) \ +X(a, STATIC, SINGULAR, FLOAT, tempL3, 15) \ +X(a, STATIC, SINGULAR, FLOAT, tempN, 16) \ +X(a, STATIC, SINGULAR, FLOAT, wattL1, 17) \ +X(a, STATIC, SINGULAR, FLOAT, wattL2, 18) \ +X(a, STATIC, SINGULAR, FLOAT, wattL3, 19) \ +X(a, STATIC, SINGULAR, FLOAT, freqL1, 20) \ +X(a, STATIC, SINGULAR, FLOAT, freqL2, 21) \ +X(a, STATIC, SINGULAR, FLOAT, freqL3, 22) \ +X(a, STATIC, SINGULAR, BOOL, phaseSeqError, 23) +#define PowerMeter_CALLBACK NULL +#define PowerMeter_DEFAULT NULL + +#define FirmwareUpdate_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, BOOL, invoke_rom_bootloader, 1) +#define FirmwareUpdate_CALLBACK NULL +#define FirmwareUpdate_DEFAULT NULL + +extern const pb_msgdesc_t EverestToMcu_msg; +extern const pb_msgdesc_t McuToEverest_msg; +extern const pb_msgdesc_t ErrorFlags_msg; +extern const pb_msgdesc_t KeepAliveLo_msg; +extern const pb_msgdesc_t KeepAlive_msg; +extern const pb_msgdesc_t Telemetry_msg; +extern const pb_msgdesc_t PowerMeter_msg; +extern const pb_msgdesc_t FirmwareUpdate_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define EverestToMcu_fields &EverestToMcu_msg +#define McuToEverest_fields &McuToEverest_msg +#define ErrorFlags_fields &ErrorFlags_msg +#define KeepAliveLo_fields &KeepAliveLo_msg +#define KeepAlive_fields &KeepAlive_msg +#define Telemetry_fields &Telemetry_msg +#define PowerMeter_fields &PowerMeter_msg +#define FirmwareUpdate_fields &FirmwareUpdate_msg + +/* Maximum encoded size of messages (where known) */ +#define ErrorFlags_size 12 +#define EverestToMcu_size 73 +#define FirmwareUpdate_size 2 +#define KeepAliveLo_size 106 +#define KeepAlive_size 70 +#define McuToEverest_size 124 +#define PowerMeter_size 121 +#define Telemetry_size 12 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/modules/YetiDriver/yeti_comms/protobuf/yeti.proto b/modules/YetiDriver/yeti_comms/protobuf/yeti.proto new file mode 100644 index 0000000000..69e0353a62 --- /dev/null +++ b/modules/YetiDriver/yeti_comms/protobuf/yeti.proto @@ -0,0 +1,132 @@ +syntax = "proto3"; + +/* + This container message is send from EVerest to MCU and may contain any allowed message in that direction. +*/ +message EverestToMcu { + oneof payload { + // Needs to remain the same to allow firmware updates of older versions + FirmwareUpdate firmware_update = 16; + + // Other IDs are 100+ to avoid compatibility issues with older firmware versions + KeepAlive keep_alive = 100; + bool connector_lock = 102; // false: unlock, true: lock + uint32 pwm_duty_cycle = 103; // in 0.01 %, 0 = State F, 10000 = X1 + bool allow_power_on = 104; + bool reset = 105; + } +} + +/* + This container message is send from MCU to EVerest and may contain any allowed message in that direction. +*/ +message McuToEverest { + oneof payload { + // Needs to remain the same to allow firmware updates of older versions + KeepAliveLo keep_alive = 3; + + // Other IDs are 100+ to avoid compatibility issues with older firmware versions + ResetReason reset = 101; + CpState cp_state = 102; + bool relais_state = 103; // false: relais are off, true: relais are on + ErrorFlags error_flags = 104; + Telemetry telemetry = 105; + PpState pp_state = 106; + LockState lock_state = 107; + PowerMeter power_meter = 108; + } +} + +enum CpState { + STATE_A = 0; + STATE_B = 1; + STATE_C = 2; + STATE_D = 3; + STATE_E = 4; + STATE_F = 5; +} + +message ErrorFlags { + bool diode_fault = 1; + bool rcd_selftest_failed = 2; + bool rcd_triggered = 3; + bool ventilation_not_available = 4; + bool connector_lock_failed = 5; + bool cp_signal_fault = 6; +} + +enum ResetReason { + USER = 0; + WATCHDOG = 1; +} + +message KeepAliveLo { + uint32 time_stamp = 1; + uint32 hw_type = 2; + uint32 hw_revision = 3; + uint32 protocol_version_major = 4; + uint32 protocol_version_minor = 5; + string sw_version_string = 6; + float hwcap_max_current = 7; + float hwcap_min_current = 8; + uint32 hwcap_max_phase_count = 9; + uint32 hwcap_min_phase_count = 10; + bool supports_changing_phases_during_charging = 11; +} + +message KeepAlive { + uint32 time_stamp = 1; + uint32 hw_type = 2; + uint32 hw_revision = 3; + string sw_version_string = 6; +} + +message Telemetry { + uint32 cp_voltage_hi = 1; + uint32 cp_voltage_lo = 2; +} + +enum PpState { + STATE_NC = 0; + STATE_13A = 1; + STATE_20A = 2; + STATE_32A = 3; + STATE_70A = 4; + STATE_FAULT = 5; +} + +enum LockState { + UNDEFINED = 0; + UNLOCKED = 1; + LOCKED = 2; +} + +message PowerMeter { + uint32 time_stamp = 1; + float vrmsL1 = 2; + float vrmsL2 = 3; + float vrmsL3 = 4; + float irmsL1 = 5; + float irmsL2 = 6; + float irmsL3 = 7; + float irmsN = 8; + float wattHrL1 = 9; + float wattHrL2 = 10; + float wattHrL3 = 11; + float totalWattHr = 12; + float tempL1 = 13; + float tempL2 = 14; + float tempL3 = 15; + float tempN = 16; + float wattL1 = 17; + float wattL2 = 18; + float wattL3 = 19; + float freqL1 = 20; + float freqL2 = 21; + float freqL3 = 22; + bool phaseSeqError = 23; +} + +message FirmwareUpdate { + bool invoke_rom_bootloader = 1; +} \ No newline at end of file diff --git a/modules/YetiDriver/yeti_extras/yeti_extrasImpl.cpp b/modules/YetiDriver/yeti_extras/yeti_extrasImpl.cpp deleted file mode 100644 index 33b60f295c..0000000000 --- a/modules/YetiDriver/yeti_extras/yeti_extrasImpl.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 - 2021 Pionix GmbH and Contributors to EVerest -#include "yeti_extrasImpl.hpp" - -namespace module { -namespace yeti_extras { - -void yeti_extrasImpl::init() { - mod->serial.signalKeepAliveLo.connect([this](const KeepAliveLo& k) { - publish_time_stamp(k.time_stamp); - publish_hw_type(k.hw_type); - publish_hw_revision(k.hw_revision); - publish_protocol_version_major(k.protocol_version_major); - publish_protocol_version_minor(k.protocol_version_minor); - publish_sw_version_string(k.sw_version_string); - }); -} - -void yeti_extrasImpl::ready() { -} - -void yeti_extrasImpl::handle_firmware_update(std::string& firmware_binary){ - // your code for cmd firmware_update goes here -}; - -} // namespace yeti_extras -} // namespace module diff --git a/modules/YetiDriver/yeti_fwupdate/CMakeLists.txt b/modules/YetiDriver/yeti_fwupdate/CMakeLists.txt index 0adb51394d..f9a8276ef1 100644 --- a/modules/YetiDriver/yeti_fwupdate/CMakeLists.txt +++ b/modules/YetiDriver/yeti_fwupdate/CMakeLists.txt @@ -3,12 +3,9 @@ cmake_minimum_required(VERSION 3.10) # set the project name project(yeti_fwupdate VERSION 0.1) # specify the C++ standard -set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED True) - -configure_file(config.h.in config.h) - # add the executable add_executable(yeti_fwupdate main.cpp) target_include_directories(yeti_fwupdate PUBLIC "${PROJECT_BINARY_DIR}" PUBLIC "../yeti_comms/nanopb" PUBLIC "../yeti_comms/protobuf" PUBLIC "../yeti_comms") diff --git a/modules/YetiDriver/yeti_fwupdate/config.h.in b/modules/YetiDriver/yeti_fwupdate/config.h.in deleted file mode 100644 index 82a9261dea..0000000000 --- a/modules/YetiDriver/yeti_fwupdate/config.h.in +++ /dev/null @@ -1,3 +0,0 @@ -// the configured options and settings for YetiDriver -#define yeti_fwupdate_VERSION_MAJOR @yeti_fwupdate_VERSION_MAJOR@ -#define yeti_fwupdate_VERSION_MINOR @yeti_fwupdate_VERSION_MINOR@ diff --git a/modules/YetiDriver/yeti_fwupdate/main.cpp b/modules/YetiDriver/yeti_fwupdate/main.cpp index 2b6a01e14f..2a4b7ccbb9 100644 --- a/modules/YetiDriver/yeti_fwupdate/main.cpp +++ b/modules/YetiDriver/yeti_fwupdate/main.cpp @@ -1,14 +1,12 @@ // SPDX-License-Identifier: Apache-2.0 // Copyright 2020 - 2021 Pionix GmbH and Contributors to EVerest -#include "config.h" #include #include #include "evSerial.h" #include -#include "hi2lo.pb.h" -#include "lo2hi.pb.h" +#include "yeti.pb.h" #include volatile bool sw_version_received = false; @@ -25,7 +23,7 @@ void help() { } int main(int argc, char* argv[]) { - printf("Yeti ROM Bootloader Firmware Updater %i.%i\n", yeti_fwupdate_VERSION_MAJOR, yeti_fwupdate_VERSION_MINOR); + printf("Yeti ROM Bootloader Firmware Updater\n"); if (argc != 3) { help(); exit(0); @@ -46,8 +44,9 @@ int main(int argc, char* argv[]) { } printf("\nRebooting Yeti in ROM Bootloader mode...\n"); // send some dummy commands to make sure protocol is in sync - p->setMaxCurrent(6.); - p->setMaxCurrent(6.); + p->keepAlive(); + p->keepAlive(); + // now reboot uC in boot loader mode p->firmwareUpdate(true); sleep(1); diff --git a/modules/YetiDriver/yeti_simulation_control/yeti_simulation_controlImpl.cpp b/modules/YetiDriver/yeti_simulation_control/yeti_simulation_controlImpl.cpp deleted file mode 100644 index 01ed7d279f..0000000000 --- a/modules/YetiDriver/yeti_simulation_control/yeti_simulation_controlImpl.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2020 - 2021 Pionix GmbH and Contributors to EVerest -#include "yeti_simulation_controlImpl.hpp" - -namespace module { -namespace yeti_simulation_control { - -Everest::json simulation_feedback_to_json(const SimulationFeedback& s) { - Everest::json j; - - j["pwm_duty_cycle"] = s.pwmDutyCycle; - j["relais_on"] = s.relais_on; - j["evse_pwm_running"] = s.evse_pwm_running; - j["evse_pwm_voltage_hi"] = s.evse_pwm_voltage_hi; - j["evse_pwm_voltage_lo"] = s.evse_pwm_voltage_lo; - - return j; -} - -SimulationData json_to_simulation_data(Object& v) { - SimulationData s; - - s.cp_voltage = v["cp_voltage"]; - s.diode_fail = v["diode_fail"]; - s.error_e = v["error_e"]; - s.pp_resistor = v["pp_resistor"]; - s.rcd_current = v["rcd_current"]; - - s.currentL1 = v["currents"]["L1"]; - s.currentL2 = v["currents"]["L2"]; - s.currentL3 = v["currents"]["L3"]; - s.currentN = v["currents"]["N"]; - - s.voltageL1 = v["voltages"]["L1"]; - s.voltageL2 = v["voltages"]["L2"]; - s.voltageL3 = v["voltages"]["L3"]; - - s.freqL1 = v["frequencies"]["L1"]; - s.freqL2 = v["frequencies"]["L2"]; - s.freqL3 = v["frequencies"]["L3"]; - - return s; -} - -void yeti_simulation_controlImpl::init() { - mod->serial.signalSimulationFeedback.connect( - [this](const SimulationFeedback& s) { publish_simulation_feedback(simulation_feedback_to_json(s)); }); -} - -void yeti_simulation_controlImpl::ready() { -} - -void yeti_simulation_controlImpl::handle_enable(bool& value) { - EVLOG_info << "void YetiDriverModule::Yeti_simulation_control::enable: " << value; - mod->serial.enableSimulation(value); -}; - -void yeti_simulation_controlImpl::handle_setSimulationData(::types::yeti::SimulationData& value) { - json j_value = value; - Object o_value = j_value; - mod->serial.setSimulationData(json_to_simulation_data(o_value)); -}; - -} // namespace yeti_simulation_control -} // namespace module diff --git a/modules/simulation/JsCarSimulator/index.js b/modules/simulation/JsCarSimulator/index.js index e8a6605cc5..36514f4427 100644 --- a/modules/simulation/JsCarSimulator/index.js +++ b/modules/simulation/JsCarSimulator/index.js @@ -239,10 +239,12 @@ function car_statemachine(mod) { break; case 'error_e': + mod.simdata_setting.cp_voltage = 0.0; drawPower(mod, 0, 0, 0, 0); mod.simdata.error_e = true; break; case 'diode_fail': + mod.simdata_setting.cp_voltage = 9.0; drawPower(mod, 0, 0, 0, 0); mod.simdata.diode_fail = true; break; diff --git a/modules/simulation/JsYetiSimulator/index.js b/modules/simulation/JsYetiSimulator/index.js index 1f1d095782..eb1f377bad 100644 --- a/modules/simulation/JsYetiSimulator/index.js +++ b/modules/simulation/JsYetiSimulator/index.js @@ -12,26 +12,76 @@ const STATE_C = 3; const STATE_D = 4; const STATE_E = 5; const STATE_F = 6; -const STATE_DF = 7; - -const Event_CarPluggedIn = 0; -const Event_CarRequestedPower = 1; -const Event_PowerOn = 2; -const Event_PowerOff = 3; -const Event_CarRequestedStopPower = 4; -const Event_CarUnplugged = 5; -const Event_Error_E = 6; -const Event_Error_DF = 7; -const Event_Error_Relais = 8; -const Event_Error_RCD = 9; -const Event_Error_VentilationNotAvailable = 10; -const Event_EFtoBCD = 11; -const Event_BCDtoEF = 12; -const Event_PermanentFault = 13; + +const Event_PowerOn = 8; +const Event_PowerOff = 9; var module_id; let global_info; +let active_errors = { + DiodeFault: false, + BrownOut: false, + EnergyManagement: false, + PermanentFault: false, + MREC2GroundFailure: false, + MREC3HighTemperature: false, + MREC4OverCurrentFailure: false, + MREC5OverVoltage: false, + MREC6UnderVoltage: false, + MREC8EmergencyStop: false, + MREC10InvalidVehicleMode: false, + MREC14PilotFault: false, + MREC15PowerLoss: false, + MREC17EVSEContactorFault: false, + MREC18CableOverTempDerate: false, + MREC19CableOverTempStop: false, + MREC20PartialInsertion: false, + MREC23ProximityFault: false, + MREC24ConnectorVoltageHigh: false, + MREC25BrokenLatch: false, + MREC26CutCable: false, + + ac_rcd_MREC2GroundFailure: false, + ac_rcd_VendorError: false, + ac_rcd_Selftest: false, + ac_rcd_AC: false, + ac_rcd_DC: false, + + lock_ConnectorLockCapNotCharged: false, + lock_ConnectorLockUnexpectedOpen: false, + lock_ConnectorLockUnexpectedClose: false, + lock_ConnectorLockFailedLock: false, + lock_ConnectorLockFailedUnlock: false, + lock_MREC1ConnectorLockFailure: false, + lock_VendorError: false, +}; + +function publish_ac_nr_of_phases_available(mod, n) { + mod.provides.board_support.publish.ac_nr_of_phases_available(n); +} + +function read_pp_ampacity(mod) { + let pp_resistor = mod.simulation_data.pp_resistor; + if (pp_resistor < 80.0 || pp_resistor > 2460) { + evlog.error(`PP resistor value "${pp_resistor}" Ohm seems to be outside the allowed range.`); + return "None" + } + + // PP resistor value in spec, use a conservative interpretation of the resistance ranges + if (pp_resistor > 936.0 && pp_resistor <= 2460.0) { + return "A_13"; + } else if (pp_resistor > 308.0 && pp_resistor <= 936.0) { + return "A_20"; + } else if (pp_resistor > 140.0 && pp_resistor <= 308.0) { + return "A_32"; + } else if (pp_resistor > 80.0 && pp_resistor <= 140.0) { + return "A_63"; + } + + return "None"; +} + boot_module(async ({ setup, info, config, mqtt, }) => { @@ -39,11 +89,9 @@ boot_module(async ({ // register commands setup.provides.yeti_simulation_control.register.enable(enable_simulation); setup.provides.yeti_simulation_control.register.setSimulationData((mod, args) => { - /* evlog.error(args.value); */ mod.simulation_data = args.value; }); - setup.provides.yeti_extras.register.firmware_update((mod, args) => { }); setup.provides.powermeter.register.stop_transaction((mod, args) => ({ status: 'NOT_IMPLEMENTED', error: 'YetiDriver does not support stop transaction request.', @@ -54,8 +102,10 @@ boot_module(async ({ mod.three_phases = args.three_phases; mod.has_ventilation = args.has_ventilation; mod.country_code = args.country_code; - mod.rcd_enabled = args.rcd_enabled; - publish_nr_of_phases_available(mod, (mod.use_three_phases_confirmed ? 3 : 1)); + publish_ac_nr_of_phases_available(mod, (mod.use_three_phases_confirmed ? 3 : 1)); + }); + + setup.provides.board_support.register.ac_set_overcurrent_limit_A((mod, args) => { }); setup.provides.board_support.register.enable((mod, args) => { @@ -64,20 +114,21 @@ boot_module(async ({ } else mod.current_state = STATE_DISABLED; }); - setup.provides.board_support.register.pwm_on((mod, args) => { pwmOn(mod, args.value); }); + setup.provides.board_support.register.pwm_on((mod, args) => { pwmOn(mod, args.value / 100.0); }); setup.provides.board_support.register.pwm_off((mod, args) => { pwmOff(mod); }); setup.provides.board_support.register.pwm_F((mod, args) => { pwmF(mod); }); setup.provides.board_support.register.evse_replug((mod, args) => { evlog.error('Replugging not supported'); }); + setup.provides.board_support.register.allow_power_on((mod, args) => { - mod.power_on_allowed = args.value; + mod.power_on_allowed = args.value.allow_power_on; }); - setup.provides.board_support.register.force_unlock((mod, args) => /* lock/unlock not implemented */ true); - setup.provides.board_support.register.switch_three_phases_while_charging((mod, args) => { + + setup.provides.board_support.register.ac_switch_three_phases_while_charging((mod, args) => { mod.use_three_phases = args.value; mod.use_three_phases_confirmed = args.value; - publish_nr_of_phases_available(mod, (mod.use_three_phases_confirmed ? 3 : 1)); + ac_publish_nr_of_phases_available(mod, (mod.use_three_phases_confirmed ? 3 : 1)); }); setup.provides.board_support.register.get_hw_capabilities((mod, args) => ({ max_current_A_import: 32.0, @@ -89,13 +140,142 @@ boot_module(async ({ max_phase_count_export: 3, min_phase_count_export: 1, supports_changing_phases_during_charging: true, + connector_type: "IEC62196Type2Cable", })); - setup.provides.board_support.register.read_pp_ampacity((mod, args) => { - let amp = read_pp_ampacity(mod); + setup.provides.board_support.register.ac_read_pp_ampacity((mod, args) => { + let amp = { ampacity: read_pp_ampacity(mod) }; return amp; }); + setup.provides.connector_lock.register.lock((mod, args) => { + evlog.info('Lock connector'); + }); + setup.provides.connector_lock.register.unlock((mod, args) => { + evlog.info('Unlock connector'); + }); + + // Subscribe to nodered error injection + mqtt.subscribe(`everest_external/nodered/${config.module.connector_id}/carsim/error`, (mod, en) => { + let e = JSON.parse(en); + let raise = e.raise == 'true'; + + switch (e.error_type) { + case "DiodeFault": + error_DiodeFault(mod, raise); + break; + case "BrownOut": + error_BrownOut(mod, raise); + break; + case "EnergyManagement": + error_EnergyManagement(mod, raise); + break; + case "PermanentFault": + error_PermanentFault(mod, raise); + break; + case "MREC2GroundFailure": + error_MREC2GroundFailure(mod, raise); + break; + case "MREC3HighTemperature": + error_MREC3HighTemperature(mod, raise); + break; + case "MREC4OverCurrentFailure": + error_MREC4OverCurrentFailure(mod, raise); + break; + case "MREC5OverVoltage": + error_MREC5OverVoltage(mod, raise); + break; + case "MREC6UnderVoltage": + error_MREC6UnderVoltage(mod, raise); + break; + case "MREC8EmergencyStop": + error_MREC8EmergencyStop(mod, raise); + break; + case "MREC10InvalidVehicleMode": + error_MREC10InvalidVehicleMode(mod, raise); + break; + case "MREC14PilotFault": + error_MREC14PilotFault(mod, raise); + break; + case "MREC15PowerLoss": + error_MREC15PowerLoss(mod, raise); + break; + case "MREC17EVSEContactorFault": + error_MREC17EVSEContactorFault(mod, raise); + break; + case "MREC18CableOverTempDerate": + error_MREC18CableOverTempDerate(mod, raise); + break; + case "MREC19CableOverTempStop": + error_MREC19CableOverTempStop(mod, raise); + break; + case "MREC20PartialInsertion": + error_MREC20PartialInsertion(mod, raise); + break; + case "MREC23ProximityFault": + error_MREC23ProximityFault(mod, raise); + break; + case "MREC24ConnectorVoltageHigh": + error_MREC24ConnectorVoltageHigh(mod, raise); + break; + case "MREC25BrokenLatch": + error_MREC25BrokenLatch(mod, raise); + break; + case "MREC26CutCable": + error_MREC26CutCable(mod, raise); + break; + + case "ac_rcd_MREC2GroundFailure": + error_ac_rcd_MREC2GroundFailure(mod, raise); + break; + + case "ac_rcd_VendorError": + error_ac_rcd_VendorError(mod, raise); + break; + + case "ac_rcd_Selftest": + error_ac_rcd_Selftest(mod, raise); + break; + + case "ac_rcd_AC": + error_ac_rcd_AC(mod, raise); + break; + case "ac_rcd_DC": + error_ac_rcd_DC(mod, raise); + break; + + case "lock_ConnectorLockCapNotCharged": + error_lock_ConnectorLockCapNotCharged(mod, raise); + break; + + case "lock_ConnectorLockUnexpectedOpen": + error_lock_ConnectorLockUnexpectedOpen(mod, raise); + break; + + case "lock_ConnectorLockUnexpectedClose": + error_lock_ConnectorLockUnexpectedClose(mod, raise); + break; + + + case "lock_ConnectorLockFailedLock": + error_lock_ConnectorLockFailedLock(mod, raise); + break; + + case "lock_ConnectorLockFailedUnlock": + error_lock_ConnectorLockFailedUnlock(mod, raise); + break; + + case "lock_MREC1ConnectorLockFailure": + error_lock_MREC1ConnectorLockFailure(mod, raise); + break; + + case "lock_VendorError": + error_lock_VendorError(mod, raise); + break; + + default: + evlog.error("Unknown error raised via MQTT"); + } + }); - // subscribe vars of used modules }).then((mod) => { mod.pubCnt = 0; clearData(mod); @@ -117,7 +297,7 @@ function telemetry_fast(mod) { mod.telemetry_data.power_path_controller.timestamp = date.toISOString(); mod.telemetry_data.power_path_controller.cp_voltage_high = mod.cpHi; mod.telemetry_data.power_path_controller.cp_voltage_low = mod.cpLo; - mod.telemetry_data.power_path_controller.cp_pwm_duty_cycle = mod.pwm_duty_cycle * 100.; + mod.telemetry_data.power_path_controller.cp_pwm_duty_cycle = mod.pwm_duty_cycle * 100.0; mod.telemetry_data.power_path_controller.cp_state = stateToString(mod); mod.telemetry_data.power_path_controller.temperature_controller = mod.powermeter.tempL1; @@ -143,13 +323,14 @@ function telemetry_fast(mod) { } function publish_event(mod, event) { - // console.log("------------ EVENT PUB "+event); - mod.provides.board_support.publish.event(event_to_enum(event)); + //console.log("------------ EVENT PUB " + event); + mod.provides.board_support.publish.event({ event: event_to_enum(event) }); } + function enable_simulation(mod, args) { if (mod.simulation_enabled && !args.value) { - publish_event(mod, Event_CarUnplugged); + publish_event(mod, Event_A); clearData(mod); } mod.simulation_enabled = args.value; @@ -172,7 +353,6 @@ function simulation_loop(mod) { publish_telemetry(mod); break; case 2: - publish_yeti_extras(mod); break; case 3: publish_keepalive(mod); @@ -187,6 +367,10 @@ function simulation_loop(mod) { // state machine for the evse function simulation_statemachine(mod) { + if (mod.last_state != mod.current_state) { + publish_event(mod, mod.current_state); + } + switch (mod.current_state) { case STATE_DISABLED: powerOff(); @@ -199,15 +383,9 @@ function simulation_statemachine(mod) { reset_powermeter(mod); mod.simplified_mode = false; - if (mod.last_state === STATE_B || mod.last_state === STATE_C || mod.last_state === STATE_D) { - publish_event(mod, Event_BCDtoEF); - } - if (mod.last_state != STATE_A && mod.last_state != STATE_DISABLED && mod.last_state != STATE_F) { - publish_event(mod, Event_CarRequestedStopPower); powerOff(mod); - publish_event(mod, Event_CarUnplugged); // If car was unplugged, reset RCD flag. mod.rcd_current = 0.1; @@ -220,70 +398,41 @@ function simulation_statemachine(mod) { // responds to EV opens S2 (w/o PWM) if (mod.last_state != STATE_A && mod.last_state != STATE_B) { - publish_event(mod, Event_CarRequestedStopPower); + // Need to switch off according to Table A.6 Sequence 8.1 within powerOff(mod); } // Table A.6: Sequence 1.1 Plug-in if (mod.last_state === STATE_A) { - publish_event(mod, Event_CarPluggedIn); mod.simplified_mode = false; } - if (mod.last_state === STATE_E || mod.last_state === STATE_F) { - publish_event(mod, Event_EFtoBCD); - } break; case STATE_C: // Table A.6: Sequence 1.2 Plug-in if (mod.last_state === STATE_A) { - publish_event(mod, Event_CarPluggedIn); mod.simplified_mode = true; } - if (mod.last_state === STATE_B) { - publish_event(mod, Event_CarRequestedPower); - } - if (mod.last_state === STATE_E || mod.last_state === STATE_F) { - publish_event(mod, Event_EFtoBCD); - } if (!mod.pwm_running) { // C1 // Table A.6 Sequence 10.2: EV does not stop drawing power even // if PWM stops. Stop within 6 seconds (E.g. Kona1!) - // if (mod.last_pwm_running) FIXME implement 6 second timer! - // startTimer(6000); - // if (timerElapsed()) { - // force power off under load - powerOff(mod); - // } + // This is implemented in EvseManager + if (!mod.power_on_allowed) powerOff(mod); } else { // C2 if (mod.power_on_allowed) { // Table A.6: Sequence 4 EV ready to charge. // Must enable power within 3 seconds. powerOn(mod); - - // Simulate Request power Event here for simplified mode to - // ensure that this mode behaves similar for higher layers. - // Note this does not work with 5% mode correctly, but - // simplified mode does not support HLC anyway. - if (!mod.last_pwm_running && mod.simplified_mode) publish_event(mod, Event_CarRequestedPower); } } break; case STATE_D: // Table A.6: Sequence 1.2 Plug-in (w/ventilation) if (mod.last_state === STATE_A) { - publish_event(mod, Event_CarPluggedIn); - publish_event(mod, Event_CarRequestedPower); mod.simplified_mode = true; } - if (mod.last_state === STATE_B) { - publish_event(mod, Event_CarRequestedPower); - } - if (mod.last_state === STATE_E || mod.last_state === STATE_F) { - publish_event(mod, Event_EFtoBCD); - } if (!mod.pwm_running) { // Table A.6 Sequence 10.2: EV does not stop drawing power @@ -298,34 +447,15 @@ function simulation_statemachine(mod) { if (mod.power_on_allowed && !mod.relais_on) { // Table A.6: Sequence 4 EV ready to charge. // Must enable power within 3 seconds. - if (!mod.has_ventilation) publish_event(mod, Event_Error_VentilationNotAvailable); - else powerOn(mod); - } - if (mod.last_state === STATE_C) { - // Car switches to ventilation while charging. - if (!mod.has_ventilation) publish_event(mod, Event_Error_VentilationNotAvailable); + if (mod.has_ventilation) powerOn(mod); } } break; case STATE_E: - if (mod.last_state != mod.current_state) publish_event(mod, Event_Error_E); - if (mod.last_state === STATE_B || mod.last_state === STATE_C || mod.last_state === STATE_D) { - publish_event(mod, Event_BCDtoEF); - } powerOff(mod); pwmOff(mod); break; case STATE_F: - if (mod.last_state === STATE_B || mod.last_state === STATE_C || mod.last_state === STATE_D) { - publish_event(mod, Event_BCDtoEF); - } - powerOff(mod); - break; - case STATE_DF: - if (mod.last_state != mod.current_state) publish_event(mod, Event_Error_DF); - if (mod.last_state === STATE_B || mod.last_state === STATE_C || mod.last_state === STATE_D) { - publish_event(mod, Event_BCDtoEF); - } powerOff(mod); break; } @@ -335,46 +465,38 @@ function simulation_statemachine(mod) { function check_error_rcd(mod) { if (mod.rcd_enabled && mod.simulation_data.rcd_current > 5.0) { - publish_event(mod, Event_Error_RCD); + if (!mod.rcd_error_reported) { + mod.provides.board_support.raise.ac_rcd_DC('Simulated fault event', 'High'); + mod.rcd_error_reported = true; + } + } else { + mod.rcd_error_reported = false; } -} - -function publish_nr_of_phases_available(mod, n) { - // console.log("------------ NR PHASE PUB "+n); - mod.provides.board_support.publish.nr_of_phases_available(n); + mod.provides.rcd.publish.rcd_current_mA = mod.simulation_data.rcd_current; } function event_to_enum(event) { switch (event) { - case Event_CarPluggedIn: - return 'CarPluggedIn'; - case Event_CarRequestedPower: - return 'CarRequestedPower'; + case STATE_A: + return 'A'; + case STATE_B: + return 'B'; + case STATE_C: + return 'C'; + case STATE_D: + return 'D'; + case STATE_E: + return 'E'; + case STATE_F: + return 'F'; + case STATE_DISABLED: + return 'F'; case Event_PowerOn: return 'PowerOn'; case Event_PowerOff: return 'PowerOff'; - case Event_CarRequestedStopPower: - return 'CarRequestedStopPower'; - case Event_CarUnplugged: - return 'CarUnplugged'; - case Event_Error_E: - return 'ErrorE'; - case Event_Error_DF: - return 'ErrorDF'; - case Event_Error_Relais: - return 'ErrorRelais'; - case Event_Error_RCD: - return 'ErrorRCD'; - case Event_Error_VentilationNotAvailable: - return 'VentilationNotAvailable'; - case Event_EFtoBCD: - return 'EFtoBCD'; - case Event_BCDtoEF: - return 'BCDtoEF'; - case Event_PermanentFault: - return 'PermanentFault'; default: + evlog.error("Invalid event: " + event); return 'invalid'; } } @@ -448,10 +570,13 @@ function read_from_car(mod) { if (is_voltage_in_range(cpLo, 0.0) && is_voltage_in_range(cpHi, 0.0)) mod.current_state = STATE_E; // Diode fault else if (is_voltage_in_range(cpHi + cpLo, 0.0)) { - mod.current_state = STATE_DF; + // throw DF error + error_DiodeFault(mod, true); } else return; } else if (is_voltage_in_range(cpHi, 12.0)) { // +12V State A IDLE (open circuit) + // clear all errors that clear on disconnection + clear_disconnect_errors(mod); mod.current_state = STATE_A; } else if (is_voltage_in_range(cpHi, 9.0)) { mod.current_state = STATE_B; @@ -466,6 +591,351 @@ function read_from_car(mod) { } } +function error_BrownOut(mod, raise) { + if (!active_errors.BrownOut) { + mod.provides.board_support.raise.evse_board_support_BrownOut('Simulated fault event', 'High'); + active_errors.BrownOut = true; + } else if (!raise && active_errors.BrownOut) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_BrownOut(); + active_errors.BrownOut = false; + } +} + +function error_EnergyManagement(mod, raise) { + if (!active_errors.EnergyManagement) { + mod.provides.board_support.raise.evse_board_support_EnergyManagement('Simulated fault event', 'High'); + active_errors.EnergyManagement = true; + } else if (!raise && active_errors.EnergyManagement) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_EnergyManagement(); + active_errors.EnergyManagement = false; + } +} + +function error_PermanentFault(mod, raise) { + if (!active_errors.PermanentFault) { + mod.provides.board_support.raise.evse_board_support_PermanentFault('Simulated fault event', 'High'); + active_errors.PermanentFault = true; + } else if (!raise && active_errors.PermanentFault) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_PermanentFault(); + active_errors.PermanentFault = false; + } +} + +function error_MREC2GroundFailure(mod, raise) { + if (!active_errors.MREC2GroundFailure) { + mod.provides.board_support.raise.evse_board_support_MREC2GroundFailure('Simulated fault event', 'High'); + active_errors.MREC2GroundFailure = true; + } else if (!raise && active_errors.MREC2GroundFailure) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC2GroundFailure(); + active_errors.MREC2GroundFailure = false; + } +} + +function error_MREC3HighTemperature(mod, raise) { + if (!active_errors.MREC3HighTemperature) { + mod.provides.board_support.raise.evse_board_support_MREC3HighTemperature('Simulated fault event', 'High'); + active_errors.MREC3HighTemperature = true; + } else if (!raise && active_errors.MREC3HighTemperature) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC3HighTemperature(); + active_errors.MREC3HighTemperature = false; + } +} + +function error_MREC4OverCurrentFailure(mod, raise) { + if (!active_errors.MREC4OverCurrentFailure) { + mod.provides.board_support.raise.evse_board_support_MREC4OverCurrentFailure('Simulated fault event', 'High'); + active_errors.MREC4OverCurrentFailure = true; + } else if (!raise && active_errors.MREC4OverCurrentFailure) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC4OverCurrentFailure(); + active_errors.MREC4OverCurrentFailure = false; + } +} + +function error_MREC5OverVoltage(mod, raise) { + if (!active_errors.MREC5OverVoltage) { + mod.provides.board_support.raise.evse_board_support_MREC5OverVoltage('Simulated fault event', 'High'); + active_errors.MREC5OverVoltage = true; + } else if (!raise && active_errors.MREC5OverVoltage) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC5OverVoltage(); + active_errors.MREC5OverVoltage = false; + } +} + +function error_MREC6UnderVoltage(mod, raise) { + if (!active_errors.MREC6UnderVoltage) { + mod.provides.board_support.raise.evse_board_support_MREC6UnderVoltage('Simulated fault event', 'High'); + active_errors.MREC6UnderVoltage = true; + } else if (!raise && active_errors.MREC6UnderVoltage) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC6UnderVoltage(); + active_errors.MREC6UnderVoltage = false; + } +} + +function error_MREC8EmergencyStop(mod, raise) { + if (!active_errors.MREC8EmergencyStop) { + mod.provides.board_support.raise.evse_board_support_MREC8EmergencyStop('Simulated fault event', 'High'); + active_errors.MREC8EmergencyStop = true; + } else if (!raise && active_errors.MREC8EmergencyStop) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC8EmergencyStop(); + active_errors.MREC8EmergencyStop = false; + } +} + +function error_MREC10InvalidVehicleMode(mod, raise) { + if (!active_errors.MREC10InvalidVehicleMode) { + mod.provides.board_support.raise.evse_board_support_MREC10InvalidVehicleMode('Simulated fault event', 'High'); + active_errors.MREC10InvalidVehicleMode = true; + } else if (!raise && active_errors.MREC10InvalidVehicleMode) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC10InvalidVehicleMode(); + active_errors.MREC10InvalidVehicleMode = false; + } +} + +function error_MREC14PilotFault(mod, raise) { + if (!active_errors.MREC14PilotFault) { + mod.provides.board_support.raise.evse_board_support_MREC14PilotFault('Simulated fault event', 'High'); + active_errors.MREC14PilotFault = true; + } else if (!raise && active_errors.MREC14PilotFault) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC14PilotFault(); + active_errors.MREC14PilotFault = false; + } +} + +function error_MREC15PowerLoss(mod, raise) { + if (!active_errors.MREC15PowerLoss) { + mod.provides.board_support.raise.evse_board_support_MREC15PowerLoss('Simulated fault event', 'High'); + active_errors.MREC15PowerLoss = true; + } else if (!raise && active_errors.MREC15PowerLoss) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC15PowerLoss(); + active_errors.MREC15PowerLoss = false; + } +} + +function error_MREC17EVSEContactorFault(mod, raise) { + if (!active_errors.MREC17EVSEContactorFault) { + mod.provides.board_support.raise.evse_board_support_MREC17EVSEContactorFault('Simulated fault event', 'High'); + active_errors.MREC17EVSEContactorFault = true; + } else if (!raise && active_errors.MREC17EVSEContactorFault) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC17EVSEContactorFault(); + active_errors.MREC17EVSEContactorFault = false; + } +} + +function error_MREC18CableOverTempDerate(mod, raise) { + if (!active_errors.MREC18CableOverTempDerate) { + mod.provides.board_support.raise.evse_board_support_MREC18CableOverTempDerate('Simulated fault event', 'High'); + active_errors.MREC18CableOverTempDerate = true; + } else if (!raise && active_errors.MREC18CableOverTempDerate) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC18CableOverTempDerate(); + active_errors.MREC18CableOverTempDerate = false; + } +} + +function error_MREC19CableOverTempStop(mod, raise) { + if (!active_errors.MREC19CableOverTempStop) { + mod.provides.board_support.raise.evse_board_support_MREC19CableOverTempStop('Simulated fault event', 'High'); + active_errors.MREC19CableOverTempStop = true; + } else if (!raise && active_errors.MREC19CableOverTempStop) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC19CableOverTempStop(); + active_errors.MREC19CableOverTempStop = false; + } +} + +function error_MREC20PartialInsertion(mod, raise) { + if (!active_errors.MREC20PartialInsertion) { + mod.provides.board_support.raise.evse_board_support_MREC20PartialInsertion('Simulated fault event', 'High'); + active_errors.MREC20PartialInsertion = true; + } else if (!raise && active_errors.MREC20PartialInsertion) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC20PartialInsertion(); + active_errors.MREC20PartialInsertion = false; + } +} + +function error_MREC23ProximityFault(mod, raise) { + if (!active_errors.MREC23ProximityFault) { + mod.provides.board_support.raise.evse_board_support_MREC23ProximityFault('Simulated fault event', 'High'); + active_errors.MREC23ProximityFault = true; + } else if (!raise && active_errors.MREC23ProximityFault) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC23ProximityFault(); + active_errors.MREC23ProximityFault = false; + } +} + +function error_MREC24ConnectorVoltageHigh(mod, raise) { + if (!active_errors.MREC24ConnectorVoltageHigh) { + mod.provides.board_support.raise.evse_board_support_MREC24ConnectorVoltageHigh('Simulated fault event', 'High'); + active_errors.MREC24ConnectorVoltageHigh = true; + } else if (!raise && active_errors.MREC24ConnectorVoltageHigh) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC24ConnectorVoltageHigh(); + active_errors.MREC24ConnectorVoltageHigh = false; + } +} + +function error_MREC25BrokenLatch(mod, raise) { + if (!active_errors.MREC25BrokenLatch) { + mod.provides.board_support.raise.evse_board_support_MREC25BrokenLatch('Simulated fault event', 'High'); + active_errors.MREC25BrokenLatch = true; + } else if (!raise && active_errors.MREC25BrokenLatch) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC25BrokenLatch(); + active_errors.MREC25BrokenLatch = false; + } +} + +function error_MREC26CutCable(mod, raise) { + if (raise && !active_errors.MREC26CutCable) { + mod.provides.board_support.raise.evse_board_support_MREC26CutCable('Simulated fault event', 'High'); + active_errors.MREC26CutCable = true; + } else if (!raise && active_errors.MREC26CutCable) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_MREC26CutCable('Simulated fault event', 'High'); + active_errors.MREC26CutCable = false; + } +} + +function error_DiodeFault(mod, raise) { + if (raise && !active_errors.DiodeFault) { + mod.provides.board_support.raise.evse_board_support_DiodeFault('Simulated fault event', 'High'); + active_errors.DiodeFault = true; + } else if (!raise && active_errors.DiodeFault) { + mod.provides.board_support.request_clear_all_of_type.evse_board_support_DiodeFault(); + active_errors.DiodeFault = false; + } +} + +function error_ac_rcd_MREC2GroundFailure(mod, raise) { + + if (raise && !active_errors.ac_rcd_MREC2GroundFailure) { + mod.provides.rcd.raise.ac_rcd_MREC2GroundFailure('Simulated fault event', 'High'); + active_errors.ac_rcd_MREC2GroundFailure = true; + } else if (!raise && active_errors.ac_rcd_MREC2GroundFailure) { + + mod.provides.rcd.request_clear_all_of_type.ac_rcd_MREC2GroundFailure(); + active_errors.ac_rcd_MREC2GroundFailure = false; + } +} + +function error_ac_rcd_VendorError(mod, raise) { + if (raise && !active_errors.ac_rcd_VendorError) { + mod.provides.rcd.raise.ac_rcd_VendorError('Simulated fault event', 'High'); + active_errors.ac_rcd_VendorError = true; + } else if (!raise && active_errors.ac_rcd_VendorError) { + mod.provides.rcd.request_clear_all_of_type.ac_rcd_VendorError(); + active_errors.ac_rcd_VendorError = false; + } +} + + +function error_ac_rcd_Selftest(mod, raise) { + if (raise && !active_errors.ac_rcd_Selftest) { + mod.provides.rcd.raise.ac_rcd_Selftest('Simulated fault event', 'High'); + active_errors.ac_rcd_Selftest = true; + } else if (!raise && active_errors.ac_rcd_Selftest) { + mod.provides.rcd.request_clear_all_of_type.ac_rcd_Selftest(); + active_errors.ac_rcd_Selftest = false; + } +} + +function error_ac_rcd_AC(mod, raise) { + if (raise && !active_errors.ac_rcd_AC) { + mod.provides.rcd.raise.ac_rcd_AC('Simulated fault event', 'High'); + active_errors.ac_rcd_AC = true; + } else if (!raise && active_errors.ac_rcd_AC) { + mod.provides.rcd.request_clear_all_of_type.ac_rcd_AC(); + active_errors.ac_rcd_AC = false; + } +} + +function error_ac_rcd_DC(mod, raise) { + if (raise && !active_errors.ac_rcd_DC) { + mod.provides.rcd.raise.ac_rcd_DC('Simulated fault event', 'High'); + active_errors.ac_rcd_DC = true; + } else if (!raise && active_errors.ac_rcd_DC) { + mod.provides.rcd.request_clear_all_of_type.ac_rcd_DC(); + active_errors.ac_rcd_DC = false; + } +} + + +function error_lock_ConnectorLockCapNotCharged(mod, raise) { + if (raise && !active_errors.lock_ConnectorLockCapNotCharged) { + mod.provides.connector_lock.raise.connector_lock_ConnectorLockCapNotCharged('Simulated fault event', 'High'); + active_errors.lock_ConnectorLockCapNotCharged = true; + } else if (!raise && active_errors.lock_ConnectorLockCapNotCharged) { + mod.provides.connector_lock.request_clear_all_of_type.connector_lock_ConnectorLockCapNotCharged(); + active_errors.lock_ConnectorLockCapNotCharged = false; + } +} + +function error_lock_ConnectorLockUnexpectedOpen(mod, raise) { + if (raise && !active_errors.lock_ConnectorLockUnexpectedOpen) { + mod.provides.connector_lock.raise.connector_lock_ConnectorLockUnexpectedOpen('Simulated fault event', 'High'); + active_errors.lock_ConnectorLockUnexpectedOpen = true; + } else if (!raise && active_errors.lock_ConnectorLockUnexpectedOpen) { + mod.provides.connector_lock.request_clear_all_of_type.connector_lock_ConnectorLockUnexpectedOpen(); + active_errors.lock_ConnectorLockUnexpectedOpen = false; + } +} + +function error_lock_ConnectorLockUnexpectedClose(mod, raise) { + if (raise && !active_errors.lock_ConnectorLockUnexpectedClose) { + mod.provides.connector_lock.raise.connector_lock_ConnectorLockUnexpectedClose('Simulated fault event', 'High'); + active_errors.lock_ConnectorLockUnexpectedClose = true; + } else if (!raise && active_errors.lock_ConnectorLockUnexpectedClose) { + mod.provides.connector_lock.request_clear_all_of_type.connector_lock_ConnectorLockUnexpectedClose(); + active_errors.lock_ConnectorLockUnexpectedClose = false; + } +} + +function error_lock_ConnectorLockFailedLock(mod, raise) { + if (raise && !active_errors.lock_ConnectorLockFailedLock) { + mod.provides.connector_lock.raise.connector_lock_ConnectorLockFailedLock('Simulated fault event', 'High'); + active_errors.lock_ConnectorLockFailedLock = true; + } else if (!raise && active_errors.ConnectorLockFailedLock) { + mod.provides.connector_lock.request_clear_all_of_type.connector_lock_ConnectorLockFailedLock(); + active_errors.lock_ConnectorLockFailedLock = false; + } +} + +function error_lock_ConnectorLockFailedUnlock(mod, raise) { + if (raise && !active_errors.lock_ConnectorLockFailedUnlock) { + mod.provides.connector_lock.raise.connector_lock_ConnectorLockFailedUnlock('Simulated fault event', 'High'); + active_errors.lock_ConnectorLockFailedUnlock = true; + } else if (!raise && active_errors.lock_ConnectorLockFailedUnlock) { + mod.provides.connector_lock.request_clear_all_of_type.connector_lock_ConnectorLockFailedUnlock(); + active_errors.lock_ConnectorLockFailedUnlock = false; + } +} + + +function error_lock_MREC1ConnectorLockFailure(mod, raise) { + if (raise && !active_errors.lock_MREC1ConnectorLockFailure) { + mod.provides.connector_lock.raise.connector_lock_MREC1ConnectorLockFailure('Simulated fault event', 'High'); + active_errors.lock_MREC1ConnectorLockFailure = true; + } else if (!raise && active_errors.lock_MREC1ConnectorLockFailure) { + mod.provides.connector_lock.request_clear_all_of_type.connector_lock_MREC1ConnectorLockFailure(); + active_errors.lock_MREC1ConnectorLockFailure = false; + } +} + +function error_lock_VendorError(mod, raise) { + if (raise && !active_errors.lock_VendorError) { + mod.provides.connector_lock.raise.connector_lock_VendorError('Simulated fault event', 'High'); + active_errors.lock_VendorError = true; + } else if (!raise && active_errors.lock_VendorError) { + mod.provides.connector_lock.request_clear_all_of_type.connector_lock_VendorError(); + active_errors.lock_VendorError = false; + } +} + +// Example of automatically reset errors up on disconnection of the vehicle. +// All other errors need to be cleared explicitly. +// Note that in real life the clearing of errors may differ between BSPs depending on the +// hardware implementation. +function clear_disconnect_errors(mod) { + if (active_errors.DiodeFault) { + error_DiodeFault(mod, false); + } +} + // checks if voltage is within center+-interval function is_voltage_in_range(voltage, center) { const interval = 1.1; @@ -516,6 +986,7 @@ function clearData(mod) { mod.rcd_current = 0.1; mod.rcd_enabled = true; mod.rcd_error = false; + mod.rcd_error_reported = false; mod.simulation_enabled = false; mod.pwm_duty_cycle = 0; @@ -653,9 +1124,6 @@ function stateToString(mod) { case STATE_F: return 'F'; break; - case STATE_DF: - return 'DF'; - break; } } @@ -699,9 +1167,6 @@ function power_meter_external(p) { function publish_powermeter(mod) { mod.provides.powermeter.publish.powermeter(power_meter_external(mod.powermeter)); - // Publish raw packet for debugging purposes - mod.provides.debug_powermeter.publish.debug_json(mod.powermeter); - // Deprecated external stuff mod.mqtt.publish('/external/powermeter/vrmsL1', mod.powermeter.vrmsL1); mod.mqtt.publish('/external/powermeter/phaseSeqError', false); @@ -743,24 +1208,14 @@ function publish_keepalive(mod) { function publish_telemetry(mod) { mod.provides.board_support.publish.telemetry({ - temperature: mod.powermeter.tempL1, + evse_temperature_C: mod.powermeter.tempL1, fan_rpm: 1500.0, supply_voltage_12V: 12.01, supply_voltage_minus_12V: -11.8, - rcd_current: mod.rcd_current, relais_on: mod.relais_on, }); } -function publish_yeti_extras(mod) { - mod.provides.yeti_extras.publish.time_stamp(Math.round(new Date().getTime() / 1000)); - mod.provides.yeti_extras.publish.hw_type(0); - mod.provides.yeti_extras.publish.hw_revision(0); - mod.provides.yeti_extras.publish.protocol_version_major(0); - mod.provides.yeti_extras.publish.protocol_version_minor(1); - mod.provides.yeti_extras.publish.sw_version_string('simulation'); -} - function publish_yeti_simulation_control(mod) { mod.provides.yeti_simulation_control.publish.enabled(mod.simulation_enabled); mod.provides.yeti_simulation_control.publish.simulation_feedback({ @@ -770,13 +1225,6 @@ function publish_yeti_simulation_control(mod) { evse_pwm_voltage_hi: mod.pwm_voltage_hi, evse_pwm_voltage_lo: mod.pwm_voltage_lo, }); - /* evlog.error({ - pwm_duty_cycle: mod.pwm_duty_cycle, - relais_on: (mod.relais_on?(mod.use_three_phases_confirmed?3:1):0), - evse_pwm_running: mod.pwm_running, - evse_pwm_voltage_hi: mod.pwm_voltage_hi, - evse_pwm_voltage_lo: mod.pwm_voltage_lo - }); */ } function simulate_powermeter(mod) { @@ -824,23 +1272,4 @@ function simulate_powermeter(mod) { }; } -function read_pp_ampacity(mod) { - let pp_resistor = mod.simulation_data.pp_resistor; - if (pp_resistor < 80.0 || pp_resistor > 2460) { - evlog.error(`PP resistor value "${pp_resistor}" Ohm seems to be outside the allowed range.`); - return 0.0 - } - // PP resistor value in spec, use a conservative interpretation of the resistance ranges - if (pp_resistor > 936.0 && pp_resistor <= 2460.0) { - return 13.0; - } else if (pp_resistor > 308.0 && pp_resistor <= 936.0) { - return 20.0; - } else if (pp_resistor > 140.0 && pp_resistor <= 308.0) { - return 32.0; - } else if (pp_resistor > 80.0 && pp_resistor <= 140.0) { - return 63.0; - } - - return 0.0; -} diff --git a/modules/simulation/JsYetiSimulator/manifest.yaml b/modules/simulation/JsYetiSimulator/manifest.yaml index e009ecd942..7d05987b5f 100644 --- a/modules/simulation/JsYetiSimulator/manifest.yaml +++ b/modules/simulation/JsYetiSimulator/manifest.yaml @@ -1,29 +1,24 @@ description: SIL simulator for YETI hardware v1.0 +config: + connector_id: + description: Connector id of the evse manager to which this simulator is connected to + type: integer provides: powermeter: interface: powermeter description: provides the Yeti Internal Power Meter board_support: - interface: board_support_AC + interface: evse_board_support description: provides the board support Interface to low level control control pilot, relais, rcd, motor lock - yeti_extras: - interface: yeti_extras - description: extra functionality special for Yeti - debug_yeti: - interface: debug_json - description: provides the debug information of the charging driver - debug_powermeter: - interface: debug_json - description: Provides the powermeter as a json object - debug_state: - interface: debug_json - description: Provides the state as a json object - debug_keepalive: - interface: debug_json - description: Provides the keepalive as a json object yeti_simulation_control: interface: yeti_simulation_control description: Interface for the Yeti HIL simulator + rcd: + interface: ac_rcd + description: Interface for the simulated AC RCD + connector_lock: + interface: connector_lock + description: Interface for the simulated Connector lock enable_external_mqtt: true enable_telemetry: true metadata: diff --git a/types/board_support_common.yaml b/types/board_support_common.yaml new file mode 100644 index 0000000000..2b4163ec52 --- /dev/null +++ b/types/board_support_common.yaml @@ -0,0 +1,48 @@ +description: EV and EVSE board support types +types: + BspEvent: + description: >- + Event stream from ControlPilot signal/relais. + + A-F: CP states as defined in IEC61851-1 + PowerOn: Hardware confirms that contactors switched on correctly (typically mirror contacts indicated successful switch on) + PowerOff: Hardware confirms that contactors switched off correctly and are not welded (typically mirror contacts indicated successful switch off) + + EvseReplugStarted: Special testing sequence: virtual replugging started + EvseReplugFinished: Special testing sequence: virtual replugging stopped + Disconnected: Only used on EV side: Not connected to a charging station. Do not use on EVSE side. + type: object + additionalProperties: false + required: + - event + properties: + event: + type: string + enum: + - 'A' + - 'B' + - 'C' + - 'D' + - 'E' + - 'F' + - 'PowerOn' + - 'PowerOff' + - 'EvseReplugStarted' + - 'EvseReplugFinished' + - 'Disconnected' + ProximityPilot: + description: Current capability (ampacity) of the cable + type: object + additionalProperties: false + required: + - ampacity + properties: + ampacity: + description: Ampacity value of the cable assembly + type: string + enum: + - None + - A_13 + - A_20 + - A_32 + - A_63_3ph_70_1ph diff --git a/types/board_support.yaml b/types/evse_board_support.yaml similarity index 72% rename from types/board_support.yaml rename to types/evse_board_support.yaml index 965f1d2791..e74a5b40dd 100644 --- a/types/board_support.yaml +++ b/types/evse_board_support.yaml @@ -14,6 +14,7 @@ types: - max_phase_count_export - min_phase_count_export - supports_changing_phases_during_charging + - connector_type properties: max_current_A_import: description: Maximum current (ampere) the hardware can handle (import from grid) @@ -56,52 +57,31 @@ types: Indicates whether changing number of phases is supported during charging (true) or not (false) type: boolean - Event: - description: Event from ControlPilot signal/Relais/RCD - type: string - enum: - - CarPluggedIn - - CarRequestedPower - - PowerOn - - PowerOff - - CarRequestedStopPower - - CarUnplugged - - ErrorE - - ErrorDF - - ErrorRelais - - ErrorRCD - - ErrorRCD_DC - - ErrorVentilationNotAvailable - - ErrorOverCurrent - - ErrorOverVoltage - - ErrorUnderVoltage - - ErrorMotorLock - - ErrorOverTemperature - - ErrorBrownOut - - ErrorCablePP - - ErrorEnergyManagement - - ErrorNeutralPEN - - ErrorCpDriver - - EFtoBCD - - BCDtoEF - - PermanentFault - - EvseReplugStarted - - EvseReplugFinished + max_plug_temperature_C: + type: number + connector_type: + description: Type of charging connector available at this EVSE + type: string + enum: + - IEC62196Type2Cable + - IEC62196Type2Socket Telemetry: description: Other telemetry type: object additionalProperties: false required: - - temperature + - evse_temperature_C - fan_rpm - supply_voltage_12V - supply_voltage_minus_12V - - rcd_current - relais_on properties: - temperature: + evse_temperature_C: description: Current temperature of the EVSE in degree celsius type: number + plug_temperature_C: + description: Current temperature of the plug in degree celsius + type: number fan_rpm: description: RPM of the fan. 0 if off or no fan available. type: number @@ -111,9 +91,26 @@ types: supply_voltage_minus_12V: description: Internal -12V supply voltage type: number - rcd_current: - description: Residual current in mA - type: number relais_on: description: true if power to the car is currently on, false if off type: boolean + PowerOnOff: + description: Flag and context for switching power on/off. In some architectures e.g. DC power + train needs to know whether it should switch on with limited current or full current on the output contactors. + type: object + additionalProperties: false + required: + - allow_power_on + - reason + properties: + allow_power_on: + description: Allow switching on (true) or force switching off (false) + type: boolean + reason: + description: Reason for switching on/off + type: string + enum: + - DCCableCheck + - DCPreCharge + - FullPowerCharging + - PowerOff \ No newline at end of file diff --git a/types/evse_manager.yaml b/types/evse_manager.yaml index acc4783af6..b1abc1f947 100644 --- a/types/evse_manager.yaml +++ b/types/evse_manager.yaml @@ -212,48 +212,20 @@ types: type: string ErrorEnum: description: >- - Details on error type - Car: Signals a car error - CarDiodeFault: Signals a car diode fault - Relais: Signals a relais error - RCD: Signals an RCD error (AC) - RCDDC: Signal an RCD error (DC) - VentilationNotAvailable: Signals that ventilation is not available - OverCurrent: Signals an overcurrent error - OverVoltage: Signals on overvoltage error - UnderVoltage: Signals on overvoltage error - Internal: Signals an internal error - SLAC: Signals a SLAC communication error - HLC: Signals a HLC error - MotorLock: Signals an error with the motor lock of the connector - OverTemperature: Signals an over temperature error - BrownOut: Brown out detected in electronics - CablePP: PP resistor value in cable is out of range - EnergyManagement: An error from the energy management was reported - NeutralPEN: Nutral/PEN fault - CpDriver: The CP output driver has a fault + Note this is only kept for compatibility with the legacy error handling and will be removed soon. type: string enum: - Car - CarDiodeFault - - Relais - RCD - RCDDC - VentilationNotAvailable - - OverCurrent - - OverVoltage - - UnderVoltage - Internal - SLAC - HLC - Other - - MotorLock - - OverTemperature - BrownOut - - CablePP - EnergyManagement - - NeutralPEN - - CpDriver Error: description: >- Error object that contains information about the error and optional vendor error information