Enhance DALI DT1 support: add new operations and extend DT1 status structure with additional fields

Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
Tony
2026-05-26 22:21:53 +08:00
parent faefde9467
commit 597952a75a
5 changed files with 481 additions and 8 deletions
+29
View File
@@ -88,6 +88,35 @@ enum class BridgeOperation {
resetAndAllocateShortAddresses = 48, resetAndAllocateShortAddresses = 48,
stopAddressAllocation = 49, stopAddressAllocation = 49,
batch = 50, batch = 50,
dt1Rest = 51,
dt1Inhibit = 52,
dt1RelightResetInhibit = 53,
dt1StartIdentification = 54,
dt1ResetFunctionTestDoneFlag = 55,
dt1ResetDurationTestDoneFlag = 56,
dt1ResetLampTime = 57,
dt1StoreEmergencyLevel = 58,
dt1StoreTestDelayTime = 59,
dt1StoreFunctionTestInterval = 60,
dt1StoreDurationTestInterval = 61,
dt1StoreTestExecutionTimeout = 62,
dt1StoreProlongTime = 63,
dt1PerformDtrSelectedFunction = 64,
dt1GetBatteryCharge = 65,
dt1GetFunctionTestDelayTime = 66,
dt1GetDurationTestDelayTime = 67,
dt1GetFunctionTestInterval = 68,
dt1GetDurationTestInterval = 69,
dt1GetTestExecutionTimeout = 70,
dt1GetProlongTime = 71,
dt1GetDurationTestResult = 72,
dt1GetLampEmergencyTime = 73,
dt1GetLampTotalOperationTime = 74,
dt1GetEmergencyMinLevel = 75,
dt1GetEmergencyMaxLevel = 76,
dt1GetRatedDuration = 77,
dt1GetExtendedVersion = 78,
dt1GetEmergencyDeviceType = 79,
}; };
enum class BridgeValueEncoding { enum class BridgeValueEncoding {
+31
View File
@@ -11,6 +11,23 @@ struct DT1TestStatusDetailed {
std::optional<int> emergencyMode; std::optional<int> emergencyMode;
std::optional<int> feature; std::optional<int> feature;
std::optional<int> deviceStatus; std::optional<int> deviceStatus;
std::optional<int> batteryChargeLevel;
std::optional<int> functionTestDelayTime;
std::optional<int> durationTestDelayTime;
std::optional<int> functionTestIntervalDays;
std::optional<int> durationTestIntervalWeeks;
std::optional<int> testExecutionTimeoutDays;
std::optional<int> prolongTimeHalfMinutes;
std::optional<int> durationTestResultMinutes;
std::optional<int> lampEmergencyTimeHours;
std::optional<int> lampTotalOperationTimeHours;
std::optional<int> emergencyLevel;
std::optional<int> emergencyMinLevel;
std::optional<int> emergencyMaxLevel;
std::optional<int> ratedDurationMinutes;
std::optional<int> extendedVersion;
std::optional<int> physicalMinLevel;
std::optional<int> emergencyDeviceTypeCode;
bool testInProgress = false; bool testInProgress = false;
bool lampFailure = false; bool lampFailure = false;
bool batteryFailure = false; bool batteryFailure = false;
@@ -41,6 +58,14 @@ struct DT1TestStatusDetailed {
bool supportsAdjustableEmergencyLevel = false; bool supportsAdjustableEmergencyLevel = false;
}; };
enum class DaliDT1EmergencyDeviceType {
unknown = 0,
typeA = 1,
typeB = 2,
typeC = 3,
typeD = 4,
};
class DaliDT1DeviceStatus { class DaliDT1DeviceStatus {
public: public:
explicit DaliDT1DeviceStatus(int raw) : raw_(raw & 0xFF) {} explicit DaliDT1DeviceStatus(int raw) : raw_(raw & 0xFF) {}
@@ -132,6 +157,9 @@ class DaliDT1Features {
bool hardwiredInhibitSupported() const { return bit(0x20); } bool hardwiredInhibitSupported() const { return bit(0x20); }
bool physicalSelectionSupported() const { return bit(0x40); } bool physicalSelectionSupported() const { return bit(0x40); }
bool relightInRestModeSupported() const { return bit(0x80); } bool relightInRestModeSupported() const { return bit(0x80); }
DaliDT1EmergencyDeviceType emergencyDeviceType(
const std::optional<int>& physicalMinLevel = std::nullopt) const;
int emergencyDeviceTypeCode(const std::optional<int>& physicalMinLevel = std::nullopt) const;
private: private:
int raw_ = 0; int raw_ = 0;
@@ -187,8 +215,10 @@ class DaliDT1 {
std::optional<int> getBatteryChargeLevel(int a); std::optional<int> getBatteryChargeLevel(int a);
std::optional<int> getTestTiming(int a, int selector); std::optional<int> getTestTiming(int a, int selector);
std::optional<int> getFunctionTestDelayTime(int a);
std::optional<int> getFunctionTestDelayHighByte(int a); std::optional<int> getFunctionTestDelayHighByte(int a);
std::optional<int> getFunctionTestDelayLowByte(int a); std::optional<int> getFunctionTestDelayLowByte(int a);
std::optional<int> getDurationTestDelayTime(int a);
std::optional<int> getDurationTestDelayHighByte(int a); std::optional<int> getDurationTestDelayHighByte(int a);
std::optional<int> getDurationTestDelayLowByte(int a); std::optional<int> getDurationTestDelayLowByte(int a);
std::optional<int> getEmergencyLevel(int a); std::optional<int> getEmergencyLevel(int a);
@@ -223,5 +253,6 @@ class DaliDT1 {
bool sendWithDTR(int a, int code, int value); bool sendWithDTR(int a, int code, int value);
std::optional<int> query(int a, int code); std::optional<int> query(int a, int code);
std::optional<int> queryTiming(int a, int selector); std::optional<int> queryTiming(int a, int selector);
std::optional<int> queryTimingWordFromHighSelector(int a, int selector);
}; };
+238 -5
View File
@@ -149,6 +149,21 @@ bool isReadOperation(BridgeOperation operation) {
case BridgeOperation::getSceneMap: case BridgeOperation::getSceneMap:
case BridgeOperation::getAddressSettings: case BridgeOperation::getAddressSettings:
case BridgeOperation::searchAddressRange: case BridgeOperation::searchAddressRange:
case BridgeOperation::dt1GetBatteryCharge:
case BridgeOperation::dt1GetFunctionTestDelayTime:
case BridgeOperation::dt1GetDurationTestDelayTime:
case BridgeOperation::dt1GetFunctionTestInterval:
case BridgeOperation::dt1GetDurationTestInterval:
case BridgeOperation::dt1GetTestExecutionTimeout:
case BridgeOperation::dt1GetProlongTime:
case BridgeOperation::dt1GetDurationTestResult:
case BridgeOperation::dt1GetLampEmergencyTime:
case BridgeOperation::dt1GetLampTotalOperationTime:
case BridgeOperation::dt1GetEmergencyMinLevel:
case BridgeOperation::dt1GetEmergencyMaxLevel:
case BridgeOperation::dt1GetRatedDuration:
case BridgeOperation::dt1GetExtendedVersion:
case BridgeOperation::dt1GetEmergencyDeviceType:
return true; return true;
default: default:
return false; return false;
@@ -197,6 +212,23 @@ void addDt1DetailedMetadata(DaliBridgeResult* result, const DT1TestStatusDetaile
putOptionalRaw(&result->metadata, "emergencyModeRaw", status.emergencyMode); putOptionalRaw(&result->metadata, "emergencyModeRaw", status.emergencyMode);
putOptionalRaw(&result->metadata, "featuresRaw", status.feature); putOptionalRaw(&result->metadata, "featuresRaw", status.feature);
putOptionalRaw(&result->metadata, "deviceStatusRaw", status.deviceStatus); putOptionalRaw(&result->metadata, "deviceStatusRaw", status.deviceStatus);
putOptionalInt(&result->metadata, "batteryChargeLevel", status.batteryChargeLevel);
putOptionalInt(&result->metadata, "functionTestDelayTime", status.functionTestDelayTime);
putOptionalInt(&result->metadata, "durationTestDelayTime", status.durationTestDelayTime);
putOptionalInt(&result->metadata, "functionTestIntervalDays", status.functionTestIntervalDays);
putOptionalInt(&result->metadata, "durationTestIntervalWeeks", status.durationTestIntervalWeeks);
putOptionalInt(&result->metadata, "testExecutionTimeoutDays", status.testExecutionTimeoutDays);
putOptionalInt(&result->metadata, "prolongTimeHalfMinutes", status.prolongTimeHalfMinutes);
putOptionalInt(&result->metadata, "durationTestResultMinutes", status.durationTestResultMinutes);
putOptionalInt(&result->metadata, "lampEmergencyTimeHours", status.lampEmergencyTimeHours);
putOptionalInt(&result->metadata, "lampTotalOperationTimeHours", status.lampTotalOperationTimeHours);
putOptionalInt(&result->metadata, "emergencyLevel", status.emergencyLevel);
putOptionalInt(&result->metadata, "emergencyMinLevel", status.emergencyMinLevel);
putOptionalInt(&result->metadata, "emergencyMaxLevel", status.emergencyMaxLevel);
putOptionalInt(&result->metadata, "ratedDurationMinutes", status.ratedDurationMinutes);
putOptionalInt(&result->metadata, "extendedVersion", status.extendedVersion);
putOptionalInt(&result->metadata, "physicalMinLevel", status.physicalMinLevel);
putOptionalInt(&result->metadata, "emergencyDeviceTypeCode", status.emergencyDeviceTypeCode);
result->metadata["testInProgress"] = status.testInProgress; result->metadata["testInProgress"] = status.testInProgress;
result->metadata["lampFailure"] = status.lampFailure; result->metadata["lampFailure"] = status.lampFailure;
result->metadata["batteryFailure"] = status.batteryFailure; result->metadata["batteryFailure"] = status.batteryFailure;
@@ -227,6 +259,75 @@ void addDt1DetailedMetadata(DaliBridgeResult* result, const DT1TestStatusDetaile
result->metadata["supportsAdjustableEmergencyLevel"] = status.supportsAdjustableEmergencyLevel; result->metadata["supportsAdjustableEmergencyLevel"] = status.supportsAdjustableEmergencyLevel;
} }
bool isDt1ValueReadOperation(BridgeOperation operation) {
switch (operation) {
case BridgeOperation::dt1GetBatteryCharge:
case BridgeOperation::dt1GetFunctionTestDelayTime:
case BridgeOperation::dt1GetDurationTestDelayTime:
case BridgeOperation::dt1GetFunctionTestInterval:
case BridgeOperation::dt1GetDurationTestInterval:
case BridgeOperation::dt1GetTestExecutionTimeout:
case BridgeOperation::dt1GetProlongTime:
case BridgeOperation::dt1GetDurationTestResult:
case BridgeOperation::dt1GetLampEmergencyTime:
case BridgeOperation::dt1GetLampTotalOperationTime:
case BridgeOperation::dt1GetEmergencyMinLevel:
case BridgeOperation::dt1GetEmergencyMaxLevel:
case BridgeOperation::dt1GetRatedDuration:
case BridgeOperation::dt1GetExtendedVersion:
case BridgeOperation::dt1GetEmergencyDeviceType:
return true;
default:
return false;
}
}
std::optional<int> readDt1Value(DaliDT1& dt1, DaliBase& base, BridgeOperation operation,
int address, DaliValue::Object* metadata) {
switch (operation) {
case BridgeOperation::dt1GetBatteryCharge:
return dt1.getBatteryChargeLevel(address);
case BridgeOperation::dt1GetFunctionTestDelayTime:
return dt1.getFunctionTestDelayTime(address);
case BridgeOperation::dt1GetDurationTestDelayTime:
return dt1.getDurationTestDelayTime(address);
case BridgeOperation::dt1GetFunctionTestInterval:
return dt1.getFunctionTestIntervalDays(address);
case BridgeOperation::dt1GetDurationTestInterval:
return dt1.getDurationTestIntervalWeeks(address);
case BridgeOperation::dt1GetTestExecutionTimeout:
return dt1.getTestExecutionTimeoutDays(address);
case BridgeOperation::dt1GetProlongTime:
return dt1.getProlongTimeHalfMinutes(address);
case BridgeOperation::dt1GetDurationTestResult:
return dt1.getDurationTestResult(address);
case BridgeOperation::dt1GetLampEmergencyTime:
return dt1.getLampEmergencyTimeHours(address);
case BridgeOperation::dt1GetLampTotalOperationTime:
return dt1.getLampTotalOperationTimeHours(address);
case BridgeOperation::dt1GetEmergencyMinLevel:
return dt1.getEmergencyMinLevel(address);
case BridgeOperation::dt1GetEmergencyMaxLevel:
return dt1.getEmergencyMaxLevel(address);
case BridgeOperation::dt1GetRatedDuration:
return dt1.getRatedDurationMinutes(address);
case BridgeOperation::dt1GetExtendedVersion:
return dt1.getExtendedVersionDT1(address);
case BridgeOperation::dt1GetEmergencyDeviceType: {
const auto features = dt1.getFeatureDecoded(address);
if (!features.has_value()) return std::nullopt;
const auto physicalMinLevel = base.getPhysicalMinLevel(address);
putRaw(metadata, "featuresRaw", features->raw());
putOptionalInt(metadata, "physicalMinLevel", physicalMinLevel);
const int code = features->emergencyDeviceTypeCode(physicalMinLevel);
(*metadata)["emergencyDeviceTypeCode"] = code;
return code;
}
default:
return std::nullopt;
}
}
void addDt4SnapshotMetadata(DaliBridgeResult* result, DaliDT4& dt4, int address) { void addDt4SnapshotMetadata(DaliBridgeResult* result, DaliDT4& dt4, int address) {
putOptionalInt(&result->metadata, "extendedVersion", dt4.getExtendedVersion(address)); putOptionalInt(&result->metadata, "extendedVersion", dt4.getExtendedVersion(address));
putOptionalInt(&result->metadata, "dimmingCurve", dt4.getDimmingCurve(address)); putOptionalInt(&result->metadata, "dimmingCurve", dt4.getDimmingCurve(address));
@@ -713,7 +814,22 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
case BridgeOperation::getGroupMask: case BridgeOperation::getGroupMask:
case BridgeOperation::getSceneLevel: case BridgeOperation::getSceneLevel:
case BridgeOperation::getSceneMap: case BridgeOperation::getSceneMap:
case BridgeOperation::getAddressSettings: { case BridgeOperation::getAddressSettings:
case BridgeOperation::dt1GetBatteryCharge:
case BridgeOperation::dt1GetFunctionTestDelayTime:
case BridgeOperation::dt1GetDurationTestDelayTime:
case BridgeOperation::dt1GetFunctionTestInterval:
case BridgeOperation::dt1GetDurationTestInterval:
case BridgeOperation::dt1GetTestExecutionTimeout:
case BridgeOperation::dt1GetProlongTime:
case BridgeOperation::dt1GetDurationTestResult:
case BridgeOperation::dt1GetLampEmergencyTime:
case BridgeOperation::dt1GetLampTotalOperationTime:
case BridgeOperation::dt1GetEmergencyMinLevel:
case BridgeOperation::dt1GetEmergencyMaxLevel:
case BridgeOperation::dt1GetRatedDuration:
case BridgeOperation::dt1GetExtendedVersion:
case BridgeOperation::dt1GetEmergencyDeviceType: {
const auto address = resolveTargetAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing target address"; result.error = "missing target address";
@@ -800,6 +916,14 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
result.ok = true; result.ok = true;
if (status->failureStatus.has_value()) result.data = status->failureStatus.value(); if (status->failureStatus.has_value()) result.data = status->failureStatus.value();
addDt1DetailedMetadata(&result, status.value()); addDt1DetailedMetadata(&result, status.value());
} else if (isDt1ValueReadOperation(operation)) {
const auto value = readDt1Value(dt1_, base_, operation, address.value(), &result.metadata);
if (!value.has_value()) {
result.error = "no response";
return result;
}
result.ok = true;
result.data = value.value();
} else if (operation == BridgeOperation::getDt4Snapshot) { } else if (operation == BridgeOperation::getDt4Snapshot) {
addDt4SnapshotMetadata(&result, dt4_, address.value()); addDt4SnapshotMetadata(&result, dt4_, address.value());
result.ok = !result.metadata.empty(); result.ok = !result.metadata.empty();
@@ -954,18 +1078,127 @@ DaliBridgeResult DaliBridgeEngine::executeResolved(const DaliBridgeRequest& requ
} }
case BridgeOperation::startEmergencyFunctionTest: case BridgeOperation::startEmergencyFunctionTest:
case BridgeOperation::startEmergencyDurationTest: case BridgeOperation::startEmergencyDurationTest:
case BridgeOperation::stopEmergencyTest: { case BridgeOperation::stopEmergencyTest:
case BridgeOperation::dt1Rest:
case BridgeOperation::dt1Inhibit:
case BridgeOperation::dt1RelightResetInhibit:
case BridgeOperation::dt1StartIdentification:
case BridgeOperation::dt1ResetFunctionTestDoneFlag:
case BridgeOperation::dt1ResetDurationTestDoneFlag:
case BridgeOperation::dt1ResetLampTime:
case BridgeOperation::dt1StoreEmergencyLevel:
case BridgeOperation::dt1StoreTestDelayTime:
case BridgeOperation::dt1StoreFunctionTestInterval:
case BridgeOperation::dt1StoreDurationTestInterval:
case BridgeOperation::dt1StoreTestExecutionTimeout:
case BridgeOperation::dt1StoreProlongTime:
case BridgeOperation::dt1PerformDtrSelectedFunction: {
const auto address = resolveTargetAddress(request, model); const auto address = resolveTargetAddress(request, model);
if (!address.has_value()) { if (!address.has_value()) {
result.error = "missing target address"; result.error = "missing target address";
return result; return result;
} }
if (operation == BridgeOperation::startEmergencyFunctionTest) { switch (operation) {
case BridgeOperation::startEmergencyFunctionTest:
result.ok = dt1_.startFunctionTestCmd(address.value()); result.ok = dt1_.startFunctionTestCmd(address.value());
} else if (operation == BridgeOperation::startEmergencyDurationTest) { break;
case BridgeOperation::startEmergencyDurationTest:
result.ok = dt1_.startDurationTestCmd(address.value()); result.ok = dt1_.startDurationTestCmd(address.value());
} else { break;
case BridgeOperation::stopEmergencyTest:
result.ok = dt1_.stopTest(address.value()); result.ok = dt1_.stopTest(address.value());
break;
case BridgeOperation::dt1Rest:
result.ok = dt1_.rest(address.value());
break;
case BridgeOperation::dt1Inhibit:
result.ok = dt1_.inhibit(address.value());
break;
case BridgeOperation::dt1RelightResetInhibit:
result.ok = dt1_.reLightOrResetInhibit(address.value());
break;
case BridgeOperation::dt1StartIdentification:
result.ok = dt1_.startIdentification(address.value());
break;
case BridgeOperation::dt1ResetFunctionTestDoneFlag:
result.ok = dt1_.resetFunctionTestDoneFlag(address.value());
break;
case BridgeOperation::dt1ResetDurationTestDoneFlag:
result.ok = dt1_.resetDurationTestDoneFlag(address.value());
break;
case BridgeOperation::dt1ResetLampTime:
result.ok = dt1_.resetLampTime(address.value());
break;
case BridgeOperation::dt1StoreEmergencyLevel: {
const auto value = intParam(request, {"emergencyLevel", "level", "value"});
if (!value.has_value()) {
result.error = "missing emergency level";
return result;
}
result.ok = dt1_.storeEmergencyLevel(address.value(), value.value());
result.data = value.value();
break;
}
case BridgeOperation::dt1StoreTestDelayTime: {
const auto value = intParam(request, {"delayTime", "quartersOfHour", "delay", "value"});
if (!value.has_value()) {
result.error = "missing test delay time";
return result;
}
result.ok = dt1_.storeTestDelayTime16(address.value(), value.value());
result.data = value.value();
break;
}
case BridgeOperation::dt1StoreFunctionTestInterval: {
const auto value = intParam(request, {"functionTestInterval", "days", "value"});
if (!value.has_value()) {
result.error = "missing function test interval";
return result;
}
result.ok = dt1_.storeFunctionTestIntervalDays(address.value(), value.value());
result.data = value.value();
break;
}
case BridgeOperation::dt1StoreDurationTestInterval: {
const auto value = intParam(request, {"durationTestInterval", "weeks", "value"});
if (!value.has_value()) {
result.error = "missing duration test interval";
return result;
}
result.ok = dt1_.storeDurationTestIntervalWeeks(address.value(), value.value());
result.data = value.value();
break;
}
case BridgeOperation::dt1StoreTestExecutionTimeout: {
const auto value = intParam(request, {"testExecutionTimeout", "timeoutDays", "days", "value"});
if (!value.has_value()) {
result.error = "missing test execution timeout";
return result;
}
result.ok = dt1_.storeTestExecutionTimeoutDays(address.value(), value.value());
result.data = value.value();
break;
}
case BridgeOperation::dt1StoreProlongTime: {
if (const auto minutes = intParam(request, {"minutes"})) {
result.ok = dt1_.storeProlongTimeMinutes(address.value(), minutes.value());
result.data = minutes.value();
} else if (const auto halfMinutes = intParam(request, {"halfMinutes", "half_minutes", "value"})) {
result.ok = dt1_.storeProlongTimeHalfMinutes(address.value(), halfMinutes.value());
result.data = halfMinutes.value();
} else {
result.error = "missing prolong time";
return result;
}
break;
}
case BridgeOperation::dt1PerformDtrSelectedFunction:
result.ok = dt1_.performDTRSelectedFunction(
address.value(), intParam(request, {"dtr0", "DTR0"}), intParam(request, {"dtr1", "DTR1"}));
break;
default:
result.error = "unsupported op";
return result;
} }
break; break;
} }
+128
View File
@@ -412,6 +412,64 @@ const char* bridgeOperationToString(BridgeOperation operation) {
return "stop_address_allocation"; return "stop_address_allocation";
case BridgeOperation::batch: case BridgeOperation::batch:
return "batch"; return "batch";
case BridgeOperation::dt1Rest:
return "dt1_rest";
case BridgeOperation::dt1Inhibit:
return "dt1_inhibit";
case BridgeOperation::dt1RelightResetInhibit:
return "dt1_relight_reset_inhibit";
case BridgeOperation::dt1StartIdentification:
return "dt1_start_identification";
case BridgeOperation::dt1ResetFunctionTestDoneFlag:
return "dt1_reset_function_test_done_flag";
case BridgeOperation::dt1ResetDurationTestDoneFlag:
return "dt1_reset_duration_test_done_flag";
case BridgeOperation::dt1ResetLampTime:
return "dt1_reset_lamp_time";
case BridgeOperation::dt1StoreEmergencyLevel:
return "dt1_store_emergency_level";
case BridgeOperation::dt1StoreTestDelayTime:
return "dt1_store_test_delay_time";
case BridgeOperation::dt1StoreFunctionTestInterval:
return "dt1_store_function_test_interval";
case BridgeOperation::dt1StoreDurationTestInterval:
return "dt1_store_duration_test_interval";
case BridgeOperation::dt1StoreTestExecutionTimeout:
return "dt1_store_test_execution_timeout";
case BridgeOperation::dt1StoreProlongTime:
return "dt1_store_prolong_time";
case BridgeOperation::dt1PerformDtrSelectedFunction:
return "dt1_perform_dtr_selected_function";
case BridgeOperation::dt1GetBatteryCharge:
return "dt1_get_battery_charge";
case BridgeOperation::dt1GetFunctionTestDelayTime:
return "dt1_get_function_test_delay_time";
case BridgeOperation::dt1GetDurationTestDelayTime:
return "dt1_get_duration_test_delay_time";
case BridgeOperation::dt1GetFunctionTestInterval:
return "dt1_get_function_test_interval";
case BridgeOperation::dt1GetDurationTestInterval:
return "dt1_get_duration_test_interval";
case BridgeOperation::dt1GetTestExecutionTimeout:
return "dt1_get_test_execution_timeout";
case BridgeOperation::dt1GetProlongTime:
return "dt1_get_prolong_time";
case BridgeOperation::dt1GetDurationTestResult:
return "dt1_get_duration_test_result";
case BridgeOperation::dt1GetLampEmergencyTime:
return "dt1_get_lamp_emergency_time";
case BridgeOperation::dt1GetLampTotalOperationTime:
return "dt1_get_lamp_total_operation_time";
case BridgeOperation::dt1GetEmergencyMinLevel:
return "dt1_get_emergency_min_level";
case BridgeOperation::dt1GetEmergencyMaxLevel:
return "dt1_get_emergency_max_level";
case BridgeOperation::dt1GetRatedDuration:
return "dt1_get_rated_duration";
case BridgeOperation::dt1GetExtendedVersion:
return "dt1_get_extended_version";
case BridgeOperation::dt1GetEmergencyDeviceType:
return "dt1_get_emergency_device_type";
case BridgeOperation::unknown: case BridgeOperation::unknown:
default: default:
return "unknown"; return "unknown";
@@ -483,6 +541,76 @@ BridgeOperation bridgeOperationFromString(const std::string& value) {
if (normalized == "get_scene_map" || normalized == "get_scenes") return BridgeOperation::getSceneMap; if (normalized == "get_scene_map" || normalized == "get_scenes") return BridgeOperation::getSceneMap;
if (normalized == "get_address_settings") return BridgeOperation::getAddressSettings; if (normalized == "get_address_settings") return BridgeOperation::getAddressSettings;
if (normalized == "set_address_settings") return BridgeOperation::setAddressSettings; if (normalized == "set_address_settings") return BridgeOperation::setAddressSettings;
if (normalized == "dt1_rest" || normalized == "rest") return BridgeOperation::dt1Rest;
if (normalized == "dt1_inhibit" || normalized == "inhibit") return BridgeOperation::dt1Inhibit;
if (normalized == "dt1_relight_reset_inhibit" || normalized == "dt1_re_light_reset_inhibit" ||
normalized == "dt1_reset_inhibit") {
return BridgeOperation::dt1RelightResetInhibit;
}
if (normalized == "dt1_start_identification" || normalized == "start_identification") {
return BridgeOperation::dt1StartIdentification;
}
if (normalized == "dt1_reset_function_test_done_flag") {
return BridgeOperation::dt1ResetFunctionTestDoneFlag;
}
if (normalized == "dt1_reset_duration_test_done_flag") {
return BridgeOperation::dt1ResetDurationTestDoneFlag;
}
if (normalized == "dt1_reset_lamp_time") return BridgeOperation::dt1ResetLampTime;
if (normalized == "dt1_store_emergency_level") return BridgeOperation::dt1StoreEmergencyLevel;
if (normalized == "dt1_store_test_delay_time" || normalized == "dt1_store_test_delay") {
return BridgeOperation::dt1StoreTestDelayTime;
}
if (normalized == "dt1_store_function_test_interval") {
return BridgeOperation::dt1StoreFunctionTestInterval;
}
if (normalized == "dt1_store_duration_test_interval") {
return BridgeOperation::dt1StoreDurationTestInterval;
}
if (normalized == "dt1_store_test_execution_timeout") {
return BridgeOperation::dt1StoreTestExecutionTimeout;
}
if (normalized == "dt1_store_prolong_time") return BridgeOperation::dt1StoreProlongTime;
if (normalized == "dt1_perform_dtr_selected_function") {
return BridgeOperation::dt1PerformDtrSelectedFunction;
}
if (normalized == "dt1_get_battery_charge") return BridgeOperation::dt1GetBatteryCharge;
if (normalized == "dt1_get_function_test_delay_time") {
return BridgeOperation::dt1GetFunctionTestDelayTime;
}
if (normalized == "dt1_get_duration_test_delay_time") {
return BridgeOperation::dt1GetDurationTestDelayTime;
}
if (normalized == "dt1_get_function_test_interval") {
return BridgeOperation::dt1GetFunctionTestInterval;
}
if (normalized == "dt1_get_duration_test_interval") {
return BridgeOperation::dt1GetDurationTestInterval;
}
if (normalized == "dt1_get_test_execution_timeout") {
return BridgeOperation::dt1GetTestExecutionTimeout;
}
if (normalized == "dt1_get_prolong_time") return BridgeOperation::dt1GetProlongTime;
if (normalized == "dt1_get_duration_test_result") {
return BridgeOperation::dt1GetDurationTestResult;
}
if (normalized == "dt1_get_lamp_emergency_time") {
return BridgeOperation::dt1GetLampEmergencyTime;
}
if (normalized == "dt1_get_lamp_total_operation_time") {
return BridgeOperation::dt1GetLampTotalOperationTime;
}
if (normalized == "dt1_get_emergency_min_level") {
return BridgeOperation::dt1GetEmergencyMinLevel;
}
if (normalized == "dt1_get_emergency_max_level") {
return BridgeOperation::dt1GetEmergencyMaxLevel;
}
if (normalized == "dt1_get_rated_duration") return BridgeOperation::dt1GetRatedDuration;
if (normalized == "dt1_get_extended_version") return BridgeOperation::dt1GetExtendedVersion;
if (normalized == "dt1_get_emergency_device_type" || normalized == "dt1_get_type") {
return BridgeOperation::dt1GetEmergencyDeviceType;
}
if (normalized == "search_address_range") return BridgeOperation::searchAddressRange; if (normalized == "search_address_range") return BridgeOperation::searchAddressRange;
if (normalized == "allocate_all_short_addresses" || normalized == "allocate_all_addr") { if (normalized == "allocate_all_short_addresses" || normalized == "allocate_all_addr") {
return BridgeOperation::allocateAllShortAddresses; return BridgeOperation::allocateAllShortAddresses;
+52
View File
@@ -6,6 +6,21 @@
#include <chrono> #include <chrono>
#include <thread> #include <thread>
DaliDT1EmergencyDeviceType DaliDT1Features::emergencyDeviceType(
const std::optional<int>& physicalMinLevel) const {
if (switchedMaintainedControlGear()) {
if (!physicalMinLevel.has_value()) return DaliDT1EmergencyDeviceType::unknown;
return physicalMinLevel.value() >= 254 ? DaliDT1EmergencyDeviceType::typeB
: DaliDT1EmergencyDeviceType::typeA;
}
if (maintainedControlGear()) return DaliDT1EmergencyDeviceType::typeC;
return DaliDT1EmergencyDeviceType::typeD;
}
int DaliDT1Features::emergencyDeviceTypeCode(const std::optional<int>& physicalMinLevel) const {
return static_cast<int>(emergencyDeviceType(physicalMinLevel));
}
DaliDT1::DaliDT1(DaliBase& base) : base_(base) {} DaliDT1::DaliDT1(DaliBase& base) : base_(base) {}
bool DaliDT1::enable() { return base_.dtSelect(1); } bool DaliDT1::enable() { return base_.dtSelect(1); }
@@ -31,6 +46,15 @@ std::optional<int> DaliDT1::queryTiming(int a, int selector) {
return query(a, DALI_CMD_DT1_QUERY_TEST_TIMING); return query(a, DALI_CMD_DT1_QUERY_TEST_TIMING);
} }
std::optional<int> DaliDT1::queryTimingWordFromHighSelector(int a, int selector) {
if (!base_.setDTR(selector & 0xFF)) return std::nullopt;
const auto high = query(a, DALI_CMD_DT1_QUERY_TEST_TIMING);
if (!high.has_value()) return std::nullopt;
const auto low = base_.getDTR1(a);
if (!low.has_value()) return std::nullopt;
return ((high.value() & 0xFF) << 8) | (low.value() & 0xFF);
}
bool DaliDT1::enableDT1() { return enable(); } bool DaliDT1::enableDT1() { return enable(); }
bool DaliDT1::startDT1Test(int a, int t) { bool DaliDT1::startDT1Test(int a, int t) {
@@ -63,6 +87,23 @@ std::optional<DT1TestStatusDetailed> DaliDT1::getDT1TestStatusDetailed(int a) {
const auto feature = getFeatureDecoded(a); const auto feature = getFeatureDecoded(a);
const auto deviceStatus = getDeviceStatus(a); const auto deviceStatus = getDeviceStatus(a);
result.batteryChargeLevel = getBatteryChargeLevel(a);
result.functionTestDelayTime = getFunctionTestDelayTime(a);
result.durationTestDelayTime = getDurationTestDelayTime(a);
result.functionTestIntervalDays = getFunctionTestIntervalDays(a);
result.durationTestIntervalWeeks = getDurationTestIntervalWeeks(a);
result.testExecutionTimeoutDays = getTestExecutionTimeoutDays(a);
result.prolongTimeHalfMinutes = getProlongTimeHalfMinutes(a);
result.durationTestResultMinutes = getDurationTestResult(a);
result.lampEmergencyTimeHours = getLampEmergencyTimeHours(a);
result.lampTotalOperationTimeHours = getLampTotalOperationTimeHours(a);
result.emergencyLevel = getEmergencyLevel(a);
result.emergencyMinLevel = getEmergencyMinLevel(a);
result.emergencyMaxLevel = getEmergencyMaxLevel(a);
result.ratedDurationMinutes = getRatedDurationMinutes(a);
result.extendedVersion = getExtendedVersionDT1(a);
result.physicalMinLevel = base_.getPhysicalMinLevel(a);
if (!failure.has_value()) return std::nullopt; if (!failure.has_value()) return std::nullopt;
result.failureStatus = failure->raw(); result.failureStatus = failure->raw();
@@ -118,6 +159,9 @@ std::optional<DT1TestStatusDetailed> DaliDT1::getDT1TestStatusDetailed(int a) {
result.supportsAutoTest = feature.has_value() && feature->autoTestCapability(); result.supportsAutoTest = feature.has_value() && feature->autoTestCapability();
result.supportsAdjustableEmergencyLevel = result.supportsAdjustableEmergencyLevel =
feature.has_value() && feature->adjustableEmergencyLevel(); feature.has_value() && feature->adjustableEmergencyLevel();
if (feature.has_value()) {
result.emergencyDeviceTypeCode = feature->emergencyDeviceTypeCode(result.physicalMinLevel);
}
return result; return result;
} }
@@ -237,10 +281,18 @@ std::optional<int> DaliDT1::getTestTiming(int a, int selector) {
return queryTiming(a, selector); return queryTiming(a, selector);
} }
std::optional<int> DaliDT1::getFunctionTestDelayTime(int a) {
return queryTimingWordFromHighSelector(a, 0x00);
}
std::optional<int> DaliDT1::getFunctionTestDelayHighByte(int a) { return queryTiming(a, 0x00); } std::optional<int> DaliDT1::getFunctionTestDelayHighByte(int a) { return queryTiming(a, 0x00); }
std::optional<int> DaliDT1::getFunctionTestDelayLowByte(int a) { return queryTiming(a, 0x01); } std::optional<int> DaliDT1::getFunctionTestDelayLowByte(int a) { return queryTiming(a, 0x01); }
std::optional<int> DaliDT1::getDurationTestDelayTime(int a) {
return queryTimingWordFromHighSelector(a, 0x02);
}
std::optional<int> DaliDT1::getDurationTestDelayHighByte(int a) { return queryTiming(a, 0x02); } std::optional<int> DaliDT1::getDurationTestDelayHighByte(int a) { return queryTiming(a, 0x02); }
std::optional<int> DaliDT1::getDurationTestDelayLowByte(int a) { return queryTiming(a, 0x03); } std::optional<int> DaliDT1::getDurationTestDelayLowByte(int a) { return queryTiming(a, 0x03); }