Skip to content

Commit

Permalink
Merge pull request #39 from fablab-bergamo/backendRequests
Browse files Browse the repository at this point in the history
Backend requests
  • Loading branch information
PBrunot authored Aug 14, 2024
2 parents 2991884 + 9c252c1 commit 1b0efff
Show file tree
Hide file tree
Showing 16 changed files with 272 additions and 29 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:
- 'platformio.ini'
- '.github/workflows/tests.yml'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
group: ${{ github.head_ref || github.ref_name }}
cancel-in-progress: true

jobs:
Expand Down
3 changes: 3 additions & 0 deletions conf/conf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ namespace fabomatic
/// @brief Backend reply (sub-topic of the full machine topic)
static constexpr std::string_view response_topic{"/reply"};

/// @brief Backend requests (sub-topic of the full machine topic)
static constexpr std::string_view request_topic{"/request"};

/// @brief Number of tries to get a reply from the backend
static constexpr auto MAX_TRIES{2};

Expand Down
1 change: 1 addition & 0 deletions include/BoardLogic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ namespace fabomatic
[[nodiscard]] auto getMachine() const -> const Machine &;
[[nodiscard]] auto authorize(const card::uid_t uid) -> bool;
[[nodiscard]] auto getHostname() const -> const std::string;
auto processBackendRequests() -> void;

// copy reference
BoardLogic &operator=(const BoardLogic &board) = delete;
Expand Down
5 changes: 5 additions & 0 deletions include/FabBackend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ namespace fabomatic

std::string topic{""};
std::string response_topic{""};
std::string request_topic{""};
std::string last_query{""};
std::string last_reply{""};
std::string last_request{""};

bool online{false};
bool answer_pending{false};
Expand All @@ -55,6 +57,7 @@ namespace fabomatic
Buffer buffer;

auto messageReceived(String &topic, String &payload) -> void;
auto requestReceived(String &topic, String &payload) -> void;

template <typename QueryT>
[[nodiscard]] auto publish(const QueryT &payload) -> PublishResult;
Expand Down Expand Up @@ -86,6 +89,8 @@ namespace fabomatic
[[nodiscard]] auto transmitBuffer() -> bool;
[[nodiscard]] auto saveBuffer() -> bool;

[[nodiscard]] auto checkBackendRequest() -> std::optional<std::unique_ptr<MQTTInterface::BackendRequest>>;

auto connect() -> bool;
auto connectWiFi() -> bool;
auto loop() -> bool;
Expand Down
29 changes: 19 additions & 10 deletions include/MQTTtypes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace fabomatic::MQTTInterface
const card::uid_t uid;

UserQuery() = delete;
constexpr UserQuery(card::uid_t card_uid) : uid(card_uid){};
constexpr UserQuery(card::uid_t card_uid) : uid(card_uid) {};

[[nodiscard]] auto waitForReply() const -> bool override { return true; };
[[nodiscard]] auto payload() const -> const std::string override;
Expand Down Expand Up @@ -63,7 +63,7 @@ namespace fabomatic::MQTTInterface
const card::uid_t uid;

StartUseQuery() = delete;
constexpr StartUseQuery(card::uid_t card_uid) : uid(card_uid){};
constexpr StartUseQuery(card::uid_t card_uid) : uid(card_uid) {};

[[nodiscard]] auto payload() const -> const std::string override;
[[nodiscard]] auto waitForReply() const -> bool override { return true; };
Expand All @@ -83,7 +83,7 @@ namespace fabomatic::MQTTInterface
/// @param card_uid machine user card id
/// @param mid machine id
/// @param duration duration of usage, in seconds
constexpr StopUseQuery(card::uid_t card_uid, std::chrono::seconds duration) : uid(card_uid), duration_s(duration){};
constexpr StopUseQuery(card::uid_t card_uid, std::chrono::seconds duration) : uid(card_uid), duration_s(duration) {};
[[nodiscard]] auto payload() const -> const std::string override;
[[nodiscard]] auto waitForReply() const -> bool override { return true; };
[[nodiscard]] auto buffered() const -> bool override { return true; };
Expand All @@ -102,7 +102,7 @@ namespace fabomatic::MQTTInterface
/// @param card_uid machine user card id
/// @param mid machine id
/// @param duration duration of usage, in seconds
constexpr InUseQuery(card::uid_t card_uid, std::chrono::seconds duration) : uid(card_uid), duration_s(duration){};
constexpr InUseQuery(card::uid_t card_uid, std::chrono::seconds duration) : uid(card_uid), duration_s(duration) {};
[[nodiscard]] auto payload() const -> const std::string override;
[[nodiscard]] auto waitForReply() const -> bool override { return true; };
[[nodiscard]] auto buffered() const -> bool override { return false; };
Expand All @@ -115,7 +115,7 @@ namespace fabomatic::MQTTInterface
const card::uid_t uid;

