/**************************************************************************** * This file is part of the project AqHome. * AqHome (c) by 2023 Martin Preuss, all rights reserved. * * The license for this file can be found in the file COPYING which you * should have received along with this file. ****************************************************************************/ #ifdef HAVE_CONFIG_H # include #endif #include "aqhome/aqhome.h" #include #include #include #include #include #include #include #include #define AQHOME_PM_LIBNAME "aqhome" #define AQHOME_PM_SYSCONFDIR "sysconfdir" #define AQHOME_PM_DATADIR "datadir" #define AQHOME_PM_RTDATADIR "rtdatadir" #define AQHOME_PM_LOCALEDIR "localedir" #define AQHOME_SYSCONFIG_FILE "aqhome.conf" static void _initLogging(void); static void _finiLogging(void); static void _initPathManager(void); static void _finiPathManager(void); static void _initI18n(void); static void _definePath(const char *pathName, const char *pathValue); static GWEN_STRINGLIST *_getListOfMatchingFiles(const char *pathName, const char *subFolder, const char *mask); static GWEN_BUFFER *_getRuntimeFilePath(const char *pathName, const char *sFilename); static GWEN_BUFFER *_findFileinPath(const char *pathName, const char *sFilename); static int _readUint8DataFromString(const char *s, uint16_t *pDataVal, uint16_t *pDataDenom); static int _readUint16DataFromString(const char *s, uint16_t *pDataVal, uint16_t *pDataDenom); static int _readUint32DataFromString(const char *s, uint16_t *pDataVal, uint16_t *pDataDenom); int AQH_Init(void) { int rv; rv=GWEN_Init(); if (rv) { DBG_ERROR_ERR(AQH_LOGDOMAIN, rv); return rv; } _initLogging(); _initPathManager(); _initI18n(); return 0; } void AQH_Fini(void) { _finiPathManager(); _finiLogging(); GWEN_Fini(); } GWEN_STRINGLIST *AQH_GetGlobalDataDirs(void) { return GWEN_PathManager_GetPaths(AQHOME_PM_LIBNAME, AQHOME_PM_DATADIR); } GWEN_STRINGLIST *AQH_GetGlobalSysconfDirs(void) { return GWEN_PathManager_GetPaths(AQHOME_PM_LIBNAME, AQHOME_PM_SYSCONFDIR); } GWEN_STRINGLIST *AQH_GetListOfMatchingDataFiles(const char *subFolder, const char *mask) { return _getListOfMatchingFiles(AQHOME_PM_DATADIR, subFolder, mask); } GWEN_STRINGLIST *AQH_GetListOfMatchingRuntimeDataFiles(const char *subFolder, const char *mask) { return _getListOfMatchingFiles(AQHOME_PM_RTDATADIR, subFolder, mask); } GWEN_STRINGLIST *AQH_GetListOfMatchingSysconfFiles(const char *subFolder, const char *mask) { return _getListOfMatchingFiles(AQHOME_PM_SYSCONFDIR, subFolder, mask); } GWEN_BUFFER *AQH_GetRuntimeFilePath(const char *sFilename) { return _getRuntimeFilePath(AQHOME_PM_RTDATADIR, sFilename); } GWEN_BUFFER *AQH_FindPathOfRuntimeFile(const char *sFilename) { return _findFileinPath(AQHOME_PM_RTDATADIR, sFilename); } GWEN_BUFFER *AQH_FindPathOfSysconfFile(const char *sFilename) { return _findFileinPath(AQHOME_PM_SYSCONFDIR, sFilename); } GWEN_BUFFER *AQH_FindPathOfDataFile(const char *sFilename) { return _findFileinPath(AQHOME_PM_DATADIR, sFilename); } GWEN_DB_NODE *AQH_LoadConfigFile(void) { GWEN_BUFFER *fbuf; int rv; fbuf=GWEN_Buffer_new(0, 256, 0, 1); rv=GWEN_PathManager_FindFile(AQHOME_PM_LIBNAME, AQHOME_PM_SYSCONFDIR, AQHOME_SYSCONFIG_FILE, fbuf); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "Config file \"%s\" not found (%d)", AQHOME_SYSCONFIG_FILE, rv); GWEN_Buffer_free(fbuf); return NULL; } else { GWEN_DB_NODE *db; db=GWEN_DB_Group_new("aqhome-config"); rv=GWEN_DB_ReadFile(db, GWEN_Buffer_GetStart(fbuf), GWEN_DB_FLAGS_DEFAULT); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "Error reading config file \"%s\" (%d)", AQHOME_SYSCONFIG_FILE, rv); GWEN_Buffer_free(fbuf); GWEN_DB_Group_free(db); return NULL; } GWEN_Buffer_free(fbuf); return db; } } void AQH_MergeConfigFileIntoConfig(GWEN_DB_NODE *dbArgs, const char *destDbGroupName) { GWEN_DB_NODE *dbConfig; dbConfig=AQH_LoadConfigFile(); if (dbConfig) { GWEN_DB_GroupRename(dbConfig, destDbGroupName); GWEN_DB_AddGroup(dbArgs, dbConfig); } } int AQH_ValueType_fromString(const char *s) { if (s) { if (strcasecmp(s, "sensor")==0) return AQH_ValueType_Sensor; else if (strcasecmp(s, "actor")==0) return AQH_ValueType_Actor; } return AQH_ValueType_Unknown; } const char *AQH_ValueType_toString(int i) { switch (i) { case AQH_ValueType_Sensor: return "sensor"; case AQH_ValueType_Actor: return "actor"; case AQH_ValueType_Unknown: default: return "unknown"; } } int AQH_ValueDataType_fromString(const char *s) { if (s) { if (strcasecmp(s, "int")==0) return AQH_ValueDataType_Int; else if (strcasecmp(s, "dword")==0) return AQH_ValueDataType_Uint32; else if (strcasecmp(s, "rational")==0) return AQH_ValueDataType_Rational; else if (strcasecmp(s, "uint8")==0) return AQH_ValueDataType_Uint8; else if (strcasecmp(s, "uint16")==0) return AQH_ValueDataType_Uint16; else if (strcasecmp(s, "uint32")==0) return AQH_ValueDataType_Uint32; } return AQH_ValueDataType_Unknown; } const char *AQH_ValueDataType_toString(int i) { switch(i) { case AQH_ValueDataType_Int: return "int"; case AQH_ValueDataType_Rational: return "rational"; case AQH_ValueDataType_Uint8: return "uint8"; case AQH_ValueDataType_Uint16: return "uint16"; case AQH_ValueDataType_Uint32: return "uint32"; case AQH_ValueDataType_Unknown: default: return "unknown"; } } int AQH_ValueModality_fromString(const char *s) { if (s) { if (strcasecmp(s, "temperature")==0) return AQH_ValueModality_Temperature; else if (strcasecmp(s, "humidity")==0) return AQH_ValueModality_Humidity; else if (strcasecmp(s, "door")==0) return AQH_ValueModality_Door; else if (strcasecmp(s, "rgb")==0) return AQH_ValueModality_RGB; else if (strcasecmp(s, "rgbw")==0) return AQH_ValueModality_RGBW; else if (strcasecmp(s, "motion")==0) return AQH_ValueModality_Motion; else if (strcasecmp(s, "co2")==0) return AQH_ValueModality_Co2; else if (strcasecmp(s, "tvoc")==0) return AQH_ValueModality_TVOC; else if (strcasecmp(s, "stats")==0) return AQH_ValueModality_Stats; else if (strcasecmp(s, "light")==0) return AQH_ValueModality_Light; } return AQH_ValueModality_Unknown; } const char *AQH_ValueModality_toString(int i) { switch(i) { case AQH_ValueModality_Temperature: return "temperature"; case AQH_ValueModality_Humidity: return "humidity"; case AQH_ValueModality_Door: return "door"; case AQH_ValueModality_RGB: return "rgb"; case AQH_ValueModality_RGBW: return "rgbw"; case AQH_ValueModality_Motion: return "motion"; case AQH_ValueModality_Co2: return "co2"; case AQH_ValueModality_TVOC: return "tvoc"; case AQH_ValueModality_Stats: return "stats"; case AQH_ValueModality_Light: return "light"; case AQH_ValueModality_Unknown: default: return "unknown"; } } void _initLogging(void) { const char *s; if (!GWEN_Logger_IsOpen(AQH_LOGDOMAIN)) GWEN_Logger_Open(AQH_LOGDOMAIN, "aqhome", 0, GWEN_LoggerType_Console, GWEN_LoggerFacility_User); s=getenv("AQHOME_LOGLEVEL"); if (s && *s) { GWEN_LOGGER_LEVEL ll; ll=GWEN_Logger_Name2Level(s); GWEN_Logger_SetLevel(AQH_LOGDOMAIN, ll); } else GWEN_Logger_SetLevel(AQH_LOGDOMAIN, GWEN_LoggerLevel_Notice); } void _finiLogging(void) { GWEN_Logger_Close(AQH_LOGDOMAIN); } void _initPathManager(void) { _definePath(AQHOME_PM_SYSCONFDIR, AQHOME_SYSCONF_DIR); _definePath(AQHOME_PM_LOCALEDIR, AQHOME_SYSCONF_DIR); _definePath(AQHOME_PM_DATADIR, AQHOME_DATA_DIR); _definePath(AQHOME_PM_RTDATADIR, AQHOME_RTDATA_DIR); } void _finiPathManager(void) { GWEN_PathManager_UndefinePath(AQHOME_PM_LIBNAME, AQHOME_PM_LOCALEDIR); GWEN_PathManager_UndefinePath(AQHOME_PM_LIBNAME, AQHOME_PM_RTDATADIR); GWEN_PathManager_UndefinePath(AQHOME_PM_LIBNAME, AQHOME_PM_DATADIR); GWEN_PathManager_UndefinePath(AQHOME_PM_LIBNAME, AQHOME_PM_SYSCONFDIR); GWEN_PathManager_RemovePaths(AQHOME_PM_LIBNAME); } void _initI18n(void) { GWEN_STRINGLIST *sl; sl=GWEN_PathManager_GetPaths(AQHOME_PM_LIBNAME, AQHOME_PM_LOCALEDIR); if (sl) { const char *localedir; int rv; localedir=GWEN_StringList_FirstString(sl); rv=GWEN_I18N_BindTextDomain_Dir(PACKAGE, localedir); if (rv) { DBG_ERROR(AQH_LOGDOMAIN, "Could not bind textdomain (%d)", rv); } else { rv=GWEN_I18N_BindTextDomain_Codeset(PACKAGE, "UTF-8"); if (rv) { DBG_ERROR(AQH_LOGDOMAIN, "Could not set codeset (%d)", rv); } } GWEN_StringList_free(sl); } } void _definePath(const char *pathName, const char *pathValue) { /* define sysconf paths */ GWEN_PathManager_DefinePath(AQHOME_PM_LIBNAME, pathName); #if defined(OS_WIN32) || defined(ENABLE_LOCAL_INSTALL) /* add folder relative to EXE */ GWEN_PathManager_AddRelPath(AQHOME_PM_LIBNAME, AQHOME_PM_LIBNAME, pathName, pathValue, GWEN_PathManager_RelModeExe); #else /* add absolute folder */ GWEN_PathManager_AddPath(AQHOME_PM_LIBNAME, AQHOME_PM_LIBNAME, pathName, pathValue); #endif } GWEN_STRINGLIST *_getListOfMatchingFiles(const char *pathName, const char *subFolder, const char *mask) { int rv; GWEN_STRINGLIST *sl; sl=GWEN_StringList_new(); rv=GWEN_PathManager_GetMatchingFilesRecursively(AQHOME_PM_LIBNAME, pathName, subFolder, sl, mask); if (rv<0) { DBG_INFO(AQH_LOGDOMAIN, "Error listing matching data files (folder=%s, mask=%s)", subFolder?subFolder:"", mask?mask:""); GWEN_StringList_free(sl); return NULL; } return sl; } GWEN_BUFFER *_getRuntimeFilePath(const char *pathName, const char *sFilename) { GWEN_STRINGLIST *sl; sl=GWEN_PathManager_GetPaths(AQHOME_PM_LIBNAME, pathName); if (sl) { GWEN_STRINGLISTENTRY *se; se=GWEN_StringList_FirstEntry(sl); if (se) { const char *s; s=GWEN_StringListEntry_Data(se); if (s && *s) { GWEN_BUFFER *buf; buf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(buf, s); if (sFilename && *sFilename) { GWEN_Buffer_AppendByte(buf, GWEN_DIR_SEPARATOR); GWEN_Buffer_AppendString(buf, sFilename); } GWEN_StringList_free(sl); return buf; } } GWEN_StringList_free(sl); } return NULL; } GWEN_BUFFER *_findFileinPath(const char *pathName, const char *sFilename) { GWEN_STRINGLIST *sl; sl=GWEN_PathManager_GetPaths(AQHOME_PM_LIBNAME, pathName); if (sl) { int rv; GWEN_BUFFER *buf; buf=GWEN_Buffer_new(0, 256, 0, 1); rv=GWEN_Directory_FindFileInPaths(sl, sFilename, buf); GWEN_StringList_free(sl); if (rv==0) return buf; GWEN_Buffer_free(buf); } return NULL; } int AQH_ReadDataFromString(int dataType, const char *s, uint16_t *pDataVal, uint16_t *pDataDenom) { if (s && *s) { //DBG_ERROR(NULL, "Reading \"%s\" as datatype %d (%s)", s?s:"", dataType, AQH_ValueDataType_toString(dataType)); switch(dataType) { case AQH_ValueDataType_Uint8: return _readUint8DataFromString(s, pDataVal, pDataDenom); case AQH_ValueDataType_Int: case AQH_ValueDataType_Uint16: return _readUint16DataFromString(s, pDataVal, pDataDenom); case AQH_ValueDataType_Uint32: return _readUint32DataFromString(s, pDataVal, pDataDenom); case AQH_ValueDataType_Rational: break; default: break; } } return GWEN_ERROR_INVALID; } int _readUint8DataFromString(const char *s, uint16_t *pDataVal, uint16_t *pDataDenom) { int v=0; if (1==sscanf(s, "%i", &v)) { *pDataVal=v & 0xff; *pDataDenom=1; return 0; } return GWEN_ERROR_INVALID; } int _readUint16DataFromString(const char *s, uint16_t *pDataVal, uint16_t *pDataDenom) { int v=0; if (1==sscanf(s, "%i", &v)) { *pDataVal=v & 0xffff; *pDataDenom=1; return 0; } return GWEN_ERROR_INVALID; } int _readUint32DataFromString(const char *s, uint16_t *pDataVal, uint16_t *pDataDenom) { long int v=0; if (1==sscanf(s, "%li", &v)) { *pDataVal=(v>>16) & 0xffff; *pDataDenom=v & 0xffff; return 0; } return GWEN_ERROR_INVALID; }