516 lines
18 KiB
C
516 lines
18 KiB
C
/*****************************************************************************
|
||
* @copyright 1997-2050, . POWER SUPPLY CO., LTD.
|
||
* @file app_task_regedit.c
|
||
* @brief xx功能
|
||
* @author Gary
|
||
* @date 2024-09-05
|
||
* @remark
|
||
*****************************************************************************/
|
||
#define _XOPEN_SOURCE 700
|
||
#include <errno.h>
|
||
#include "kit_db.h"
|
||
#include "drv_4g.h"
|
||
#include "drv_wifi.h"
|
||
#include "mw_schedule_handle.h"
|
||
#include "app_task_regedit.h"
|
||
|
||
// /*****************************************************************************
|
||
// * @brief 将 YYYY/DD/MM HH:MM:SS 格式的字符串转换为 timeval 结构体
|
||
// * @param[in] timeString: YYYY/DD/MM HH:MM:SS 格式的时间字符串
|
||
// * @param[out] tv: 转换后的 timeval 结构体指针
|
||
// * @return 0: 成功;1: 失败 (无效的时间字符串格式或转换错误)
|
||
// *****************************************************************************/
|
||
// static int stringToTimeval(const char *timeString, struct timeval *tv)
|
||
// {
|
||
// struct tm tm = {0}; // 初始化 tm 结构体
|
||
// char *strptime_result;
|
||
// time_t t;
|
||
|
||
// // 检查字符串长度
|
||
// if (strlen(timeString) != 19)
|
||
// {
|
||
// KITLOG(LOG_APP_EN, ERROR_EN, "错误:时间字符串长度错误: %s\n", timeString);
|
||
// return 1;
|
||
// }
|
||
|
||
// // 使用 strptime 解析时间字符串,注意格式字符串要与 timeString 格式完全匹配
|
||
// strptime_result = strptime(timeString, "%Y/%m/%d %H:%M:%S", &tm); // 修改为 %m/%d
|
||
// if (strptime_result == NULL)
|
||
// {
|
||
// KITLOG(LOG_APP_EN, ERROR_EN, "错误:strptime 解析时间字符串失败: %s\n", timeString);
|
||
// return 1;
|
||
// }
|
||
|
||
// // 将 struct tm 转换为 time_t
|
||
// t = mktime(&tm);
|
||
// if (t == -1)
|
||
// {
|
||
// KITLOG(LOG_APP_EN, ERROR_EN, "错误:mktime 转换失败: %s\n", timeString);
|
||
// return 1;
|
||
// }
|
||
|
||
// tv->tv_sec = t;
|
||
// tv->tv_usec = 0;
|
||
// return 0;
|
||
// }
|
||
|
||
/*********************************************************************
|
||
* @brief EMS时间处理初始化函数,根据配置信息设置系统时间(NTP或手动)
|
||
* @param[in] rtc_dev_config: 设备配置信息 (包含NTP和手动时间设置参数,通常为JSON格式)
|
||
* @return 0: 成功;1: 失败 (内存分配失败,JSON解析失败,NTP同步失败,或设置系统时间失败)
|
||
*********************************************************************/
|
||
static int systimeInitHandle(ems_dev_config_t *rtc_dev_config)
|
||
{
|
||
int ret = 0;
|
||
ems_dev_rtc_config_t rtcInfo = {0}; // 使用局部变量,函数结束时自动释放内存
|
||
cJSON *json_obj = cJSON_Parse((const char *)rtc_dev_config->content); // 解析JSON配置字符串
|
||
|
||
if (json_obj == NULL)
|
||
{
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "错误:解析JSON配置失败: %s\n", cJSON_GetErrorPtr());
|
||
return 1;
|
||
}
|
||
|
||
cJSON *item;
|
||
|
||
// 安全地获取JSON对象中的各个字段
|
||
item = cJSON_GetObjectItem(json_obj, "isNtp");
|
||
rtcInfo.isNtp = (item != NULL && cJSON_IsNumber(item)) ? item->valueint : 0;
|
||
|
||
// 判断是否使用 NTP 自动对时
|
||
if (rtcInfo.isNtp)
|
||
{
|
||
item = cJSON_GetObjectItem(json_obj, "port");
|
||
rtcInfo.port = (item != NULL && cJSON_IsNumber(item)) ? item->valueint : 0;
|
||
|
||
item = cJSON_GetObjectItem(json_obj, "address");
|
||
strncpy((char *)rtcInfo.address, (item != NULL && cJSON_IsString(item)) ? item->valuestring : "", MAX_ADDR_LEN);
|
||
rtcInfo.address[MAX_ADDR_LEN - 1] = '\0'; // 确保字符串以'\0'结尾
|
||
ret = sync_ntp_timestamp((char *)rtcInfo.address, rtcInfo.port, (char *)AdvancedSettingTable[kLinux_Password].value); // 调用NTP对时函数
|
||
if (ret != 0)
|
||
{
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "错误:NTP同步失败: %s\n", strerror(errno));
|
||
}
|
||
}
|
||
// 自启动时不进行手动对时
|
||
// else
|
||
// {
|
||
// item = cJSON_GetObjectItem(json_obj, "manualTime");
|
||
// strncpy((char *)rtcInfo.manualTime, (item != NULL && cJSON_IsString(item)) ? item->valuestring : "", sizeof(rtcInfo.manualTime));
|
||
// rtcInfo.manualTime[sizeof(rtcInfo.manualTime) - 1] = '\0'; // 确保字符串以'\0'结尾
|
||
|
||
// struct timeval tv;
|
||
// if (stringToTimeval((const char *)rtcInfo.manualTime, &tv) != 0)
|
||
// {
|
||
// return 1; // stringToTimeval函数已经打印了错误信息
|
||
// }
|
||
// time_t seconds = tv.tv_sec;
|
||
// ret = setSysTime(seconds); // 使用bsp_rtc.c中的setSysTime函数设置系统时间
|
||
// if (ret != 0)
|
||
// {
|
||
// KITLOG(LOG_APP_EN, ERROR_EN, "错误:设置系统时间失败\n");
|
||
// return 1;
|
||
// }
|
||
// }
|
||
cJSON_Delete(json_obj); // 释放JSON对象
|
||
|
||
return ret;
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @brief 初始化系统的IP、mack地址、网关等配置
|
||
* @param[in] eth_dev_config: 以太网口配置信息
|
||
* @return 0-成功 1-失败
|
||
*********************************************************************/
|
||
static int netInitHandble(ems_dev_config_t *eth_dev_config)
|
||
{
|
||
int ret = 0;
|
||
ems_dev_eth_config_t ethInfo = {0}; // 使用局部变量,函数结束时自动释放内存
|
||
cJSON *json_obj = cJSON_Parse((const char *)eth_dev_config->content); // 解析JSON配置字符串
|
||
|
||
if (json_obj == NULL)
|
||
{
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "错误:解析JSON配置失败: %s\n", cJSON_GetErrorPtr());
|
||
return 1;
|
||
}
|
||
|
||
cJSON *item;
|
||
|
||
// 安全地获取JSON对象中的各个字段
|
||
item = cJSON_GetObjectItem(json_obj, "netId");
|
||
ethInfo.netId = (item != NULL && cJSON_IsNumber(item)) ? item->valueint : 0;
|
||
|
||
item = cJSON_GetObjectItem(json_obj, "isDHCP");
|
||
ethInfo.isDHCP = (item != NULL && cJSON_IsNumber(item)) ? item->valueint : 0;
|
||
|
||
item = cJSON_GetObjectItem(json_obj, "address");
|
||
strncpy((char *)ethInfo.address, (item != NULL && cJSON_IsString(item)) ? item->valuestring : "", MAX_ADDR_LEN);
|
||
ethInfo.address[MAX_ADDR_LEN - 1] = '\0'; // 确保字符串以'\0'结尾
|
||
|
||
char temp[300] = {0}; // 命令缓冲区
|
||
char buffer[256]; // 获取执行返回结果
|
||
|
||
// 关闭netplan自动覆盖IP配置
|
||
snprintf(temp, sizeof(temp), "systemctl stop systemd-networkd.service"); // 使用 DHCP 获取 IP
|
||
ret = kit_popen_exec(temp, buffer, sizeof(buffer));
|
||
if (ret != 0)
|
||
{
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "systemctl 执行失败: %s\n", temp);
|
||
return 1;
|
||
}
|
||
|
||
// 判断是否使用 DHCP 动态分配 IP
|
||
if (ethInfo.isDHCP == 1)
|
||
{
|
||
snprintf(temp, sizeof(temp), "udhcpc -i eth%d -n", ethInfo.netId); // 使用 DHCP 获取 IP
|
||
ret = kit_popen_exec(temp, buffer, sizeof(buffer));
|
||
if (ret != 0)
|
||
{
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "udhcpc 执行失败: %s\n", temp);
|
||
return 1;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
item = cJSON_GetObjectItem(json_obj, "ip");
|
||
strncpy((char *)ethInfo.ip, (item != NULL && cJSON_IsString(item)) ? item->valuestring : "", MAX_IP_LEN);
|
||
ethInfo.ip[MAX_IP_LEN - 1] = '\0'; // 确保字符串以'\0'结尾
|
||
|
||
item = cJSON_GetObjectItem(json_obj, "mask");
|
||
strncpy((char *)ethInfo.mask, (item != NULL && cJSON_IsString(item)) ? item->valuestring : "", MAX_IP_LEN);
|
||
ethInfo.mask[MAX_IP_LEN - 1] = '\0'; // 确保字符串以'\0'结尾
|
||
|
||
item = cJSON_GetObjectItem(json_obj, "gateway");
|
||
strncpy((char *)ethInfo.gateway, (item != NULL && cJSON_IsString(item)) ? item->valuestring : "", MAX_IP_LEN);
|
||
ethInfo.gateway[MAX_IP_LEN - 1] = '\0'; // 确保字符串以'\0'结尾
|
||
|
||
snprintf(temp, sizeof(temp), "ifconfig eth%d %s netmask %s",
|
||
ethInfo.netId, ethInfo.ip, ethInfo.mask); // 静态分配 IP 地址和子网掩码
|
||
|
||
KITPTF(LOG_APP_EN, INFO_EN, "执行IP设置:%s", temp);
|
||
|
||
ret = kit_popen_exec(temp, buffer, sizeof(buffer));
|
||
if (ret != 0)
|
||
{
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "ifconfig 执行失败: %s\n", temp);
|
||
return 1;
|
||
}
|
||
|
||
// 设置网关(暂时不用网关地址)
|
||
// memset(temp, 0, sizeof(temp));
|
||
// snprintf(temp, sizeof(temp), "route add default gw %s eth%d", config->gateway, config->netId);
|
||
// ret = kit_popen_exec(temp, buffer, sizeof(buffer));
|
||
// if (ret != 0) {
|
||
// KITLOG(LOG_APP_EN, ERROR_EN, "route add default gw 执行失败: %s\n", temp);
|
||
// return 1;
|
||
// }
|
||
}
|
||
cJSON_Delete(json_obj); // 释放JSON对象
|
||
|
||
return ret;
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @brief 初始化系统Wifi配置
|
||
* @param[in] wifi_dev_config: wifi配置信息
|
||
* @return 0-成功 1-失败
|
||
*********************************************************************/
|
||
static int sysWifiInitHandle(ems_dev_config_t *wifi_dev_config)
|
||
{
|
||
int ret = 0;
|
||
drv_wifi_t wifiInfo = {0}; // 使用局部变量,函数结束时自动释放内存
|
||
cJSON *json_obj = cJSON_Parse((const char *)wifi_dev_config->content); // 解析JSON配置字符串
|
||
|
||
if (json_obj == NULL)
|
||
{
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "错误:解析JSON配置失败: %s\n", cJSON_GetErrorPtr());
|
||
return 1;
|
||
}
|
||
|
||
cJSON *item;
|
||
|
||
// 安全地获取JSON对象中的各个字段
|
||
item = cJSON_GetObjectItem(json_obj, "enable");
|
||
wifiInfo.enable = (item != NULL && cJSON_IsNumber(item)) ? item->valueint : 0;
|
||
// 在使能关闭时,直接返回
|
||
if (wifiInfo.enable == 0)
|
||
{
|
||
return ret;
|
||
}
|
||
|
||
item = cJSON_GetObjectItem(json_obj, "wifiName");
|
||
strncpy((char *)wifiInfo.wifiName, (item != NULL && cJSON_IsString(item)) ? item->valuestring : "", MAX_WIFI_NAME_LEN);
|
||
wifiInfo.wifiName[MAX_WIFI_NAME_LEN - 1] = '\0'; // 确保字符串以'\0'结尾
|
||
|
||
item = cJSON_GetObjectItem(json_obj, "wifiPassword");
|
||
strncpy((char *)wifiInfo.wifiPassword, (item != NULL && cJSON_IsString(item)) ? item->valuestring : "", MAX_WIFI_PASS_LEN);
|
||
wifiInfo.wifiPassword[MAX_WIFI_PASS_LEN - 1] = '\0'; // 确保字符串以'\0'结尾
|
||
|
||
cJSON_Delete(json_obj); // 释放JSON对象
|
||
|
||
ret = drvOpenWifi(&wifiInfo);
|
||
if (ret != 0)
|
||
{
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "错误:设置系统时间失败\n");
|
||
return 1;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @brief 初始化系统4G配置
|
||
* @param[in] fourthg_dev_config:4G相关配置
|
||
* @return 0-成功 1-失败
|
||
*********************************************************************/
|
||
static int sys4GInitHandle(ems_dev_config_t *fourthg_dev_config)
|
||
{
|
||
int ret = 0;
|
||
drv_4g_t fourthgInfo = {0}; // 使用局部变量,函数结束时自动释放内存
|
||
cJSON *json_obj = cJSON_Parse((const char *)fourthg_dev_config->content); // 解析JSON配置字符串
|
||
|
||
if (json_obj == NULL)
|
||
{
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "错误:解析JSON配置失败: %s\n", cJSON_GetErrorPtr());
|
||
return 1;
|
||
}
|
||
|
||
cJSON *item;
|
||
|
||
// 安全地获取JSON对象中的各个字段
|
||
item = cJSON_GetObjectItem(json_obj, "enable");
|
||
fourthgInfo.enable = (item != NULL && cJSON_IsNumber(item)) ? item->valueint : 0;
|
||
// 在使能关闭时,直接返回
|
||
if (fourthgInfo.enable == 0)
|
||
{
|
||
return ret;
|
||
}
|
||
|
||
item = cJSON_GetObjectItem(json_obj, "cmdContent");
|
||
strncpy((char *)fourthgInfo.cmdContent, (item != NULL && cJSON_IsString(item)) ? item->valuestring : "", MAX_CMD_4G_LEN);
|
||
fourthgInfo.cmdContent[MAX_CMD_4G_LEN - 1] = '\0'; // 确保字符串以'\0'结尾
|
||
|
||
cJSON_Delete(json_obj); // 释放JSON对象
|
||
|
||
ret = drvOpen4G(&fourthgInfo);
|
||
if (ret != 0)
|
||
{
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "错误:设置系统时间失败\n");
|
||
return 1;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @brief 初始化ems配置
|
||
* @param[in] void
|
||
* @return 0-成功 1-失败
|
||
*********************************************************************/
|
||
int initEmsConfig(void)
|
||
{
|
||
UT_array *emsDevConfigs = {0};
|
||
int ret = 0;
|
||
if (0 != kit_get_config_db_data(&emsDevConfigs))
|
||
{
|
||
return 1;
|
||
}
|
||
utarray_foreach(emsDevConfigs, ems_dev_config_t *, p_emsDevConfig)
|
||
{
|
||
switch (p_emsDevConfig->type)
|
||
{
|
||
case kEms_Config_Uart:
|
||
// 系统串口不需要初始化
|
||
break;
|
||
case kEms_Config_Net:
|
||
// 初始化系统的IP、MAC地址、网关等配置
|
||
ret = netInitHandble(p_emsDevConfig);
|
||
break;
|
||
case kEms_Config_DI:
|
||
break;
|
||
case kEms_Config_DO:
|
||
break;
|
||
case kEms_Config_Rtc:
|
||
// 初始化系统时间将rtc时钟同步到linux系统
|
||
ret = systimeInitHandle(p_emsDevConfig);
|
||
break;
|
||
case kEms_Config_Wifi:
|
||
ret = sysWifiInitHandle(p_emsDevConfig);
|
||
break;
|
||
case kEms_Config_4G:
|
||
ret = sys4GInitHandle(p_emsDevConfig);
|
||
break;
|
||
default:
|
||
printf("Unknown EMS device config type: %d\n", p_emsDevConfig->type);
|
||
ret = 1;
|
||
break;
|
||
}
|
||
if (ret != 0)
|
||
{
|
||
// 初始化失败,释放资源并返回错误
|
||
utarray_free(emsDevConfigs);
|
||
return 1;
|
||
}
|
||
}
|
||
// 释放数组内存
|
||
utarray_free(emsDevConfigs);
|
||
|
||
// gpio口初始化
|
||
ret = drvGpioOpen();
|
||
if (ret != 0)
|
||
{
|
||
return 1;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @brief 初始化数据库
|
||
* @param[in] void
|
||
* @return 0-成功 1-失败
|
||
*********************************************************************/
|
||
int initSqliteDb(void) // 初始化系统时间
|
||
{
|
||
int ret = 0;
|
||
// 初始化数据库,"./config"是打包里的sql文件路径
|
||
ret = kit_init_db("../initsql");
|
||
return ret;
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @brief EMS初始化
|
||
* @param[in] arg:相关配置
|
||
* @return 0-成功 1-失败
|
||
*********************************************************************/
|
||
uint8_t initEmsSystem(void *arg)
|
||
{
|
||
int ret = 0;
|
||
|
||
ret = initSqliteDb();
|
||
if (ret != 0)
|
||
{
|
||
KITPTF(LOG_APP_EN, ERROR_EN, "Sqlite数据库初始化失败!");
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "Sqlite数据库初始化失败!");
|
||
return ret;
|
||
}
|
||
|
||
#if HARDWARE_TYPE == -99
|
||
ret = initEmsConfig();
|
||
if (ret != 0)
|
||
{
|
||
KITPTF(LOG_APP_EN, ERROR_EN, "EMS盒子配置初始化失败!");
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "EMS盒子配置初始化失败!");
|
||
return ret;
|
||
}
|
||
#endif
|
||
|
||
ret = initDevInfo();
|
||
if (ret != 0)
|
||
{
|
||
KITPTF(LOG_APP_EN, ERROR_EN, "读取设备配置、电位配置信息失败!");
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "读取设备配置、电位配置信息失败!");
|
||
return ret;
|
||
}
|
||
|
||
ret = initNorthInfo();
|
||
if (ret != 0)
|
||
{
|
||
KITPTF(LOG_APP_EN, ERROR_EN, "读取北向配置失败!");
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "读取北向配置失败!");
|
||
return ret;
|
||
}
|
||
|
||
ret = initAdvancedSettingInfo();
|
||
if (ret != 0)
|
||
{
|
||
KITPTF(LOG_APP_EN, ERROR_EN, "读取高级配置失败!");
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "读取高级配置失败!");
|
||
return ret;
|
||
}
|
||
|
||
ret = initRtdb(rtdbType, NULL, kEE_SHM_CREAT);
|
||
if (ret != 0)
|
||
{
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "RTDB初始化失败!");
|
||
KITPTF(LOG_APP_EN, ERROR_EN, "RTDB初始化失败!");
|
||
return ret;
|
||
}
|
||
|
||
ret = initWebSign(kSign_ShMem, kEE_SHM_CREAT);
|
||
if (ret != 0)
|
||
{
|
||
KITLOG(LOG_APP_EN, ERROR_EN, "websign初始化失败!");
|
||
KITPTF(LOG_APP_EN, ERROR_EN, "websign初始化失败!");
|
||
return ret;
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @brief 创建任务的总入口
|
||
* @param[in] arg:相关配置
|
||
* @return void
|
||
*********************************************************************/
|
||
void regeditThreadEntry(void *map_t) // 创建线程入口
|
||
{
|
||
// 创建各种采集任务
|
||
|
||
creatUartModbusTaskEntry(&protoTable[kProto_ModbusRTU_Master]);
|
||
creatNetModbusTaskEntry(&protoTable[kProto_ModbusTCP_Master]);
|
||
creatGetLocalParamTaskEntry(100); // 100*50 ms 换算5秒执行一次
|
||
|
||
/* 创建各种转发任务 */
|
||
//creatNetMqttTaskEntry();
|
||
|
||
/*创建存储任务*/
|
||
creatScheduledStorageTask();
|
||
|
||
/*创建gpio任务*/
|
||
//creatGpioModTaskEntry(10); // 初始化 GPIO模块 10*50 ms 换算500ms执行一次
|
||
|
||
/*创建温控任务*/
|
||
//creatLogicTempCtrlEntry();
|
||
|
||
/*创建策略任务*/
|
||
//creatLogicCtrTaskEntry();
|
||
}
|
||
|
||
/*********************************************************************
|
||
* @brief 启动EMS的web后台
|
||
* @return void
|
||
*********************************************************************/
|
||
// void runEmsWebApi()
|
||
// {
|
||
// char temp[300] = {0};
|
||
// char buffer[256] = {0};
|
||
// char original_dir[500];
|
||
|
||
// // 获取当前工作目录
|
||
// if (getcwd(original_dir, sizeof(original_dir)) == NULL)
|
||
// {
|
||
// KITLOG(LOG_APP_EN, ERROR_EN, "获取当前工作目录失败: %s\n", strerror(errno));
|
||
// return;
|
||
// }
|
||
|
||
// // 更改工作目录
|
||
// if (chdir("/opt/ems") != 0)
|
||
// {
|
||
// KITLOG(LOG_APP_EN, ERROR_EN, "更改工作目录失败: %s\n", strerror(errno));
|
||
// return;
|
||
// }
|
||
|
||
// snprintf(temp, sizeof(temp), "nohup /opt/ems/edge-ems-server > /opt/ems/output.log 2>&1 &");
|
||
// int ret = kit_popen_exec(temp, buffer, sizeof(buffer));
|
||
// if (ret != 0)
|
||
// {
|
||
// KITLOG(LOG_APP_EN, ERROR_EN, "启动 Ems Web 失败: %s\n", buffer);
|
||
// }
|
||
|
||
// // 恢复原始工作目录
|
||
// if (chdir(original_dir) != 0)
|
||
// {
|
||
// KITLOG(LOG_APP_EN, ERROR_EN, "恢复原始工作目录失败: %s\n", strerror(errno));
|
||
// }
|
||
// }
|