RegisterMaintenanceQuery() = delete;
constexpr RegisterMaintenanceQuery(card::uid_t card_uid) : uid(card_uid){};
constexpr RegisterMaintenanceQuery(card::uid_t card_uid) : uid(card_uid) {};

[[nodiscard]] auto payload() const -> const std::string override;
[[nodiscard]] auto waitForReply() const -> bool override { return true; };
Expand All @@ -129,7 +129,7 @@ namespace fabomatic::MQTTInterface
const bool request_ok{false}; /* True if the request was processed by the server */

Response() = delete;
constexpr Response(bool result) : request_ok(result){};
constexpr Response(bool result) : request_ok(result) {};
};

/// @brief Result code for user authentication result
Expand All @@ -150,10 +150,10 @@ namespace fabomatic::MQTTInterface
FabUser::UserLevel user_level{FabUser::UserLevel::Unknown}; /* User priviledges */

UserResponse() = delete;
UserResponse(bool rok) : Response(rok){};
UserResponse(bool rok) : Response(rok) {};

UserResponse(bool rok, UserResult res) : Response(rok),
result(static_cast<uint8_t>(res)){};
result(static_cast<uint8_t>(res)) {};

[[nodiscard]] static auto fromJson(JsonDocument &doc) -> std::unique_ptr<UserResponse>;

Expand All @@ -174,7 +174,7 @@ namespace fabomatic::MQTTInterface
uint16_t grace{0}; /* Grace period in minutes */
std::string description{""}; /* Description of the expired maintenance */
MachineResponse() = delete;
MachineResponse(bool rok) : Response(rok){};
MachineResponse(bool rok) : Response(rok) {};

[[nodiscard]] static auto fromJson(JsonDocument &doc) -> std::unique_ptr<MachineResponse>;
};
Expand All @@ -184,10 +184,19 @@ namespace fabomatic::MQTTInterface
{
public:
SimpleResponse() = delete;
constexpr SimpleResponse(bool rok) : Response(rok){};
constexpr SimpleResponse(bool rok) : Response(rok) {};

[[nodiscard]] static auto fromJson(JsonDocument &doc) -> std::unique_ptr<SimpleResponse>;
};

/// @brief Class for server request
class BackendRequest
{
public:
card::uid_t requester;
std::string request_type;
BackendRequest(const card::uid_t &uid, const std::string &request) : requester{uid}, request_type(request) {};
[[nodiscard]] static auto fromJson(const JsonDocument &doc) -> std::optional<std::unique_ptr<BackendRequest>>;
};
} // namespace fabomatic::MQTTInterface
#endif // MQTTTYPES_HPP_
16 changes: 16 additions & 0 deletions include/card.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@ namespace fabomatic::card
return ss.str();
}

/**
* @brief Returns an UID from its string representation
* @param str hex string to convert
* @return uid value
*/
[[nodiscard]] inline auto str_uid(const std::string &str) -> card::uid_t
{
uint64_t ll_value;

std::stringstream ss{};
ss << std::hex << str;
ss >> ll_value;

return ll_value;
}

/**
* @brief Converts a UID from an array of bytes to a number
* @param uid array of bytes
Expand Down
4 changes: 3 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ name = fab-o-matic

[env]
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.08.10/platform-espressif32.zip
#platform =https://github.com/pioarduino/platform-espressif32/releases/download/51.03.04/platform-espressif32.zip
framework = arduino
test_framework = unity
check_tool = clangtidy
Expand All @@ -31,8 +32,9 @@ lib_deps = https://github.com/PBrunot/LiquidCrystal.git#use_const
adafruit/Adafruit NeoPixel@^1.12.3
https://github.com/tzapu/WiFiManager.git@2.0.17
ArduinoOTA
build_unflags = -std=gnu++11 -fexceptions
build_unflags = -std=gnu++11 -fexceptions -fno-lto
build_flags = -std=gnu++2b
-flto=auto
-g3
-Os
-I conf
Expand Down
24 changes: 24 additions & 0 deletions src/BoardLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -652,4 +652,28 @@ namespace fabomatic
std::to_string(conf::default_config::machine_id.id);
}

auto BoardLogic::processBackendRequests() -> void
{
auto &backend = getServer();
backend.loop();
if (auto result = backend.checkBackendRequest(); result.has_value())
{
const auto &req = result->get();
ESP_LOGI(TAG, "Processing backend request : %s", req->request_type.c_str());
FabUser fu{req->requester, "BACKEND", true, FabUser::UserLevel::FabAdmin};

if (req->request_type == "start")
{
logout();
if (!authorize(fu.card_uid))
{
ESP_LOGE(TAG, "Failure to execute start request from backend");
}
}
if (req->request_type == "stop")
{
logout();
}
}
}
} // namespace fabomatic
62 changes: 55 additions & 7 deletions src/FabBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,23 @@ namespace fabomatic
*/
void FabBackend::messageReceived(String &s_topic, String &s_payload)
{
ESP_LOGI(TAG, "MQTT Client: Received on %s -> %s", s_topic.c_str(), s_payload.c_str());
ESP_LOGI(TAG, "MQTT Client: message received on %s -> %s", s_topic.c_str(), s_payload.c_str());

last_reply.assign(s_payload.c_str());
answer_pending = false;
// Needed for equality test below
std::string_view view_topic{s_topic.c_str()};
if (view_topic == this->response_topic)
{
last_reply.assign(s_payload.c_str());
answer_pending = false;
}
else if (view_topic == this->request_topic)
{
last_request.assign(s_payload.c_str());
}
else if (view_topic != this->topic)
{
ESP_LOGW(TAG, "MQTT Client: unrecognized topic %s", s_topic.c_str());
}
}

