Skip to content

Commit

Permalink
Bugfix #32 + Buzzer class and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
PBrunot committed Jun 2, 2024
1 parent 26b9e2e commit 00a5b62
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 33 deletions.
4 changes: 3 additions & 1 deletion include/BoardLogic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "card.hpp"
#include "pins.hpp"
#include "secrets.hpp"
#include <Adafruit_NeoPixel.h>
#include "Buzzer.hpp"

namespace fabomatic
{
Expand Down Expand Up @@ -73,6 +73,7 @@ namespace fabomatic
[[nodiscard]] auto getRebootRequest() const -> bool;
[[nodiscard]] auto getServer() -> FabBackend &;
[[nodiscard]] auto getMachineForTesting() -> Machine &;
[[nodiscard]] auto getBuzzerForTesting() -> Buzzer *;
[[nodiscard]] auto getMachine() const -> const Machine &;
[[nodiscard]] auto authorize(const card::uid_t uid) -> bool;
[[nodiscard]] auto getHostname() const -> const std::string;
Expand Down Expand Up @@ -102,6 +103,7 @@ namespace fabomatic
BaseLCDWrapper &getLcd() const;

bool rebootRequest{false};
Buzzer buzzer;

[[nodiscard]] auto longTap(const card::uid_t card, const std::string &short_prompt) const -> bool;
};
Expand Down
22 changes: 22 additions & 0 deletions include/Buzzer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#ifndef BUZZER_HPP_
#define BUZZER_HPP_

#include <inttypes.h>

namespace fabomatic
{
class Buzzer
{
private:
mutable uint16_t beepCount{0};

public:
auto configure() -> void;
auto beepOk() const -> void;
auto beepFail() const -> void;
// For testing purposes
auto getBeepCount() const -> uint16_t;
};
} // namespace fabomatic

#endif // BUZZER_HPP_
3 changes: 1 addition & 2 deletions include/PinsConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#include <cstdint>
#include <array>
#include <Adafruit_NeoPixel.h>

namespace fabomatic
{
Expand Down Expand Up @@ -100,6 +99,6 @@ namespace fabomatic
}
return true;
}

} // namespace fabomatic
#endif // PINSCONFIG_HPP_
33 changes: 14 additions & 19 deletions src/BoardLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,26 +444,12 @@ namespace fabomatic

void BoardLogic::beepOk() const
{
if constexpr (conf::buzzer::STANDARD_BEEP_DURATION > 0ms && pins.buzzer.pin != NO_PIN)
{
digitalWrite(pins.buzzer.pin, 1);
Tasks::delay(conf::buzzer::STANDARD_BEEP_DURATION);
digitalWrite(pins.buzzer.pin, 0);
}
buzzer.beepOk();
}

void BoardLogic::beepFail() const
{
if constexpr (conf::buzzer::STANDARD_BEEP_DURATION > 0ms && pins.buzzer.pin != NO_PIN)
{
for (auto i = 0; i < conf::buzzer::NB_BEEPS; i++)
{
digitalWrite(pins.buzzer.pin, 1);
Tasks::delay(conf::buzzer::STANDARD_BEEP_DURATION);
digitalWrite(pins.buzzer.pin, 0);
Tasks::delay(conf::buzzer::STANDARD_BEEP_DURATION);
}
}
buzzer.beepFail();
}

/// @brief Configures the board with the given references
Expand Down Expand Up @@ -503,7 +489,7 @@ namespace fabomatic
conf::machine::DEFAULT_GRACE_PERIOD);

machine.configure(machine_conf, server);

buzzer.configure();
auth.loadCache();

return success;
Expand Down Expand Up @@ -598,11 +584,18 @@ namespace fabomatic

/// @brief returns a modificable machine for testing only
/// @return machine
Machine &BoardLogic::getMachineForTesting()
auto BoardLogic::getMachineForTesting() -> Machine &
{
return machine;
}

/// @brief returns a modificable machine for testing only
/// @return a non-null Buzzer*
auto BoardLogic::getBuzzerForTesting() -> Buzzer *
{
return &buzzer;
}

