p26001-store-acs-soc-fw-app/Application.cpp
2026-09-28 21:33:04 +08:00

308 lines
8.2 KiB
C++

/*
*******************************************************************************
* INCLUDE
*******************************************************************************
*/
#include "Application.h"
#ifdef USING_NETWORK_SUBSYSTEM
#include "NetworkSubsystem.h"
#endif
#ifdef USING_GRAPHICS_SUBSYSTEM
#include "GraphicsSubsystem.h"
#endif
#include <Poco/Dynamic/Var.h>
#include <Poco/File.h>
#include <Poco/FileStream.h>
#include <Poco/JSON/Object.h>
#include <Poco/JSON/Parser.h>
#include <Poco/JSON/PrintHandler.h>
#include <Poco/Net/DNS.h>
#include <Poco/Net/IPAddress.h>
#include <Poco/Net/NetworkInterface.h>
#include <Poco/Path.h>
#include <Poco/Pipe.h>
#include <Poco/PipeStream.h>
#include <Poco/Process.h>
#include <Poco/StreamCopier.h>
#include <Poco/Timespan.h>
#include <Poco/Util/JSONConfiguration.h>
#include <Poco/Util/Timer.h>
#include <Poco/Checksum.h>
#include <atca_basic.h>
#include <atca_cfgs.h>
#include <atca_device.h>
#include <host/atca_host.h>
#include <sys/stat.h>
#include <iostream>
#include <fstream>
#include <arpa/inet.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/reboot.h>
#include <sys/time.h>
#include <time.h>
#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<std::string>& 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<Poco::Util::JSONConfiguration>(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<Poco::Util::JSONConfiguration>(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<Poco::Util::JSONConfiguration>(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);
}