Enhance DALI device type discovery and query handling
- Introduce DaliDeviceTypeDiscovery struct for managing device type queries. - Implement discoverDeviceTypes method in DaliBase for improved device type detection. - Update DaliComm to handle query responses more robustly, including handling multiple device replies. - Add setDetectedDeviceTypes method in DaliDevice to manage detected device types and capabilities.
This commit is contained in:
@@ -4,6 +4,19 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int kDeviceTypeNone = 0xFE;
|
||||
constexpr int kDeviceTypeMultiple = 0xFF;
|
||||
constexpr uint8_t kQueryExtendedVersion = 0xFF;
|
||||
|
||||
const std::vector<int>& defaultDeviceTypeFallbackProbeOrder() {
|
||||
static const std::vector<int> types = {1, 4, 5, 6, 8};
|
||||
return types;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
DaliStatus DaliStatus::fromByte(uint8_t status) {
|
||||
DaliStatus s;
|
||||
s.controlGearPresent = (status & 0x01) != 0;
|
||||
@@ -17,6 +30,16 @@ DaliStatus DaliStatus::fromByte(uint8_t status) {
|
||||
return s;
|
||||
}
|
||||
|
||||
std::optional<int> DaliDeviceTypeDiscovery::primaryType() const {
|
||||
if (types.empty()) return std::nullopt;
|
||||
return types.front();
|
||||
}
|
||||
|
||||
std::vector<int> DaliDeviceTypeDiscovery::extraTypes() const {
|
||||
if (types.size() <= 1) return {};
|
||||
return std::vector<int>(types.begin() + 1, types.end());
|
||||
}
|
||||
|
||||
DaliBase::DaliBase(DaliComm& comm) : comm_(comm) {}
|
||||
|
||||
int64_t DaliBase::mcuTicks() const {
|
||||
@@ -154,6 +177,40 @@ std::optional<int> DaliBase::getBright(int a) {
|
||||
|
||||
std::optional<int> DaliBase::getDeviceType(int a) { return queryCmd(encodeCmdAddr(a), DALI_CMD_QUERY_DEVICE_TYPE); }
|
||||
|
||||
std::optional<DaliDeviceTypeDiscovery> DaliBase::discoverDeviceTypes(
|
||||
int a, const std::vector<int>& fallbackTypes, int maxNextTypes) {
|
||||
const auto rawQueryType = getDeviceType(a);
|
||||
if (!rawQueryType.has_value()) return std::nullopt;
|
||||
|
||||
DaliDeviceTypeDiscovery discovery;
|
||||
discovery.rawQueryType = rawQueryType;
|
||||
|
||||
const auto addType = [&discovery](int value) {
|
||||
if (!isRealDeviceTypeValue(value)) return;
|
||||
if (std::find(discovery.types.begin(), discovery.types.end(), value) == discovery.types.end()) {
|
||||
discovery.types.push_back(value);
|
||||
}
|
||||
};
|
||||
|
||||
addType(rawQueryType.value());
|
||||
|
||||
if (rawQueryType.value() == kDeviceTypeMultiple) {
|
||||
const auto enumerated = discoverNextDeviceTypes(a, maxNextTypes);
|
||||
for (const int type : enumerated) {
|
||||
addType(type);
|
||||
}
|
||||
if (discovery.types.empty()) {
|
||||
const auto& probeTypes = fallbackTypes.empty() ? defaultDeviceTypeFallbackProbeOrder() : fallbackTypes;
|
||||
const auto probed = probeSupportedDeviceTypes(a, probeTypes);
|
||||
for (const int type : probed) {
|
||||
addType(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return discovery;
|
||||
}
|
||||
|
||||
std::optional<int> DaliBase::getPhysicalMinLevel(int a) {
|
||||
return queryCmd(encodeCmdAddr(a), DALI_CMD_QUERY_PHYSICAL_MINIMUM_LEVEL);
|
||||
}
|
||||
@@ -245,6 +302,45 @@ std::optional<int> DaliBase::getFadeRate(int a) {
|
||||
|
||||
std::optional<int> DaliBase::getNextDeviceType(int a) { return query(a, DALI_CMD_QUERY_NEXT_DEVICE_TYPE); }
|
||||
|
||||
std::vector<int> DaliBase::discoverNextDeviceTypes(int a, int maxNextTypes) {
|
||||
std::vector<int> types;
|
||||
types.reserve(std::max(maxNextTypes, 0));
|
||||
|
||||
for (int i = 0; i < maxNextTypes; i++) {
|
||||
const auto next = getNextDeviceType(a);
|
||||
if (!next.has_value() || !isRealDeviceTypeValue(next.value())) {
|
||||
break;
|
||||
}
|
||||
if (std::find(types.begin(), types.end(), next.value()) != types.end()) {
|
||||
break;
|
||||
}
|
||||
types.push_back(next.value());
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
std::vector<int> DaliBase::probeSupportedDeviceTypes(int a, const std::vector<int>& fallbackTypes) {
|
||||
std::vector<int> types;
|
||||
|
||||
for (const int type : fallbackTypes) {
|
||||
if (!isRealDeviceTypeValue(type)) continue;
|
||||
if (std::find(types.begin(), types.end(), type) != types.end()) continue;
|
||||
if (queryExtendedVersionForDeviceType(a, type).has_value()) {
|
||||
types.push_back(type);
|
||||
}
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
std::optional<int> DaliBase::queryExtendedVersionForDeviceType(int a, int deviceType) {
|
||||
if (!dtSelect(deviceType)) return std::nullopt;
|
||||
return queryCmd(encodeCmdAddr(a), kQueryExtendedVersion);
|
||||
}
|
||||
|
||||
bool DaliBase::isRealDeviceTypeValue(int value) { return value >= 0 && value < kDeviceTypeNone; }
|
||||
|
||||
std::optional<int> DaliBase::getGroupH(int a) { return query(a, DALI_CMD_QUERY_GROUP_8_15); }
|
||||
|
||||
std::optional<int> DaliBase::getGroupL(int a) { return query(a, DALI_CMD_QUERY_GROUPS_0_7); }
|
||||
|
||||
Reference in New Issue
Block a user