/// @brief Gets the current machine
/// @return a machine object
auto BoardLogic::getMachine() const -> const Machine &
Expand Down Expand Up @@ -661,6 +654,8 @@ namespace fabomatic
auto BoardLogic::getHostname() const -> const std::string
{
// Hostname is BOARD + machine_id (which shall be unique) e.g. BOARD1
return conf::default_config::hostname.data() + std::to_string(conf::default_config::machine_id.id);
return conf::default_config::hostname.data() +
std::to_string(conf::default_config::machine_id.id);
}

} // namespace fabomatic
47 changes: 47 additions & 0 deletions src/Buzzer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "Buzzer.hpp"
#include "conf.hpp"
#include "pins.hpp"
#include "Arduino.h"
#include "Tasks.hpp"

namespace fabomatic
{
auto Buzzer::configure() -> void
{
if constexpr (pins.buzzer.pin != NO_PIN)
{
pinMode(pins.buzzer.pin, OUTPUT);
}
}
auto Buzzer::beepOk() const -> void
{
if constexpr (conf::buzzer::STANDARD_BEEP_DURATION > 0ms && pins.buzzer.pin != NO_PIN)
{
digitalWrite(pins.buzzer.pin, 1);
Tasks::delay(conf::buzzer::STANDARD_BEEP_DURATION);
digitalWrite(pins.buzzer.pin, 0);
}
beepCount++;
}

auto Buzzer::beepFail() const -> void
{
if constexpr (conf::buzzer::STANDARD_BEEP_DURATION > 0ms && pins.buzzer.pin != NO_PIN)
{
for (auto i = 0; i < conf::buzzer::NB_BEEPS; i++)
{
digitalWrite(pins.buzzer.pin, 1);
Tasks::delay(conf::buzzer::STANDARD_BEEP_DURATION);
digitalWrite(pins.buzzer.pin, 0);
Tasks::delay(conf::buzzer::STANDARD_BEEP_DURATION);
beepCount++;
}
}
}

auto Buzzer::getBeepCount() const -> uint16_t
{
return beepCount;
}

} // namespace fabomatic
8 changes: 4 additions & 4 deletions src/Machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ namespace fabomatic
}

/// @brief indicates if the machine can be powered off
/// @return true if the delay has expired
/// @return true if the grace period has expired
auto Machine::canPowerOff() const -> bool
{
if (!logoff_timestamp.has_value())
Expand All @@ -119,16 +119,16 @@ namespace fabomatic
}

/// @brief indicates if the machine is about to shudown and board should beep
/// @return true if shutdown is imminent
/// @return true if shutdown is imminent (within grace_period after last logoff)
auto Machine::isShutdownImminent() const -> bool
{
if (!logoff_timestamp.has_value() || conf::machine::BEEP_PERIOD == 0ms)
if (!logoff_timestamp.has_value())
return false;

CHECK_CONFIGURED(bool);

return (power_state == PowerState::WaitingPowerOff &&
std::chrono::system_clock::now() - logoff_timestamp.value() > config.value().grace_period);
std::chrono::system_clock::now() - logoff_timestamp.value() <= config.value().grace_period);
}

/// @brief sets the machine power to on (true) or off (false)
Expand Down
8 changes: 6 additions & 2 deletions test/test_logic/test_common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,16 @@ namespace fabomatic::tests
{
driver.setUid(uid.value(), duration_tap);
TEST_ASSERT_TRUE_MESSAGE(uid == rfid.getUid(), "Card UID not equal");
auto start = std::chrono::system_clock::now();
auto start = millis();
do
{
logic.checkRfid();
delay(50);
} while (duration_tap.has_value() && std::chrono::system_clock::now() - start < duration_tap);
} while (duration_tap.has_value() && millis() - start < duration_tap.value_or(0ms).count());
}
else if (duration_tap)
{
delay(duration_tap.value().count());
}
return logic.getStatus();
}
Expand Down
40 changes: 35 additions & 5 deletions test/test_logic/test_logic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,19 @@ namespace fabomatic::tests

