From c27a76b8e53aeaea8e3e855b329eacf5e454e632 Mon Sep 17 00:00:00 2001 From: john30 Date: Sat, 4 Mar 2017 15:19:31 +0100 Subject: [PATCH] added update check --- src/ebusd/bushandler.cpp | 111 ++++++++++++++++++++++++++------------- src/ebusd/bushandler.h | 6 +++ src/ebusd/mainloop.cpp | 79 +++++++++++++++++++++++++++- src/ebusd/mainloop.h | 3 ++ 4 files changed, 162 insertions(+), 37 deletions(-) diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index bc1e6e92..589aaa52 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -1199,48 +1199,87 @@ void BusHandler::formatScanResult(ostringstream& output) { void BusHandler::formatSeenInfo(ostringstream& output) { symbol_t address = 0; for (int index = 0; index < 256; index++, address++) { - if (isValidAddress(address, false) && ((m_seenAddresses[address]&SEEN) != 0 - || (!m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress)))) { - output << endl << "address " << setfill('0') << setw(2) << hex << static_cast(address); - symbol_t master; - if (isMaster(address)) { - output << ": master"; - master = address; - } else { - output << ": slave"; - master = getMasterAddress(address); + bool self = !m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress); + if (!isValidAddress(address, false) || ((m_seenAddresses[address]&SEEN) == 0 && !self)) { + continue; + } + output << endl << "address " << setfill('0') << setw(2) << hex << static_cast(address); + symbol_t master; + if (isMaster(address)) { + output << ": master"; + master = address; + } else { + output << ": slave"; + master = getMasterAddress(address); + } + if (master != SYN) { + output << " #" << setw(0) << dec << static_cast(getMasterNumber(master)); + } + if (self) { + output << ", ebusd"; + if (m_answer) { + output << " (answering)"; } - if (master != SYN) { - output << " #" << setw(0) << dec << static_cast(getMasterNumber(master)); + if (m_addressConflict && (m_seenAddresses[address]&SEEN) != 0) { + output << ", conflict"; } - if (!m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress)) { - output << ", ebusd"; - if (m_answer) { - output << " (answering)"; - } - if (m_addressConflict && (m_seenAddresses[address]&SEEN) != 0) { - output << ", conflict"; + } + if ((m_seenAddresses[address]&SCAN_DONE) != 0) { + output << ", scanned"; + Message* message = m_messages->getScanMessage(address); + if (message != NULL && message->getLastUpdateTime() > 0) { + // add detailed scan info: Manufacturer ID SW HW + output << " \""; + result_t result = message->decodeLastData(output, OF_NAMES); + if (result != RESULT_OK) { + output << "\" error: " << getResultCode(result); + } else { + output << "\""; } } - if ((m_seenAddresses[address]&SCAN_DONE) != 0) { - output << ", scanned"; - Message* message = m_messages->getScanMessage(address); - if (message != NULL && message->getLastUpdateTime() > 0) { - // add detailed scan info: Manufacturer ID SW HW - output << " \""; - result_t result = message->decodeLastData(output, OF_NAMES); - if (result != RESULT_OK) { - output << "\" error: " << getResultCode(result); - } else { - output << "\""; - } - } - } - string loadedFiles = m_messages->getLoadedFiles(address); - if (!loadedFiles.empty()) { - output << ", loaded " << loadedFiles; + } + string loadedFiles = m_messages->getLoadedFiles(address); + if (!loadedFiles.empty()) { + output << ", loaded " << loadedFiles; + } + } +} + +void BusHandler::formatUpdateInfo(ostringstream& output) { + if (hasSignal()) { + output << "&s=" << static_cast(m_symPerSec); + } + output << "&m=" << static_cast(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); + 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)) { + continue; + } + output << "&a["; + output << setfill('0') << setw(2) << hex << static_cast(address); + output << "]="; + if (self) { + output << "self"; + } + map::iterator it = m_scanResults.find(address); + if (it != m_scanResults.end()) { + output << it->second; + } else 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); } } + string loadedFiles = m_messages->getLoadedFiles(address); + if (!loadedFiles.empty()) { + output << "|" << loadedFiles; + } } } diff --git a/src/ebusd/bushandler.h b/src/ebusd/bushandler.h index 1ade0c2b..fd3ae714 100644 --- a/src/ebusd/bushandler.h +++ b/src/ebusd/bushandler.h @@ -455,6 +455,12 @@ class BusHandler : public WaitThread { */ void formatSeenInfo(ostringstream& output); + /** + * Format information for running the update check to the @a ostringstream. + * @param output the @a ostringstream to append the info to. + */ + void formatUpdateInfo(ostringstream& output); + /** * Send a scan message on the bus and wait for the answer. * @param dstAddress the destination slave address to send to. diff --git a/src/ebusd/mainloop.cpp b/src/ebusd/mainloop.cpp index 2f9d9ca6..79203c8b 100644 --- a/src/ebusd/mainloop.cpp +++ b/src/ebusd/mainloop.cpp @@ -189,13 +189,20 @@ MainLoop::~MainLoop() { } } +/** the delay for running the update check. */ +#define CHECK_DELAY 24*3600 + +/** the initial delay for running the update check. */ +#define CHECK_INITIAL_DELAY 5 + void MainLoop::run() { bool reload = true; - time_t lastTaskRun, now, lastSignal = 0, since, sinkSince = 1; + time_t lastTaskRun, now, lastSignal = 0, since, sinkSince = 1, nextCheckRun; int taskDelay = 5; symbol_t lastScanAddress = 0; // 0 is known to be a master time(&now); lastTaskRun = now; + nextCheckRun = now + CHECK_INITIAL_DELAY; ostringstream updates; list dataSinks; deque messages; @@ -257,6 +264,7 @@ void MainLoop::run() { taskDelay = 5; lastScanAddress = 0; } else { + nextCheckRun = now + CHECK_INITIAL_DELAY; SlaveSymbolString slave; if (scanned) { Message* message = m_messages->getScanMessage(lastScanAddress); @@ -284,6 +292,72 @@ void MainLoop::run() { } } } + if (now > nextCheckRun) { + TCPClient client; + TCPSocket* socket = client.connect("ebusd.eu", 80); + if (socket) { + socket->setTimeout(5); + ostringstream ostr; + ostr << "GET /updatecheck/?v=" << PACKAGE_VERSION << "." << REVISION; + if (m_reconnectCount) { + ostr << "&c=" << m_reconnectCount; + } + m_busHandler->formatUpdateInfo(ostr); + ostr << " HTTP/1.0\r\n"; + ostr << "Host: ebusd.eu" << "\r\n"; + ostr << "User-Agent: " << PACKAGE_NAME << "/" << PACKAGE_VERSION << "\r\n"; + ostr << "\r\n"; + string str = ostr.str(); + const char* cstr = str.c_str(); + size_t len = str.size(); + for (size_t pos = 0; pos < len; ) { + ssize_t sent = socket->send(cstr + pos, len - pos); + if (sent < 0) { + len = 0; + logError(lf_main, "update check send error"); + break; + } + pos += sent; + } + if (len) { + char buf[512]; + ssize_t received = socket->recv(buf, sizeof(buf)); + string result; + if (received > 15) { // "HTTP/1.1 200 OK" + buf[received - (received == sizeof(buf) ? 1 : 0)] = 0; + result = string(buf); + } + if (result.substr(0, 5) == "HTTP/") { + string message; + size_t pos = result.find("\r\n\r\n"); + if (pos != string::npos) { + message = result.substr(pos+4); + } + pos = result.find(" "); + if (pos != string::npos) { + result = result.substr(pos+1); + } + pos = result.find("\r\n"); + if (pos != string::npos) { + result = result.substr(0, pos); + } + if (result == "200 OK") { + m_updateCheck = message == "" ? "unknown" : message; + logNotice(lf_main, "update check: %s", message.c_str()); + } else { + logError(lf_main, "update check error: %s", result.c_str()); + } + } else { + logError(lf_main, "update check receive error"); + } + } + delete socket; + socket = NULL; + } else { + logError(lf_main, "update check connect error"); + } + nextCheckRun = now + CHECK_DELAY; + } time(&lastTaskRun); } time(&now); @@ -1398,6 +1472,9 @@ string MainLoop::executeInfo(vector &args, const string user) { } ostringstream result; result << "version: " << PACKAGE_STRING "." REVISION "\n"; + if (!m_updateCheck.empty()) { + result << "update check: " << m_updateCheck << "\n"; + } if (!user.empty()) { result << "user: " << user << "\n"; } diff --git a/src/ebusd/mainloop.h b/src/ebusd/mainloop.h index 255905eb..551bb149 100644 --- a/src/ebusd/mainloop.h +++ b/src/ebusd/mainloop.h @@ -343,6 +343,9 @@ class MainLoop : public Thread, DeviceListener { /** the registered @a DataHandler instances. */ list m_dataHandlers; + + /** the result of the last update check, or empty. */ + string m_updateCheck; }; } // namespace ebusd