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
+386
View File
@@ -0,0 +1,386 @@
#include "addr.hpp"
#include <algorithm>
#include <chrono>
#include <random>
#include <thread>
DaliAddr::DaliAddr(DaliBase& base) : base_(base) {}
bool DaliAddr::isAllocAddr() const { return base_.isAllocAddr; }
void DaliAddr::setIsAllocAddr(bool value) { base_.isAllocAddr = value; }
int DaliAddr::lastAllocAddr() const { return base_.lastAllocAddr; }
void DaliAddr::setLastAllocAddr(int value) { base_.lastAllocAddr = value; }
void DaliAddr::selectDevice(int address) { base_.selectedAddress = address; }
bool DaliAddr::writeAddr(int addr, int newAddr) {
const int nAddr = newAddr * 2 + 1;
return base_.setDTR(nAddr) && base_.storeDTRAsAddr(addr);
}
bool DaliAddr::removeAddr(int addr) { return base_.setDTR(0xFF) && base_.storeDTRAsAddr(addr); }
bool DaliAddr::removeAllAddr() { return removeAddr(base_.broadcast); }
std::vector<int> DaliAddr::searchAddr(int addr) {
isSearching = true;
onlineDevices.clear();
const int maxAddr = std::clamp(addr, 0, 63);
for (int i = 0; i < maxAddr; i++) {
if (!isSearching) break;
const auto status = base_.getOnlineStatus(i);
if (status.has_value() && status.value()) {
onlineDevices.push_back(i);
}
}
isSearching = false;
return onlineDevices;
}
std::vector<int> DaliAddr::searchAddrRange(int start, int end) {
int s = std::clamp(start, 0, 63);
int e = std::clamp(end, 0, 63);
if (s > e) return {};
isSearching = true;
onlineDevices.clear();
for (int i = s; i <= e; i++) {
if (!isSearching) break;
const auto status = base_.getOnlineStatus(i);
if (status.has_value() && status.value()) {
onlineDevices.push_back(i);
}
}
isSearching = false;
return onlineDevices;
}
void DaliAddr::stopSearch() { isSearching = false; }
bool DaliAddr::compareSingleAddress(int typ, int addr) {
bool ok = false;
if (typ == 1) {
ok = base_.queryAddressH(addr);
} else if (typ == 2) {
ok = base_.queryAddressM(addr);
} else if (typ == 3) {
ok = base_.queryAddressL(addr);
}
if (!ok) return false;
const auto matched = base_.compareAddress();
return matched.has_value() && matched.value();
}
std::pair<int, int> DaliAddr::precompareNew(int typ, int m) {
int min = m;
int max = 255;
while ((max - min) > 6) {
const int mid = static_cast<int>((max - min) / 2.0 + min);
const bool ok = compareSingleAddress(typ, mid);
if (ok) {
max = mid;
} else {
min = mid;
}
}
return {min, max};
}
int DaliAddr::compareAddress(int typ) {
int min = 0;
int max = 255;
int vAct = 0;
const auto mm = precompareNew(typ);
min = mm.first;
max = mm.second;
std::mt19937 rng(528643246);
for (int i = 0; i <= 100; i++) {
if (!base_.isAllocAddr) break;
if (min >= max) break;
std::uniform_int_distribution<int> dist(min, max);
const int v = dist(rng);
const bool res = compareSingleAddress(typ, v);
if (res) {
if (v == 0) {
vAct = v;
compareSingleAddress(typ, v);
break;
}
const bool res2 = compareSingleAddress(typ, v - 1);
if (res2) {
max = v - 1;
} else {
vAct = v - 1;
compareSingleAddress(typ, v - 1);
break;
}
} else if (v <= 254) {
const bool res3 = compareSingleAddress(typ, v + 1);
if (res3) {
vAct = v;
compareSingleAddress(typ, v);
break;
}
min = v + 1;
} else {
break;
}
}
return vAct;
}
int DaliAddr::compareAddressNew(int typ, int m) {
int minVal = m;
int maxVal = 255;
int vAct = 0;
const auto mm = precompareNew(typ, minVal);
minVal = mm.first;
maxVal = mm.second;
int v = maxVal;
for (int i = 0; i <= 10; i++) {
const bool ok = compareSingleAddress(typ, v);
if (ok) {
if (v == 0) {
vAct = v;
compareSingleAddress(typ, v);
break;
}
const bool ok2 = compareSingleAddress(typ, v - 1);
if (ok2) {
maxVal = v - 1;
} else {
vAct = v - 1;
compareSingleAddress(typ, v - 1);
break;
}
}
}
return vAct;
}
DaliCompareAddrResult DaliAddr::compareAddr(int ad, std::optional<int> /*minH*/,
std::optional<int> /*minM*/, std::optional<int> /*minL*/) {
DaliCompareAddrResult result;
result.nextAddr = ad;
if (ad > 63) {
result.nextAddr = 63;
return result;
}
base_.compare(128, 0, 0);
result.retH = compareAddress(1);
result.retM = compareAddress(2);
result.retL = compareAddress(3);
if (!base_.isAllocAddr) {
result.retH = 0;
result.retM = 0;
result.retL = 0;
return result;
}
if (result.retH == 0 && result.retM == 0 && result.retL == 0) {
return result;
}
const auto res = base_.compare(result.retH, result.retM, result.retL + 1);
if (!res.has_value() || !res.value()) {
base_.isAllocAddr = false;
result.retH = 0;
result.retM = 0;
result.retL = 0;
return result;
}
while (true) {
const auto status = base_.getOnlineStatus(ad);
if (!status.has_value() || !status.value()) break;
ad++;
if (ad > 63) break;
}
if (!base_.programShortAddr(ad)) return result;
const auto qsa = base_.queryShortAddr();
if (qsa.has_value() && qsa.value() == ad) {
base_.withdraw();
base_.setBright(ad, 254);
}
result.nextAddr = ad;
return result;
}
int DaliAddr::compareMulti(int h, int m, int l, int ad) {
int addr = ad + 1;
int retL = l;
for (int i = 0; i < 12; i++) {
if (!base_.isAllocAddr) return addr - 1;
retL++;
if (retL > 255) break;
const auto ok = base_.compare(h, m, retL);
if (!ok.has_value() || !ok.value()) {
addr--;
break;
}
while (true) {
const auto status = base_.getOnlineStatus(addr);
if (!status.has_value() || !status.value()) break;
addr++;
}
if (!base_.programShortAddr(addr)) continue;
const auto qsa = base_.queryShortAddr();
if (qsa.has_value() && qsa.value() == addr) {
base_.withdraw();
base_.setBright(addr, 254);
addr++;
}
}
return addr;
}
bool DaliAddr::allocateAllAddr(int ads) {
int ad = ads;
base_.isAllocAddr = true;
base_.lastAllocAddr = 255;
for (int i = 0; i <= 80; i++) {
if (!base_.isAllocAddr) break;
bool anyDevice = false;
const auto dev1 = base_.compare(255, 255, 255);
if (dev1.has_value() && dev1.value()) {
anyDevice = true;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
} else {
const auto dev2 = base_.compare(255, 255, 255);
if (dev2.has_value() && dev2.value()) {
anyDevice = true;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
} else {
const auto dev3 = base_.compare(255, 255, 255);
if (dev3.has_value() && dev3.value()) {
anyDevice = true;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
}
if (!anyDevice) {
break;
}
const auto retVals = compareAddr(ad, std::nullopt, std::nullopt, std::nullopt);
ad = retVals.nextAddr;
if (!base_.isAllocAddr) break;
if (!(retVals.retH == 0 && retVals.retM == 0 && retVals.retL == 0)) {
i = 0;
}
ad = compareMulti(retVals.retH, retVals.retM, retVals.retL + 1, ad);
base_.lastAllocAddr = ad;
ad++;
if (ad > 63) {
base_.isAllocAddr = false;
break;
}
if (i == 80) {
base_.isAllocAddr = false;
break;
}
}
base_.isAllocAddr = false;
if (ad <= 0) {
base_.lastAllocAddr = 255;
} else {
base_.lastAllocAddr = ad - 1;
}
return true;
}
void DaliAddr::stopAllocAddr() { base_.isAllocAddr = false; }
bool DaliAddr::removeFromScene(int addr, int scene) {
const int value = scene + 80;
return base_.send(addr, static_cast<uint8_t>(value));
}
std::optional<int> DaliAddr::getSceneBright(int addr, int scene) {
const int value = scene + 176;
return base_.query(addr, static_cast<uint8_t>(value));
}
bool DaliAddr::resetAndAllocAddr(int n, bool removeAddrFirst, bool closeLight) {
const int startTime = static_cast<int>(base_.mcuTicks());
base_.isAllocAddr = true;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (closeLight) {
base_.off(base_.broadcast);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
if (!base_.terminate()) {
base_.isAllocAddr = false;
return false;
}
std::this_thread::sleep_for(std::chrono::milliseconds(200));
if (removeAddrFirst) {
if (!base_.initialiseAll()) {
base_.isAllocAddr = false;
return false;
}
std::this_thread::sleep_for(std::chrono::milliseconds(200));
if (!removeAllAddr()) {
base_.isAllocAddr = false;
return false;
}
} else {
if (!base_.initialise()) {
base_.isAllocAddr = false;
return false;
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(500));
if (!base_.randomise()) {
base_.isAllocAddr = false;
return false;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (!base_.randomise()) {
base_.isAllocAddr = false;
return false;
}
std::this_thread::sleep_for(std::chrono::milliseconds(300));
const bool ok = allocateAllAddr(n);
(void)startTime;
return ok;
}