Refactor DALI command handling: streamline send methods and enhance scene color reporting
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
// Lightweight communicator for DALI gateway type 1 (USB UART new frame format).
|
||||
// Frames:
|
||||
// - Send: [0x10, addr, cmd]
|
||||
// - Ext: [0x11, addr, cmd] (sent twice with a small delay)
|
||||
// - Ext: [0x11, addr, cmd] (one logical send; gateway/transceiver handles any required repeat timing)
|
||||
// - Query: [0x12, addr, cmd] -> expects [0xFF, data] on success
|
||||
// COMPARE may also return [0xFD, data] when multiple devices reply together
|
||||
// Callers provide UART callbacks; this class only builds frames and parses basic responses.
|
||||
@@ -49,7 +49,7 @@ class DaliComm {
|
||||
|
||||
// Send standard command frame (0x10).
|
||||
bool sendCmd(uint8_t addr, uint8_t cmd) const;
|
||||
// Send extended command frame (0x11).
|
||||
// Send one logical extended command frame (0x11).
|
||||
bool sendExtCmd(uint8_t addr, uint8_t cmd) const;
|
||||
// Send query frame (0x12) and parse single-byte response. Returns nullopt on no/invalid response,
|
||||
// except COMPARE where 0xFD collisions are treated as a positive match.
|
||||
|
||||
+1
-1
@@ -73,6 +73,6 @@ class DaliDT5 {
|
||||
|
||||
bool enable();
|
||||
static int addrOf(int a);
|
||||
bool send(int a, int code, bool twice = false);
|
||||
bool send(int a, int code);
|
||||
std::optional<int> query(int a, int code);
|
||||
};
|
||||
+1
-1
@@ -124,7 +124,7 @@ class DaliDT6 {
|
||||
|
||||
bool enable();
|
||||
static int addrOf(int a);
|
||||
bool send(int a, int code, bool twice = false);
|
||||
bool send(int a, int code);
|
||||
std::optional<int> query(int a, int code);
|
||||
std::optional<bool> queryYesNo(int a, int code);
|
||||
};
|
||||
@@ -25,6 +25,20 @@ class ColorStatus {
|
||||
int status_ = 0;
|
||||
};
|
||||
|
||||
class ColorType {
|
||||
public:
|
||||
explicit ColorType(int type) : type_(type) {}
|
||||
|
||||
int raw() const { return type_; }
|
||||
bool xy() const { return (type_ & 0x10) != 0; }
|
||||
bool ct() const { return (type_ & 0x20) != 0; }
|
||||
bool primaryN() const { return (type_ & 0x40) != 0; }
|
||||
bool rgbWaf() const { return (type_ & 0x80) != 0; }
|
||||
|
||||
private:
|
||||
int type_ = 0;
|
||||
};
|
||||
|
||||
class ColorTypeFeature {
|
||||
public:
|
||||
explicit ColorTypeFeature(int features) : features_(features) {}
|
||||
@@ -41,6 +55,17 @@ class ColorTypeFeature {
|
||||
int features_ = 0;
|
||||
};
|
||||
|
||||
struct SceneColorReport {
|
||||
int brightness = 0;
|
||||
int colorTypeValue = 0;
|
||||
std::vector<double> xy;
|
||||
std::optional<int> colorTemperature;
|
||||
|
||||
ColorType colorType() const { return ColorType(colorTypeValue); }
|
||||
bool hasXy() const { return xy.size() == 2; }
|
||||
bool hasColorTemperature() const { return colorTemperature.has_value(); }
|
||||
};
|
||||
|
||||
class DaliDT8 {
|
||||
public:
|
||||
explicit DaliDT8(DaliBase& base);
|
||||
@@ -135,6 +160,7 @@ class DaliDT8 {
|
||||
std::optional<int> getPrimaryYRaw(int a, int n);
|
||||
std::optional<int> getPrimaryTy(int a, int n);
|
||||
|
||||
std::optional<SceneColorReport> getSceneColorReport(int a, int sense);
|
||||
std::vector<double> getSceneColor(int a, int sense);
|
||||
|
||||
// Store / config
|
||||
|
||||
+6
-4
@@ -266,19 +266,21 @@ std::optional<int> DaliBase::getGradualChangeSpeed(int a) {
|
||||
|
||||
bool DaliBase::setPowerOnLevel(int a, int value) { return setDTR(value) && storeDTRAsPoweredBright(a); }
|
||||
|
||||
std::optional<int> DaliBase::getPowerOnLevel(int a) { return query(a, DALI_CMD_QUERY_MAX_LEVEL); }
|
||||
std::optional<int> DaliBase::getPowerOnLevel(int a) { return query(a, DALI_CMD_QUERY_POWER_ON_LEVEL); }
|
||||
|
||||
bool DaliBase::setSystemFailureLevel(int a, int value) { return setDTR(value) && storeDTRAsSystemFailureLevel(a); }
|
||||
|
||||
std::optional<int> DaliBase::getSystemFailureLevel(int a) { return query(a, DALI_CMD_QUERY_MIN_LEVEL); }
|
||||
std::optional<int> DaliBase::getSystemFailureLevel(int a) {
|
||||
return query(a, DALI_CMD_QUERY_SYSTEM_FAILURE_LEVEL);
|
||||
}
|
||||
|
||||
bool DaliBase::setMinLevel(int a, int value) { return setDTR(value) && storeDTRAsMinLevel(a); }
|
||||
|
||||
std::optional<int> DaliBase::getMinLevel(int a) { return query(a, DALI_CMD_QUERY_POWER_ON_LEVEL); }
|
||||
std::optional<int> DaliBase::getMinLevel(int a) { return query(a, DALI_CMD_QUERY_MIN_LEVEL); }
|
||||
|
||||
bool DaliBase::setMaxLevel(int a, int value) { return setDTR(value) && storeDTRAsMaxLevel(a); }
|
||||
|
||||
std::optional<int> DaliBase::getMaxLevel(int a) { return query(a, DALI_CMD_QUERY_SYSTEM_FAILURE_LEVEL); }
|
||||
std::optional<int> DaliBase::getMaxLevel(int a) { return query(a, DALI_CMD_QUERY_MAX_LEVEL); }
|
||||
|
||||
bool DaliBase::setFadeTime(int a, int value) {
|
||||
int v = value;
|
||||
|
||||
@@ -201,6 +201,7 @@ bool DaliComm::sendCmd(uint8_t addr, uint8_t cmd) const {
|
||||
return writeFrame(frame);
|
||||
}
|
||||
|
||||
// Send extended command frame (0x11). Gateway will send twice for 0x11, but we only need to send once.
|
||||
bool DaliComm::sendExtCmd(uint8_t addr, uint8_t cmd) const {
|
||||
const std::vector<uint8_t> frame{0x11, addr, cmd};
|
||||
const bool ret = writeFrame(frame);
|
||||
|
||||
+3
-4
@@ -3,6 +3,7 @@
|
||||
#include "dali_define.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
|
||||
DaliDT4::DaliDT4(DaliBase& base) : base_(base) {}
|
||||
|
||||
@@ -24,14 +25,12 @@ std::optional<bool> DaliDT4::queryYesNo(int a, int code) {
|
||||
bool DaliDT4::enableDT4() { return enable(); }
|
||||
|
||||
bool DaliDT4::referenceSystemPower(int a) {
|
||||
return enable() && base_.sendExtCmd(addrOf(a), DALI_CMD_DT4_REFERENCE_SYSTEM_POWER) &&
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT4_REFERENCE_SYSTEM_POWER);
|
||||
return enable() && base_.sendExtCmd(addrOf(a), DALI_CMD_DT4_REFERENCE_SYSTEM_POWER);
|
||||
}
|
||||
|
||||
bool DaliDT4::selectDimmingCurve(int a, int curve) {
|
||||
const int value = std::clamp(curve, 0, 255);
|
||||
return enable() && base_.setDTR(value) &&
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT4_SELECT_DIMMING_CURVE) &&
|
||||
return base_.setDTR(value) && enable() &&
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT4_SELECT_DIMMING_CURVE);
|
||||
}
|
||||
|
||||
|
||||
+10
-12
@@ -3,6 +3,7 @@
|
||||
#include "dali_define.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
|
||||
DaliDT5::DaliDT5(DaliBase& base) : base_(base) {}
|
||||
|
||||
@@ -10,10 +11,9 @@ bool DaliDT5::enable() { return base_.dtSelect(5); }
|
||||
|
||||
int DaliDT5::addrOf(int a) { return a * 2 + 1; }
|
||||
|
||||
bool DaliDT5::send(int a, int code, bool twice) {
|
||||
bool DaliDT5::send(int a, int code) {
|
||||
if (!enable()) return false;
|
||||
if (!base_.sendExtCmd(addrOf(a), code)) return false;
|
||||
if (twice && !base_.sendExtCmd(addrOf(a), code)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -25,37 +25,35 @@ std::optional<int> DaliDT5::query(int a, int code) {
|
||||
bool DaliDT5::enableDT5() { return enable(); }
|
||||
|
||||
bool DaliDT5::setOutputRange1To10V(int a) {
|
||||
return send(a, DALI_CMD_DT5_SET_OUTPUT_RANGE_1_TO_10V, true);
|
||||
return send(a, DALI_CMD_DT5_SET_OUTPUT_RANGE_1_TO_10V);
|
||||
}
|
||||
|
||||
bool DaliDT5::setOutputRange0To10V(int a) {
|
||||
return send(a, DALI_CMD_DT5_SET_OUTPUT_RANGE_0_TO_10V, true);
|
||||
return send(a, DALI_CMD_DT5_SET_OUTPUT_RANGE_0_TO_10V);
|
||||
}
|
||||
|
||||
bool DaliDT5::switchOnInternalPullUp(int a) {
|
||||
return send(a, DALI_CMD_DT5_SWITCH_ON_INTERNAL_PULL_UP, true);
|
||||
return send(a, DALI_CMD_DT5_SWITCH_ON_INTERNAL_PULL_UP);
|
||||
}
|
||||
|
||||
bool DaliDT5::switchOffInternalPullUp(int a) {
|
||||
return send(a, DALI_CMD_DT5_SWITCH_OFF_INTERNAL_PULL_UP, true);
|
||||
return send(a, DALI_CMD_DT5_SWITCH_OFF_INTERNAL_PULL_UP);
|
||||
}
|
||||
|
||||
bool DaliDT5::storePhysicalMinimum(int a, int level) {
|
||||
const int value = std::clamp(level, 0, 254);
|
||||
return enable() && base_.setDTR(value) &&
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT5_STORE_DTR_AS_PHYSICAL_MINIMUM) &&
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT5_STORE_DTR_AS_PHYSICAL_MINIMUM);
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT5_STORE_DTR_AS_PHYSICAL_MINIMUM);
|
||||
}
|
||||
|
||||
bool DaliDT5::selectDimmingCurve(int a, int curve) {
|
||||
const int value = std::clamp(curve, 0, 255);
|
||||
return enable() && base_.setDTR(value) &&
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT5_SELECT_DIMMING_CURVE) &&
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT5_SELECT_DIMMING_CURVE);
|
||||
return base_.setDTR(value) && enable() &&
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT5_SELECT_DIMMING_CURVE);
|
||||
}
|
||||
|
||||
bool DaliDT5::resetConverterSettings(int a) {
|
||||
return send(a, DALI_CMD_DT5_RESET_CONVERTER_SETTINGS, true);
|
||||
return send(a, DALI_CMD_DT5_RESET_CONVERTER_SETTINGS);
|
||||
}
|
||||
|
||||
std::optional<int> DaliDT5::getDimmingCurve(int a) { return query(a, DALI_CMD_DT5_QUERY_DIMMING_CURVE); }
|
||||
|
||||
+7
-10
@@ -10,10 +10,9 @@ bool DaliDT6::enable() { return base_.dtSelect(6); }
|
||||
|
||||
int DaliDT6::addrOf(int a) { return a * 2 + 1; }
|
||||
|
||||
bool DaliDT6::send(int a, int code, bool twice) {
|
||||
bool DaliDT6::send(int a, int code) {
|
||||
if (!enable()) return false;
|
||||
if (!base_.sendExtCmd(addrOf(a), code)) return false;
|
||||
if (twice && !base_.sendExtCmd(addrOf(a), code)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -31,29 +30,27 @@ std::optional<bool> DaliDT6::queryYesNo(int a, int code) {
|
||||
bool DaliDT6::enableDT6() { return enable(); }
|
||||
|
||||
bool DaliDT6::referenceSystemPower(int a) {
|
||||
return send(a, DALI_CMD_DT6_REFERENCE_SYSTEM_POWER, true);
|
||||
return send(a, DALI_CMD_DT6_REFERENCE_SYSTEM_POWER);
|
||||
}
|
||||
|
||||
bool DaliDT6::enableCurrentProtector(int a) {
|
||||
return send(a, DALI_CMD_DT6_ENABLE_CURRENT_PROTECTOR, true);
|
||||
return send(a, DALI_CMD_DT6_ENABLE_CURRENT_PROTECTOR);
|
||||
}
|
||||
|
||||
bool DaliDT6::disableCurrentProtector(int a) {
|
||||
return send(a, DALI_CMD_DT6_DISABLE_CURRENT_PROTECTOR, true);
|
||||
return send(a, DALI_CMD_DT6_DISABLE_CURRENT_PROTECTOR);
|
||||
}
|
||||
|
||||
bool DaliDT6::selectDimmingCurve(int a, int curve) {
|
||||
const int value = std::clamp(curve, 0, 255);
|
||||
return enable() && base_.setDTR(value) &&
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT6_SELECT_DIMMING_CURVE) &&
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT6_SELECT_DIMMING_CURVE);
|
||||
return base_.setDTR(value) && enable() &&
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT6_SELECT_DIMMING_CURVE);
|
||||
}
|
||||
|
||||
bool DaliDT6::storeFastFadeTime(int a, int value) {
|
||||
const int clamped = std::clamp(value, 0, 27);
|
||||
return enable() && base_.setDTR(clamped) &&
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT6_STORE_DTR_AS_FAST_FADE_TIME) &&
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT6_STORE_DTR_AS_FAST_FADE_TIME);
|
||||
base_.sendExtCmd(addrOf(a), DALI_CMD_DT6_STORE_DTR_AS_FAST_FADE_TIME);
|
||||
}
|
||||
|
||||
std::optional<DaliDT6GearType> DaliDT6::getGearType(int a) {
|
||||
|
||||
+27
-4
@@ -381,11 +381,34 @@ std::optional<int> DaliDT8::getPrimaryTy(int a, int n) {
|
||||
return getColourRaw(a, 66 + 3 * n);
|
||||
}
|
||||
|
||||
std::optional<SceneColorReport> DaliDT8::getSceneColorReport(int a, int sense) {
|
||||
const auto brightness = base_.getScene(a, sense);
|
||||
if (!brightness.has_value() || brightness.value() == 255) return std::nullopt;
|
||||
|
||||
const int colorTypeValue = getReportColourType(a).value_or(0);
|
||||
const ColorType colorType(colorTypeValue);
|
||||
|
||||
SceneColorReport report;
|
||||
report.brightness = brightness.value();
|
||||
report.colorTypeValue = colorTypeValue;
|
||||
|
||||
if (colorType.xy()) {
|
||||
report.xy = getReportColour(a);
|
||||
return report;
|
||||
}
|
||||
|
||||
if (colorType.ct()) {
|
||||
report.colorTemperature = getReportColorTemperature(a);
|
||||
return report;
|
||||
}
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
std::vector<double> DaliDT8::getSceneColor(int a, int sense) {
|
||||
const auto bright = base_.getScene(a, sense);
|
||||
if (!bright.has_value() || bright.value() == 255) return {};
|
||||
base_.copyReportColourToTemp(a);
|
||||
return getColour(a);
|
||||
const auto report = getSceneColorReport(a, sense);
|
||||
if (!report.has_value() || !report->colorType().xy() || !report->hasXy()) return {};
|
||||
return report->xy;
|
||||
}
|
||||
|
||||
bool DaliDT8::storePrimaryTy(int a, int n, int ty) {
|
||||
|
||||
Reference in New Issue
Block a user