Files
2026-06-09 12:42:15 +08:00

72 lines
2.5 KiB
C++

#pragma once
#include "line_laser_modbus/protocol.hpp"
#include <array>
namespace line_laser_modbus {
constexpr std::size_t kRegisterBankSize =
static_cast<std::size_t>(kLastMappedAddress - kModeCommandAddress + 1U);
class RegisterBank {
public:
RegisterBank();
// 地址检查集中在这里处理。V1.2 寄存器表从 0xD000 到 0xD06B 是连续区域,
// 包含预留寄存器,因此紧凑数组比 map 更快、更省内存,同时保留后续启用
// 预留寄存器的空间。
[[nodiscard]] bool contains(std::uint16_t start_address,
std::uint16_t quantity) const noexcept;
[[nodiscard]] std::optional<RegisterVector> read(
std::uint16_t start_address,
std::uint16_t quantity) const;
[[nodiscard]] bool write(std::uint16_t start_address,
const RegisterVector& registers);
[[nodiscard]] WorkMode mode() const noexcept;
[[nodiscard]] DeviceState state() const noexcept;
bool set_mode(WorkMode mode) noexcept;
void set_state(DeviceState state) noexcept;
void set_current_pose(const Pose6D& pose);
[[nodiscard]] std::optional<Pose6D> current_pose() const;
[[nodiscard]] std::optional<Pose6D> target_pose() const;
[[nodiscard]] std::optional<Pose6D> correction() const;
private:
[[nodiscard]] static std::size_t index_of(std::uint16_t address) noexcept;
void apply_mode_side_effects(WorkMode mode) noexcept;
std::array<std::uint16_t, kRegisterBankSize> registers_{};
};
// DeviceServer 是下位机/从站侧帧处理器。
//
// 固件应在 UART 收到一个完整 RTU 帧后再调用 process_request()。该类会校验
// CRC、功能码、地址范围和模式切换规则,然后返回可直接发送的完整响应帧。
// 如果返回空字节数组,表示该帧应被忽略;在共享 RS-485 总线上,错误从站
// 地址或 CRC 损坏的流量都属于这种情况。
class DeviceServer {
public:
explicit DeviceServer(std::uint8_t slave_id = kDefaultSlaveId);
[[nodiscard]] std::uint8_t slave_id() const noexcept;
[[nodiscard]] RegisterBank& bank() noexcept;
[[nodiscard]] const RegisterBank& bank() const noexcept;
[[nodiscard]] ByteVector process_request(const ByteVector& request);
private:
[[nodiscard]] ByteVector process_read_request(const ReadRequest& request) const;
[[nodiscard]] ByteVector process_write_request(const WriteRequest& request);
[[nodiscard]] bool mode_write_is_valid(const WriteRequest& request) const noexcept;
std::uint8_t slave_id_;
RegisterBank bank_;
};
} // 命名空间 line_laser_modbus