forked from gary/ems
2
0
Fork 0
sun_ems/ems_c/app/app_task_regedit.c

516 lines
18 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*****************************************************************************
* @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_config4G相关配置
* @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));
// }
// }