Skip to content

Commit

Permalink
WIP backend requests
Browse files Browse the repository at this point in the history
  • Loading branch information
PBrunot committed Aug 14, 2024
1 parent 2d7e119 commit 8ca0041
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 43 deletions.
3 changes: 1 addition & 2 deletions include/FabBackend.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ namespace fabomatic
std::string mqtt_password{""};
std::string mqtt_client_name{""};

MQTTClientCallbackSimpleFunction callback_resp;
MQTTClientCallbackSimpleFunction callback_req;
MQTTClientCallbackSimpleFunction callback;
WiFiClient wifi_client;

std::string topic{""};
Expand Down
4 changes: 3 additions & 1 deletion src/BoardLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -655,9 +655,11 @@ namespace fabomatic
auto BoardLogic::processBackendRequests() -> void
{
auto &backend = getServer();
backend.loop();
if (auto result = backend.checkBackendRequest(); result.has_value())
{
auto req = result->get();
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")
Expand Down
53 changes: 25 additions & 28 deletions src/FabBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,22 +245,23 @@ namespace fabomatic
*/
void FabBackend::messageReceived(String &s_topic, String &s_payload)
{
ESP_LOGI(TAG, "MQTT Client: Reply 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;
}

/**
* @brief Callback function for received MQTT request.
*
* @param s_topic The topic the message was received on.
* @param s_payload The payload of the message.
*/
void FabBackend::requestReceived(String &s_topic, String &s_payload)
{
ESP_LOGI(TAG, "MQTT Client: Request received on %s -> %s", s_topic.c_str(), s_payload.c_str());
last_request.assign(s_payload.c_str());
// 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 @@ -339,13 +340,10 @@ namespace fabomatic

client.begin(ip, conf::mqtt::PORT_NUMBER, wifi_client);

callback_resp = [&](String &a, String &b)
callback = [&](String &a, String &b)
{ return messageReceived(a, b); };

callback_req = [&](String &a, String &b)
{ return requestReceived(a, b); };

client.onMessage(callback_resp);
client.onMessage(callback);

if (!client.connect(mqtt_client_name.c_str(),
mqtt_user.c_str(),
Expand All @@ -358,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 @@ -372,9 +370,9 @@ namespace fabomatic
online = true;
}

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

if (!client.subscribe(request_topic.c_str()))
{
Expand Down Expand Up @@ -700,8 +698,7 @@ namespace fabomatic

last_request.clear();

auto resp = MQTTInterface::BackendRequest::fromJson(doc);
return resp;
return MQTTInterface::BackendRequest::fromJson(doc);
}
return std::nullopt;
}
Expand Down
5 changes: 3 additions & 2 deletions src/MQTTtypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,13 @@ namespace fabomatic::MQTTInterface

auto BackendRequest::fromJson(const JsonDocument &doc) -> std::optional<std::unique_ptr<BackendRequest>>
{
if (doc.containsKey("request") && doc.containsKey("uid"))
if (doc.containsKey("request_type") && doc.containsKey("uid"))
{
const auto request = doc["request"].as<std::string>();
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
6 changes: 6 additions & 0 deletions test/test_logic/test_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ namespace fabomatic::tests
std::optional<std::chrono::milliseconds> duration_tap = std::nullopt);

void machine_init(BoardLogic &logic, RFIDWrapper<MockMrfc522> &rfid);

constexpr fabomatic::card::uid_t get_test_uid(size_t idx)
{
auto [card_uid, level, name] = fabomatic::tests::test_whitelist[idx];
return card_uid;
}
}

#endif // TEST_COMMON_H_
6 changes: 0 additions & 6 deletions test/test_logic/test_logic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@ fabomatic::BoardLogic logic;

using BoardLogic = fabomatic::BoardLogic;

constexpr fabomatic::card::uid_t get_test_uid(size_t idx)
{
auto [card_uid, level, name] = fabomatic::tests::test_whitelist[idx];
return card_uid;
}

namespace fabomatic::tests
{
void test_machine_defaults()
Expand Down
105 changes: 105 additions & 0 deletions test/test_mqtt/test_mqtt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <Arduino.h>
#include <unity.h>
#include "LiquidCrystal.h"
#include "../test_logic/test_common.h"

using namespace std::chrono_literals;

Expand All @@ -36,6 +37,57 @@ namespace fabomatic::tests

std::atomic<bool> exit_request{false};

void busyWait(std::chrono::seconds d = 5s)
{
auto start = fabomatic::Tasks::arduinoNow();
while (fabomatic::Tasks::arduinoNow() - start <= d)
{
test_scheduler.execute();
delay(25);
}
}

/// @brief Simulates RFID card tap
/// @param rfid RFID wrapper for simulation
/// @param logic Board logic, the checkRfid() method will be called repeatedly
/// @param uid card UID to tap
/// @param duration_tap duration of the tap. pass milliseconds::max() to keep the card in the field
/// @return
BoardLogic::Status simulate_rfid_card(RFIDWrapper<MockMrfc522> &rfid, BoardLogic &logic, std::optional<card::uid_t> uid,
std::optional<std::chrono::milliseconds> duration_tap)
{
constexpr auto DEFAULT_CYCLES = 3;

MockMrfc522 &driver = rfid.getDriver();

driver.resetUid();
rfid.setDisabledUntil(std::nullopt);

for (auto i = 0; i < DEFAULT_CYCLES; i++)
{
logic.checkRfid();
rfid.setDisabledUntil(std::nullopt);
}

if (uid.has_value())
{
driver.setUid(uid.value(), duration_tap);
TEST_ASSERT_TRUE_MESSAGE(uid == rfid.getUid(), "Card UID not equal");
auto start = fabomatic::Tasks::arduinoNow();
do
{
logic.checkRfid();
rfid.setDisabledUntil(std::nullopt);
delay(50);
} while (duration_tap.has_value() && fabomatic::Tasks::arduinoNow() - start < duration_tap);
}
else if (duration_tap)
{
delay(duration_tap.value().count());
}
return logic.getStatus();
}

void *threadMQTTServer(void *arg)
{
while (!exit_request)
Expand Down Expand Up @@ -245,6 +297,7 @@ namespace fabomatic::tests
void test_taskCheckRfid()
{
logic.checkRfid();
logic.processBackendRequests();
}

/// @brief blink led
Expand Down Expand Up @@ -341,6 +394,57 @@ namespace fabomatic::tests
// Remove the HW Watchdog
esp32::removeWatchdog();
}

void test_backend_commands()
{
constexpr auto millis_delay = std::chrono::duration_cast<std::chrono::milliseconds>(conf::machine::DELAY_BETWEEN_SWEEPS).count();
delay(millis_delay);
auto card1 = get_test_uid(2);
auto card2 = get_test_uid(1);

TEST_ASSERT_EQUAL_UINT16_MESSAGE(BoardLogic::Status::MachineFree, logic.getStatus(), "Status not MachineFree (0)");

simulate_rfid_card(rfid, logic, card1);
TEST_ASSERT_EQUAL_UINT16_MESSAGE(BoardLogic::Status::LoggedIn, logic.getStatus(), "Status not LoggedIn (0)");
// Card away
simulate_rfid_card(rfid, logic, std::nullopt);

std::stringstream ss{}, ss2{}, ss3{};
ss3 << conf::mqtt::topic << "/" << logic.getMachine().getMachineId().id << conf::mqtt::request_topic;
std::string topic = ss3.str();

ss << "{\"request_type\":\"stop\","
<< "\"uid\":\"" << card::uid_str(card2) << "\""
<< "}";
std::string payload_stop = ss.str();
broker.publish(topic, payload_stop);

busyWait(5s);

// Stop request has been processed
TEST_ASSERT_EQUAL_UINT16_MESSAGE(BoardLogic::Status::MachineFree, logic.getStatus(), "Status not MachineFree (1)");
TEST_ASSERT_TRUE_MESSAGE(logic.getMachine().isFree(), "Machine should be available");

ss2 << "{\"request_type\":\"start\","
<< "\"uid\":\"" << card::uid_str(card2) << "\""
<< "}";
std::string payload_start = ss2.str();
broker.publish(topic, payload_start);

busyWait(5s);

// Start request has been processed
TEST_ASSERT_EQUAL_UINT16_MESSAGE(BoardLogic::Status::MachineInUse, logic.getStatus(), "Status not MachineInUse (2)");
TEST_ASSERT_TRUE_MESSAGE(!logic.getMachine().isFree(), "Machine should not be available");
TEST_ASSERT_TRUE_MESSAGE(logic.getMachine().getActiveUser().card_uid == card2, "Wrong active user");

broker.publish(topic, payload_stop);

busyWait(5s);

// Stop request has been processed
TEST_ASSERT_EQUAL_UINT16_MESSAGE(BoardLogic::Status::MachineFree, logic.getStatus(), "Status not MachineFree (2)");
}
} // namespace fabomatic::Tests

void tearDown(void) {};
Expand All @@ -365,6 +469,7 @@ void setup()
RUN_TEST(fabomatic::tests::test_check_transmission);
RUN_TEST(fabomatic::tests::test_fabserver_calls);
RUN_TEST(fabomatic::tests::test_normal_use);
RUN_TEST(fabomatic::tests::test_backend_commands);
RUN_TEST(fabomatic::tests::test_stop_broker);

UNITY_END(); // stop unit testing
Expand Down

0 comments on commit 8ca0041

Please sign in to comment.