Skip to content

Commit

Permalink
Merge branch 'main' into feature/327-use-case-h01-reservation
Browse files Browse the repository at this point in the history
  • Loading branch information
maaikez committed Nov 25, 2024
2 parents d9b3372 + c9a6f45 commit 41a8ee7
Show file tree
Hide file tree
Showing 24 changed files with 677 additions and 336 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build_and_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ on:
jobs:
ci:
name: Build, Lint and Test
uses: everest/everest-ci/.github/workflows/[email protected].2
uses: everest/everest-ci/.github/workflows/[email protected].4
permissions:
contents: read
secrets:
Expand Down
9 changes: 9 additions & 0 deletions doc/message_dispatching.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ class v201_MessageDispatcher {
- RegistrationStatusEnum& registration_status
}
class v201_MessageHandlerInterface {
+handle_message(EnhancedMessage~v201_MessageType~ message)
}
class v16_MessageHandlerInterface {
+handle_message(EnhancedMessage~v16_MessageType~ message)
}
class v201_DataTransferInterface {
+data_transfer_req(request: DataTransferRequest): std::optional~DataTransferResponse~
+handle_data_transfer_req(call: Call~DataTransferRequest~)
Expand All @@ -44,6 +52,7 @@ class v16_ChargePoint {
MessageDispatcherInterface <|-- v16_MessageDispatcher
MessageDispatcherInterface <|-- v201_MessageDispatcher
v201_DataTransferInterface <|-- v201_DataTransfer
v201_MessageHandlerInterface <|-- v201_DataTransferInterface
MessageDispatcherInterface *-- v201_DataTransfer
MessageDispatcherInterface *-- v201_ChargePoint
v201_DataTransferInterface *-- v201_ChargePoint
Expand Down
12 changes: 11 additions & 1 deletion include/ocpp/common/call_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ enum class MessageTypeId {
UNKNOWN,
};

/// \brief Creates a unique message ID
/// \returns the unique message ID
MessageId create_message_id();

/// \brief Contains a OCPP Call message
template <class T> struct Call {
T msg;
Expand All @@ -61,7 +65,13 @@ template <class T> struct Call {
Call() {
}

/// \brief Creates a new Call message object with the given OCPP message \p msg and \p uniqueID
/// \brief Creates a new Call message object with the given OCPP message \p msg
explicit Call(T msg) {
this->msg = msg;
this->uniqueId = create_message_id();
}

/// \brief Creates a new Call message object with the given OCPP message \p msg and \p uniqueId
Call(T msg, MessageId uniqueId) {
this->msg = msg;
this->uniqueId = uniqueId;
Expand Down
6 changes: 0 additions & 6 deletions include/ocpp/common/charging_station_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,6 @@ class ChargingStationBase {
boost::asio::io_service io_service;
std::thread io_service_thread;

boost::uuids::random_generator uuid_generator;

/// \brief Generates a uuid
/// \return uuid
std::string uuid();

public:
/// \brief Constructor for ChargingStationBase
/// \param evse_security Pointer to evse_security that manages security related operations; if nullptr
Expand Down
20 changes: 3 additions & 17 deletions include/ocpp/common/message_queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@
#include <set>
#include <thread>

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

#include <everest/timer.hpp>

#include <ocpp/common/call_types.hpp>
Expand Down Expand Up @@ -186,7 +182,6 @@ template <typename M> class MessageQueue {
bool running;
bool new_message;
bool is_registration_status_accepted;
boost::uuids::random_generator uuid_generator;
std::recursive_mutex next_message_mutex;
std::optional<MessageId> next_message_to_send;

Expand Down Expand Up @@ -405,7 +400,6 @@ template <typename M> class MessageQueue {
running(true),
new_message(false),
is_registration_status_accepted(false),
uuid_generator(boost::uuids::random_generator()),
start_transaction_message_retry_callback(start_transaction_message_retry_callback) {

this->send_callback = send_callback;
Expand Down Expand Up @@ -641,7 +635,7 @@ template <typename M> class MessageQueue {
// MeterValues have to be delivered in chronological order

// intentionally break this message for testing...
// message->message[CALL_PAYLOAD]["broken"] = this->createMessageId();
// message->message[CALL_PAYLOAD]["broken"] = ocpp::create_message_id();
this->add_to_transaction_message_queue(control_message);
} else {
// all other messages are allowed to "jump the queue" to improve user experience
Expand Down Expand Up @@ -833,7 +827,7 @@ template <typename M> class MessageQueue {
EVLOG_warning << "Message shall be persisted and will therefore be sent again";
// Generate a new message ID for the retry
const auto old_message_id = this->in_flight->message[MESSAGE_ID];
this->in_flight->message[MESSAGE_ID] = this->createMessageId();
this->in_flight->message[MESSAGE_ID] = ocpp::create_message_id();
if (this->config.transaction_message_retry_interval > 0) {
// exponential backoff
this->in_flight->timestamp =
Expand Down Expand Up @@ -890,7 +884,7 @@ template <typename M> class MessageQueue {
} else if (is_boot_notification_message(this->in_flight->messageType)) {
EVLOG_warning << "Message is BootNotification.req and will therefore be sent again";
// Generate a new message ID for the retry
this->in_flight->message[MESSAGE_ID] = this->createMessageId();
this->in_flight->message[MESSAGE_ID] = ocpp::create_message_id();
// Spec does not define how to handle retries for BootNotification.req: We use the
// the boot_notification_retry_interval_seconds
this->in_flight->timestamp =
Expand Down Expand Up @@ -1013,14 +1007,6 @@ template <typename M> class MessageQueue {
this->config.message_timeout_seconds = timeout;
}

/// \brief Creates a unique message ID
/// \returns the unique message ID
MessageId createMessageId() {
std::stringstream s;
s << this->uuid_generator();
return MessageId(s.str());
}

/// \brief Adds the given \p transaction_id to the message_id_transaction_id_map using the key \p
/// stop_transaction_message_id
void add_stopped_transaction_id(std::string stop_transaction_message_id, int32_t transaction_id) {
Expand Down
2 changes: 0 additions & 2 deletions include/ocpp/common/websocket/websocket_libwebsockets.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,6 @@ class WebsocketLibwebsockets final : public WebsocketBase {
private:
std::shared_ptr<EvseSecurity> evse_security;

std::function<void()> reconnect_callback;

// Connection related data
Everest::SteadyTimer reconnect_timer_tpm;
std::unique_ptr<std::thread> websocket_thread;
Expand Down
4 changes: 0 additions & 4 deletions include/ocpp/v16/transaction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
#include <ocpp/v16/ocpp_types.hpp>
#include <ocpp/v16/types.hpp>

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

namespace ocpp {
namespace v16 {

Expand Down
8 changes: 3 additions & 5 deletions include/ocpp/v201/charge_point.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <set>

#include <ocpp/common/message_dispatcher.hpp>
#include <ocpp/v201/functional_blocks/data_transfer.hpp>

#include <ocpp/common/charging_station_base.hpp>

Expand Down Expand Up @@ -400,6 +401,7 @@ class ChargePoint : public ChargePointInterface, private ocpp::ChargingStationBa
std::unique_ptr<ConnectivityManager> connectivity_manager;

std::unique_ptr<MessageDispatcherInterface<MessageType>> message_dispatcher;
std::unique_ptr<DataTransferInterface> data_transfer;

// utility
std::shared_ptr<MessageQueue<v201::MessageType>> message_queue;
Expand Down Expand Up @@ -786,16 +788,12 @@ class ChargePoint : public ChargePointInterface, private ocpp::ChargingStationBa
void handle_set_display_message(Call<SetDisplayMessageRequest> call);
void handle_clear_display_message(Call<ClearDisplayMessageRequest> call);

// Functional Block P: DataTransfer
void handle_data_transfer_req(Call<DataTransferRequest> call);

// Generates async sending callbacks
template <class RequestType, class ResponseType>
std::function<ResponseType(RequestType)> send_callback(MessageType expected_response_message_type) {
return [this, expected_response_message_type](auto request) {
MessageId message_id = MessageId(to_string(this->uuid_generator()));
const auto enhanced_response =
this->message_dispatcher->dispatch_call_async(ocpp::Call<RequestType>(request, message_id)).get();
this->message_dispatcher->dispatch_call_async(ocpp::Call<RequestType>(request)).get();
if (enhanced_response.messageType != expected_response_message_type) {
throw UnexpectedMessageTypeFromCSMS(
std::string("Got unexpected message type from CSMS, expected: ") +
Expand Down
60 changes: 60 additions & 0 deletions include/ocpp/v201/functional_blocks/data_transfer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest

#pragma once

#include <ocpp/v201/message_dispatcher.hpp>
#include <ocpp/v201/message_handler.hpp>
#include <ocpp/v201/messages/DataTransfer.hpp>

namespace ocpp {
namespace v201 {

class DataTransferInterface : public MessageHandlerInterface {

public:
virtual ~DataTransferInterface(){};

/// \brief Sends a DataTransfer.req message to the CSMS using the given parameters
/// \param vendorId
/// \param messageId
/// \param data
/// \return DataTransferResponse containing the result from CSMS
virtual std::optional<DataTransferResponse> data_transfer_req(const CiString<255>& vendorId,
const std::optional<CiString<50>>& messageId,
const std::optional<json>& data) = 0;

/// \brief Sends a DataTransfer.req message to the CSMS using the given \p request
/// \param request message shall be sent to the CSMS
/// \return DataTransferResponse containing the result from CSMS. In case no response is received from the CSMS
/// because the message timed out or the charging station is offline, std::nullopt is returned
virtual std::optional<DataTransferResponse> data_transfer_req(const DataTransferRequest& request) = 0;
};

class DataTransfer : public DataTransferInterface {

private:
MessageDispatcherInterface<MessageType>& message_dispatcher;
std::optional<std::function<DataTransferResponse(const DataTransferRequest& request)>> data_transfer_callback;
std::chrono::seconds response_timeout;

public:
DataTransfer(MessageDispatcherInterface<MessageType>& message_dispatcher,
const std::optional<std::function<DataTransferResponse(const DataTransferRequest& request)>>&
data_transfer_callback,
const std::chrono::seconds response_timeout) :
message_dispatcher(message_dispatcher),
data_transfer_callback(data_transfer_callback),
response_timeout(response_timeout){};

void handle_message(const EnhancedMessage<MessageType>& message) override;

std::optional<DataTransferResponse> data_transfer_req(const CiString<255>& vendorId,
const std::optional<CiString<50>>& messageId,
const std::optional<json>& data) override;

std::optional<DataTransferResponse> data_transfer_req(const DataTransferRequest& request) override;
};

} // namespace v201
} // namespace ocpp
39 changes: 39 additions & 0 deletions include/ocpp/v201/message_handler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright Pionix GmbH and Contributors to EVerest

#pragma once

#include <ocpp/common/message_queue.hpp>

namespace ocpp {
namespace v201 {

/// \brief Interface for handling OCPP2.0.1 CALL messages from the CSMS. Classes implementing a functional block shall
/// extend this interface.
class MessageHandlerInterface {

public:
virtual ~MessageHandlerInterface() {
}
/// \brief Handles the given \p message from the CSMS. This includes dispatching a CALLRESULT as a response to the
/// incoming \p message .
/// @param message
virtual void handle_message(const EnhancedMessage<MessageType>& message) = 0;
};

class MessageTypeNotImplementedException : public std::exception {
private:
std::string message;

public:
MessageTypeNotImplementedException(MessageType message_type) :
message("Message is not implemented: " + conversions::messagetype_to_string(message_type)) {
}

const char* what() const noexcept override {
return message.c_str();
}
};

} // namespace v201
} // namespace ocpp
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ if(LIBOCPP_ENABLE_V201)
ocpp/v201/component_state_manager.cpp
ocpp/v201/connectivity_manager.cpp
ocpp/v201/message_dispatcher.cpp
ocpp/v201/functional_blocks/data_transfer.cpp
)
add_subdirectory(ocpp/v201/messages)
endif()
Expand Down
12 changes: 12 additions & 0 deletions lib/ocpp/common/call_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,20 @@

#include <ocpp/common/call_types.hpp>

#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>

namespace ocpp {

MessageId create_message_id() {
static boost::uuids::random_generator uuid_generator;
boost::uuids::uuid uuid = uuid_generator();
std::stringstream s;
s << uuid;
return MessageId(s.str());
}

bool operator<(const MessageId& lhs, const MessageId& rhs) {
return lhs.get() < rhs.get();
}
Expand Down
9 changes: 1 addition & 8 deletions lib/ocpp/common/charging_station_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

namespace ocpp {
ChargingStationBase::ChargingStationBase(const std::shared_ptr<EvseSecurity> evse_security,
const std::optional<SecurityConfiguration> security_configuration) :
uuid_generator(boost::uuids::random_generator()) {
const std::optional<SecurityConfiguration> security_configuration) {

if (evse_security != nullptr) {
this->evse_security = evse_security;
Expand All @@ -28,10 +27,4 @@ ChargingStationBase::~ChargingStationBase() {
io_service_thread.join();
}

std::string ChargingStationBase::uuid() {
std::stringstream s;
s << this->uuid_generator();
return s.str();
}

} // namespace ocpp
Loading

0 comments on commit 41a8ee7

Please sign in to comment.