void test_simple_methods()
{
logic.beepFail();
logic.beepOk();
{
auto cpt = logic.getBuzzerForTesting()->getBeepCount();
logic.beepFail();
auto beeps = logic.getBuzzerForTesting()->getBeepCount() - cpt;
TEST_ASSERT_EQUAL_UINT16_MESSAGE(conf::buzzer::NB_BEEPS, beeps, "Buzzer FAIL has been beeped");
}
{
auto cpt = logic.getBuzzerForTesting()->getBeepCount();
logic.beepOk();
auto beeps = logic.getBuzzerForTesting()->getBeepCount() - cpt;
TEST_ASSERT_EQUAL_UINT16_MESSAGE(1, beeps, "Buzzer OK has been beeped");
}

logic.blinkLed();

std::vector statuses{BoardLogic::Status::Error, BoardLogic::Status::ErrorHardware, BoardLogic::Status::Connected,
Expand Down Expand Up @@ -193,6 +204,8 @@ namespace fabomatic::tests
void test_user_autologoff()
{
machine_init(logic, rfid);
auto &machine = logic.getMachineForTesting();
machine.setGracePeriod(5s);

TEST_ASSERT_TRUE_MESSAGE(logic.getMachine().getAutologoffDelay() == conf::machine::DEFAULT_AUTO_LOGOFF_DELAY, "Autologoff delay not default");

Expand All @@ -201,6 +214,7 @@ namespace fabomatic::tests

simulate_rfid_card(rfid, logic, get_test_uid(0));
TEST_ASSERT_EQUAL_UINT16_MESSAGE(BoardLogic::Status::LoggedIn, logic.getStatus(), "Status not LoggedIn");
TEST_ASSERT_TRUE_MESSAGE(machine.getPowerState() == Machine::PowerState::PoweredOn, "Machine is powered on");
// Card away
simulate_rfid_card(rfid, logic, std::nullopt);

Expand All @@ -209,14 +223,30 @@ namespace fabomatic::tests
TEST_ASSERT_EQUAL_UINT16_MESSAGE(BoardLogic::Status::MachineInUse, logic.getStatus(), "Status not MachineInUse");

// Now shall expire afer 10s
simulate_rfid_card(rfid, logic, std::nullopt);
delay(10000);
simulate_rfid_card(rfid, logic, std::nullopt, 10s);
TEST_ASSERT_TRUE_MESSAGE(logic.getMachine().isAutologoffExpired(), "Autologoff expired");

logic.logout();
simulate_rfid_card(rfid, logic, std::nullopt);
simulate_rfid_card(rfid, logic, std::nullopt, 5s);
TEST_ASSERT_TRUE_MESSAGE(logic.getMachine().isFree(), "Machine is free");
TEST_ASSERT_EQUAL_UINT16_MESSAGE(BoardLogic::Status::MachineFree, logic.getStatus(), "Status not MachineFree");
TEST_ASSERT_TRUE_MESSAGE(machine.canPowerOff(), "Machine should be powered off");
machine.power(false);
TEST_ASSERT_EQUAL_UINT8_MESSAGE(Machine::PowerState::PoweredOff, machine.getPowerState(), "(2) Machine is powered off");

// Check Grace period
simulate_rfid_card(rfid, logic, get_test_uid(0), 1s); // Login
TEST_ASSERT_EQUAL_UINT8_MESSAGE(Machine::PowerState::PoweredOn, machine.getPowerState(), "(2) Machine is ON");
simulate_rfid_card(rfid, logic, get_test_uid(0), 1s); // Logout
TEST_ASSERT_EQUAL_UINT8_MESSAGE(Machine::PowerState::WaitingPowerOff, machine.getPowerState(), "(2) Machine is waiting for power off");
TEST_ASSERT_TRUE_MESSAGE(machine.isShutdownImminent(), "Machine in grace period");
TEST_ASSERT_FALSE_MESSAGE(machine.canPowerOff(), "Machine cannot be powered off yet");
simulate_rfid_card(rfid, logic, std::nullopt, 5s); // Let grace period expire
TEST_ASSERT_FALSE_MESSAGE(machine.isShutdownImminent(), "Machine is still in grace period");
TEST_ASSERT_TRUE_MESSAGE(machine.canPowerOff(), "Machine can now be powered off");
machine.power(false);

TEST_ASSERT_EQUAL_UINT8_MESSAGE(Machine::PowerState::PoweredOff, machine.getPowerState(), "Machine is powered off");

auto save_result = logic.getServer().saveBuffer();
TEST_ASSERT_TRUE_MESSAGE(save_result, "Saving buffered messages works");
Expand Down

0 comments on commit 00a5b62

Please sign in to comment.