#include "dt1.hpp" #include "dali_define.hpp" #include #include #include DaliDT1::DaliDT1(DaliBase& base) : base_(base) {} bool DaliDT1::enable() { return base_.dtSelect(1); } int DaliDT1::addrOf(int a) { return a * 2 + 1; } bool DaliDT1::send(int a, int code) { return enable() && base_.sendExtCmd(addrOf(a), code); } std::optional DaliDT1::query(int a, int code) { if (!enable()) return std::nullopt; const auto v = base_.queryCmd(static_cast(addrOf(a)), static_cast(code)); if (!v.has_value() || v.value() == 0xFF) return std::nullopt; return v; } bool DaliDT1::enableDT1() { return enable(); } bool DaliDT1::startDT1Test(int a, int t) { if (t != 1) return false; return send(a, DALI_CMD_DT1_START_FUNCTION_TEST); } std::optional DaliDT1::getDT1EmergencyMode(int a) { return query(a, DALI_CMD_DT1_QUERY_EMERGENCY_MODE); } std::optional DaliDT1::getDT1Feature(int a) { return query(a, DALI_CMD_DT1_QUERY_FEATURE); } std::optional DaliDT1::getDT1FailureStatus(int a) { return query(a, DALI_CMD_DT1_QUERY_FAILURE_STATUS); } std::optional DaliDT1::getDT1Status(int a) { return query(a, DALI_CMD_DT1_QUERY_STATUS); } std::optional DaliDT1::getDT1SelfTestStatus(int a) { const auto ret = getDT1FailureStatus(a); if (!ret.has_value()) return std::nullopt; const bool inProgress = (ret.value() & 0x01) != 0; return inProgress ? 1 : 0; } std::optional DaliDT1::getDT1TestStatusDetailed(int a) { DT1TestStatusDetailed result; result.failureStatus = getDT1FailureStatus(a); result.emergencyStatus = getDT1Status(a); result.emergencyMode = getDT1EmergencyMode(a); result.feature = getDT1Feature(a); if (!result.failureStatus.has_value()) return std::nullopt; const int failure = result.failureStatus.value(); result.testInProgress = (failure & 0x01) != 0; result.lampFailure = (failure & 0x02) != 0; result.batteryFailure = (failure & 0x04) != 0; result.functionTestActive = (failure & 0x08) != 0; result.durationTestActive = (failure & 0x10) != 0; result.testDone = (failure & 0x20) != 0; result.identifyActive = (failure & 0x40) != 0; result.physicalSelectionActive = (failure & 0x80) != 0; return result; } bool DaliDT1::performDT1Test(int a, int timeout) { if (!startDT1Test(a)) return false; for (int i = 0; i < timeout; i++) { const auto ret = getDT1SelfTestStatus(a); if (!ret.has_value()) return false; if (ret.value() == 0) return true; if (ret.value() != 1) return false; std::this_thread::sleep_for(std::chrono::seconds(1)); } return false; } bool DaliDT1::rest(int a) { return send(a, DALI_CMD_DT1_REST); } bool DaliDT1::inhibit(int a) { return send(a, DALI_CMD_DT1_INHIBIT); } bool DaliDT1::reLightOrResetInhibit(int a) { return send(a, DALI_CMD_DT1_RE_LIGHT_RESET_INHIBIT); } bool DaliDT1::startFunctionTestCmd(int a) { return send(a, DALI_CMD_DT1_START_FUNCTION_TEST); } bool DaliDT1::startDurationTestCmd(int a) { return send(a, DALI_CMD_DT1_START_DURATION_TEST); } bool DaliDT1::stopTest(int a) { return send(a, DALI_CMD_DT1_STOP_TEST); } bool DaliDT1::resetFunctionTestDoneFlag(int a) { return send(a, DALI_CMD_DT1_RESET_FUNCTION_TEST_DONE_FLAG); } bool DaliDT1::resetDurationTestDoneFlag(int a) { return send(a, DALI_CMD_DT1_RESET_DURATION_TEST_DONE_FLAG); } bool DaliDT1::resetLampTime(int a) { return send(a, DALI_CMD_DT1_RESET_LAMP_TIME); } bool DaliDT1::resetStatusFlags(int a) { return resetFunctionTestDoneFlag(a); } bool DaliDT1::resetLampOperationTime(int a) { return resetDurationTestDoneFlag(a); } bool DaliDT1::resetTestResults(int a) { return resetLampTime(a); } bool DaliDT1::storeEmergencyLevel(int a, int level) { const int v = std::clamp(level, 0, 254); return enable() && base_.setDTR(v) && base_.sendExtCmd(addrOf(a), DALI_CMD_DT1_STORE_DTR_AS_EMERGENCY_LEVEL); } bool DaliDT1::storeTestDelayTimeHighByte(int a, int highByte) { const int v = std::clamp(highByte, 0, 255); return enable() && base_.setDTR(v) && base_.sendExtCmd(addrOf(a), DALI_CMD_DT1_STORE_DTR_AS_DELAY_TIME_HIGH); } bool DaliDT1::storeTestDelayTimeLowByte(int a, int lowByte) { const int v = std::clamp(lowByte, 0, 255); return enable() && base_.setDTR(v) && base_.sendExtCmd(addrOf(a), DALI_CMD_DT1_STORE_DTR_AS_DELAY_TIME_LOW); } bool DaliDT1::storeFunctionTestIntervalDays(int a, int days) { return storeTestDelayTimeHighByte(a, days); } bool DaliDT1::storeDurationTestIntervalWeeks(int a, int weeks) { return storeTestDelayTimeLowByte(a, weeks); } bool DaliDT1::storeTestDelayTime16(int a, int quartersOfHour) { const int v = std::clamp(quartersOfHour, 0, 0xFFFF); const int hi = (v >> 8) & 0xFF; const int lo = v & 0xFF; return storeTestDelayTimeHighByte(a, hi) && storeTestDelayTimeLowByte(a, lo); } bool DaliDT1::storeProlongTimeMinutes(int a, int minutes) { const int v = std::clamp(minutes, 0, 255); return enable() && base_.setDTR(v) && base_.sendExtCmd(addrOf(a), DALI_CMD_DT1_STORE_DTR_AS_PROLONG_TIME); } bool DaliDT1::storeRatedDurationMinutes(int a, int minutes) { const int v = std::clamp(minutes, 0, 255); return enable() && base_.setDTR(v) && base_.sendExtCmd(addrOf(a), DALI_CMD_DT1_STORE_DTR_AS_RATED_DURATION); } bool DaliDT1::storeEmergencyMinLevel(int a, int level) { const int v = std::clamp(level, 0, 254); return enable() && base_.setDTR(v) && base_.sendExtCmd(addrOf(a), DALI_CMD_DT1_STORE_DTR_AS_EMERGENCY_MIN_LEVEL); } bool DaliDT1::storeEmergencyMaxLevel(int a, int level) { const int v = std::clamp(level, 0, 254); return enable() && base_.setDTR(v) && base_.sendExtCmd(addrOf(a), DALI_CMD_DT1_STORE_DTR_AS_EMERGENCY_MAX_LEVEL); } bool DaliDT1::startIdentification(int a) { return send(a, DALI_CMD_DT1_START_IDENTIFICATION); } bool DaliDT1::performDTRSelectedFunction(int a, const std::optional& dtr0, const std::optional& dtr1) { if (!enable()) return false; if (dtr0.has_value() && !base_.setDTR(dtr0.value() & 0xFF)) return false; if (dtr1.has_value() && !base_.setDTR1(dtr1.value() & 0xFF)) return false; return base_.sendExtCmd(addrOf(a), DALI_CMD_DT1_PERFORM_DTR_SELECTED_FUNCTION); } std::optional DaliDT1::getExtendedVersionDT1(int a) { return query(a, DALI_CMD_DT1_QUERY_EXTENDED_VERSION); } std::optional DaliDT1::getEmergencyLevel(int a) { return query(a, DALI_CMD_DT1_QUERY_EMERGENCY_LEVEL); } std::optional DaliDT1::getEmergencyMinLevel(int a) { return query(a, DALI_CMD_DT1_QUERY_EMERGENCY_MIN_LEVEL); } std::optional DaliDT1::getEmergencyMaxLevel(int a) { return query(a, DALI_CMD_DT1_QUERY_EMERGENCY_MAX_LEVEL); } std::optional DaliDT1::getProlongTimeMinutes(int a) { return query(a, DALI_CMD_DT1_QUERY_PROLONG_TIME); } std::optional DaliDT1::getFunctionTestIntervalDays(int a) { return query(a, DALI_CMD_DT1_QUERY_FUNCTION_TEST_INTERVAL); } std::optional DaliDT1::getDurationTestIntervalWeeks(int a) { return query(a, DALI_CMD_DT1_QUERY_DURATION_TEST_INTERVAL); } std::optional DaliDT1::getDurationTestResult(int a) { return query(a, DALI_CMD_DT1_QUERY_DURATION_TEST_RESULT); } std::optional DaliDT1::getLampEmergencyTimeMinutes(int a) { return query(a, DALI_CMD_DT1_QUERY_LAMP_EMERGENCY_TIME); } std::optional DaliDT1::getRatedDurationMinutes(int a) { return query(a, DALI_CMD_DT1_QUERY_RATED_DURATION); } std::optional DaliDT1::getDeviceStatus(int a) { if (!enable()) return std::nullopt; const auto raw = base_.queryCmd(static_cast(addrOf(a)), DALI_CMD_QUERY_STATUS); if (!raw.has_value()) return std::nullopt; return DaliDT1DeviceStatus(raw.value()); } std::optional DaliDT1::getEmergencyStatusDecoded(int a) { const auto v = getDT1Status(a); if (!v.has_value()) return std::nullopt; return DaliDT1EmergencyStatus(v.value()); }