Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infra - Testing #114

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
20 changes: 16 additions & 4 deletions lib/core/mqtt_logger.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
#include "mqtt.hpp"
#include "mqtt_logger.hpp"

#include <cstdarg>
#include <cstdio>
#include <utility>

namespace hyped::core {

MqttLogger::MqttLogger(const char *const label,
const LogLevel level,
const core::ITimeSource &timer,
Expand All @@ -19,13 +22,22 @@ MqttLogger::MqttLogger(const char *const label,

void MqttLogger::log(const LogLevel level, const char *format, ...)
{
logger_.log(level, format);
const auto topic = MqttTopic::kTest;
char buffer[256]; // NOLINT
va_list args;
va_start(args, format);
vsprintf(buffer, format, args);
va_end(args);
logger_.log(level, "%s", buffer);
const auto topic = MqttTopic::kLog;
std::shared_ptr<rapidjson::Document> message_payload = std::make_shared<rapidjson::Document>();
message_payload->SetObject();
message_payload->AddMember("log", *format, message_payload->GetAllocator());
const MqttMessage::Header header{.timestamp = 0, .priority = MqttMessagePriority::kCritical};
rapidjson::Value log_string_value;
log_string_value.SetString(buffer, message_payload->GetAllocator());
message_payload->AddMember("log", log_string_value, message_payload->GetAllocator());
const auto now = static_cast<std::uint64_t>(time_source_.now().time_since_epoch().count());
const MqttMessage::Header header{.timestamp = now, .priority = MqttMessagePriority::kCritical};
const MqttMessage message{topic, header, message_payload};
mqtt_->publish(message, MqttMessageQos::kAtLeastOnce);
}

} // namespace hyped::core
8 changes: 4 additions & 4 deletions lib/core/mqtt_topics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

namespace hyped::core {

enum class MqttTopic { kTest, kState };
enum class MqttTopic { kTest, kState, kLog };

const std::unordered_map<MqttTopic, std::string> mqtt_topic_to_string
= {{MqttTopic::kTest, "test"}, {MqttTopic::kState, "state"}};
= {{MqttTopic::kTest, "test"}, {MqttTopic::kState, "state"}, {MqttTopic::kLog, "log"}};
const std::unordered_map<std::string, MqttTopic> mqtt_string_to_topic
= {{"test", MqttTopic::kTest}, {"state", MqttTopic::kState}};
= {{"test", MqttTopic::kTest}, {"state", MqttTopic::kState}, {"log", MqttTopic::kLog}};

} // namespace hyped::core
} // namespace hyped::core
17 changes: 8 additions & 9 deletions lib/debug/commands/spi_commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ core::Result SpiCommands::addCommands(core::ILogger &logger, std::shared_ptr<Rep
const auto spi = std::move(*optional_spi);

std::uint16_t register_address = std::stoi(args[5], nullptr, 16);
std::uint8_t read_buffer;
const core::Result result = spi->read(register_address, &read_buffer, 1);
if (result == core::Result::kFailure) {
auto optional_read_byte = spi->read(register_address, 1);
if (!optional_read_byte) {
logger.log(core::LogLevel::kFatal, "Failed to read from SPI bus %d", bus);
return;
}
logger.log(core::LogLevel::kDebug, "SPI value from bus %d: %d", bus, read_buffer);
const auto read_byte = *optional_read_byte;
logger.log(core::LogLevel::kDebug, "SPI value from bus %d: %d", bus, read_byte[0]);
};
auto spi_read_byte_command = std::make_unique<Command>(spi_read_byte_command_name,
spi_read_byte_command_description,
Expand Down Expand Up @@ -66,11 +66,10 @@ core::Result SpiCommands::addCommands(core::ILogger &logger, std::shared_ptr<Rep
}
const auto spi = std::move(*optional_spi);

std::uint16_t register_address = std::stoi(args[5], nullptr, 16);
std::uint8_t data = std::stoi(args[6], nullptr, 16);

const auto *data_ptr = reinterpret_cast<const std::uint8_t *>(&data);
const core::Result result = spi->write(register_address, data_ptr, 1);
std::uint16_t register_address = std::stoi(args[5], nullptr, 16);
std::uint8_t data = std::stoi(args[6], nullptr, 16);
const std::vector<std::uint8_t> data_array = {data};
const core::Result result = spi->write(register_address, data_array);
if (result == core::Result::kFailure) {
logger.log(core::LogLevel::kFatal, "Failed to write to SPI bus: %d", bus);
return;
Expand Down
25 changes: 15 additions & 10 deletions lib/io/hardware_spi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,41 +65,44 @@ HardwareSpi::~HardwareSpi()
close(file_descriptor_);
}

core::Result HardwareSpi::read(const std::uint8_t register_address,
const std::uint8_t *rx,
const std::uint16_t len)
std::optional<std::vector<std::uint8_t>> HardwareSpi::read(const std::uint8_t register_address,
const std::uint16_t len)
{
std::vector<std::uint8_t> rx(len);
spi_ioc_transfer message[2] = {}; // NOLINT
// send address
message[0].tx_buf = reinterpret_cast<std::uint64_t>(&register_address);
message[0].rx_buf = 0;
message[0].len = 1;
// receive data
message[1].tx_buf = 0;
message[1].rx_buf = reinterpret_cast<std::uint64_t>(rx);
message[1].rx_buf = reinterpret_cast<std::uint64_t>(rx.data());
message[1].len = len;
const int read_result = ioctl(file_descriptor_, SPI_IOC_MESSAGE(2), message);
if (read_result < 0) {
logger_.log(core::LogLevel::kFatal, "Failed to read from SPI device");
return core::Result::kFailure;
return std::nullopt;
}
if (rx.size() != len) {
logger_.log(core::LogLevel::kFatal, "Failed to read the correct number of bytes from SPI");
return std::nullopt;
}
logger_.log(core::LogLevel::kDebug, "Successfully read from SPI device");
return core::Result::kSuccess;
return rx;
}

core::Result HardwareSpi::write(const std::uint8_t register_address,
const std::uint8_t *tx,
const std::uint16_t len)
const std::vector<std::uint8_t> tx)
{
spi_ioc_transfer message[2] = {}; // NOLINT
// send address
message[0].tx_buf = reinterpret_cast<std::uint64_t>(&register_address);
message[0].rx_buf = 0;
message[0].len = 1;
// write data
message[1].tx_buf = reinterpret_cast<std::uint64_t>(tx);
message[1].tx_buf = reinterpret_cast<std::uint64_t>(tx.data());
message[1].rx_buf = 0;
message[1].len = len;
message[1].len = tx.size();
const int write_result = ioctl(file_descriptor_, SPI_IOC_MESSAGE(2), message);
if (write_result < 0) {
logger_.log(core::LogLevel::kFatal, "Failed to write to SPI device");
Expand All @@ -126,6 +129,8 @@ std::uint32_t HardwareSpi::getClockValue(SpiClock clock)
return 500'000;
case SpiClock::k1MHz:
return 1'000'000;
case SpiClock::k2MHz:
return 2'000'000;
case SpiClock::k4MHz:
return 4'000'000;
case SpiClock::k16MHz:
Expand Down
17 changes: 11 additions & 6 deletions lib/io/hardware_spi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,14 @@ enum class SpiMode { kMode0 = 0, kMode1, kMode2, kMode3 };
enum class SpiWordSize { kWordSize4 = 4, kWordSize8 = 8, kWordSize16 = 16, kWordSize32 = 32 };
enum class SpiBitOrder { kMsbFirst = 0, kLsbFirst };
// Maximum clock frequency for SPI is 100MHz
enum class SpiClock { k500KHz, k1MHz, k4MHz, k16MHz, k20MHz };
enum class SpiClock {
k500KHz = 500'000,
k1MHz = 1'000'000,
k2MHz = 2'000'000,
k4MHz = 4'000'000,
k16MHz = 16'000'000,
k20MHz = 20'000'000
};

class HardwareSpi : public ISpi {
public:
Expand All @@ -69,12 +76,10 @@ class HardwareSpi : public ISpi {
HardwareSpi(core::ILogger &logger, const int file_descriptor);
~HardwareSpi();

core::Result read(const std::uint8_t register_address,
const std::uint8_t *rx,
const std::uint16_t len) override;
std::optional<std::vector<std::uint8_t>> read(const std::uint8_t register_address,
const std::uint16_t len) override;
core::Result write(const std::uint8_t register_address,
const std::uint8_t *tx,
const std::uint16_t len) override;
const std::vector<std::uint8_t> tx) override;

private:
/**
Expand Down
18 changes: 7 additions & 11 deletions lib/io/spi.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#pragma once

#include <cstdint>
#include <optional>
#include <vector>

#include <core/types.hpp>

Expand All @@ -11,24 +13,18 @@ class ISpi {
/**
* @brief Get data from sensor, starting at some address.
* @param addr - register from which the reading should start
* @param rx - pointer to head of read buffer
* @param len - number of bytes to be read, i.e. size of the read buffer
* @param len - number of bytes to be read
*/
virtual core::Result read(const std::uint8_t addr,
const std::uint8_t *rx,
const std::uint16_t len)
virtual std::optional<std::vector<std::uint8_t>> read(const std::uint8_t addr,
const std::uint16_t len)
= 0;

/**
* @brief Write data to sensor, starting at some address.
* @param addr - register from which writing to starts
* @param tx - pointer to head of write buffer
* @param len - number of bytes to be written, i.e. size of the write buffer
* @param tx - data to be written
*/
virtual core::Result write(const std::uint8_t addr,
const std::uint8_t *tx,
const std::uint16_t len)
= 0;
virtual core::Result write(const std::uint8_t addr, const std::vector<std::uint8_t> tx) = 0;
};

} // namespace hyped::io
19 changes: 17 additions & 2 deletions lib/utils/dummy_adc.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,25 @@
#include "dummy_adc.hpp"

#include <optional>
#include <utility>

namespace hyped::utils {

DummyAdc::DummyAdc() : values_(0.0)
{
}

std::optional<core::Float> DummyAdc::readValue()
{
return std::nullopt;
if (values_.empty()) { return std::nullopt; }
const auto val = values_.front();
values_.erase(values_.begin());
return val;
}

void DummyAdc::setValue(std::vector<std::optional<core::Float>> values)
{
values_ = std::move(values);
}

} // namespace hyped::utils
} // namespace hyped::utils
7 changes: 7 additions & 0 deletions lib/utils/dummy_adc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ namespace hyped::utils {

class DummyAdc : public io::IAdc {
public:
DummyAdc();
~DummyAdc() = default;

std::optional<core::Float> readValue() override;
void setValue(std::vector<std::optional<core::Float>> values);

private:
std::vector<std::optional<core::Float>> values_;
};

} // namespace hyped::utils
32 changes: 28 additions & 4 deletions lib/utils/dummy_i2c.cpp
Original file line number Diff line number Diff line change
@@ -1,30 +1,54 @@
#include "dummy_i2c.hpp"

#include <utility>

namespace hyped::utils {

std::optional<std::uint8_t> DummyI2c::readByte(const std::uint8_t device_address,
const std::uint8_t register_address)
{
return std::nullopt;
if (read_byte_results_.empty()) { return std::nullopt; }
const auto next_byte = read_byte_results_.at(0);
read_byte_results_.erase(read_byte_results_.begin());
return next_byte;
}

core::Result DummyI2c::writeByteToRegister(const std::uint8_t device_address,
const std::uint8_t register_address,
const std::uint8_t data)
{
return core::Result::kFailure;
return writeByte(0, 0);
}

core::Result DummyI2c::writeByteToRegister(const std::uint8_t device_address,
const std::uint16_t register_address,
const std::uint8_t data)
{
return core::Result::kFailure;
return writeByte(0, 0);
}

core::Result DummyI2c::writeByte(const std::uint8_t device_address, const std::uint8_t data)
{
return core::Result::kFailure;
if (write_byte_results_.empty()) { return core::Result::kFailure; }
const auto next_result = write_byte_results_.at(0);
write_byte_results_.erase(write_byte_results_.begin());
if (next_result == core::Result::kSuccess) { sent_data_.emplace_back(device_address, data); }
return next_result;
}

void DummyI2c::setWriteByteResults(std::vector<core::Result> results)
{
write_byte_results_ = std::move(results);
}

void DummyI2c::setReadByteResults(std::vector<std::optional<std::uint8_t>> results)
{
read_byte_results_ = std::move(results);
}

std::vector<std::pair<std::uint8_t, std::uint8_t>> DummyI2c::getSentData()
{
return sent_data_;
}

} // namespace hyped::utils
12 changes: 12 additions & 0 deletions lib/utils/dummy_i2c.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ class DummyI2c : public io::II2c {
const std::uint16_t register_address,
const std::uint8_t data) override;
core::Result writeByte(const std::uint8_t device_address, const std::uint8_t data) override;

void setWriteByteResults(std::vector<core::Result> results);
void setReadByteResults(std::vector<std::optional<std::uint8_t>> results);
/**
* @return a vector of pairs of device address and data that was sent
*/
std::vector<std::pair<std::uint8_t, std::uint8_t>> getSentData();

private:
std::vector<core::Result> write_byte_results_;
std::vector<std::optional<std::uint8_t>> read_byte_results_;
std::vector<std::pair<std::uint8_t, std::uint8_t>> sent_data_;
};

} // namespace hyped::utils
24 changes: 19 additions & 5 deletions lib/utils/dummy_mqtt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,37 @@

namespace hyped::utils {

void MockMqtt::publish(const core::MqttMessage &message, const core::MqttMessageQos qos)
void DummyMqtt::publish(const core::MqttMessage &message, const core::MqttMessageQos qos)
{
messages_sent_.push_back(message);
}

core::Result MockMqtt::subscribe(const core::MqttTopic topic)
core::Result DummyMqtt::subscribe(const core::MqttTopic topic)
{
return core::Result::kSuccess;
}

core::Result MockMqtt::consume()
core::Result DummyMqtt::consume()
{
return core::Result::kSuccess;
}

std::optional<core::MqttMessage> MockMqtt::getMessage()
std::optional<core::MqttMessage> DummyMqtt::getMessage()
{
return std::nullopt;
if (messages_to_receive_.empty()) { return std::nullopt; }
const auto next_message = messages_to_receive_.at(0);
messages_to_receive_.erase(messages_to_receive_.begin());
return next_message;
}

std::vector<core::MqttMessage> DummyMqtt::getSentMessages()
{
return messages_sent_;
}

void DummyMqtt::addMessageToReceive(const core::MqttMessage &message)
{
messages_to_receive_.emplace_back(message);
}

} // namespace hyped::utils
Loading
Loading