Enhance DALI communication: introduce DaliQueryResult structure, update query handling, and improve logging of query results

Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
Tony
2026-05-21 13:22:15 +08:00
parent b52a95b50a
commit 0c662ecdc3
4 changed files with 151 additions and 21 deletions
+103 -12
View File
@@ -1,8 +1,11 @@
#include "dali_comm.hpp"
#include "dali_define.hpp"
#include "log.hpp"
#include <chrono>
#include <cstdio>
#include <string>
#include <thread>
#ifdef ESP_PLATFORM
@@ -14,6 +17,23 @@ namespace {
constexpr uint32_t kQueryTimeoutMs = 100;
std::string hexByte(uint8_t value) {
char buffer[5]{};
std::snprintf(buffer, sizeof(buffer), "0x%02X", static_cast<unsigned>(value));
return buffer;
}
std::string formatBytes(const std::vector<uint8_t>& bytes) {
if (bytes.empty()) return "[]";
std::string out = "[";
for (size_t i = 0; i < bytes.size(); ++i) {
if (i > 0) out += ' ';
out += hexByte(bytes[i]);
}
out += ']';
return out;
}
std::vector<uint8_t> readQueryResponse(const DaliComm::ReadCallback& read_cb, uint32_t timeout_ms) {
if (!read_cb) return {};
@@ -40,31 +60,75 @@ std::vector<uint8_t> readQueryResponse(const DaliComm::ReadCallback& read_cb, ui
return collected;
}
std::optional<uint8_t> parseQueryResponse(const std::vector<uint8_t>& resp, uint8_t addr) {
if (resp.empty()) return std::nullopt;
DaliQueryResult parseQueryResponse(const std::vector<uint8_t>& resp, uint8_t addr) {
DaliQueryResult result;
result.raw = resp;
if (resp.empty()) {
result.status = DaliQueryStatus::timeout;
return result;
}
// Gateway type 1 returns: 0xFF <data> on success; 0xFE 0x00 on no response;
// 0xFD xx on invalid frame. COMPARE is special: collisions still mean a match.
if (resp[0] == 0xFE) {
return std::nullopt;
result.status = DaliQueryStatus::noResponse;
return result;
}
if (resp[0] == 0xFD) {
if (addr == DALI_CMD_SPECIAL_COMPARE) {
return static_cast<uint8_t>(resp.size() >= 2 ? resp[1] : 0xFF);
result.status = DaliQueryStatus::success;
result.value = static_cast<uint8_t>(resp.size() >= 2 ? resp[1] : 0xFF);
return result;
}
return std::nullopt;
result.status = DaliQueryStatus::invalidFrame;
return result;
}
if (resp.size() == 1) {
return resp[0];
result.status = DaliQueryStatus::success;
result.value = resp[0];
return result;
}
if (resp[0] == 0xFF && resp.size() >= 2) {
return resp[1];
result.status = DaliQueryStatus::success;
result.value = resp[1];
return result;
}
return resp.back();
result.status = DaliQueryStatus::unknownFrame;
return result;
}
void logQueryResult(uint8_t addr, uint8_t cmd, const DaliQueryResult& result) {
std::string message = "dali:query addr=" + hexByte(addr) + " cmd=" + hexByte(cmd) +
" status=" + daliQueryStatusName(result.status);
if (result.value.has_value()) {
message += " value=" + hexByte(result.value.value());
}
message += " raw=" + formatBytes(result.raw);
DaliLog::instance().debugLog(message);
}
} // namespace
const char* daliQueryStatusName(DaliQueryStatus status) {
switch (status) {
case DaliQueryStatus::success:
return "success";
case DaliQueryStatus::noResponse:
return "noResponse";
case DaliQueryStatus::invalidFrame:
return "invalidFrame";
case DaliQueryStatus::unknownFrame:
return "unknownFrame";
case DaliQueryStatus::sendFailed:
return "sendFailed";
case DaliQueryStatus::transportUnavailable:
return "transportUnavailable";
case DaliQueryStatus::timeout:
return "timeout";
}
return "unknown";
}
DaliComm::DaliComm(SendCallback send_cb,
ReadCallback read_cb,
TransactCallback transact_cb,
@@ -157,6 +221,14 @@ std::optional<uint8_t> DaliComm::queryRawNew(uint8_t addr, uint8_t cmd) const {
return queryCmd(addr, cmd);
}
DaliQueryResult DaliComm::queryRawResult(uint8_t addr, uint8_t cmd) const {
return queryCmdResult(addr, cmd);
}
DaliQueryResult DaliComm::queryRawNewResult(uint8_t addr, uint8_t cmd) const {
return queryCmdResult(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 {
@@ -210,14 +282,33 @@ bool DaliComm::sendExtCmd(uint8_t addr, uint8_t cmd) const {
}
std::optional<uint8_t> DaliComm::queryCmd(uint8_t addr, uint8_t cmd) const {
const auto result = queryCmdResult(addr, cmd);
if (!result.hasValue()) return std::nullopt;
return result.value;
}
DaliQueryResult DaliComm::queryCmdResult(uint8_t addr, uint8_t cmd) const {
const std::vector<uint8_t> frame{0x12, addr, cmd};
DaliQueryResult result;
if (send_ && read_) {
prepareForQuery();
if (!writeFrame(frame)) return std::nullopt;
return parseQueryResponse(readQueryResponse(read_, kQueryTimeoutMs), addr);
if (!writeFrame(frame)) {
result.status = DaliQueryStatus::sendFailed;
logQueryResult(addr, cmd, result);
return result;
}
result = parseQueryResponse(readQueryResponse(read_, kQueryTimeoutMs), addr);
logQueryResult(addr, cmd, result);
return result;
}
prepareForQuery();
if (!transact_) return std::nullopt;
return parseQueryResponse(transact_(frame.data(), frame.size()), addr);
if (!transact_) {
result.status = DaliQueryStatus::transportUnavailable;
logQueryResult(addr, cmd, result);
return result;
}
result = parseQueryResponse(transact_(frame.data(), frame.size()), addr);
logQueryResult(addr, cmd, result);
return result;
}