delay scanning when using broadcast, moved loading scan files to bushandler, reworked update check, add max symbol rate to info result, keep scan results for each message separate, also do a decent scan on individual address and delay scan subsequent scan messages if necessary
This commit is contained in:
+218
-114
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "ebusd/bushandler.h"
|
||||
#include <iomanip>
|
||||
#include "ebusd/main.h"
|
||||
#include "lib/utils/log.h"
|
||||
|
||||
namespace ebusd {
|
||||
@@ -102,16 +103,12 @@ result_t ScanRequest::prepare(symbol_t ownMasterAddress) {
|
||||
return RESULT_ERR_EOF;
|
||||
}
|
||||
symbol_t dstAddress = m_slaves.front();
|
||||
if (m_index == 0 && m_messages.size() == m_allMessages.size()) { // first message for this address
|
||||
m_busHandler->setScanResult(dstAddress, "");
|
||||
}
|
||||
istringstream input;
|
||||
result_t result = m_message->prepareMaster(ownMasterAddress, m_master, input, UI_FIELD_SEPARATOR, dstAddress,
|
||||
m_index);
|
||||
if (result >= RESULT_OK) {
|
||||
m_result = m_message->prepareMaster(ownMasterAddress, m_master, input, UI_FIELD_SEPARATOR, dstAddress, m_index);
|
||||
if (m_result >= RESULT_OK) {
|
||||
logInfo(lf_bus, "scan %2.2x cmd: %s", dstAddress, m_master.getStr().c_str());
|
||||
}
|
||||
return result;
|
||||
return m_result;
|
||||
}
|
||||
|
||||
bool ScanRequest::notify(result_t result, SlaveSymbolString& slave) {
|
||||
@@ -137,43 +134,52 @@ bool ScanRequest::notify(result_t result, SlaveSymbolString& slave) {
|
||||
}
|
||||
}
|
||||
if (result == RESULT_OK) {
|
||||
result = m_message->decodeLastData(m_scanResult, 0, true); // decode data
|
||||
ostringstream output;
|
||||
result = m_message->decodeLastData(output, 0, true); // decode data
|
||||
string str = output.str();
|
||||
m_busHandler->setScanResult(dstAddress, m_notifyIndex+m_index, str);
|
||||
}
|
||||
}
|
||||
if (result < RESULT_OK) {
|
||||
if (!m_slaves.empty()) {
|
||||
m_slaves.pop_front();
|
||||
}
|
||||
if (result == RESULT_ERR_TIMEOUT) {
|
||||
logNotice(lf_bus, "scan %2.2x timed out (%d slaves left)", dstAddress, m_slaves.size());
|
||||
} else {
|
||||
logError(lf_bus, "scan %2.2x failed (%d slaves left): %s", dstAddress, m_slaves.size(), getResultCode(result));
|
||||
if (m_deleteOnFinish) {
|
||||
if (result == RESULT_ERR_TIMEOUT) {
|
||||
logNotice(lf_bus, "scan %2.2x timed out (%d slaves left)", dstAddress, m_slaves.size());
|
||||
} else {
|
||||
logError(lf_bus, "scan %2.2x failed (%d slaves left): %s", dstAddress, m_slaves.size(), getResultCode(result));
|
||||
}
|
||||
}
|
||||
m_messages.clear(); // skip remaining secondary messages
|
||||
} else if (m_messages.empty()) {
|
||||
if (!m_slaves.empty()) {
|
||||
m_slaves.pop_front();
|
||||
}
|
||||
logNotice(lf_bus, "scan %2.2x completed (%d slaves left)", dstAddress, m_slaves.size());
|
||||
}
|
||||
if (m_messages.empty()) { // last message for this address
|
||||
m_busHandler->setScanResult(dstAddress, m_scanResult.str());
|
||||
if (m_deleteOnFinish) {
|
||||
logNotice(lf_bus, "scan %2.2x completed (%d slaves left)", dstAddress, m_slaves.size());
|
||||
}
|
||||
}
|
||||
m_result = result;
|
||||
if (m_slaves.empty()) {
|
||||
logNotice(lf_bus, "scan finished");
|
||||
if (m_deleteOnFinish) {
|
||||
logNotice(lf_bus, "scan finished");
|
||||
}
|
||||
m_busHandler->setScanFinished();
|
||||
return false;
|
||||
}
|
||||
if (m_messages.empty()) {
|
||||
m_messages = m_allMessages;
|
||||
m_scanResult.str("");
|
||||
m_scanResult.clear();
|
||||
}
|
||||
m_index = 0;
|
||||
m_message = m_messages.front();
|
||||
m_messages.pop_front();
|
||||
if (prepare(m_master[0]) < RESULT_OK) {
|
||||
result = prepare(m_master[0]);
|
||||
if (result < RESULT_OK) {
|
||||
m_busHandler->setScanFinished();
|
||||
if (result != RESULT_ERR_EOF) {
|
||||
m_result = result;
|
||||
}
|
||||
return false; // give up
|
||||
}
|
||||
return true;
|
||||
@@ -373,16 +379,16 @@ result_t BusHandler::readFromBus(Message* message, string inputStr, const symbol
|
||||
|
||||
void BusHandler::run() {
|
||||
unsigned int symCount = 0;
|
||||
time_t lastTime;
|
||||
time_t now, lastTime;
|
||||
time(&lastTime);
|
||||
lastTime += 2;
|
||||
do {
|
||||
if (m_device->isValid() && !m_reconnect) {
|
||||
result_t result = handleSymbol();
|
||||
if (result != RESULT_ERR_TIMEOUT) {
|
||||
time(&now);
|
||||
if (result != RESULT_ERR_TIMEOUT && now >= lastTime) {
|
||||
symCount++;
|
||||
}
|
||||
time_t now;
|
||||
time(&now);
|
||||
if (now > lastTime) {
|
||||
m_symPerSec = symCount / (unsigned int)(now-lastTime);
|
||||
if (m_symPerSec > m_maxSymPerSec) {
|
||||
@@ -407,6 +413,8 @@ void BusHandler::run() {
|
||||
setState(bs_noSignal, result);
|
||||
}
|
||||
symCount = 0;
|
||||
time(&lastTime);
|
||||
lastTime += 2;
|
||||
}
|
||||
} while (isRunning());
|
||||
}
|
||||
@@ -1029,7 +1037,6 @@ void BusHandler::receiveCompleted() {
|
||||
Message* message = m_messages->getScanMessage(slaveAddress);
|
||||
if (message && (message->getLastUpdateTime() == 0 || message->getLastSlaveData().getDataSize() < 10)) {
|
||||
// e.g. 10fe07040a b5564149303001248901
|
||||
m_seenAddresses[slaveAddress] |= SCAN_INIT;
|
||||
MasterSymbolString dummyMaster;
|
||||
istringstream input;
|
||||
result_t result = message->prepareMaster(m_ownMasterAddress, dummyMaster, input);
|
||||
@@ -1040,9 +1047,14 @@ void BusHandler::receiveCompleted() {
|
||||
idData.push_back(m_command.dataAt(i));
|
||||
}
|
||||
result = message->storeLastData(idData, 0);
|
||||
}
|
||||
if (result == RESULT_OK) {
|
||||
m_seenAddresses[slaveAddress] |= SCAN_DONE;
|
||||
if (result == RESULT_OK) {
|
||||
ostringstream output;
|
||||
result = message->decodeLastData(output, 0, true);
|
||||
if (result == RESULT_OK) {
|
||||
string str = output.str();
|
||||
setScanResult(slaveAddress, 0, str);
|
||||
}
|
||||
}
|
||||
}
|
||||
logNotice(lf_update, "store BC ident: %s", getResultCode(result));
|
||||
}
|
||||
@@ -1103,10 +1115,12 @@ void BusHandler::receiveCompleted() {
|
||||
}
|
||||
}
|
||||
|
||||
result_t BusHandler::startScan(bool full, string levels) {
|
||||
if (m_runningScans > 0) {
|
||||
return RESULT_ERR_DUPLICATE;
|
||||
result_t BusHandler::prepareScan(symbol_t slave, bool full, string levels, bool& reload, ScanRequest*& request) {
|
||||
Message* scanMessage = m_messages->getScanMessage();
|
||||
if (scanMessage == NULL) {
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
deque<Message*> messages = m_messages->findAll("scan", "", levels, true);
|
||||
for (deque<Message*>::iterator it = messages.begin(); it < messages.end(); it++) {
|
||||
Message* message = *it;
|
||||
@@ -1115,42 +1129,74 @@ result_t BusHandler::startScan(bool full, string levels) {
|
||||
}
|
||||
}
|
||||
|
||||
Message* scanMessage = m_messages->getScanMessage();
|
||||
if (scanMessage == NULL) {
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
m_scanResults.clear();
|
||||
|
||||
deque<symbol_t> slaves;
|
||||
for (symbol_t slave = 1; slave != 0; slave++) { // 0 is known to be a master
|
||||
if (!isValidAddress(slave, false) || isMaster(slave)) {
|
||||
continue;
|
||||
}
|
||||
if (!full && (m_seenAddresses[slave]&SEEN) == 0) {
|
||||
symbol_t master = getMasterAddress(slave); // check if we saw the corresponding master already
|
||||
if (master == SYN || (m_seenAddresses[master]&SEEN) == 0) {
|
||||
continue;
|
||||
if (slave != SYN) {
|
||||
slaves.push_back(slave);
|
||||
if (!reload) {
|
||||
Message* message = m_messages->getScanMessage(slave);
|
||||
if (message == NULL || message->getLastChangeTime() == 0) {
|
||||
reload = true;
|
||||
}
|
||||
}
|
||||
slaves.push_back(slave);
|
||||
} else {
|
||||
reload = true;
|
||||
for (slave = 1; slave != 0; slave++) { // 0 is known to be a master
|
||||
if (!isValidAddress(slave, false) || isMaster(slave)) {
|
||||
continue;
|
||||
}
|
||||
if (!full && (m_seenAddresses[slave]&SEEN) == 0) {
|
||||
symbol_t master = getMasterAddress(slave); // check if we saw the corresponding master already
|
||||
if (master == SYN || (m_seenAddresses[master]&SEEN) == 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
slaves.push_back(slave);
|
||||
}
|
||||
}
|
||||
messages.push_front(scanMessage);
|
||||
ScanRequest* request = new ScanRequest(m_messages, messages, slaves, this);
|
||||
if (reload) {
|
||||
messages.push_front(scanMessage);
|
||||
}
|
||||
if (messages.empty()) {
|
||||
return RESULT_OK;
|
||||
}
|
||||
request = new ScanRequest(slave == SYN, m_messages, messages, slaves, this, reload ? 0 : 1);
|
||||
result_t result = request->prepare(m_ownMasterAddress);
|
||||
if (result < RESULT_OK) {
|
||||
delete request;
|
||||
request = NULL;
|
||||
return result == RESULT_ERR_EOF ? RESULT_EMPTY : result;
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t BusHandler::startScan(bool full, string levels) {
|
||||
if (m_runningScans > 0) {
|
||||
return RESULT_ERR_DUPLICATE;
|
||||
}
|
||||
ScanRequest* request = NULL;
|
||||
bool reload = true;
|
||||
result_t result = prepareScan(SYN, full, levels, reload, request);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
if (!request) {
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
m_scanResults.clear();
|
||||
m_runningScans++;
|
||||
m_nextRequests.push(request);
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void BusHandler::setScanResult(symbol_t dstAddress, string str) {
|
||||
void BusHandler::setScanResult(symbol_t dstAddress, size_t index, string str) {
|
||||
m_seenAddresses[dstAddress] |= SCAN_INIT;
|
||||
if (str.length() > 0) {
|
||||
m_seenAddresses[dstAddress] |= SCAN_DONE;
|
||||
m_scanResults[dstAddress] = str;
|
||||
vector<string>& result = m_scanResults[dstAddress];
|
||||
if (index >= result.size()) {
|
||||
result.resize(index+1);
|
||||
}
|
||||
result[index] = str;
|
||||
logNotice(lf_bus, "scan %2.2x: %s", dstAddress, str.c_str());
|
||||
}
|
||||
}
|
||||
@@ -1161,20 +1207,29 @@ void BusHandler::setScanFinished() {
|
||||
}
|
||||
}
|
||||
|
||||
bool BusHandler::formatScanResult(symbol_t slave, ostringstream& output, bool leadingNewline) {
|
||||
map<symbol_t, vector<string>>::iterator it = m_scanResults.find(slave);
|
||||
if (it == m_scanResults.end()) {
|
||||
return false;
|
||||
}
|
||||
if (leadingNewline) {
|
||||
output << endl;
|
||||
}
|
||||
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(slave);
|
||||
for (auto result : it->second) {
|
||||
output << result;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void BusHandler::formatScanResult(ostringstream& output) {
|
||||
if (m_runningScans > 0) {
|
||||
output << m_runningScans << " scan(s) still running" << endl;
|
||||
}
|
||||
bool first = true;
|
||||
for (symbol_t slave = 1; slave != 0; slave++) { // 0 is known to be a master
|
||||
map<symbol_t, string>::iterator it = m_scanResults.find(slave);
|
||||
if (it != m_scanResults.end()) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
output << endl;
|
||||
}
|
||||
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(slave) << it->second;
|
||||
if (formatScanResult(slave, output, !first)) {
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
if (first) {
|
||||
@@ -1199,8 +1254,8 @@ void BusHandler::formatScanResult(ostringstream& output) {
|
||||
void BusHandler::formatSeenInfo(ostringstream& output) {
|
||||
symbol_t address = 0;
|
||||
for (int index = 0; index < 256; index++, address++) {
|
||||
bool self = !m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress);
|
||||
if (!isValidAddress(address, false) || ((m_seenAddresses[address]&SEEN) == 0 && !self)) {
|
||||
bool ownAddress = !m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress);
|
||||
if (!isValidAddress(address, false) || ((m_seenAddresses[address]&SEEN) == 0 && !ownAddress)) {
|
||||
continue;
|
||||
}
|
||||
output << endl << "address " << setfill('0') << setw(2) << hex << static_cast<unsigned>(address);
|
||||
@@ -1215,7 +1270,7 @@ void BusHandler::formatSeenInfo(ostringstream& output) {
|
||||
if (master != SYN) {
|
||||
output << " #" << setw(0) << dec << static_cast<unsigned>(getMasterNumber(master));
|
||||
}
|
||||
if (self) {
|
||||
if (ownAddress) {
|
||||
output << ", ebusd";
|
||||
if (m_answer) {
|
||||
output << " (answering)";
|
||||
@@ -1238,81 +1293,121 @@ void BusHandler::formatSeenInfo(ostringstream& output) {
|
||||
}
|
||||
}
|
||||
}
|
||||
string loadedFiles = m_messages->getLoadedFiles(address);
|
||||
vector<string> loadedFiles = m_messages->getLoadedFiles(address);
|
||||
if (!loadedFiles.empty()) {
|
||||
output << ", loaded " << loadedFiles;
|
||||
bool first = true;
|
||||
for (vector<string>::iterator it = loadedFiles.begin(); it != loadedFiles.end(); it++) {
|
||||
if (first) {
|
||||
first = false;
|
||||
output << ", loaded \"";
|
||||
} else {
|
||||
output << ", \"";
|
||||
}
|
||||
output << *it << "\"";
|
||||
it++;
|
||||
if (!(*it).empty()) {
|
||||
output << " (" << *it << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BusHandler::formatUpdateInfo(ostringstream& output) {
|
||||
if (hasSignal()) {
|
||||
output << "&s=" << static_cast<unsigned>(m_symPerSec);
|
||||
output << ",\"s\":" << m_maxSymPerSec;
|
||||
}
|
||||
output << "&m=" << static_cast<unsigned>(m_masterCount);
|
||||
output << "&ms=" << m_messages->size();
|
||||
output << "&r=" << (m_device->isReadOnly() ? 1 : 0);
|
||||
output << "&an=" << (m_answer ? 1 : 0);
|
||||
output << "&c=" << (m_addressConflict ? 1 : 0);
|
||||
output << ",\"c\":" << m_masterCount;
|
||||
output << ",\"m\":" << m_messages->size();
|
||||
output << ",\"r\":" << (m_device->isReadOnly() ? 1 : 0);
|
||||
output << ",\"an\":" << (m_answer ? 1 : 0);
|
||||
output << ",\"ac\":" << (m_addressConflict ? 1 : 0);
|
||||
unsigned char address = 0;
|
||||
for (int index = 0; index < 256; index++, address++) {
|
||||
bool self = !m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress);
|
||||
if (!isValidAddress(address, false) || ((m_seenAddresses[address]&SEEN) == 0 && !self)) {
|
||||
bool ownAddress = !m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress);
|
||||
if (!isValidAddress(address, false) || ((m_seenAddresses[address]&SEEN) == 0 && !ownAddress)) {
|
||||
continue;
|
||||
}
|
||||
output << "&a[";
|
||||
output << setfill('0') << setw(2) << hex << static_cast<unsigned>(address);
|
||||
output << "]=";
|
||||
if (self) {
|
||||
output << "self";
|
||||
}
|
||||
map<symbol_t, string>::iterator it = m_scanResults.find(address);
|
||||
output << ",\"" << setfill('0') << setw(2) << hex << static_cast<unsigned>(address);
|
||||
output << "\":{\"o\":" << (ownAddress ? 1 : 0);
|
||||
map<symbol_t, vector<string>>::iterator it = m_scanResults.find(address);
|
||||
if (it != m_scanResults.end()) {
|
||||
output << it->second;
|
||||
} else if ((m_seenAddresses[address]&SCAN_DONE) != 0) {
|
||||
output << ",\"s\":\"";
|
||||
for (auto result : it->second) {
|
||||
output << result;
|
||||
}
|
||||
output << "\"";
|
||||
}
|
||||
if ((m_seenAddresses[address]&SCAN_DONE) != 0) {
|
||||
Message* message = m_messages->getScanMessage(address);
|
||||
if (message != NULL && message->getLastUpdateTime() > 0) {
|
||||
// add detailed scan info: Manufacturer ID SW HW
|
||||
message->decodeLastData(output, OF_NUMERIC);
|
||||
message->decodeLastData(output, OF_NAMES|OF_NUMERIC|OF_JSON|OF_SHORT, true);
|
||||
}
|
||||
}
|
||||
string loadedFiles = m_messages->getLoadedFiles(address);
|
||||
vector<string> loadedFiles = m_messages->getLoadedFiles(address);
|
||||
if (!loadedFiles.empty()) {
|
||||
output << "|" << loadedFiles;
|
||||
output << ",\"f\":[";
|
||||
bool first = true;
|
||||
for (vector<string>::iterator it = loadedFiles.begin(); it != loadedFiles.end(); it++) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
output << ",";
|
||||
}
|
||||
output << "{\"f\":\"" << *it << "\"";
|
||||
it++;
|
||||
if (!(*it).empty()) {
|
||||
output << ",\"c\":\"" << *it << "\"";
|
||||
}
|
||||
output << "}";
|
||||
}
|
||||
output << "]";
|
||||
}
|
||||
output << "}";
|
||||
}
|
||||
}
|
||||
|
||||
result_t BusHandler::scanAndWait(symbol_t dstAddress, SlaveSymbolString& slave) {
|
||||
if (!isValidAddress(dstAddress) || isMaster(dstAddress)) {
|
||||
result_t BusHandler::scanAndWait(symbol_t dstAddress, bool loadScanConfig, bool reload) {
|
||||
if (!isValidAddress(dstAddress, false) || isMaster(dstAddress)) {
|
||||
return RESULT_ERR_INVALID_ADDR;
|
||||
}
|
||||
m_seenAddresses[dstAddress] |= SCAN_INIT;
|
||||
Message* scanMessage = m_messages->getScanMessage();
|
||||
if (scanMessage == NULL) {
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
istringstream input;
|
||||
MasterSymbolString master;
|
||||
result_t result = scanMessage->prepareMaster(m_ownMasterAddress, master, input, UI_FIELD_SEPARATOR, dstAddress);
|
||||
if (result == RESULT_OK) {
|
||||
result = sendAndWait(master, slave);
|
||||
if (result == RESULT_OK) {
|
||||
Message* message = m_messages->getScanMessage(dstAddress);
|
||||
if (message != NULL && message != scanMessage) {
|
||||
scanMessage = message;
|
||||
// update the cache, expected to work since this is a clone
|
||||
scanMessage->storeLastData(master, 0);
|
||||
}
|
||||
}
|
||||
if (result != RESULT_ERR_NO_SIGNAL) {
|
||||
m_seenAddresses[dstAddress] |= SCAN_DONE;
|
||||
}
|
||||
}
|
||||
if (result != RESULT_OK || slave.getDataSize() == 0) { // avoid "invalid position" during decode
|
||||
ScanRequest* request = NULL;
|
||||
bool hasAdditionalScanMessages = m_messages->hasAdditionalScanMessages();
|
||||
result_t result = prepareScan(dstAddress, false, "", reload, request);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
return scanMessage->storeLastData(slave, 0); // update the cache
|
||||
if (request) {
|
||||
if (reload) {
|
||||
m_scanResults.erase(dstAddress);
|
||||
} else if (m_scanResults.find(dstAddress) != m_scanResults.end()) {
|
||||
m_scanResults[dstAddress].resize(1);
|
||||
}
|
||||
m_runningScans++;
|
||||
m_nextRequests.push(request);
|
||||
bool success = m_finishedRequests.remove(request, true);
|
||||
result = success ? request->m_result : RESULT_ERR_TIMEOUT;
|
||||
delete request;
|
||||
request = NULL;
|
||||
}
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
if (loadScanConfig) {
|
||||
string file;
|
||||
result = loadScanConfigFile(m_messages, dstAddress, file);
|
||||
if (result == RESULT_OK) {
|
||||
setScanConfigLoaded(dstAddress, file);
|
||||
if (!hasAdditionalScanMessages && m_messages->hasAdditionalScanMessages()) {
|
||||
// additional scan messages now available
|
||||
scanAndWait(dstAddress, false, false);
|
||||
}
|
||||
} else {
|
||||
setScanConfigLoaded(dstAddress, "");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool BusHandler::enableGrab(bool enable) {
|
||||
@@ -1340,7 +1435,7 @@ void BusHandler::formatGrabResult(const bool unknown, ostringstream& output, con
|
||||
}
|
||||
}
|
||||
|
||||
symbol_t BusHandler::getNextScanAddress(symbol_t lastAddress, bool& scanned) {
|
||||
symbol_t BusHandler::getNextScanAddress(symbol_t lastAddress, bool onlyScanned) {
|
||||
if (lastAddress == SYN) {
|
||||
return SYN;
|
||||
}
|
||||
@@ -1348,13 +1443,22 @@ symbol_t BusHandler::getNextScanAddress(symbol_t lastAddress, bool& scanned) {
|
||||
if (!isValidAddress(lastAddress, false) || isMaster(lastAddress)) {
|
||||
continue;
|
||||
}
|
||||
if ((m_seenAddresses[lastAddress]&(SEEN|LOAD_INIT)) == SEEN) {
|
||||
scanned = (m_seenAddresses[lastAddress]&SCAN_INIT) != 0;
|
||||
if (onlyScanned) {
|
||||
if ((m_seenAddresses[lastAddress]&(LOAD_INIT|SCAN_DONE)) == SCAN_DONE) {
|
||||
return lastAddress;
|
||||
}
|
||||
} else if ((m_seenAddresses[lastAddress]&(SEEN|LOAD_INIT)) == SEEN) {
|
||||
return lastAddress;
|
||||
}
|
||||
symbol_t master = getMasterAddress(lastAddress);
|
||||
if (master != SYN && (m_seenAddresses[master]&SEEN) != 0 && (m_seenAddresses[lastAddress]&LOAD_INIT) == 0) {
|
||||
scanned = (m_seenAddresses[lastAddress]&SCAN_INIT) != 0;
|
||||
if (master == SYN || (m_seenAddresses[master]&SEEN) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (onlyScanned) {
|
||||
if ((m_seenAddresses[lastAddress]&(LOAD_INIT|SCAN_DONE)) == SCAN_DONE) {
|
||||
return lastAddress;
|
||||
}
|
||||
} else if ((m_seenAddresses[lastAddress]&LOAD_INIT) == 0) {
|
||||
return lastAddress;
|
||||
}
|
||||
}
|
||||
|
||||
+39
-13
@@ -190,14 +190,18 @@ class ScanRequest : public BusRequest {
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param deleteOnFinish whether to automatically delete this @a ScanRequest when finished.
|
||||
* @param messageMap the @a MessageMap instance.
|
||||
* @param messages the @a Message instances to query starting with the primary one.
|
||||
* @param slaves the slave addresses to scan.
|
||||
* @param busHandler the @a BusHandler instance to notify of final scan result.
|
||||
* @param notifyIndex the offset to the index for notifying the scan result.
|
||||
*/
|
||||
ScanRequest(MessageMap* messageMap, deque<Message*> messages, deque<symbol_t> slaves, BusHandler* busHandler)
|
||||
: BusRequest(m_master, true), m_messageMap(messageMap), m_index(0), m_allMessages(messages), m_messages(messages),
|
||||
m_slaves(slaves), m_busHandler(busHandler) {
|
||||
ScanRequest(bool deleteOnFinish, MessageMap* messageMap, deque<Message*> messages, deque<symbol_t> slaves,
|
||||
BusHandler* busHandler, size_t notifyIndex = 0)
|
||||
: BusRequest(m_master, deleteOnFinish), m_messageMap(messageMap), m_index(0), m_allMessages(messages),
|
||||
m_messages(messages), m_slaves(slaves), m_busHandler(busHandler), m_notifyIndex(notifyIndex),
|
||||
m_result(RESULT_ERR_NO_SIGNAL) {
|
||||
m_message = m_messages.front();
|
||||
m_messages.pop_front();
|
||||
}
|
||||
@@ -240,11 +244,14 @@ class ScanRequest : public BusRequest {
|
||||
/** the slave addresses to scan. */
|
||||
deque<symbol_t> m_slaves;
|
||||
|
||||
/** the @a ostringstream for building the scan result of a single slave. */
|
||||
ostringstream m_scanResult;
|
||||
|
||||
/** the @a BusHandler instance to notify of final scan result. */
|
||||
BusHandler* m_busHandler;
|
||||
|
||||
/** the offset to the index for notifying the scan result. */
|
||||
size_t m_notifyIndex;
|
||||
|
||||
/** the overall result of handling the request. */
|
||||
result_t m_result;
|
||||
};
|
||||
|
||||
|
||||
@@ -434,15 +441,25 @@ class BusHandler : public WaitThread {
|
||||
/**
|
||||
* Set the scan result @a string for a scanned slave address.
|
||||
* @param dstAddress the scanned slave address.
|
||||
* @param index the index of the result to set (starting with 0 for the ident message).
|
||||
* @param str the scan result @a string to set, or empty if not a single part of the scan was successful.
|
||||
*/
|
||||
void setScanResult(symbol_t dstAddress, string str);
|
||||
void setScanResult(symbol_t dstAddress, size_t index, string str);
|
||||
|
||||
/**
|
||||
* Called from @a ScanRequest upon completion.
|
||||
*/
|
||||
void setScanFinished();
|
||||
|
||||
/**
|
||||
* Format the scan result for a single slave to the @a ostringstream.
|
||||
* @param slave the slave address for which to format the scan result.
|
||||
* @param leadingNewline whether to insert a newline before the scan result.
|
||||
* @param output the @a ostringstream to format the scan result to.
|
||||
* @return true when a scan result was formatted, false otherwise.
|
||||
*/
|
||||
bool formatScanResult(symbol_t slave, ostringstream& output, bool leadingNewline);
|
||||
|
||||
/**
|
||||
* Format the scan result to the @a ostringstream.
|
||||
* @param output the @a ostringstream to format the scan result to.
|
||||
@@ -464,10 +481,9 @@ class BusHandler : public WaitThread {
|
||||
/**
|
||||
* Send a scan message on the bus and wait for the answer.
|
||||
* @param dstAddress the destination slave address to send to.
|
||||
* @param slave the @a SlaveSymbolString that will be filled with retrieved slave data.
|
||||
* @return the result code.
|
||||
*/
|
||||
result_t scanAndWait(symbol_t dstAddress, SlaveSymbolString& slave);
|
||||
result_t scanAndWait(symbol_t dstAddress, bool loadScanConfig = false, bool reload = false);
|
||||
|
||||
/**
|
||||
* Start or stop grabbing unknown messages.
|
||||
@@ -516,10 +532,9 @@ class BusHandler : public WaitThread {
|
||||
/**
|
||||
* Get the next slave address that still needs to be scanned or loaded.
|
||||
* @param lastAddress the last returned slave address, or 0 for returning the first one.
|
||||
* @param scanned set to true when the slave is already scanned but not yet loaded, set to false when it still needs to be scanned and loaded.
|
||||
* @return the next slave address that still needs to be scanned or loaded, or @a SYN.
|
||||
*/
|
||||
symbol_t getNextScanAddress(symbol_t lastAddress, bool& scanned);
|
||||
symbol_t getNextScanAddress(symbol_t lastAddress, bool onlyScanned = false);
|
||||
|
||||
/**
|
||||
* Set the state of the participant to configuration @a LOADED.
|
||||
@@ -556,6 +571,17 @@ class BusHandler : public WaitThread {
|
||||
*/
|
||||
void receiveCompleted();
|
||||
|
||||
/**
|
||||
* Prepare a @a ScanRequest.
|
||||
* @param slave the single slave address to scan, or @a SYN for multiple.
|
||||
* @param full true for a full scan (all slaves), false for scanning only already seen slaves.
|
||||
* @param levels the current user's access levels.
|
||||
* @param reload true to force sending the scan message, false to send only if necessary (only for single slave).
|
||||
* @param request the created @a ScanRequest (may be NULL with positive result if scan is not needed).
|
||||
* @return the result code.
|
||||
*/
|
||||
result_t prepareScan(symbol_t slave, bool full, string levels, bool& reload, ScanRequest*& request);
|
||||
|
||||
/** the @a Device instance for accessing the bus. */
|
||||
Device* m_device;
|
||||
|
||||
@@ -662,8 +688,8 @@ class BusHandler : public WaitThread {
|
||||
/** the participating bus addresses seen so far (0 if not seen yet, or combination of @a SEEN bits). */
|
||||
symbol_t m_seenAddresses[256];
|
||||
|
||||
/** the scan results by slave address. */
|
||||
map<symbol_t, string> m_scanResults;
|
||||
/** the scan results by slave address and index. */
|
||||
map<symbol_t, vector<string>> m_scanResults;
|
||||
|
||||
/** whether to grab messages. */
|
||||
bool m_grabMessages;
|
||||
|
||||
+46
-45
@@ -197,10 +197,11 @@ MainLoop::~MainLoop() {
|
||||
|
||||
void MainLoop::run() {
|
||||
bool reload = true;
|
||||
time_t lastTaskRun, now, lastSignal = 0, since, sinkSince = 1, nextCheckRun;
|
||||
time_t lastTaskRun, now, start, lastSignal = 0, since, sinkSince = 1, nextCheckRun;
|
||||
int taskDelay = 5;
|
||||
symbol_t lastScanAddress = 0; // 0 is known to be a master
|
||||
time(&now);
|
||||
start = now;
|
||||
lastTaskRun = now;
|
||||
nextCheckRun = now + CHECK_INITIAL_DELAY;
|
||||
ostringstream updates;
|
||||
@@ -233,20 +234,33 @@ void MainLoop::run() {
|
||||
m_reconnectCount++;
|
||||
}
|
||||
if (m_scanConfig) {
|
||||
bool loadDelay = false;
|
||||
if (m_initialScan != ESC && reload && m_busHandler->hasSignal()) {
|
||||
loadDelay = true;
|
||||
result_t result = RESULT_ERR_NO_SIGNAL;
|
||||
if (m_initialScan == SYN) {
|
||||
logNotice(lf_main, "initiating full scan");
|
||||
logNotice(lf_main, "starting initial full scan");
|
||||
result = m_busHandler->startScan(true, "*");
|
||||
} else if (m_initialScan == BROADCAST) {
|
||||
logNotice(lf_main, "starting initial broadcast scan");
|
||||
Message* message = m_messages->getScanMessage(BROADCAST);
|
||||
if (message) {
|
||||
MasterSymbolString master;
|
||||
SlaveSymbolString slave;
|
||||
istringstream input;
|
||||
result = message->prepareMaster(m_address, master, input);
|
||||
if (result == RESULT_OK) {
|
||||
result = m_busHandler->sendAndWait(master, slave);
|
||||
}
|
||||
} else {
|
||||
result = RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
} else {
|
||||
logNotice(lf_main, "starting initial scan for %2.2x", m_initialScan);
|
||||
SlaveSymbolString slave;
|
||||
result = m_busHandler->scanAndWait(m_initialScan, slave);
|
||||
Message* message = m_messages->getScanMessage(m_initialScan);
|
||||
if (result == RESULT_OK && message != NULL) {
|
||||
result = m_busHandler->scanAndWait(m_initialScan, true);
|
||||
if (result == RESULT_OK) {
|
||||
ostringstream ret;
|
||||
result = message->decodeLastData(ret, 0, true); // decode data
|
||||
if (result == RESULT_OK) {
|
||||
if (m_busHandler->formatScanResult(m_initialScan, ret, false)) {
|
||||
logNotice(lf_main, "initial scan result: %2.2x%s", m_initialScan, ret.str().c_str());
|
||||
}
|
||||
}
|
||||
@@ -258,38 +272,21 @@ void MainLoop::run() {
|
||||
reload = false;
|
||||
}
|
||||
}
|
||||
bool scanned = false;
|
||||
lastScanAddress = m_busHandler->getNextScanAddress(lastScanAddress, scanned);
|
||||
if (lastScanAddress == SYN) {
|
||||
taskDelay = 5;
|
||||
lastScanAddress = 0;
|
||||
} else {
|
||||
nextCheckRun = now + CHECK_INITIAL_DELAY;
|
||||
SlaveSymbolString slave;
|
||||
if (scanned) {
|
||||
Message* message = m_messages->getScanMessage(lastScanAddress);
|
||||
slave = message->getLastSlaveData();
|
||||
scanned = message->getLastUpdateTime() > 0;
|
||||
if (!loadDelay) {
|
||||
lastScanAddress = m_busHandler->getNextScanAddress(lastScanAddress);
|
||||
if (lastScanAddress == SYN) {
|
||||
taskDelay = 5;
|
||||
lastScanAddress = 0;
|
||||
} else {
|
||||
result_t result = m_busHandler->scanAndWait(lastScanAddress, slave);
|
||||
nextCheckRun = now + CHECK_INITIAL_DELAY;
|
||||
result_t result = m_busHandler->scanAndWait(lastScanAddress, true);
|
||||
taskDelay = (result == RESULT_ERR_NO_SIGNAL) ? 10 : 1;
|
||||
if (result != RESULT_OK) {
|
||||
logError(lf_main, "scan config %2.2x message: %s", lastScanAddress, getResultCode(result));
|
||||
logError(lf_main, "scan config %2.2x: %s", lastScanAddress, getResultCode(result));
|
||||
} else {
|
||||
scanned = true;
|
||||
logInfo(lf_main, "scan config %2.2x message received", lastScanAddress);
|
||||
}
|
||||
}
|
||||
if (scanned) {
|
||||
string file;
|
||||
result_t result = loadScanConfigFile(m_messages, lastScanAddress, slave, file);
|
||||
if (result == RESULT_OK) {
|
||||
logNotice(lf_main, "scan config %2.2x: file %s loaded", lastScanAddress, file.c_str());
|
||||
m_busHandler->setScanConfigLoaded(lastScanAddress, file);
|
||||
} else {
|
||||
m_busHandler->setScanConfigLoaded(lastScanAddress, "");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (now > nextCheckRun) {
|
||||
@@ -298,16 +295,24 @@ void MainLoop::run() {
|
||||
if (socket) {
|
||||
socket->setTimeout(5);
|
||||
ostringstream ostr;
|
||||
ostr << "GET /updatecheck/?v=" << PACKAGE_VERSION << "." << REVISION;
|
||||
ostr << "{\"v\":\"" << PACKAGE_VERSION << "." << REVISION << "\"";
|
||||
ostr << ",\"u\":" << (now-start);
|
||||
if (m_reconnectCount) {
|
||||
ostr << "&c=" << m_reconnectCount;
|
||||
ostr << ",\"c\":" << m_reconnectCount;
|
||||
}
|
||||
m_busHandler->formatUpdateInfo(ostr);
|
||||
ostr << " HTTP/1.0\r\n";
|
||||
ostr << "}";
|
||||
string str = ostr.str();
|
||||
ostr.clear();
|
||||
ostr.str("");
|
||||
ostr << "POST /updatecheck/ HTTP/1.0\r\n";
|
||||
ostr << "Host: ebusd.eu" << "\r\n";
|
||||
ostr << "User-Agent: " << PACKAGE_NAME << "/" << PACKAGE_VERSION << "\r\n";
|
||||
ostr << "Content-Type: application/json; charset=utf-8\r\n";
|
||||
ostr << "Content-Length: " << str.length() << "\r\n";
|
||||
ostr << "\r\n";
|
||||
string str = ostr.str();
|
||||
ostr << str;
|
||||
str = ostr.str();
|
||||
const char* cstr = str.c_str();
|
||||
size_t len = str.size();
|
||||
for (size_t pos = 0; pos < len; ) {
|
||||
@@ -1379,18 +1384,13 @@ string MainLoop::executeScan(vector<string> &args, string levels) {
|
||||
if (result != RESULT_OK) {
|
||||
return getResultCode(result);
|
||||
}
|
||||
SlaveSymbolString slave;
|
||||
result = m_busHandler->scanAndWait(dstAddress, slave);
|
||||
result = m_busHandler->scanAndWait(dstAddress);
|
||||
if (result != RESULT_OK) {
|
||||
return getResultCode(result);
|
||||
}
|
||||
Message* message = m_messages->getScanMessage(dstAddress);
|
||||
// never NULL due to scanAndWait() == RESULT_OK && dstAddress != BROADCAST
|
||||
ostringstream ret;
|
||||
ret << hex << setw(2) << setfill('0') << static_cast<unsigned>(dstAddress);
|
||||
result = message->decodeLastData(ret, 0, true); // decode data
|
||||
if (result != RESULT_OK) {
|
||||
return getResultCode(result);
|
||||
if (!m_busHandler->formatScanResult(dstAddress, ret, false)) {
|
||||
return getResultCode(RESULT_EMPTY);
|
||||
}
|
||||
return ret.str();
|
||||
}
|
||||
@@ -1485,6 +1485,7 @@ string MainLoop::executeInfo(vector<string> &args, const string user) {
|
||||
if (m_busHandler->hasSignal()) {
|
||||
result << "signal: acquired\n";
|
||||
result << "symbol rate: " << m_busHandler->getSymbolRate() << "\n";
|
||||
result << "max symbol rate: " << m_busHandler->getMaxSymbolRate() << "\n";
|
||||
} else {
|
||||
result << "signal: no signal\n";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user