#include <signal.h>
#include <iostream>
#include <thread>
#include <sstream>
#include "../include/Gobbledegook.h"
static const int kMaxAsyncInitTimeoutMS = 30 * 1000;
static uint8_t serverDataBatteryLevel = 78;
static std::string serverDataTextString = "Hello, world!";
enum LogLevel
{
Debug,
Verbose,
Normal,
ErrorsOnly
};
LogLevel logLevel = Normal;
void LogDebug(const char *pText) { if (logLevel <= Debug) { std::cout << " DEBUG: " << pText << std::endl; } }
void LogInfo(const char *pText) { if (logLevel <= Verbose) { std::cout << " INFO: " << pText << std::endl; } }
void LogStatus(const char *pText) { if (logLevel <= Normal) { std::cout << " STATUS: " << pText << std::endl; } }
void LogWarn(const char *pText) { std::cout << "WARNING: " << pText << std::endl; }
void LogError(const char *pText) { std::cout << "!!ERROR: " << pText << std::endl; }
void LogFatal(const char *pText) { std::cout << "**FATAL: " << pText << std::endl; }
void LogAlways(const char *pText) { std::cout << "..Log..: " << pText << std::endl; }
void LogTrace(const char *pText) { std::cout << "-Trace-: " << pText << std::endl; }
void signalHandler(int signum)
{
switch (signum)
{
case SIGINT:
LogStatus("SIGINT recieved, shutting down");
ggkTriggerShutdown();
break;
case SIGTERM:
LogStatus("SIGTERM recieved, shutting down");
ggkTriggerShutdown();
break;
}
}
const void *dataGetter(const char *pName)
{
if (nullptr == pName)
{
LogError("NULL name sent to server data getter");
return nullptr;
}
std::string strName = pName;
if (strName == "battery/level")
{
return &serverDataBatteryLevel;
}
else if (strName == "text/string")
{
return serverDataTextString.c_str();
}
LogWarn((std::string("Unknown name for server data getter request: '") + pName + "'").c_str());
return nullptr;
}
int dataSetter(const char *pName, const void *pData)
{
if (nullptr == pName)
{
LogError("NULL name sent to server data setter");
return 0;
}
if (nullptr == pData)
{
LogError("NULL pData sent to server data setter");
return 0;
}
std::string strName = pName;
if (strName == "battery/level")
{
serverDataBatteryLevel = *static_cast<const uint8_t *>(pData);
LogDebug((std::string("Server data: battery level set to ") + std::to_string(serverDataBatteryLevel)).c_str());
return 1;
}
else if (strName == "text/string")
{
serverDataTextString = static_cast<const char *>(pData);
LogDebug((std::string("Server data: text string set to '") + serverDataTextString + "'").c_str());
return 1;
}
LogWarn((std::string("Unknown name for server data setter request: '") + pName + "'").c_str());
return 0;
}
int main(int argc, char **ppArgv)
{
for (int i = 1; i < argc; ++i)
{
std::string arg = ppArgv[i];
if (arg == "-q")
{
logLevel = ErrorsOnly;
}
else if (arg == "-v")
{
logLevel = Verbose;
}
else if (arg == "-d")
{
logLevel = Debug;
}
else
{
LogFatal((std::string("Unknown parameter: '") + arg + "'").c_str());
LogFatal("");
LogFatal("Usage: standalone [-q | -v | -d]");
return -1;
}
}
signal(SIGINT, signalHandler);
signal(SIGTERM, signalHandler);
ggkLogRegisterDebug(LogDebug);
ggkLogRegisterInfo(LogInfo);
ggkLogRegisterStatus(LogStatus);
ggkLogRegisterWarn(LogWarn);
ggkLogRegisterError(LogError);
ggkLogRegisterFatal(LogFatal);
ggkLogRegisterAlways(LogAlways);
ggkLogRegisterTrace(LogTrace);
if (!ggkStart(dataGetter, dataSetter, kMaxAsyncInitTimeoutMS))
{
return -1;
}
while (ggkGetServerRunState() < EStopping)
{
std::this_thread::sleep_for(std::chrono::seconds(15));
serverDataBatteryLevel = std::max(serverDataBatteryLevel - 1, 0);
ggkNofifyUpdatedCharacteristic("/com/gobbledegook/battery/level");
}
if (!ggkWait())
{
return -1;
}
return ggkGetServerHealth() == EOk ? 0 : 1;
}