Skip to content

Commit

Permalink
Merge branch 'main' into feature/844-configuration-service-create-ske…
Browse files Browse the repository at this point in the history
…leton-for-device-model-storage
  • Loading branch information
maaikez committed Sep 23, 2024
2 parents 15e70bf + edb9b8f commit 9eff3af
Show file tree
Hide file tree
Showing 26 changed files with 425 additions and 1,150 deletions.
20 changes: 14 additions & 6 deletions .github/workflows/build_and_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ jobs:

# Since env variables can't be passed to reusable workflows, we need to pass them as outputs
setup-env:
# This job is currently disabled to allow running ci on PRs from forks
if: false
name: Setup Environment
runs-on: ${{ inputs.runner || 'ubuntu-22.04' }}
outputs:
Expand All @@ -46,6 +48,8 @@ jobs:
run: |
echo "Setting up environment"
build-and-push-build-kit:
# This job is currently disabled to allow running ci on PRs from forks
if: false
name: Build and Push Build Kit
uses: everest/everest-ci/.github/workflows/[email protected]
needs: setup-env
Expand All @@ -67,10 +71,12 @@ jobs:
build:
name: Build and Unit Tests
needs: build-and-push-build-kit
# needs: build-and-push-build-kit
runs-on: ${{ inputs.runner || 'ubuntu-22.04' }}
env:
BUILD_KIT_IMAGE: ${{ needs.build-and-push-build-kit.outputs.one_image_tag_long }}
# Currently the build-kit-base image is used to allow running ci on PRs from forks
# BUILD_KIT_IMAGE: ${{ needs.build-and-push-build-kit.outputs.one_image_tag_long }}
BUILD_KIT_IMAGE: ghcr.io/everest/everest-ci/build-kit-base:v1.3.1
steps:
- name: Format branch name for cache key
run: |
Expand Down Expand Up @@ -140,20 +146,22 @@ jobs:
name: Integration Tests
needs:
- build
- build-and-push-build-kit
# - build-and-push-build-kit
env:
BUILD_KIT_IMAGE: ${{ needs.build-and-push-build-kit.outputs.one_image_tag_long }}
# Currently the build-kit-base image is used to allow running ci on PRs from forks
# BUILD_KIT_IMAGE: ${{ needs.build-and-push-build-kit.outputs.one_image_tag_long }}
BUILD_KIT_IMAGE: ghcr.io/everest/everest-ci/build-kit-base:v1.3.1
runs-on: ${{ inputs.runner || 'ubuntu-22.04' }}
steps:
- name: Download dist dir
uses: actions/[email protected].2
uses: actions/[email protected].7
with:
name: dist
- name: Extract dist.tar.gz
run: |
tar -xzf ${{ github.workspace }}/dist.tar.gz -C ${{ github.workspace }}
- name: Download wheels
uses: actions/[email protected].2
uses: actions/[email protected].7
with:
name: wheels
path: wheels
Expand Down
5 changes: 5 additions & 0 deletions config/config-sil-ocpp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ active_modules:
ac_hlc_use_5percent: false
ac_enforce_hlc: false
external_ready_to_start_charging: true
request_zero_power_in_idle: true
connections:
bsp:
- module_id: yeti_driver_1
Expand Down Expand Up @@ -57,6 +58,7 @@ active_modules:
ac_hlc_use_5percent: false
ac_enforce_hlc: false
external_ready_to_start_charging: true
request_zero_power_in_idle: true
connections:
bsp:
- module_id: yeti_driver_2
Expand Down Expand Up @@ -159,6 +161,9 @@ active_modules:
display_message:
- module_id: display_message
implementation_id: display_message
connector_zero_sink:
- module_id: grid_connection_point
implementation_id: external_limits
display_message:
module: TerminalCostAndPriceMessage
connections:
Expand Down
5 changes: 5 additions & 0 deletions config/config-sil-ocpp201.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ active_modules:
ac_hlc_enabled: false
ac_hlc_use_5percent: false
ac_enforce_hlc: false
request_zero_power_in_idle: true
connections:
bsp:
- module_id: yeti_driver_1
Expand All @@ -50,6 +51,7 @@ active_modules:
ac_hlc_enabled: false
ac_hlc_use_5percent: false
ac_enforce_hlc: false
request_zero_power_in_idle: true
connections:
bsp:
- module_id: yeti_driver_2
Expand Down Expand Up @@ -125,6 +127,9 @@ active_modules:
security:
- module_id: evse_security
implementation_id: main
connector_zero_sink:
- module_id: grid_connection_point
implementation_id: external_limits
persistent_store:
module: PersistentStore
evse_security:
Expand Down
4 changes: 2 additions & 2 deletions dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
---
everest-framework:
git: https://github.com/EVerest/everest-framework.git
git_tag: v0.16.0
git_tag: v0.17.0
options: [
"BUILD_TESTING OFF",
"everest-framework_USE_PYTHON_VENV ${PROJECT_NAME}_USE_PYTHON_VENV",
Expand Down Expand Up @@ -60,7 +60,7 @@ libevse-security:
# OCPP
libocpp:
git: https://github.com/EVerest/libocpp.git
git_tag: 3fef09231f0033a4af5d0af97d35851ecc00d399
git_tag: 4a62b490fb89efd9c2f36d21d7949ee273d2c8b9
cmake_condition: "EVEREST_DEPENDENCY_ENABLED_LIBOCPP"
# Josev
Josev:
Expand Down
41 changes: 32 additions & 9 deletions modules/EvseManager/Charger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,13 @@ Charger::Charger(const std::unique_ptr<IECStateMachine>& bsp, const std::unique_
Everest::scoped_lock_timeout lock(state_machine_mutex, Everest::MutexDescription::Charger_signal_loop);
for (auto& event : events) {
switch (event) {
case ErrorHandlingEvents::prevent_charging:
case ErrorHandlingEvents::PreventCharging:
shared_context.error_prevent_charging_flag = true;
break;
case ErrorHandlingEvents::all_errors_cleared:
case ErrorHandlingEvents::AllErrorsPreventingChargingCleared:
shared_context.error_prevent_charging_flag = false;
break;
case ErrorHandlingEvents::AllErrorCleared:
shared_context.error_prevent_charging_flag = false;
break;
default:
Expand All @@ -93,13 +96,16 @@ Charger::Charger(const std::unique_ptr<IECStateMachine>& bsp, const std::unique_
error_handling->signal_error.connect([this](const bool prevent_charging) {
if (prevent_charging) {
// raise external error to signal we cannot charge anymore
error_handling_event_queue.push(ErrorHandlingEvents::prevent_charging);
error_handling_event_queue.push(ErrorHandlingEvents::PreventCharging);
} else {
EVLOG_info << "All errors cleared that prevented charging";
error_handling_event_queue.push(ErrorHandlingEvents::AllErrorsPreventingChargingCleared);
}
});

error_handling->signal_all_errors_cleared.connect([this]() {
EVLOG_info << "All errors cleared";
error_handling_event_queue.push(ErrorHandlingEvents::all_errors_cleared);
error_handling_event_queue.push(ErrorHandlingEvents::AllErrorCleared);
});
}

Expand Down Expand Up @@ -348,6 +354,7 @@ void Charger::run_state_machine() {
// Figure 4 of ISO15118-3: X1 start, PnC and EIM
internal_context.t_step_EF_return_state = target_state;
internal_context.t_step_EF_return_pwm = 0.;
internal_context.t_step_EF_return_ampere = 0.;
// fall back to nominal PWM after the t_step_EF break. Note that
// ac_hlc_enabled_current_session remains untouched as HLC can still start later in
// nominal PWM mode
Expand All @@ -363,6 +370,7 @@ void Charger::run_state_machine() {
"t_step_X1 and disable 5 percent.");
internal_context.t_step_X1_return_state = target_state;
internal_context.t_step_X1_return_pwm = 0.;
internal_context.t_step_EF_return_ampere = 0.;
hlc_use_5percent_current_session = false;
shared_context.current_state = EvseState::T_step_X1;
} else {
Expand Down Expand Up @@ -451,16 +459,23 @@ void Charger::run_state_machine() {
case EvseState::T_step_EF:
if (initialize_state) {
session_log.evse(false, "Enter T_step_EF");
internal_context.t_step_ef_x1_pause = false;
pwm_F();
}
if (time_in_current_state >= T_STEP_EF) {
if (time_in_current_state >= T_STEP_EF + STAY_IN_X1_AFTER_TSTEP_EF_MS) {
session_log.evse(false, "Exit T_step_EF");
if (internal_context.t_step_EF_return_pwm == 0.) {
pwm_off();
} else {
update_pwm_now(internal_context.t_step_EF_return_pwm);
internal_context.pwm_set_last_ampere = internal_context.t_step_EF_return_ampere;
}
shared_context.current_state = internal_context.t_step_EF_return_state;
} else if (time_in_current_state >= T_STEP_EF and not internal_context.t_step_ef_x1_pause) {
internal_context.t_step_ef_x1_pause = true;
// stay in X1 for a little while as required by EV READY regulations
session_log.evse(false, "Pause in X1 for EV READY regulations");
pwm_off();
}
break;

Expand All @@ -475,6 +490,7 @@ void Charger::run_state_machine() {
pwm_off();
} else {
update_pwm_now(internal_context.t_step_X1_return_pwm);
internal_context.pwm_set_last_ampere = internal_context.t_step_EF_return_ampere;
}
shared_context.current_state = internal_context.t_step_X1_return_state;
}
Expand Down Expand Up @@ -532,6 +548,7 @@ void Charger::run_state_machine() {
shared_context.legacy_wakeup_done = true;
internal_context.t_step_EF_return_state = EvseState::PrepareCharging;
internal_context.t_step_EF_return_pwm = ampere_to_duty_cycle(get_max_current_internal());
internal_context.t_step_EF_return_ampere = get_max_current_internal();
shared_context.current_state = EvseState::T_step_EF;
} else if (not shared_context.hlc_charging_active and shared_context.legacy_wakeup_done and
time_in_current_state > PREPARING_TIMEOUT_PAUSED_BY_EV) {
Expand Down Expand Up @@ -826,7 +843,6 @@ void Charger::process_cp_events_state(CPEvent cp_event) {
session_log.car(false, "B->C transition before PWM is enabled at this stage violates IEC61851-1");
shared_context.iec_allow_close_contactor = true;
} else if (cp_event == CPEvent::CarRequestedStopPower) {
session_log.car(false, "C->B transition at this stage violates IEC61851-1");
shared_context.iec_allow_close_contactor = false;
}
break;
Expand Down Expand Up @@ -1061,7 +1077,8 @@ bool Charger::pause_charging_wait_for_power() {

// pause charging since no power is available at the moment
bool Charger::pause_charging_wait_for_power_internal() {
if (shared_context.current_state == EvseState::Charging) {
if (shared_context.current_state == EvseState::Charging or
shared_context.current_state == EvseState::ChargingPausedEV) {
shared_context.current_state = EvseState::WaitingForEnergy;
return true;
}
Expand Down Expand Up @@ -1290,7 +1307,8 @@ bool Charger::switch_three_phases_while_charging(bool n) {
void Charger::setup(bool has_ventilation, 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,
const int _switch_3ph1ph_delay_s, const std::string _switch_3ph1ph_cp_state) {
const int _switch_3ph1ph_delay_s, const std::string _switch_3ph1ph_cp_state,
const int _soft_over_current_timeout_ms) {
// set up board support package
bsp->setup(has_ventilation);

Expand All @@ -1300,6 +1318,7 @@ void Charger::setup(bool has_ventilation, const ChargeMode _charge_mode, bool _a
ac_hlc_enabled_current_session = config_context.ac_hlc_enabled = _ac_hlc_enabled;
config_context.ac_hlc_use_5percent = _ac_hlc_use_5percent;
config_context.ac_enforce_hlc = _ac_enforce_hlc;
config_context.soft_over_current_timeout_ms = _soft_over_current_timeout_ms;
shared_context.ac_with_soc_timeout = _ac_with_soc_timeout;
shared_context.ac_with_soc_timer = 3600000;
soft_over_current_tolerance_percent = _soft_over_current_tolerance_percent;
Expand Down Expand Up @@ -1638,7 +1657,8 @@ void Charger::check_soft_over_current() {
auto now = std::chrono::steady_clock::now();
auto time_since_over_current_started =
std::chrono::duration_cast<std::chrono::milliseconds>(now - internal_context.last_over_current_event).count();
if (internal_context.over_current and time_since_over_current_started >= SOFT_OVER_CURRENT_TIMEOUT) {
if (internal_context.over_current and
time_since_over_current_started >= config_context.soft_over_current_timeout_ms) {
auto errstr =
fmt::format("Soft overcurrent event (L1:{}, L2:{}, L3:{}, limit {}) triggered",
shared_context.current_drawn_by_vehicle[0], shared_context.current_drawn_by_vehicle[1],
Expand Down Expand Up @@ -1669,6 +1689,7 @@ void Charger::request_error_sequence() {
if (shared_context.current_state == EvseState::WaitingForAuthentication or
shared_context.current_state == EvseState::PrepareCharging) {
internal_context.t_step_EF_return_state = shared_context.current_state;
internal_context.t_step_EF_return_ampere = 0.;
shared_context.current_state = EvseState::T_step_EF;
signal_slac_reset();
if (hlc_use_5percent_current_session) {
Expand Down Expand Up @@ -1748,6 +1769,7 @@ void Charger::dlink_error() {
// the t_step_EF state.
internal_context.t_step_X1_return_state = EvseState::T_step_EF;
internal_context.t_step_X1_return_pwm = 0.;
internal_context.t_step_EF_return_ampere = 0.;
shared_context.current_state = EvseState::T_step_X1;

// After returning from T_step_EF, go to Waiting for Auth (We are restarting the session)
Expand All @@ -1758,6 +1780,7 @@ void Charger::dlink_error() {

// [V2G3-M07-05] says we need to go through X1 at the end of the sequence
internal_context.t_step_EF_return_pwm = 0.;
internal_context.t_step_EF_return_ampere = 0.;
}
// else {
// [V2G3-M07-10] Gives us two options for nominal PWM mode and HLC in case of error: We choose
Expand Down
16 changes: 12 additions & 4 deletions modules/EvseManager/Charger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class Charger {
void setup(bool has_ventilation, 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, const int switch_3ph1ph_delay_s,
const std::string switch_3ph1ph_cp_state);
const std::string switch_3ph1ph_cp_state, const int soft_over_current_timeout_ms);

bool enable_disable(int connector_id, const types::evse_manager::EnableDisableSource& source);

Expand Down Expand Up @@ -320,6 +320,8 @@ class Charger {
int switch_3ph1ph_delay_s{10};
// Use state F if true, otherwise use X1
bool switch_3ph1ph_cp_state_F{false};
// Tolerate soft over current for given time
int soft_over_current_timeout_ms{7000};
} config_context;

// Used by different threads, but requires no complete state machine locking
Expand All @@ -342,6 +344,7 @@ class Charger {

EvseState t_step_EF_return_state;
float t_step_EF_return_pwm;
float t_step_EF_return_ampere;

EvseState switching_phases_return_state;

Expand All @@ -358,6 +361,7 @@ class Charger {
bool pp_warning_printed{false};
bool no_energy_warning_printed{false};
float pwm_set_last_ampere{0};
bool t_step_ef_x1_pause{false};
} internal_context;

// main Charger thread
Expand All @@ -373,8 +377,9 @@ class Charger {

// ErrorHandling events
enum class ErrorHandlingEvents : std::uint8_t {
prevent_charging,
all_errors_cleared
PreventCharging,
AllErrorsPreventingChargingCleared,
AllErrorCleared
};

EventQueue<ErrorHandlingEvents> error_handling_event_queue;
Expand All @@ -399,8 +404,11 @@ class Charger {
static constexpr int T_STEP_X1 = 3000;
// 4 seconds according to table 3 of ISO15118-3
static constexpr int T_STEP_EF = 4000;
static constexpr int SOFT_OVER_CURRENT_TIMEOUT = 7000;
static constexpr int IEC_PWM_MAX_UPDATE_INTERVAL = 5000;
// EV READY certification requires a small pause of 500-1000 ms in X1 after a t_step_EF sequence before going to X2-
// This is not required by IEC61851-1, but it is allowed by the IEC. It helps some older EVs to start charging
// after the wake-up sequence.
static constexpr int STAY_IN_X1_AFTER_TSTEP_EF_MS = 750;

types::evse_manager::EnableDisableSource active_enable_disable_source{
types::evse_manager::Enable_source::Unspecified, types::evse_manager::Enable_state::Unassigned, 10000};
Expand Down
Loading

0 comments on commit 9eff3af

Please sign in to comment.