initial commit

This commit is contained in:
Tony
2026-03-26 12:04:08 +08:00
commit 7e8ac7f566
31 changed files with 4304 additions and 0 deletions

226
src/dt1.cpp Normal file
View File

@@ -0,0 +1,226 @@
#include "dt1.hpp"
#include "dali_define.hpp"
#include <algorithm>
#include <chrono>
#include <thread>
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<int> DaliDT1::query(int a, int code) {
if (!enable()) return std::nullopt;
const auto v = base_.queryCmd(static_cast<uint8_t>(addrOf(a)), static_cast<uint8_t>(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<int> DaliDT1::getDT1EmergencyMode(int a) { return query(a, DALI_CMD_DT1_QUERY_EMERGENCY_MODE); }
std::optional<int> DaliDT1::getDT1Feature(int a) { return query(a, DALI_CMD_DT1_QUERY_FEATURE); }
std::optional<int> DaliDT1::getDT1FailureStatus(int a) {
return query(a, DALI_CMD_DT1_QUERY_FAILURE_STATUS);
}
std::optional<int> DaliDT1::getDT1Status(int a) { return query(a, DALI_CMD_DT1_QUERY_STATUS); }
std::optional<int> 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<DT1TestStatusDetailed> 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<int>& dtr0,
const std::optional<int>& 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<int> DaliDT1::getExtendedVersionDT1(int a) {
return query(a, DALI_CMD_DT1_QUERY_EXTENDED_VERSION);
}
std::optional<int> DaliDT1::getEmergencyLevel(int a) { return query(a, DALI_CMD_DT1_QUERY_EMERGENCY_LEVEL); }
std::optional<int> DaliDT1::getEmergencyMinLevel(int a) {
return query(a, DALI_CMD_DT1_QUERY_EMERGENCY_MIN_LEVEL);
}
std::optional<int> DaliDT1::getEmergencyMaxLevel(int a) {
return query(a, DALI_CMD_DT1_QUERY_EMERGENCY_MAX_LEVEL);
}
std::optional<int> DaliDT1::getProlongTimeMinutes(int a) {
return query(a, DALI_CMD_DT1_QUERY_PROLONG_TIME);
}
std::optional<int> DaliDT1::getFunctionTestIntervalDays(int a) {
return query(a, DALI_CMD_DT1_QUERY_FUNCTION_TEST_INTERVAL);
}
std::optional<int> DaliDT1::getDurationTestIntervalWeeks(int a) {
return query(a, DALI_CMD_DT1_QUERY_DURATION_TEST_INTERVAL);
}
std::optional<int> DaliDT1::getDurationTestResult(int a) {
return query(a, DALI_CMD_DT1_QUERY_DURATION_TEST_RESULT);
}
std::optional<int> DaliDT1::getLampEmergencyTimeMinutes(int a) {
return query(a, DALI_CMD_DT1_QUERY_LAMP_EMERGENCY_TIME);
}
std::optional<int> DaliDT1::getRatedDurationMinutes(int a) {
return query(a, DALI_CMD_DT1_QUERY_RATED_DURATION);
}
std::optional<DaliDT1DeviceStatus> DaliDT1::getDeviceStatus(int a) {
if (!enable()) return std::nullopt;
const auto raw = base_.queryCmd(static_cast<uint8_t>(addrOf(a)), DALI_CMD_QUERY_STATUS);
if (!raw.has_value()) return std::nullopt;
return DaliDT1DeviceStatus(raw.value());
}
std::optional<DaliDT1EmergencyStatus> DaliDT1::getEmergencyStatusDecoded(int a) {
const auto v = getDT1Status(a);
if (!v.has_value()) return std::nullopt;
return DaliDT1EmergencyStatus(v.value());
}