/* ******************************************************************************* * INCLUDE ******************************************************************************* */ #include "Application.h" #ifdef USING_NETWORK_SUBSYSTEM #include "NetworkSubsystem.h" #endif #ifdef USING_GRAPHICS_SUBSYSTEM #include "GraphicsSubsystem.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "hardware/BoardInfo.h" #include "hardware/GPIO.h" #include "hardware/HardwareSubsystem.h" #include "util/HexBinaryCodec.h" #include "util/SystemInfo.h" #include "util/Temperature.h" /* ******************************************************************************* * CONSTANTS ******************************************************************************* */ static const std::string CONFIG_ROOT_PATH = "/customer/conf"; static const std::string ROOTCFG_FILENAME = CONFIG_ROOT_PATH + "/config.json"; static const std::string DEFAULT_ROOTCFG_FILENAME = CONFIG_ROOT_PATH + "/config_default.json"; const std::string VERSION_FILE = "/customer/VERSION"; const std::string IMAGE_VERSION_FILE = "/etc/IMAGE_VERSION"; /* ******************************************************************************* * CLASS DEFINE ******************************************************************************* */ const std::string Application::ROOT_CONFIG = "config"; void Application::initialize(Poco::Util::Application& self) { _exitRequst = false; initConfigAll(); Poco::Util::Application::initialize(self); } void Application::uninitialize() { Poco::Util::Application::uninitialize(); } int Application::main(const std::vector& args) { while (!_exitRequst) Poco::Thread::sleep(1000); return EXIT_OK; } std::string Application::getConfigFilePath(const std::string& label) { Poco::Path path(getConfig(Application::ROOT_CONFIG).getString("buss_params_path")); if (path.isRelative()) path = path.makeAbsolute(Poco::Path::current()); return path.toString() + label + ".json"; } void Application::initConfigAll() { config().add(new Poco::Util::JSONConfiguration(ROOTCFG_FILENAME), ROOT_CONFIG, PRIO_SYSTEM, true); } void Application::initConfig(const std::string& label) { int retry = 0; while (retry++ < 3) { try { config().add(new Poco::Util::JSONConfiguration(getConfigFilePath(label)), label, PRIO_APPLICATION, true); break; } catch (Poco::Exception& e) { logger().error("Load config file '%s' FAIL: %s, USE DEFAULT CONFIG FILE INSTEAD!", label, e.displayText()); Poco::File dFile(getConfigFilePath(label + "_default")); if (dFile.exists()) { dFile.copyTo(getConfigFilePath(label)); } else { logger().error("Load config file '%s' FAIL: %s, DEFAULT CONFIG FILE IS NOT EXIST", label, e.displayText()); } } } } std::string Application::version() const { try { Poco::FileInputStream istr(VERSION_FILE); std::string version; istr >> version; return version; } catch (...) { return "0.0.0"; } } Poco::Util::AbstractConfiguration& Application::getConfig() const { return config(); } Poco::Util::AbstractConfiguration& Application::getConfig(const std::string& label) const { return findConfig(label); } void Application::saveConfig(const std::string& label) { logger().information("Saving config..."); std::string tmpFilePath = "/tmp/" + label + ".json.tmp"; std::string filePath = getConfigFilePath(label); Poco::FileOutputStream fost(tmpFilePath); dumpConfig(label, fost); fost.flush(); fost.close(); try { Poco::File(tmpFilePath).moveTo(filePath); logger().information("Config saved successfully."); } catch (Poco::Exception& e) { logger().error("Save config file ERROR: %s", e.displayText()); } } void Application::loadConfig(const std::string& label, std::istream& istr) { auto& config = findConfig(label); config.load(istr); saveConfig(label); ConfigChanged.notifyAsync(this, label); } void Application::loadConfig(const std::string& label, const std::string& str) { std::istringstream istr(str); loadConfig(label, istr); } void Application::dumpConfig(const std::string& label, std::ostream& os) { auto& config = findConfig(label); config.save(os); } void Application::configNotifyAsync(const std::string& label) { ConfigChanged.notifyAsync(this, label); } void Application::restoreFactorySettings() { try { printf("Restore system factory settings...\r\n"); system("/customer/reset-key -Pweb"); } catch (...) { } reboot(2000); } void Application::reboot(uint32_t delay) { _delayRebootThread.startFunc([=]() -> void { logger().warning("Reboot after %u ms ...", delay); Poco::Thread::sleep(delay); exit(); ::sync(); if (system("reboot") != 0) logger().error("System reboot command failed!"); ::reboot(RB_AUTOBOOT); }); } void Application::setSystemTime(uint32_t timestamp, int timezone) { struct timeval tv; tv.tv_sec = timestamp; tv.tv_usec = 0; settimeofday(&tv, NULL); try { std::string cmd = ""; if (timezone >= 0) { cmd = Poco::format("ln -snf /customer/zoneinfo/Etc/GMT-%d /etc/localtime", timezone); } else { cmd = Poco::format("ln -snf /customer/zoneinfo/Etc/GMT+%d /etc/localtime", -1 * timezone); } system(cmd.c_str()); } catch (const std::exception& e) { std::cerr << e.what() << '\n'; } system("hwclock -w -l"); } void Application::exit() { ApplicationExitNotify.notify(this); _exitRequst = true; } void Application::upgrade(const std::string& file) { #if defined(FIRMWARE_UPGRADE_FROM_BACKUP_PARTITION) Poco::File("/customer/DIRTY").createFile(); logger().warning("Reboot to upgrade firmware ...."); #else std::string specCharacters[] = { "\\", " ", "\"", "'", "(", ")", "*", "!", "$", "%", "&", ">", "<", "|", "`", }; for (auto& c : specCharacters) file = Poco::replace(file, c, "\\" + c); Poco::Pipe inPipe, outPipe; Poco::Process::Args args; Poco::ProcessHandle handle = Poco::Process::launch("sh", args, &inPipe, &outPipe, 0); Poco::PipeOutputStream outputStream(inPipe); std::string tmpdir = "/tmp/upgrade"; outputStream << Poco::format("mkdir -p %s", tmpdir) << std::endl; outputStream << Poco::format("tar xf %s -C %s", file, tmpdir) << std::endl; outputStream << Poco::format("%s/upgrade.sh", tmpdir) << std::endl; outputStream.flush(); outputStream.close(); handle.wait(); Poco::PipeInputStream inputStream(outPipe); std::string str; Poco::StreamCopier::copyToString(inputStream, str); logger().information("Firmware upgrade complete, reboot...."); #endif reboot(2000); }