Skip to content

Commit

Permalink
Connectivity manager refactoring (#874)
Browse files Browse the repository at this point in the history
* Add autoconnect option to connectivity manager and charge_point

Signed-off-by: Marc Emmers <[email protected]>

* Refactor init_websocket logic

Signed-off-by: Marc Emmers <[email protected]>

* Add check security profile while initializing the websocket

Signed-off-by: Marc Emmers <[email protected]>

* Some fixes with false connection to websocket

Signed-off-by: Marc Emmers <[email protected]>

* Move removal of invalid profiles to conn manager, also remove on reconnect

Signed-off-by: Marc Emmers <[email protected]>

* Add clearing of cache if security level increased

Signed-off-by: Marc Emmers <[email protected]>

* Refactor logic of connectivity manager

Signed-off-by: Marc Emmers <[email protected]>

* Change the start method parameters

Signed-off-by: Marc Emmers <[email protected]>

* Small fixes

Signed-off-by: Marc Emmers <[email protected]>

* Reorder functions a bit, move check for empty slots to connect()

Signed-off-by: Marc Emmers <[email protected]>

* Clean up of some changes we made, remove slot from confignetwork

Signed-off-by: Marc Emmers <[email protected]>

* Improve some logging

Signed-off-by: Marc Emmers <[email protected]>

* Improve const awareness

Signed-off-by: Marc Emmers <[email protected]>

* Fix linter issues

Signed-off-by: Marc Emmers <[email protected]>

* Fix review comments, allow interface to be nullopt

Signed-off-by: Marc Emmers <[email protected]>

---------

Signed-off-by: Marc Emmers <[email protected]>
Co-authored-by: Ivan Rogach <[email protected]>
  • Loading branch information
marcemmers and jannejy authored Nov 26, 2024
1 parent 173af8d commit 9836ac4
Show file tree
Hide file tree
Showing 5 changed files with 409 additions and 449 deletions.
61 changes: 21 additions & 40 deletions include/ocpp/v201/charge_point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,20 @@ class ChargePointInterface {
virtual ~ChargePointInterface() = default;

/// \brief Starts the ChargePoint, initializes and connects to the Websocket endpoint
/// \param bootreason Optional bootreason (default: PowerUp).
virtual void start(BootReasonEnum bootreason = BootReasonEnum::PowerUp) = 0;
/// \param bootreason Optional bootreason (default: PowerUp).
/// \param start_connecting Optional, set to false to initialize but not start connecting. Otherwise will connect to
/// the first network profile. (default: true)
virtual void start(BootReasonEnum bootreason = BootReasonEnum::PowerUp, bool start_connecting = true) = 0;

/// \brief Stops the ChargePoint. Disconnects the websocket connection and stops MessageQueue and all timers
virtual void stop() = 0;

/// \brief Initializes the websocket and connects to CSMS if it is not yet connected
virtual void connect_websocket() = 0;
/// \brief Initializes the websocket and connects to a CSMS. Provide a network_profile_slot to connect to that
/// specific slot.
///
/// \param network_profile_slot Optional slot to use when connecting. std::nullopt means the slot will be determined
/// automatically.
virtual void connect_websocket(std::optional<int32_t> network_profile_slot = std::nullopt) = 0;

/// \brief Disconnects the the websocket connection to the CSMS if it is connected
virtual void disconnect_websocket() = 0;
Expand All @@ -121,16 +127,6 @@ class ChargePointInterface {
/// The handlers
/// @{

///
/// \brief Can be called when a network is disconnected, for example when an ethernet cable is removed.
///
/// This is introduced because the websocket can take several minutes to timeout when a network interface becomes
/// unavailable, whereas the system can detect this sooner.
///
/// \param configuration_slot The slot of the network connection profile that is disconnected.
///
virtual void on_network_disconnected(int32_t configuration_slot) = 0;

///
/// \brief Can be called when a network is disconnected, for example when an ethernet cable is removed.
///
Expand All @@ -141,14 +137,6 @@ class ChargePointInterface {
///
virtual void on_network_disconnected(OCPPInterfaceEnum ocpp_interface) = 0;

/// \brief Switch to a specific network connection profile given the configuration slot.
///
/// Switch will only be done when the configuration slot has a higher priority.
///
/// \param configuration_slot Slot in which the configuration is stored
/// \return true if the switch is possible.
virtual bool on_try_switch_network_connection_profile(const int32_t configuration_slot) = 0;

/// \brief Chargepoint notifies about new firmware update status firmware_update_status. This function should be
/// called during a Firmware Update to indicate the current firmware_update_status.
/// \param request_id The request_id. When it is -1, it will not be included in the request.
Expand Down Expand Up @@ -376,20 +364,20 @@ class ChargePointInterface {
/// present. This returns the value from the cached network connection profiles. \param
/// network_configuration_priority \return
virtual std::optional<NetworkConnectionProfile>
get_network_connection_profile(const int32_t configuration_slot) = 0;
get_network_connection_profile(const int32_t configuration_slot) const = 0;

/// \brief Get the priority of the given configuration slot.
/// \param configuration_slot The configuration slot to get the priority from.
/// \return The priority if the configuration slot exists.
///
virtual std::optional<int> get_configuration_slot_priority(const int configuration_slot) = 0;
virtual std::optional<int> get_priority_from_configuration_slot(const int configuration_slot) const = 0;

/// @brief Get the network connection priorities.
/// @brief Get the network connection slots sorted by priority.
/// Each item in the vector contains the configured configuration slots, where the slot with index 0 has the highest
/// priority.
/// @return The network connection priorities
/// @return The network connection slots
///
virtual const std::vector<int>& get_network_connection_priorities() const = 0;
virtual const std::vector<int>& get_network_connection_slots() const = 0;
};

/// \brief Class implements OCPP2.0.1 Charging Station
Expand Down Expand Up @@ -503,10 +491,6 @@ class ChargePoint : public ChargePointInterface, private ocpp::ChargingStationBa
get_composite_schedule_internal(const GetCompositeScheduleRequest& request,
const std::set<ChargingProfilePurposeEnum>& profiles_to_ignore = {});

/// \brief Removes all network connection profiles below the actual security profile and stores the new list in the
/// device model
void remove_network_connection_profiles_below_actual_security_profile();

void message_callback(const std::string& message);
void update_aligned_data_interval();

Expand Down Expand Up @@ -890,19 +874,15 @@ class ChargePoint : public ChargePointInterface, private ocpp::ChargingStationBa

~ChargePoint();

void start(BootReasonEnum bootreason = BootReasonEnum::PowerUp) override;
void start(BootReasonEnum bootreason = BootReasonEnum::PowerUp, bool start_connecting = true) override;

void stop() override;

virtual void connect_websocket() override;
void connect_websocket(std::optional<int32_t> network_profile_slot = std::nullopt) override;
virtual void disconnect_websocket() override;

void on_network_disconnected(int32_t configuration_slot) override;

void on_network_disconnected(OCPPInterfaceEnum ocpp_interface) override;

bool on_try_switch_network_connection_profile(const int32_t configuration_slot) override;

void on_firmware_update_status_notification(int32_t request_id,
const FirmwareStatusEnum& firmware_update_status) override;

Expand Down Expand Up @@ -991,11 +971,12 @@ class ChargePoint : public ChargePointInterface, private ocpp::ChargingStationBa
std::vector<CompositeSchedule> get_all_composite_schedules(const int32_t duration,
const ChargingRateUnitEnum& unit) override;

std::optional<NetworkConnectionProfile> get_network_connection_profile(const int32_t configuration_slot) override;
std::optional<NetworkConnectionProfile>
get_network_connection_profile(const int32_t configuration_slot) const override;

std::optional<int> get_configuration_slot_priority(const int configuration_slot) override;
std::optional<int> get_priority_from_configuration_slot(const int configuration_slot) const override;

const std::vector<int>& get_network_connection_priorities() const override;
const std::vector<int>& get_network_connection_slots() const override;

/// \brief Requests a value of a VariableAttribute specified by combination of \p component_id and \p variable_id
/// from the device model
Expand Down
121 changes: 59 additions & 62 deletions include/ocpp/v201/connectivity_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,14 @@ class ConnectivityManager {
std::optional<ConfigureNetworkConnectionProfileCallback> configure_network_connection_profile_callback;

Everest::SteadyTimer websocket_timer;
bool disable_automatic_websocket_reconnects;
int network_configuration_priority;
std::optional<int32_t> pending_configuration_slot;
bool wants_to_be_connected;
int32_t active_network_configuration_priority;
int last_known_security_level;
/// @brief Local cached network connection profiles
std::vector<SetNetworkProfileRequest> network_connection_profiles;
std::vector<SetNetworkProfileRequest> cached_network_connection_profiles;
/// @brief local cached network connection priorities
std::vector<int> network_connection_priorities;
WebsocketConnectionOptions current_connection_options{};
std::vector<int32_t> network_connection_slots;

public:
ConnectivityManager(DeviceModel& device_model, std::shared_ptr<EvseSecurity> evse_security,
Expand Down Expand Up @@ -84,45 +85,38 @@ class ConnectivityManager {
///
void set_configure_network_connection_profile_callback(ConfigureNetworkConnectionProfileCallback callback);

/// \brief Gets the configured NetworkConnectionProfile based on the given \p configuration_slot . The
/// central system uri of the connection options will not contain ws:// or wss:// because this method removes it if
/// present. This returns the value from the cached network connection profiles. \param
/// network_configuration_priority \return
std::optional<NetworkConnectionProfile> get_network_connection_profile(const int32_t configuration_slot);
/// \brief Gets the cached NetworkConnectionProfile based on the given \p configuration_slot.
/// This returns the value from the cached network connection profiles.
/// \return Returns a profile if the slot is found
std::optional<NetworkConnectionProfile> get_network_connection_profile(const int32_t configuration_slot) const;

/// \brief Get the priority of the given configuration slot.
/// \param configuration_slot The configuration slot to get the priority from.
/// \return The priority if the configuration slot exists.
///
std::optional<int> get_configuration_slot_priority(const int configuration_slot);
std::optional<int32_t> get_priority_from_configuration_slot(const int configuration_slot) const;

/// @brief Get the network connection priorities.
/// @brief Get the network connection slots sorted by priority.
/// Each item in the vector contains the configured configuration slots, where the slot with index 0 has the highest
/// priority.
/// @return The network connection priorities
/// @return The network connection slots
///
const std::vector<int>& get_network_connection_priorities() const;
const std::vector<int>& get_network_connection_slots() const;

/// \brief Check if the websocket is connected
/// \return True is the websocket is connected, else false
///
bool is_websocket_connected();

/// \brief Start the connectivity manager
///
void start();

/// \brief Stop the connectivity manager
///
void stop();

/// \brief Connect to the websocket
/// \param configuration_slot Optional the network_profile_slot to connect to. std::nullopt will select the slot
/// internally.
///
void connect();
void connect(std::optional<int32_t> network_profile_slot = std::nullopt);

/// \brief Disconnect the websocket with a specific \p reason
/// \brief Disconnect the websocket
///
void disconnect_websocket(WebsocketCloseReason code = WebsocketCloseReason::Normal);
void disconnect();

/// \brief send a \p message over the websocket
/// \returns true if the message was sent successfully
Expand All @@ -135,37 +129,35 @@ class ConnectivityManager {
/// This is introduced because the websocket can take several minutes to timeout when a network interface becomes
/// unavailable, whereas the system can detect this sooner.
///
/// \param configuration_slot The slot of the network connection profile that is disconnected.
///
void on_network_disconnected(int32_t configuration_slot);

///
/// \brief Can be called when a network is disconnected, for example when an ethernet cable is removed.
///
/// This is introduced because the websocket can take several minutes to timeout when a network interface becomes
/// unavailable, whereas the system can detect this sooner.
///
/// \param ocpp_interface The interface that is disconnected.
/// \param ocpp_interface The interface that is disconnected.
///
void on_network_disconnected(OCPPInterfaceEnum ocpp_interface);

/// \brief Switch to a specific network connection profile given the configuration slot.
/// \brief Called when the charging station certificate is changed
///
/// Switch will only be done when the configuration slot has a higher priority.
///
/// \param configuration_slot Slot in which the configuration is stored
/// \return true if the switch is possible.
bool on_try_switch_network_connection_profile(const int32_t configuration_slot);
void on_charging_station_certificate_changed();

/// \brief Confirms the connection is successful so the security profile requirements can be handled
void confirm_successful_connection();

private:
/// \brief Init the websocket
/// \brief Initializes the websocket and tries to connect
///
void init_websocket();
void try_connect_websocket();

/// \brief Get the current websocket connection options
/// \returns the current websocket connection options
/// \return the current websocket connection options
///
std::optional<WebsocketConnectionOptions> get_ws_connection_options(const int32_t configuration_slot);

/// \brief Calls the configuration callback to get the interface to use, if there is a callback
/// \param slot The configuration slot to get the interface for
/// \param profile The network connection profile to get the interface for
///
WebsocketConnectionOptions get_ws_connection_options(const int32_t configuration_slot);
/// \return The network configuration containing the network interface to use, nullptr if the request failed or the
/// callback is not configured
std::optional<ConfigNetworkResult>
handle_configure_network_connection_profile_callback(int slot, const NetworkConnectionProfile& profile);

/// \brief Function invoked when the web socket connected with the \p security_profile
///
Expand All @@ -179,31 +171,36 @@ class ConnectivityManager {
///
void on_websocket_closed(ocpp::WebsocketCloseReason reason);

/// \brief Reconnect with the give websocket \p reason
///
void reconnect(WebsocketCloseReason reason, std::optional<int> next_priority = std::nullopt);
/// \brief Get the active network configuration slot in use.
/// \return The active slot the network is connected to or the pending slot.
///
int get_active_network_configuration_slot() const;

///
/// \brief Returns true if the provided configuration slot is of higher priority compared to the one currently
/// in use.
/// \param new_configuration_slot The configuration slot to check.
/// \return True when given slot is of higher priority.
/// \brief Get the network configuration slot of the given priority.
/// \param priority The priority to get the configuration slot.
/// \return The configuration slot.
///
bool is_higher_priority_profile(const int new_configuration_slot);
int get_configuration_slot_from_priority(const int priority);

///
/// \brief Get the active network configuration slot in use.
/// \return The active slot the network is connected to or the pending slot.
/// \brief Get the next prioritized network configuration slot of the given configuration slot.
/// \param configuration_slot The current configuration slot.
/// \return The next prioritized configuration slot.
///
int get_active_network_configuration_slot();
int get_next_configuration_slot(int32_t configuration_slot);

/// \brief Moves websocket network_configuration_priority to next profile
///
void next_network_configuration_priority();
/// \brief Cache all the network connection profiles
void cache_network_connection_profiles();

/// \brief Removes all connection profiles from the cache that have a security profile lower than the currently
/// connected security profile
void check_cache_for_invalid_security_profiles();

/// @brief Cache all the network connection profiles. Must be called once during initialization
/// \return True if the network connection profiles could be cached, else False.
bool cache_network_connection_profiles();
/// \brief Removes all connection profiles from the database that have a security profile lower than the currently
/// connected security profile
void remove_network_connection_profiles_below_actual_security_profile();
};

} // namespace v201
Expand Down
1 change: 0 additions & 1 deletion include/ocpp/v201/ocpp_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -891,7 +891,6 @@ std::ostream& operator<<(std::ostream& os, const SetMonitoringResult& k);

/// @brief The result of a configuration of a network profile.
struct ConfigNetworkResult {
uint8_t network_profile_slot; ///< @brief Network profile slot.
std::optional<std::string> interface_address; ///< ip address or interface string
bool success; ///< true if the configuration was successful
};
Expand Down
Loading

0 comments on commit 9836ac4

Please sign in to comment.