#include <glib.h>
#include <string>
#include <fstream>
#include <regex>
#include "ServerUtils.h"
#include "DBusObject.h"
#include "DBusInterface.h"
#include "GattProperty.h"
#include "GattService.h"
#include "GattCharacteristic.h"
#include "GattDescriptor.h"
#include "Server.h"
#include "Logger.h"
#include "Utils.h"
namespace ggk {
static void addManagedObjectsNode(const DBusObject &object, const DBusObjectPath &basePath, GVariantBuilder *pObjectArray)
{
if (!object.isPublished())
{
return;
}
if (!object.getInterfaces().empty())
{
DBusObjectPath path = basePath + object.getPathNode();
Logger::debug(SSTR << " Object: " << path);
GVariantBuilder *pInterfaceArray = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
for (std::shared_ptr<const DBusInterface> pInterface : object.getInterfaces())
{
Logger::debug(SSTR << " + Interface (type: " << pInterface->getInterfaceType() << ")");
if (std::shared_ptr<const GattService> pService = TRY_GET_CONST_INTERFACE_OF_TYPE(pInterface, GattService))
{
if (!pService->getProperties().empty())
{
Logger::debug(SSTR << " GATT Service interface: " << pService->getName());
GVariantBuilder *pPropertyArray = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
for (const GattProperty &property : pService->getProperties())
{
Logger::debug(SSTR << " Property " << property.getName());
g_variant_builder_add
(
pPropertyArray,
"{sv}",
property.getName().c_str(),
property.getValue()
);
}
g_variant_builder_add
(
pInterfaceArray,
"{sa{sv}}",
pService->getName().c_str(),
pPropertyArray
);
}
}
else if (std::shared_ptr<const GattCharacteristic> pCharacteristic = TRY_GET_CONST_INTERFACE_OF_TYPE(pInterface, GattCharacteristic))
{
if (!pCharacteristic->getProperties().empty())
{
Logger::debug(SSTR << " GATT Characteristic interface: " << pCharacteristic->getName());
GVariantBuilder *pPropertyArray = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
for (const GattProperty &property : pCharacteristic->getProperties())
{
Logger::debug(SSTR << " Property " << property.getName());
g_variant_builder_add
(
pPropertyArray,
"{sv}",
property.getName().c_str(),
property.getValue()
);
}
g_variant_builder_add
(
pInterfaceArray,
"{sa{sv}}",
pCharacteristic->getName().c_str(),
pPropertyArray
);
}
}
else if (std::shared_ptr<const GattDescriptor> pDescriptor = TRY_GET_CONST_INTERFACE_OF_TYPE(pInterface, GattDescriptor))
{
if (!pDescriptor->getProperties().empty())
{
Logger::debug(SSTR << " GATT Descriptor interface: " << pDescriptor->getName());
GVariantBuilder *pPropertyArray = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
for (const GattProperty &property : pDescriptor->getProperties())
{
Logger::debug(SSTR << " Property " << property.getName());
g_variant_builder_add
(
pPropertyArray,
"{sv}",
property.getName().c_str(),
property.getValue()
);
}
g_variant_builder_add
(
pInterfaceArray,
"{sa{sv}}",
pDescriptor->getName().c_str(),
pPropertyArray
);
}
}
else
{
Logger::error(SSTR << " Unknown interface type");
return;
}
}
g_variant_builder_add
(
pObjectArray,
"{oa{sa{sv}}}",
path.c_str(),
pInterfaceArray
);
}
for (const DBusObject &child : object.getChildren())
{
addManagedObjectsNode(child, basePath + object.getPathNode(), pObjectArray);
}
}
void ServerUtils::getManagedObjects(GDBusMethodInvocation *pInvocation)
{
Logger::debug(SSTR << "Reporting managed objects");
GVariantBuilder *pObjectArray = g_variant_builder_new(G_VARIANT_TYPE_ARRAY);
for (const DBusObject &object : TheServer->getObjects())
{
addManagedObjectsNode(object, DBusObjectPath(""), pObjectArray);
}
GVariant *pParams = g_variant_new("(a{oa{sa{sv}}})", pObjectArray);
g_dbus_method_invocation_return_value(pInvocation, pParams);
}
std::string ServerUtils::getCpuInfo(int16_t &cpuCount)
{
static int16_t cachedCount = -1;
static std::string cachedModel;
static const std::string kCpuInfoFile = "/proc/cpuinfo";
if (cachedCount == -1)
{
cachedCount = 0;
std::ifstream cpuInfo(kCpuInfoFile);
if (cpuInfo.is_open())
{
std::string line;
while(getline(cpuInfo, line))
{
std::regex processorRegex("^processor.*: [0-9].*$", std::regex::ECMAScript);
std::smatch processorMatch;
if (std::regex_search(line, processorMatch, processorRegex))
{
cachedCount++;
}
if (cachedModel.empty())
{
std::regex modelRegex("^model name.*: (.*)$", std::regex::ECMAScript);
std::smatch modelMatch;
if (std::regex_search(line, modelMatch, modelRegex))
{
if (modelMatch.size() == 2)
{
cachedModel = Utils::trim(modelMatch[1].str());
}
}
}
}
cpuInfo.close();
}
if (cachedModel.empty()) { cachedModel = "Gooberfest Cyclemaster 3000 (v8)"; }
if (cachedCount == 0) { cachedCount = 42; }
}
cpuCount = cachedCount;
return cachedModel;
}
GVariant *ServerUtils::gvariantCurrentTime()
{
time_t timeValue = time(nullptr);
struct tm *pTimeStruct = localtime(&timeValue);
guint16 year = pTimeStruct->tm_year + 1900;
guint8 wday = guint8(pTimeStruct->tm_wday == 0 ? 7 : pTimeStruct->tm_wday);
g_auto(GVariantBuilder) builder;
g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
g_variant_builder_add(&builder, "y", (year >> 0) & 0xff);
g_variant_builder_add(&builder, "y", (year >> 8) & 0xff);
g_variant_builder_add(&builder, "y", guint8(pTimeStruct->tm_mon+1));
g_variant_builder_add(&builder, "y", guint8(pTimeStruct->tm_mday));
g_variant_builder_add(&builder, "y", guint8(pTimeStruct->tm_hour));
g_variant_builder_add(&builder, "y", guint8(pTimeStruct->tm_min));
g_variant_builder_add(&builder, "y", guint8(pTimeStruct->tm_sec));
g_variant_builder_add(&builder, "y", wday);
g_variant_builder_add(&builder, "y", guint8(0));
g_variant_builder_add(&builder, "y", guint8(0));
GVariant * const pVariant = g_variant_builder_end(&builder);
return pVariant;
}
GVariant *ServerUtils::gvariantLocalTime()
{
tzset();
time_t timeValue = time(nullptr);
struct tm *pTimeStruct = localtime(&timeValue);
gint8 utcOffset = -gint8(timezone / 60 / 15);
guint8 dstOffset = pTimeStruct->tm_isdst == 0 ? 0 : 4;
g_auto(GVariantBuilder) builder;
g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
g_variant_builder_add(&builder, "y", utcOffset);
g_variant_builder_add(&builder, "y", dstOffset);
GVariant * const pVariant = g_variant_builder_end(&builder);
return pVariant;
}
};