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:
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+241
-8
@@ -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) {
|
||||||
result.ok = dt1_.startFunctionTestCmd(address.value());
|
case BridgeOperation::startEmergencyFunctionTest:
|
||||||
} else if (operation == BridgeOperation::startEmergencyDurationTest) {
|
result.ok = dt1_.startFunctionTestCmd(address.value());
|
||||||
result.ok = dt1_.startDurationTestCmd(address.value());
|
break;
|
||||||
} else {
|
case BridgeOperation::startEmergencyDurationTest:
|
||||||
result.ok = dt1_.stopTest(address.value());
|
result.ok = dt1_.startDurationTestCmd(address.value());
|
||||||
|
break;
|
||||||
|
case BridgeOperation::stopEmergencyTest:
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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); }
|
||||||
|
|||||||
Reference in New Issue
Block a user