forked from gary/ems
2
0
Fork 0
sun_ems/ems_c/mw/mw_schedule_handle.c

948 lines
38 KiB
C
Raw Normal View History

2025-05-13 17:49:49 +08:00
/*****************************************************************************
* @copyright 2024-2024, . POWER SUPPLY CO., LTD.
* @file mw_schedule_save.h
* @brief RTDB数据保存到数据库
* @author Gary
* @date 2024/10/17
* @remark
*****************************************************************************/
#define _POSIX_C_SOURCE 199309L
#define UPGRADE_START_MESSAGE 1
#define UPGRADE_END_MESSAGE 0
#define EMS_CONFIG_START_MESSAGE 1
#define EMS_CONFIG_END_MESSAGE 0
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdint.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include "bsp_rtdb.h"
#include "bsp_data_mode.h"
#include "kit_db.h"
#include "kit_log.h"
#include "utextend.h"
2025-06-21 16:57:11 +08:00
2025-05-13 17:49:49 +08:00
#include "mw_schedule_handle.h"
#include "drv_4g.h"
#include "drv_wifi.h"
#include "bsp_ntp.h"
uint32_t exeCount = 0; // 线程执行次数计数器,用于取余数
UT_array* timedDataConfigs, * faultsDataConfigs; // 时序数据配置、故障数据配置
// 时序数据的ICD结构定义
static UT_icd timed_data_storage_icd =
{
sizeof(timed_data_storage_t),
NULL,
NULL,
NULL,
};
// 故障数据的ICD结构定义
static UT_icd faults_data_storage_icd =
{
sizeof(faults_data_storage_t),
NULL,
NULL,
NULL,
};
// 功率数据的ICD结构定义
static UT_icd power_data_storage_icd =
{
sizeof(power_data_storage_t),
NULL,
NULL,
NULL,
};
/*****************************************************************************
* @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 RTDB参数
* @param[in] devType
* @param[in] pointId
* @param[in] value
* @param[in] dataType
* @return
*****************************************************************************/
static void logic_getValue(dev_type_e devType, uint16_t pointId, void* value, data_type_e dataType)
{
switch (dataType)
{
case Uint8:
{
// 对于 uint8_t 类型
uint8_t* uint8Value = (uint8_t*)value;
for (uint16_t i = 0; i < gStDevTypeNum[devType]; i++)
{
uint8Value[i] = (uint8_t)getRtdbPointValue(Rtdb_ShMem, devType, i, pointId);
}
break;
}
case Int8:
{
// 对于 int8_t 类型
int8_t* int8Value = (int8_t*)value;
for (uint16_t i = 0; i < gStDevTypeNum[devType]; i++)
{
int8Value[i] = (int8_t)getRtdbPointValue(Rtdb_ShMem, devType, i, pointId);
}
break;
}
case Uint16:
{
// 对于 uint16_t 类型
uint16_t* uint16Value = (uint16_t*)value;
for (uint16_t i = 0; i < gStDevTypeNum[devType]; i++)
{
uint16Value[i] = (uint16_t)getRtdbPointValue(Rtdb_ShMem, devType, i, pointId);
}
break;
}
case Int16:
{
// 对于 int16_t 类型
int16_t* int16Value = (int16_t*)value;
for (uint16_t i = 0; i < gStDevTypeNum[devType]; i++)
{
int16Value[i] = (int16_t)getRtdbPointValue(Rtdb_ShMem, devType, i, pointId);
}
break;
}
case Uint32:
{
// 对于 uint32_t 类型
uint32_t* uint32Value = (uint32_t*)value;
for (uint16_t i = 0; i < gStDevTypeNum[devType]; i++)
{
uint32Value[i] = (uint32_t)getRtdbPointValue(Rtdb_ShMem, devType, i, pointId);
}
break;
}
case Int32:
{
// 对于 int32_t 类型
int32_t* int32Value = (int32_t*)value;
for (uint16_t i = 0; i < gStDevTypeNum[devType]; i++)
{
int32Value[i] = (int32_t)getRtdbPointValue(Rtdb_ShMem, devType, i, pointId);
}
break;
}
case Uint64:
{
// 对于 uint64_t 类型
uint64_t* uint64Value = (uint64_t*)value;
for (uint16_t i = 0; i < gStDevTypeNum[devType]; i++)
{
uint64Value[i] = (uint64_t)getRtdbPointValue(Rtdb_ShMem, devType, i, pointId);
}
break;
}
case Int64:
{
// 对于 int64_t 类型
int64_t* int64Value = (int64_t*)value;
for (uint16_t i = 0; i < gStDevTypeNum[devType]; i++)
{
int64Value[i] = (int64_t)getRtdbPointValue(Rtdb_ShMem, devType, i, pointId);
}
break;
}
case Float32:
{
// 对于 float_t (Float32) 类型
float_t* floatValue = (float_t*)value;
for (uint16_t i = 0; i < gStDevTypeNum[devType]; i++)
{
floatValue[i] = (float_t)getRtdbPointValue(Rtdb_ShMem, devType, i, pointId);
}
break;
}
case Float64:
{
// 对于 double (Float64) 类型
double* doubleValue = (double*)value;
for (uint16_t i = 0; i < gStDevTypeNum[devType]; i++)
{
doubleValue[i] = getRtdbPointValue(Rtdb_ShMem, devType, i, pointId);
}
break;
}
default:
// 不支持的类型
return;
}
return;
}
/*****************************************************************************
* @brief
* @param[in] timestamp:
*****************************************************************************/
static void deletePowerData(time_t timestamp)
{
struct tm tm_time;
localtime_r(&timestamp, &tm_time);
char time_str[32];
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &tm_time);
// 调用删除数据库函数
int ret = kit_del_power_data_by_date(time_str);
if (ret != 0)
{
KITLOG(LOG_WM_EN, ERROR_EN, "数据删除失败, date: %s", time_str);
}
}
/*****************************************************************************
* @brief
* @param[in] interval:
* @param[in] timestamp:
*****************************************************************************/
static void deleteTimedData(int interval, time_t timestamp)
{
struct tm tm_time;
localtime_r(&timestamp, &tm_time);
char time_str[32];
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &tm_time);
// 调用删除数据库函数
int ret = kit_del_timed_data_by_date(interval, time_str);
if (ret != 0)
{
KITLOG(LOG_WM_EN, ERROR_EN, "数据删除失败, interval: %d, date: %s", interval, time_str);
}
}
/*****************************************************************************
* @brief
* @param[in] interval:
* @param[in] timestamp:
*****************************************************************************/
static void deleteFaultsData(time_t timestamp)
{
struct tm tm_time;
localtime_r(&timestamp, &tm_time);
char time_str[32];
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &tm_time);
// 调用删除数据库函数
int ret = kit_del_faults_data_by_date(time_str);
if (ret != 0)
{
KITLOG(LOG_WM_EN, ERROR_EN, "数据删除失败, date: %s", time_str);
}
}
/*****************************************************************************
* @brief
* @param[in] timestamp:
*****************************************************************************/
static void deleteBreakData(time_t timestamp)
{
struct tm tm_time;
localtime_r(&timestamp, &tm_time);
char time_str[32];
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &tm_time);
// 调用删除数据库函数
int ret = kit_del_break_data_by_date(time_str);
if (ret != 0)
{
KITLOG(LOG_WM_EN, ERROR_EN, "数据删除失败, date: %s", time_str);
}
}
/*****************************************************************************
* @brief
*****************************************************************************/
static void delDbBusDataInterval()
{
time_t now;
time(&now);
struct tm tm_time;
localtime_r(&now, &tm_time);
tm_time.tm_hour += 8; // 加8个小时考虑时区
time_t oneDayAgo = now - 24 * 60 * 60; // 1天前
time_t oneWeekAgo = now - 7 * 24 * 60 * 60; // 7天前
time_t twoWeekAgo = now - 14 * 24 * 60 * 60; // 14天前
time_t threeWeekAgo = now - 21 * 24 * 60 * 60; // 21天前
time_t oneMonthAgo = now - 30 * 24 * 60 * 60; // 30天前
time_t twoMonthAgo = now - 2 * 30 * 24 * 60 * 60; // 60天前
time_t threeMonthAgo = now - 3 * 30 * 24 * 60 * 60; // 90天前
time_t fiveMonthAgo = now - 5 * 30 * 24 * 60 * 60; // 150天前
time_t sixMonthsAgo = now - 6 * 30 * 24 * 60 * 60; // 180天前
// 删除功率数据
deletePowerData(oneDayAgo);
// 删除断点续传数据
deleteBreakData(oneWeekAgo);
// 删除时序数据
deleteTimedData(500, oneDayAgo);
deleteTimedData(1000, oneWeekAgo);
deleteTimedData(2000, twoWeekAgo);
deleteTimedData(3000, threeWeekAgo);
deleteTimedData(4000, threeWeekAgo);
deleteTimedData(5000, oneMonthAgo);
deleteTimedData(6000, oneMonthAgo);
deleteTimedData(7000, oneMonthAgo);
deleteTimedData(8000, oneMonthAgo);
deleteTimedData(9000, oneMonthAgo);
deleteTimedData(10000, twoMonthAgo);
deleteTimedData(15000, threeMonthAgo);
deleteTimedData(20000, fiveMonthAgo);
deleteTimedData(30000, sixMonthsAgo);
// 删除故障数据
deleteFaultsData(sixMonthsAgo);
}
/*****************************************************************************
* @brief RTDB数据保存到数据库
* @param[in] storageIntervalType
*****************************************************************************/
static void saveRTDBToDbInterval(storage_interval_type_e storageIntervalType)
{
UT_array* timedDatas = NULL;
// 为时序数据动态数组分配空间
utarray_new(timedDatas, &timed_data_storage_icd);
for (int i = 0; i < utarray_len(timedDataConfigs); ++i)
{
timed_data_config_t* p_config = (timed_data_config_t*)utarray_eltptr(timedDataConfigs, i);
if (p_config != NULL && p_config->storageInterval == storageIntervalType)
{
timed_data_storage_t data = { 0 };
data.devType = p_config->devType; // 设备种类
data.devDbId = p_config->devDbId; // 设备数据库Id
data.storageInterval = p_config->storageInterval; // 存储间隔
data.pointDbId = p_config->pointDbId; // 点位Id
data.timedValue = getRtdbPointValue(Rtdb_ShMem, data.devType, p_config->devId - 1, p_config->pointId); // 从实时库获取时序数据
// if (data.timedValue == 0 || data.timedValue == 128)
// {
// KITLOG(LOG_WM_EN, ERROR_EN, "getRtdbPointValue 失败");
// continue;
// }
utarray_push_back(timedDatas, &data);
}
}
// 插入时序数据
if (utarray_len(timedDatas) > 0 && kit_insert_timed_data(timedDatas) != 0)
{
KITLOG(LOG_WM_EN, ERROR_EN, "kit_insert_timed_data 失败");
}
}
/*****************************************************************************
* @brief
*****************************************************************************/
static void saveFaultsDataInterval()
{
UT_array* faultsDatas = NULL;
// 为故障数据动态数组分配空间
utarray_new(faultsDatas, &faults_data_storage_icd);
for (int i = 0; i < utarray_len(faultsDataConfigs); ++i)
{
faults_data_config_t* p_config = (faults_data_config_t*)utarray_eltptr(faultsDataConfigs, i);
if (p_config != NULL)
{
faults_data_storage_t data = { 0 };
data.faultsValue = getRtdbPointValue(Rtdb_ShMem, data.devType, p_config->devId - 1, p_config->pointId); // 从实时库获取时序数据
if (data.faultsValue != 1) // 不是故障时,直接跳过
{
continue;
}
data.devType = p_config->devType; // 设备种类
data.devDbId = p_config->devDbId; // 设备数据库Id
data.pointDbId = p_config->pointDbId; // 点位Id
utarray_push_back(faultsDatas, &data);
}
}
// 插入时序数据
if (utarray_len(faultsDatas) > 0 && kit_insert_faults_data(faultsDatas) != 0)
{
KITLOG(LOG_WM_EN, ERROR_EN, "kit_insert_faults_data 失败");
}
}
/*****************************************************************************
* @brief
*****************************************************************************/
static void savePowerDataInterval()
{
// 定义存储功率数据的变量
float_t pccTotalActivePwr[MAX_NUM_CABINT], pccTotalReactivePwr[MAX_NUM_CABINT], pccTotalApparentPwr[MAX_NUM_CABINT], pccTotalPwrFactor[MAX_NUM_CABINT],
bsTotalActivePwr[MAX_NUM_CABINT], bsTotalReactivePwr[MAX_NUM_CABINT], bsTotalApparentPwr[MAX_NUM_CABINT], bsTotalPwrFactor[MAX_NUM_CABINT],
pcsTotalActivePwr[MAX_NUM_CABINT], pcsTotalReactivePwr[MAX_NUM_CABINT], pcsTotalApparentPwr[MAX_NUM_CABINT], pcsTotalPwrFactor[MAX_NUM_CABINT];
UT_array* powerDatas;
utarray_new(powerDatas, &power_data_storage_icd); // 初始化powerDatas
// pcc电表
logic_getValue(kDev_Type_Pccmeter, kPCC_TotalActivePwr, pccTotalActivePwr, Float32); // pcc电表总有功功率
logic_getValue(kDev_Type_Pccmeter, kPCC_TotalReactivePwr, pccTotalReactivePwr, Float32); // pcc电表总无功功率
logic_getValue(kDev_Type_Pccmeter, kPCC_TotalApparentPwr, pccTotalApparentPwr, Float32); // pcc电表总视在功率
logic_getValue(kDev_Type_Pccmeter, kPCC_TotalPwrFactor, pccTotalPwrFactor, Float32); // pcc电表总功率因数
// bs储能表
logic_getValue(kDev_Type_Bsmeter, kBs_TotalActivePwr, bsTotalActivePwr, Float32); // bs储能表总有功功率
logic_getValue(kDev_Type_Bsmeter, kBs_TotalReactivePwr, bsTotalReactivePwr, Float32); // bs储能表总无功功率
logic_getValue(kDev_Type_Bsmeter, kBs_TotalApparentPwr, bsTotalApparentPwr, Float32); // bs储能表总视在功率
logic_getValue(kDev_Type_Bsmeter, kBs_TotalPwrFactor, bsTotalPwrFactor, Float32); // bs储能表总功率因数
// pcs电表
logic_getValue(kDev_Type_PCS, kPcs_TotalActivePwr, pcsTotalActivePwr, Float32); // PCS总有功功率
logic_getValue(kDev_Type_PCS, kPcs_TotalReactivePwr, pcsTotalReactivePwr, Float32); // PCS总无功功率
logic_getValue(kDev_Type_PCS, kPcs_TotalApparentPwr, pcsTotalApparentPwr, Float32); // PCS总视在功率
logic_getValue(kDev_Type_PCS, kPcs_TotalPwrFactor, pcsTotalPwrFactor, Float32); // PCS总功率因数
// 遍历bs储能表
for (int i = 0; i < gStDevTypeNum[kDev_Type_Pccmeter]; ++i)
{
// pcc电表总有功功率
power_data_storage_t pccTotalActivePwrData = { 0 };
pccTotalActivePwrData.devType = kDev_Type_Pccmeter; // 设备种类
pccTotalActivePwrData.devId = i; // 设备编号
pccTotalActivePwrData.pointId = kPCC_TotalActivePwr; // 点位编号
pccTotalActivePwrData.value = pccTotalActivePwr[i]; // 值
utarray_push_back(powerDatas, &pccTotalActivePwrData);
// pcc电表总无功功率
power_data_storage_t pccTotalReactivePwrData = { 0 };
pccTotalReactivePwrData.devType = kDev_Type_Pccmeter; // 设备种类
pccTotalReactivePwrData.devId = i; // 设备编号
pccTotalReactivePwrData.pointId = kPCC_TotalReactivePwr; // 点位编号
pccTotalReactivePwrData.value = pccTotalReactivePwr[i]; // 值
utarray_push_back(powerDatas, &pccTotalReactivePwrData);
// pcc电表总视在功率
power_data_storage_t pccTotalApparentPwrData = { 0 };
pccTotalApparentPwrData.devType = kDev_Type_Pccmeter; // 设备种类
pccTotalApparentPwrData.devId = i; // 设备编号
pccTotalApparentPwrData.pointId = kPCC_TotalApparentPwr; // 点位编号
pccTotalApparentPwrData.value = pccTotalApparentPwr[i]; // 值
utarray_push_back(powerDatas, &pccTotalApparentPwrData);
// pcc电表总功率因数
power_data_storage_t pccTotalPwrFactorData = { 0 };
pccTotalPwrFactorData.devType = kDev_Type_Pccmeter; // 设备种类
pccTotalPwrFactorData.devId = i; // 设备编号
pccTotalPwrFactorData.pointId = kPCC_TotalPwrFactor; // 点位编号
pccTotalPwrFactorData.value = pccTotalPwrFactor[i]; // 值
utarray_push_back(powerDatas, &pccTotalPwrFactorData);
}
// 遍历bs储能表
for (int i = 0; i < gStDevTypeNum[kDev_Type_Bsmeter]; ++i)
{
// bs储能表总有功功率
power_data_storage_t bsTotalActivePwrData = { 0 };
bsTotalActivePwrData.devType = kDev_Type_Bsmeter; // 设备种类
bsTotalActivePwrData.devId = i; // 设备编号
bsTotalActivePwrData.pointId = kBs_TotalActivePwr; // 点位编号
bsTotalActivePwrData.value = bsTotalActivePwr[i]; // 值
utarray_push_back(powerDatas, &bsTotalActivePwrData);
// bs储能表总无功功率
power_data_storage_t bsTotalReactivePwrData = { 0 };
bsTotalReactivePwrData.devType = kDev_Type_Bsmeter; // 设备种类
bsTotalReactivePwrData.devId = i; // 设备编号
bsTotalReactivePwrData.pointId = kBs_TotalReactivePwr; // 点位编号
bsTotalReactivePwrData.value = bsTotalReactivePwr[i]; // 值
utarray_push_back(powerDatas, &bsTotalReactivePwrData);
// bs储能表总视在功率
power_data_storage_t bsTotalApparentPwrData = { 0 };
bsTotalApparentPwrData.devType = kDev_Type_Bsmeter; // 设备种类
bsTotalApparentPwrData.devId = i; // 设备编号
bsTotalApparentPwrData.pointId = kBs_TotalApparentPwr; // 点位编号
bsTotalApparentPwrData.value = bsTotalApparentPwr[i]; // 值
utarray_push_back(powerDatas, &bsTotalApparentPwrData);
// bs储能表总功率因数
power_data_storage_t bsTotalPwrFactorData = { 0 };
bsTotalPwrFactorData.devType = kDev_Type_Bsmeter; // 设备种类
bsTotalPwrFactorData.devId = i; // 设备编号
bsTotalPwrFactorData.pointId = kBs_TotalPwrFactor; // 点位编号
bsTotalPwrFactorData.value = bsTotalPwrFactor[i]; // 值
utarray_push_back(powerDatas, &bsTotalPwrFactorData);
}
// 遍历pcs
for (int i = 0; i < gStDevTypeNum[kDev_Type_PCS]; ++i)
{
// PCS总有功功率
power_data_storage_t pcsTotalActivePwrData = { 0 };
pcsTotalActivePwrData.devType = kDev_Type_PCS; // 设备种类
pcsTotalActivePwrData.devId = i; // 设备编号
pcsTotalActivePwrData.pointId = kPcs_TotalActivePwr; // 点位编号
pcsTotalActivePwrData.value = pcsTotalActivePwr[i]; // 值
utarray_push_back(powerDatas, &pcsTotalActivePwrData);
// PCS总无功功率
power_data_storage_t pcsTotalReactivePwrData = { 0 };
pcsTotalReactivePwrData.devType = kDev_Type_PCS; // 设备种类
pcsTotalReactivePwrData.devId = i; // 设备编号
pcsTotalReactivePwrData.pointId = kPcs_TotalReactivePwr; // 点位编号
pcsTotalReactivePwrData.value = pcsTotalReactivePwr[i]; // 值
utarray_push_back(powerDatas, &pcsTotalReactivePwrData);
// PCS总视在功率
power_data_storage_t pcsTotalApparentPwrData = { 0 };
pcsTotalApparentPwrData.devType = kDev_Type_PCS; // 设备种类
pcsTotalApparentPwrData.devId = i; // 设备编号
pcsTotalApparentPwrData.pointId = kPcs_TotalApparentPwr; // 点位编号
pcsTotalApparentPwrData.value = pcsTotalApparentPwr[i]; // 值
utarray_push_back(powerDatas, &pcsTotalApparentPwrData);
// PCS总功率因数
power_data_storage_t pcsTotalPwrFactorData = { 0 };
pcsTotalPwrFactorData.devType = kDev_Type_PCS; // 设备种类
pcsTotalPwrFactorData.devId = i; // 设备编号
pcsTotalPwrFactorData.pointId = kPcs_TotalPwrFactor; // 点位编号
pcsTotalPwrFactorData.value = pcsTotalPwrFactor[i]; // 值
utarray_push_back(powerDatas, &pcsTotalPwrFactorData);
}
// 调用保存功率数据库函数
int ret = kit_insert_power_data(powerDatas);
if (ret != 0)
{
KITLOG(LOG_WM_EN, ERROR_EN, "批量插入插入功率数据失败");
}
}
/*********************************************************************
* @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 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 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, (char *)AdvancedSettingTable[kLinux_Password].value); // 使用bsp_rtc.c中的setSysTime函数设置系统时间
if (ret != 0)
{
KITLOG(LOG_APP_EN, ERROR_EN, "错误:设置系统时间失败\n");
return 1;
}
}
cJSON_Delete(json_obj); // 释放JSON对象
return ret;
}
/*********************************************************************
* @brief EMS的基础设置到系统
* @param[in] void
* @return 0- 1-
*********************************************************************/
static void changeEmsConfig(void)
{
// EMS修改标志位被修改
if(EMS_CONFIG_START_MESSAGE == readWebSign(kSign_ShMem, kSign_EmsConfig))
{
UT_array *emsDevConfigs = {0};
int ret = 0;
if (0 != kit_get_config_db_data(&emsDevConfigs))
{
return;
}
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);
emsDevConfigs = NULL;
return;
}
}
// 释放数组内存
utarray_free(emsDevConfigs);
emsDevConfigs = NULL;
return;
}
}
/*****************************************************************************
* @brief
*****************************************************************************/
static void installUpgradePackage()
{
// 读取升级是否需要标志位
if(UPGRADE_START_MESSAGE == readWebSign(kSign_ShMem, kSign_SysUpdate))
{
upgrade_record_t p_upgradeRecord = {0};
if(0 == kit_get_upgrade_record(&p_upgradeRecord))
{
char buffer[1000]; // 接收执行返回值
char command[MAX_UPGRADE_PATH_LEN + 8]; // 命令字符串
snprintf(command, MAX_UPGRADE_PATH_LEN + 8, "dpkg -i %s", p_upgradeRecord.path);
// 使用 kit_popen_exec 执行"dpkg i "
if (kit_popen_exec(command, buffer, sizeof(buffer)) != 0)
{
snprintf((char *)p_upgradeRecord.errMsg, MAX_UPGRADE_ERR_MSG_LEN, "%s", buffer);
p_upgradeRecord.status = kUpgrade_Err; // 升级失败
kit_update_upgrade_record(&p_upgradeRecord); // 更新升级记录
KITLOG(LOG_DRIVER_EN, ERROR_EN, "EMS升级失败\n");
return;
}
// 设置EMS自启动
if (kit_popen_exec("systemctl enable company-ems-start", buffer, sizeof(buffer)) != 0)
{
KITLOG(LOG_DRIVER_EN, ERROR_EN, "EMS自启动设置失败\n");
return;
}
// LINUX重启
if (kit_popen_exec("reboot", buffer, sizeof(buffer)) != 0)
{
KITLOG(LOG_DRIVER_EN, ERROR_EN, "重启失败\n");
return;
}
p_upgradeRecord.status = kUpgrade_Succ; // 升级成功
kit_update_upgrade_record(&p_upgradeRecord); // 更新升级记录
// 写入升级结束标志位
writeWebSign(kSign_ShMem, kSign_SysUpdate, UPGRADE_END_MESSAGE);
}
}
}
/*****************************************************************************
* @brief 1
* @param[in] arg线
*****************************************************************************/
static void* oneSecondTaskHandle(void* arg)
{
struct timespec start, end;
struct timespec interval = { .tv_sec = 1, .tv_nsec = 0 };
struct timespec tv;
while (1)
{
clock_gettime(CLOCK_MONOTONIC, &start);
if (exeCount % 1 == 0) // 1秒执行一次
{
saveRTDBToDbInterval(kStorage_Interval_1s); // 定时落库
saveFaultsDataInterval(); // 保存故障
changeEmsConfig(); // 更新EMS基础配置
installUpgradePackage(); // 安装升级包
}
if (exeCount % 2 == 0) // 2秒执行一次
{
saveRTDBToDbInterval(kStorage_Interval_2s);
}
if (exeCount % 3 == 0) // 3秒执行一次
{
saveRTDBToDbInterval(kStorage_Interval_3s);
}
if (exeCount % 4 == 0) // 4秒执行一次
{
saveRTDBToDbInterval(kStorage_Interval_4s);
}
if (exeCount % 5 == 0) // 5秒执行一次
{
saveRTDBToDbInterval(kStorage_Interval_5s);
}
if (exeCount % 6 == 0) // 6秒执行一次
{
saveRTDBToDbInterval(kStorage_Interval_6s);
}
if (exeCount % 7 == 0) // 7秒执行一次
{
saveRTDBToDbInterval(kStorage_Interval_7s);
}
if (exeCount % 8 == 0) // 8秒执行一次
{
saveRTDBToDbInterval(kStorage_Interval_8s);
}
if (exeCount % 9 == 0) // 9秒执行一次
{
saveRTDBToDbInterval(kStorage_Interval_9s);
}
if (exeCount % 10 == 0) // 10秒执行一次
{
saveRTDBToDbInterval(kStorage_Interval_10s);
}
if (exeCount % 15 == 0) // 15秒执行一次
{
saveRTDBToDbInterval(kStorage_Interval_15s);
}
if (exeCount % 20 == 0) // 20秒执行一次
{
saveRTDBToDbInterval(kStorage_Interval_20s);
}
if (exeCount % 30 == 0) // 30秒执行一次
{
saveRTDBToDbInterval(kStorage_Interval_30s);
}
if (exeCount % 60 == 0) // 60秒执行一次
{
savePowerDataInterval(); // 每分钟定时保存功率数据
}
if (exeCount % 86400 == 0) // 86400秒执行一次一天
{
delDbBusDataInterval(); // 每天定时删除业务数据间隔
}
// 获取循环结束时间并计算执行时间
clock_gettime(CLOCK_MONOTONIC, &end);
long elapsed_ns = (end.tv_sec - start.tv_sec) * 1e9 + (end.tv_nsec - start.tv_nsec);
long sleep_ns = (interval.tv_sec * 1e9 + interval.tv_nsec) - elapsed_ns;
// 如果任务执行时间小于1秒休眠剩余时间
if (sleep_ns > 0)
{
tv.tv_sec = sleep_ns / 1e9;
tv.tv_nsec = sleep_ns % (long)1e9;
nanosleep(&tv, NULL);
}
// 执行次数
exeCount = (exeCount + 1) % MAX_EXE_COUNT;
}
return NULL;
}
/*****************************************************************************
* @brief
* @return 0- 1-
*****************************************************************************/
void creatScheduledStorageTask()
{
int ret = 0;
pthread_t tid_one_sec; // 定义线程描述符
// 从数据库里查询到所有时序数据存储的配置
ret = kit_get_tdata_config(&timedDataConfigs);
if (ret != 0)
{
KITLOG(LOG_WM_EN, ERROR_EN, "获取时序数据存储的配置失败!");
return (void)1;
}
// 从数据库获取故障点位配置
ret = kit_get_faults_config(&faultsDataConfigs);
if (ret != 0)
{
KITLOG(LOG_WM_EN, ERROR_EN, "获取故障点位配置失败!");
return (void)1;
}
// 创建每1秒钟执行一次的线程
ret = pthread_create(&tid_one_sec, NULL, oneSecondTaskHandle, NULL);
if (ret != 0)
{
KITLOG(LOG_WM_EN, ERROR_EN, "创建每1秒钟执行一次的线程失败");
return (void)1; // 创建失败,返回错误
}
return (void)0;
}