/**
Expand Down Expand Up @@ -343,9 +356,9 @@ namespace fabomatic
// Setup subscriptions
if (client.connected())
{
std::stringstream tmp_topic;
tmp_topic << topic << conf::mqtt::response_topic;
response_topic.assign(tmp_topic.str());
std::stringstream ss_resp{};
ss_resp << topic << conf::mqtt::response_topic;
response_topic.assign(ss_resp.str());

if (!client.subscribe(response_topic.c_str()))
{
Expand All @@ -356,6 +369,21 @@ namespace fabomatic
ESP_LOGD(TAG, "MQTT Client: subscribed to reply topic %s", response_topic.c_str());
online = true;
}

std::stringstream ss_req{};
ss_req << topic << conf::mqtt::request_topic;
request_topic.assign(ss_req.str());

if (!client.subscribe(request_topic.c_str()))
{
ESP_LOGE(TAG, "MQTT Client: failure to subscribe to requests topic %s", request_topic.c_str());
}
else
{
ESP_LOGD(TAG, "MQTT Client: subscribed to requests topic %s", request_topic.c_str());
online = true;
}

// Announce the board to the server
if (auto query = MQTTInterface::AliveQuery{}; publish(query) == PublishResult::PublishedWithoutAnswer)
{
Expand Down Expand Up @@ -622,7 +650,7 @@ namespace fabomatic
}
}
}
last_reply = "";
last_reply.clear();

ESP_LOGW(TAG, "Retransmittion completed, remaining messages=%d", buffer.count());
return !hasBufferedMsg();
Expand Down Expand Up @@ -655,4 +683,24 @@ namespace fabomatic
buffer.setChanged(false);
ESP_LOGI(TAG, "Loaded buffer with %d messages", buffer.count());
}

auto FabBackend::checkBackendRequest() -> std::optional<std::unique_ptr<MQTTInterface::BackendRequest>>
{
if (!this->last_request.empty())
{
const auto payload = last_request.c_str();
if (DeserializationError error = deserializeJson(doc, payload))
{
ESP_LOGE(TAG, "Failed to parse json: %s (%s)", payload, error.c_str());
last_request.clear();
return std::nullopt;
}

last_request.clear();

return MQTTInterface::BackendRequest::fromJson(doc);
}
return std::nullopt;
}

} // namespace fabomatic
12 changes: 12 additions & 0 deletions src/MQTTtypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,16 @@ namespace fabomatic::MQTTInterface
auto response = std::make_unique<SimpleResponse>(doc["request_ok"].as<bool>());
return response;
}

auto BackendRequest::fromJson(const JsonDocument &doc) -> std::optional<std::unique_ptr<BackendRequest>>
{
if (doc.containsKey("request_type") && doc.containsKey("uid"))
{
const auto request = doc["request_type"].as<std::string>();
const auto struid = doc["uid"].as<std::string>();
return std::make_unique<BackendRequest>(card::str_uid(struid), request);
}
ESP_LOGW(TAG, "Cannot decode backend request from JsonDocument");
return std::nullopt;
}
} // namespace fabomatic::MQTTInterface
8 changes: 4 additions & 4 deletions src/RFIDWrapper.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ namespace fabomatic
{
const auto result = driver->PICC_IsNewCardPresent();

if (conf::debug::ENABLE_LOGS && result)
ESP_LOGD(TAG, "isNewCardPresent=%d", result);

if (disabledUntil && disabledUntil > fabomatic::Tasks::arduinoNow())
if (disabledUntil.has_value() && disabledUntil > fabomatic::Tasks::arduinoNow())
{
ESP_LOGD(TAG, "isNewCardPresent is disabled");
return false;
}

if (conf::debug::ENABLE_LOGS && result)
ESP_LOGD(TAG, "isNewCardPresent=%d", result);

return result;
}

Expand Down
1 change: 1 addition & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ namespace fabomatic
void taskCheckRfid()
{
Board::logic.checkRfid();
Board::logic.processBackendRequests();
}

/// @brief blink led
Expand Down
Loading

0 comments on commit 1b0efff

Please sign in to comment.