Commit bda47403 authored by luz's avatar luz

DALI: Added dSUID duplicate checker as last resort for sorting out bad devices...

DALI: Added dSUID duplicate checker as last resort for sorting out bad devices with non-unique-GTIN/SN. If any two bus devices get the same dSUID, revert both of them to dSUID derived from short address, not GTIN/SN.

Also fixed hardwareGUID(): will only return something when deviceInfo is considered valid (but not necessarily used for dSUID, in devinf_maybe/devinf_notForID cases)
parent 3cb26732
......@@ -1061,8 +1061,7 @@ private:
if (maxSame>=10 || (numFFs>=6 && maxSame>=3)) {
// this is tuned heuristics: >=6 FFs total plus >=3 consecutive equal non-zeros are considered suspect (because linealight.com/i-LÈD/eral LED-FGI332 has that)
LOG(LOG_ERR, "DALI shortaddress %d Bank 0 has %d consecutive bytes of 0x%02X and %d bytes of 0xFF - indicates invalid GTIN/Serial data -> ignoring\n", busAddress, maxSame, sameByte, numFFs);
deviceInfo->devInfStatus = DaliDeviceInfo::devinf_none; // no valid device info
return complete(ErrorPtr(new DaliCommError(DaliCommErrorBadDeviceInfo,string_format("bad repetitive DALI memory bank 0 contents at shortAddress %d", busAddress))));
deviceInfo->devInfStatus = DaliDeviceInfo::devinf_none; // consider invalid
}
// GTIN: bytes 0x03..0x08, MSB first
deviceInfo->gtin = 0;
......@@ -1241,6 +1240,11 @@ private:
void complete(ErrorPtr aError)
{
daliComm.endProcedure();
// clean device info in case it has been detected invalid by now
if (deviceInfo->devInfStatus==DaliDeviceInfo::devinf_none) {
deviceInfo->clear(); // clear everything except shortaddress
}
// report
callback(deviceInfo, aError);
// done, delete myself
delete this;
......@@ -1260,6 +1264,14 @@ void DaliComm::daliReadDeviceInfo(DaliDeviceInfoCB aResultCB, DaliAddress aAddre
DaliDeviceInfo::DaliDeviceInfo()
{
clear();
shortAddress = DaliBroadcast; // undefined short address
}
void DaliDeviceInfo::clear()
{
// clear everything except short address
gtin = 0;
fw_version_major = 0;
fw_version_minor = 0;
......
......@@ -91,7 +91,9 @@ namespace p44 {
} DaliDevInfStatus;
DaliDeviceInfo();
// short address
/// clear everything except short address
void clear();
/// short address
DaliAddress shortAddress;
// DALI device information
long long gtin; /// < 48 bit global trade identification number (GTIN / EAN)
......
......@@ -64,6 +64,13 @@ void DaliBusDevice::setDeviceInfo(DaliDeviceInfo aDeviceInfo)
}
void DaliBusDevice::clearDeviceInfo()
{
deviceInfo.clear();
deriveDsUid();
}
void DaliBusDevice::deriveDsUid()
{
if (isDummy) return;
......@@ -632,9 +639,10 @@ void DaliDimmerDevice::deriveDsUid()
string DaliDimmerDevice::hardwareGUID()
{
if (brightnessDimmer->deviceInfo.gtin==0)
if (brightnessDimmer->deviceInfo.devInfStatus==DaliDeviceInfo::devinf_none)
return ""; // none
// return as GS1 element strings
// Note: GTIN/Serial will be reported even if it could not be used for deriving dSUID (e.g. devinf_maybe/devinf_notForID cases)
return string_format("gs1:(01)%llu(21)%llu", brightnessDimmer->deviceInfo.gtin, brightnessDimmer->deviceInfo.serialNo);
}
......
......@@ -78,8 +78,12 @@ namespace p44 {
DaliBusDevice(DaliDeviceContainer &aDaliDeviceContainer);
/// use passed device info and derive dSUID from it
void setDeviceInfo(DaliDeviceInfo aDeviceInfo);
/// clear all device info except short address and revert to short address derived dSUID
void clearDeviceInfo();
/// derive the dSUID from collected device info
virtual void deriveDsUid();
......
......@@ -157,6 +157,21 @@ void DaliDeviceContainer::queryNextDev(DaliBusDeviceListPtr aBusDevices, DaliBus
while (aBusDevices->size()>0) {
// get first remaining
DaliBusDevicePtr busDevice = aBusDevices->front();
// duplicate dSUID check
bool anyDuplicates = false;
for (DaliBusDeviceList::iterator refpos = ++aBusDevices->begin(); refpos!=aBusDevices->end(); ++refpos) {
if (busDevice->dSUID==(*refpos)->dSUID) {
// duplicate dSUID, indicates DALI devices with invalid device info that slipped all heuristics
LOG(LOG_ERR,"Bus devices #%d and #%d have same dSUID -> assuming invalid device info, reverting both to short address based dSUID\n", busDevice->deviceInfo.shortAddress, (*refpos)->deviceInfo.shortAddress);
// - clear all device info except short address and revert to short address derived dSUID
(*refpos)->clearDeviceInfo();
anyDuplicates = true; // at least one found
}
}
if (anyDuplicates) {
// consider my own info invalid as well
busDevice->clearDeviceInfo();
}
// check if this device is part of a DALI group
sqlite3pp::query qry(db);
string sql = string_format("SELECT groupNo FROM compositeDevices WHERE dimmerUID = '%s' AND dimmerType='GRP'", busDevice->dSUID.getString().c_str());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment