initial commit
This commit is contained in:
@@ -0,0 +1,156 @@
|
||||
#include "dali_comm.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#endif
|
||||
|
||||
DaliComm::DaliComm(SendCallback send_cb,
|
||||
ReadCallback read_cb,
|
||||
TransactCallback transact_cb,
|
||||
DelayCallback delay_cb)
|
||||
: send_(std::move(send_cb)),
|
||||
read_(std::move(read_cb)),
|
||||
transact_(std::move(transact_cb)),
|
||||
delay_(std::move(delay_cb)) {}
|
||||
|
||||
void DaliComm::setSendCallback(SendCallback cb) { send_ = std::move(cb); }
|
||||
|
||||
void DaliComm::setReadCallback(ReadCallback cb) { read_ = std::move(cb); }
|
||||
|
||||
void DaliComm::setTransactCallback(TransactCallback cb) { transact_ = std::move(cb); }
|
||||
|
||||
void DaliComm::setDelayCallback(DelayCallback cb) { delay_ = std::move(cb); }
|
||||
|
||||
std::vector<uint8_t> DaliComm::checksum(const std::vector<uint8_t>& data) {
|
||||
std::vector<uint8_t> out = data;
|
||||
uint32_t sum = 0;
|
||||
for (const auto b : out) {
|
||||
sum += b;
|
||||
}
|
||||
out.push_back(static_cast<uint8_t>(sum & 0xFF));
|
||||
return out;
|
||||
}
|
||||
|
||||
bool DaliComm::write(const std::vector<uint8_t>& data) const { return writeFrame(data); }
|
||||
|
||||
std::vector<uint8_t> DaliComm::read(size_t len, uint32_t timeout_ms) const {
|
||||
if (!read_) return {};
|
||||
return read_(len, timeout_ms);
|
||||
}
|
||||
|
||||
int DaliComm::checkGatewayType(int gateway) const {
|
||||
if (!transact_) return 0;
|
||||
|
||||
const std::vector<uint8_t> usbProbe{0x01, 0x00, 0x00};
|
||||
const std::vector<uint8_t> legacyProbe{0x28, 0x01, static_cast<uint8_t>(gateway), 0x11, 0x00, 0x00,
|
||||
0xFF};
|
||||
const std::vector<uint8_t> newProbe{0x28, 0x01, static_cast<uint8_t>(gateway), 0x11, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF};
|
||||
|
||||
const auto usbResp = transact_(usbProbe.data(), usbProbe.size());
|
||||
if (!usbResp.empty() && usbResp[0] > 0) return 1;
|
||||
|
||||
const auto legacyResp = transact_(legacyProbe.data(), legacyProbe.size());
|
||||
if (legacyResp.size() >= 2 && legacyResp[0] == gateway) return 2;
|
||||
|
||||
const auto newResp = transact_(newProbe.data(), newProbe.size());
|
||||
if (newResp.size() >= 2 && newResp[0] == gateway) return 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DaliComm::flush() const {
|
||||
if (!read_) return;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
const auto data = read_(2, 100);
|
||||
if (data.empty()) break;
|
||||
}
|
||||
}
|
||||
|
||||
bool DaliComm::resetBus() const {
|
||||
const std::vector<uint8_t> frame{0x00, 0x00, 0x00};
|
||||
if (!write(frame)) return false;
|
||||
sleepMs(100);
|
||||
if (!write(frame)) return false;
|
||||
sleepMs(100);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DaliComm::sendRaw(uint8_t addr, uint8_t cmd) const { return sendCmd(addr, cmd); }
|
||||
|
||||
bool DaliComm::sendRawNew(uint8_t addr, uint8_t cmd, bool needVerify) const {
|
||||
if (!needVerify) return sendCmd(addr, cmd);
|
||||
return queryCmd(addr, cmd).has_value();
|
||||
}
|
||||
|
||||
bool DaliComm::sendExtRaw(uint8_t addr, uint8_t cmd) const { return sendExtCmd(addr, cmd); }
|
||||
|
||||
bool DaliComm::sendExtRawNew(uint8_t addr, uint8_t cmd) const { return sendExtCmd(addr, cmd); }
|
||||
|
||||
std::optional<uint8_t> DaliComm::queryRaw(uint8_t addr, uint8_t cmd) const { return queryCmd(addr, cmd); }
|
||||
|
||||
std::optional<uint8_t> DaliComm::queryRawNew(uint8_t addr, uint8_t cmd) const {
|
||||
return queryCmd(addr, cmd);
|
||||
}
|
||||
|
||||
bool DaliComm::send(int dec_addr, uint8_t cmd) const { return sendCmd(toCmdAddr(dec_addr), cmd); }
|
||||
|
||||
std::optional<uint8_t> DaliComm::query(int dec_addr, uint8_t cmd) const {
|
||||
return queryCmd(toCmdAddr(dec_addr), cmd);
|
||||
}
|
||||
|
||||
bool DaliComm::getBusStatus() const { return checkGatewayType(0) > 0; }
|
||||
|
||||
uint8_t DaliComm::toCmdAddr(int dec_addr) { return static_cast<uint8_t>(dec_addr * 2 + 1); }
|
||||
|
||||
uint8_t DaliComm::toArcAddr(int dec_addr) { return static_cast<uint8_t>(dec_addr * 2); }
|
||||
|
||||
bool DaliComm::writeFrame(const std::vector<uint8_t>& frame) const {
|
||||
if (!send_) return false;
|
||||
return send_(frame.data(), frame.size());
|
||||
}
|
||||
|
||||
void DaliComm::sleepMs(uint32_t ms) const {
|
||||
if (delay_) {
|
||||
delay_(ms);
|
||||
return;
|
||||
}
|
||||
#ifdef ESP_PLATFORM
|
||||
vTaskDelay(pdMS_TO_TICKS(ms));
|
||||
#else
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool DaliComm::sendCmd(uint8_t addr, uint8_t cmd) const {
|
||||
const std::vector<uint8_t> frame{0x10, addr, cmd};
|
||||
return writeFrame(frame);
|
||||
}
|
||||
|
||||
bool DaliComm::sendExtCmd(uint8_t addr, uint8_t cmd) const {
|
||||
const std::vector<uint8_t> frame{0x11, addr, cmd};
|
||||
const bool ret = writeFrame(frame);
|
||||
sleepMs(100);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::optional<uint8_t> DaliComm::queryCmd(uint8_t addr, uint8_t cmd) const {
|
||||
if (!transact_) return std::nullopt;
|
||||
const std::vector<uint8_t> frame{0x12, addr, cmd};
|
||||
const auto resp = transact_(frame.data(), frame.size());
|
||||
if (resp.empty()) return std::nullopt;
|
||||
|
||||
// Gateway type 1 returns: 0xFF <data> on success; 0xFE no response; 0xFD invalid frame.
|
||||
if (resp.size() == 1) {
|
||||
if (resp[0] == 0xFE || resp[0] == 0xFD) return std::nullopt;
|
||||
return resp[0];
|
||||
}
|
||||
if (resp[0] == 0xFF && resp.size() >= 2) {
|
||||
return resp[1];
|
||||
}
|
||||
return resp.back();
|
||||
}
|
||||
Reference in New Issue
Block a user