/**************************************************************************** ** File name : HTIEC104.h ** Description : define 104 worker thread group ** Create date : 2018.09.01 ** Auther by : Liuyx ** Version info : V1.0.01 ** Copyrigth By: xi'an huatek, Inc Co., Ltd ** Update record: ** DATE AUTHER DESC ** ------------------------------------------------------------------------- ** 2018.09.01 Liuyx first build ****************************************************************************/ //#include #include "HTGlobal.h" #include "HTIEC104.h" static const char *_FILE_ = "HTIEC104.cpp"; static FILE *fpIec = NULL; // iec104 config file handle. static ST_IEC104_CONF g_iec_conf; static time_t g_Internal_time; list g_list_pack; mutex g_list_pack_mutex; list g_list_dbset; mutex g_list_dbset_mutex; list g_list_origin; mutex g_list_origin_mutex; list g_list_origin_new; mutex g_list_origin_mutex_new; list g_list_busi_data; mutex g_list_busi_data_mutex; list g_list_pingce; mutex g_list_pingce_mutex; list g_list_warn; mutex g_list_warn_mutex; mutex g_sendno_mutex; CIEC104::CIEC104() { } CIEC104::~CIEC104() { } static void vPrtListCount() { vPrtLogMsg(LOG_WARNG, RET_OK, "-----> g_list_pack count:%d", g_list_pack.size()); vPrtLogMsg(LOG_WARNG, RET_OK, "-----> g_list_dbset count:%d", g_list_dbset.size()); vPrtLogMsg(LOG_WARNG, RET_OK, "-----> g_list_origin count:%d", g_list_origin.size()); vPrtLogMsg(LOG_WARNG, RET_OK, "-----> g_list_pingce count:%d", g_list_pingce.size()); vPrtLogMsg(LOG_WARNG, RET_OK, "-----> g_list_warn count:%d", g_list_warn.size()); vPrtLogMsg(LOG_WARNG, RET_OK, "-----> g_map_thres_byq count:%d", g_map_thres_byq.size()); vPrtLogMsg(LOG_WARNG, RET_OK, "-----> g_map_relation count:%d", g_map_relation.size()); vPrtLogMsg(LOG_WARNG, RET_OK, "-----> g_map_iec count:%d", g_map_iec.size()); vPrtLogMsg(LOG_WARNG, RET_OK, "-----> g_map_sadr count:%d", g_map_sadr.size()); vPrtLogMsg(LOG_WARNG, RET_OK, "-----> g_map_img_thres count:%d", g_map_img_thres.size()); vPrtLogMsg(LOG_WARNG, RET_OK, "-----> g_map_sadr count:%d", g_map_sadr.size()); } /************************************************************************* Function iniGetString Rectives a character string from the specified section in the specified inifile Param In : pszSection : address of section pszEntry : address of entry uiBufLen : size of destination buffer pszFileName: address of inifile name Param Out : pszRetBuf : destination buffer Return Code : 0 : success <0 : failed *************************************************************************/ static int iGetString(const char *pszSection, const char *pszEntry, char *pszRetBuf, unsigned int uiBufLen) { //FILE *fpIni; char szBuf[DEF_BUFFER_1K + 1], *psz1, *psz2, *psz; int iSectFlag, iLen; if (fpIec == NULL) { if ((fpIec = fopen(IEC_CONFIMG_FILE, "r")) == NULL) return (-1); } fseek(fpIec, 0, SEEK_SET); /*** check section ***/ iSectFlag = 0; while (!feof(fpIec)) { if (fgets(szBuf, DEF_BUFFER_1K, fpIec) == NULL) break; psz = szBuf; while (*psz != '[' && *psz != '#' && *psz != '\0') psz++; if (*psz != '[') continue; psz++; while (*psz == ' ' || *psz == '\t') psz++; psz1 = psz; while (*psz != ']' && *psz != '\0') psz++; if (*psz == '\0') continue; while (*(psz - 1) == ' ' || *(psz - 1) == '\t') psz--; *psz = '\0'; if (!strcmp(psz1, pszSection)) { iSectFlag = 1; break; } }/*** while ***/ if (!iSectFlag) { //fclose(fpIni); return (-1); } /*** check entry ***/ while (!feof(fpIec)) { if (fgets(szBuf, DEF_BUFFER_1K, fpIec) == NULL) break; psz = szBuf; while (*psz == ' ' || *psz == '\t') psz++; if (*psz == '#' || *psz == '\0') continue; if (*psz == '[') break; psz1 = psz; while (*psz != '=' && *psz != '\0') psz++; if (*psz == '\0') continue; psz2 = psz + 1; if (psz1 == psz) continue; while (*(psz - 1) == ' ' || *(psz - 1) == '\t') psz--; *psz = '\0'; #ifdef _WIN32 if (strcmp(psz1, pszEntry)) continue; #else if (strcasecmp(psz1, pszEntry)) continue; #endif //fclose(fpIni); psz = psz2; while (*psz == ' ' || *psz == '\t') psz++; psz2 = psz; while (*psz != '#' && *psz != '\0' && !(*psz == '/' && (*(psz + 1) == '*' || *(psz + 1) == '/'))) psz++; while (*(psz - 1) == ' ' || *(psz - 1) == '\t' || *(psz - 1) == 0x0a || *(psz - 1) == 0x0d) { *(psz - 1) = '\0'; psz--; } //*psz= '\0'; iLen = strlen(psz2); if (psz2[iLen - 1] == 0x0a || psz2[iLen - 1] == 0x0d) psz2[iLen - 1] = 0x00; if (iLen == 0) return (0); //return (-1); // 参数未设置,即参数值为空的情况 if (iLen > (int)uiBufLen) iLen = uiBufLen; memcpy(pszRetBuf, psz2, iLen); *(pszRetBuf + iLen) = '\0'; return (0); } //fclose(fpIni); return (-1); } static void setSadrMatchRelations(unsigned int key, ST_SADR_MATCH *pstAdr) { ST_SADR_MATCH stAdr; memset(&stAdr, 0x00, sizeof(ST_SADR_MATCH)); if (key <= 0) return; // key=0时,表示104配置文件中无此点表地址、地址为空的情况 stAdr.eqm_type = pstAdr->eqm_type; stAdr.count = pstAdr->count; stAdr.psadr = (ST_MATCH_LIST*)calloc(pstAdr->count, sizeof(ST_MATCH_LIST)); memcpy(stAdr.psadr, pstAdr->psadr, (pstAdr->count * sizeof(ST_MATCH_LIST))); mutex_lock(g_map_sadr_mutex); g_map_sadr.insert(map::value_type(key, stAdr)); mutex_unlock(g_map_sadr_mutex); } // 加IEC104业务配置文件数据 static bool iGetIEC104Conf() { int iRet = -1, i; char szTmp[512], szSection[128]; memset(&g_iec_conf, 0x00, sizeof(ST_IEC104_CONF)); // 初始化IEC104配置. g_iec_conf.orgin_data_save_internal = 3600; // 打开配置文件,准备加载配置参数 if (fpIec == NULL) { if ((fpIec = fopen(IEC_CONFIMG_FILE, "r")) == NULL) { vPrtLogMsg(LOG_ERROR, errno, "open config file: %s failed!", HT_CONFIMG_FILE); return NULL; } } // 获取变压器配置项的个数 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString("IEC_DEVCOUNT", "iec_byq_count", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get iec_byq_count parameter failed!"); fclose(fpIec); return false; } g_iec_conf.iec_byq_count = (unsigned int)atoi(szTmp); // 申请变压器设备编码缓冲区 g_iec_conf.pstByqCode = (ST_BYQ_EQM_CODE*)calloc(g_iec_conf.iec_byq_count, sizeof(ST_BYQ_EQM_CODE)); if (!g_iec_conf.pstByqCode) { vPrtLogMsg(LOG_ERROR, iRet, "calloc byq_eqm_code cache size: %d failed!", g_iec_conf.iec_byq_count * sizeof(ST_BYQ_EQM_CODE)); fclose(fpIec); return false; } // 获取断路器配置项的个数 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString("IEC_DEVCOUNT", "iec_break_count", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get iec_break_count parameter failed!"); // fclose(fpIec); // return false; g_iec_conf.iec_break_count = 0; } else { g_iec_conf.iec_break_count = (unsigned int)atoi(szTmp); } // 申请断路器设备编码缓冲区 g_iec_conf.pstBrkCode = (ST_BREAK_EQM_CODE*)calloc(g_iec_conf.iec_break_count, sizeof(ST_BREAK_EQM_CODE)); if (!g_iec_conf.pstBrkCode) { vPrtLogMsg(LOG_ERROR, iRet, "calloc brk_eqm_code cache size: %d failed!", g_iec_conf.iec_break_count * sizeof(ST_BREAK_EQM_CODE)); fclose(fpIec); return false; } // 获取站点ID配置项 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString("IEC_DEVCOUNT", "iec_site_id", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get iec_site_id parameter failed!"); fclose(fpIec); return false; } strcpy((char*)g_iec_conf.site_id , szTmp); vPrtLogMsg(LOG_DEBUG, 0, "get iec_byq_count config count: byq_cnt:%d,gis_cnt:%d,site_id:%s", g_iec_conf.iec_byq_count, g_iec_conf.iec_break_count, szTmp); // 104时间保存间隔时间(s) memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString("COMM_SAVE_INTERNAL", "DATA_SAVE_INTERNAL", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get DATA_SAVE_INTERNAL parameter failed!"); fclose(fpIec); return false; } g_iec_conf.save_internal = (unsigned int)atoi(szTmp); // 总召间隔时间(s) memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString("IEC_INTERVAL", "action_interval", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get action_interval parameter failed!"); fclose(fpIec); return false; } g_iec_conf.action_interval = (unsigned int)atoi(szTmp); // 104原始数据保存时间(s) memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString("COMM_SAVE_INTERNAL", "ORIGIN_DATA_SAVE_INTERNAL", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get DATA_SAVE_INTERNAL parameter failed!"); fclose(fpIec); return false; } g_iec_conf.orgin_data_save_internal = (unsigned int)atoi(szTmp); // 获取公共地址配置 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString("IEC_OBJS_ADDR", "iec_global_addr", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get iec_global_addr parameter failed!"); fclose(fpIec); return false; } g_iec_conf.iec_global_addr = (unsigned short)atoi(szTmp); // 获取YC地址配置 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString("IEC_OBJS_ADDR", "yx_start_addr", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get yx_start_addr parameter failed!"); fclose(fpIec); return false; } g_iec_conf.yx_start_addr = (unsigned int)atoi(szTmp); memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString("IEC_OBJS_ADDR", "yx_stop_addr", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get yx_stop_addr parameter failed!"); fclose(fpIec); return false; } g_iec_conf.yx_stop_addr = (unsigned int)atoi(szTmp); // 获取JB地址配置 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString("IEC_OBJS_ADDR", "jb_start_addr", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get jb_start_addr parameter failed!"); fclose(fpIec); return false; } g_iec_conf.jb_start_addr = (unsigned int)atoi(szTmp); memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString("IEC_OBJS_ADDR", "jb_stop_addr", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get jb_stop_addr parameter failed!"); fclose(fpIec); return false; } g_iec_conf.jb_stop_addr = (unsigned int)atoi(szTmp); // 获取YC地址配置 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString("IEC_OBJS_ADDR", "yc_start_addr", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get yc_start_addr parameter failed!"); fclose(fpIec); return false; } g_iec_conf.yc_start_addr = (unsigned int)atoi(szTmp); memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString("IEC_OBJS_ADDR", "yc_stop_addr", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get yc_stop_addr parameter failed!"); fclose(fpIec); return false; } g_iec_conf.yc_stop_addr = (unsigned int)atoi(szTmp); // 获取BYQ配置各项参数 for (i = 0; i < (int)g_iec_conf.iec_byq_count; i++) { snprintf(szSection, sizeof(szSection), "IEC_BYQ_CODE_%02d", i + 1); memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "EQM_CODE", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: EQM_CODE parameter failed", szSection); fclose(fpIec); return false; } strcpy((char*)g_iec_conf.pstByqCode[i].szEqmCode, szTmp); // 主变高压侧电压、电流点位HIGH_VOLTAGE, HIGH_CURRENT = 16387 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "HIGH_VOLTAGE", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: HIGH_VOLTAGE parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiHighVoltage = atoi(szTmp); memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "HIGH_CURRENT", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: HIGH_CURRENT parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiHighCurrent = atoi(szTmp); //主变低压(出口)侧电压、电流点位 LOW_VOLTAGE = 16700 LOW_CURRENT = 16701 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "LOW_VOLTAGE", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: LOW_VOLTAGE parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiLowVoltage = atoi(szTmp); memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "LOW_CURRENT", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: LOW_CURRENT parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiLowCurrent = atoi(szTmp); //# 运行工况点位 //# 主变冷却水进口压力点位 COOL_WATER_PRESS_ENTRY = 16365 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "COOL_WATER_PRESS_ENTRY", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: COOL_WATER_PRESS_ENTRY parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiCoolWaterPressEntry = atoi(szTmp); //# 主变冷却水出口压力点位 COOL_WATER_PRESS_OUTER = 16366 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "COOL_WATER_PRESS_OUTER", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: COOL_WATER_PRESS_OUTER parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiCoolWaterPressOuter = atoi(szTmp); //# 主变冷却水进口温度点位 COOL_WATER_TEMP_ENTRY = 16366 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "COOL_WATER_TEMP_ENTRY", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: COOL_WATER_TEMP_ENTRY parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiCoolWaterTempEntry = atoi(szTmp); //# 主变冷却水出口温度点位 COOL_WATER_TEMP_OUTER = 16366 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "COOL_WATER_TEMP_OUTER", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: COOL_WATER_TEMP_OUTER parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiCoolWaterTempOuter = atoi(szTmp); //# 主变油进口压力点位 OIL_PRESS_ENTRY = 16366 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "OIL_PRESS_ENTRY", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: OIL_PRESS_ENTRY parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiOilPressEntry = atoi(szTmp); //# 主变油出口压力点位 OIL_PRESS_OUTER = 16366 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "OIL_PRESS_OUTER", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: OIL_PRESS_OUTER parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiOilPressOuter = atoi(szTmp); //# 主变油进口温度点位 OIL_TEMP_ENTRY = 16366 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "OIL_TEMP_ENTRY", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: OIL_TEMP_ENTRY parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiOilTempEntry = atoi(szTmp); //# 主变油出口温度点位 OIL_TEMP_OUTER = 16366 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "OIL_TEMP_OUTER", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: OIL_TEMP_OUTER parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiOilTempOuter = atoi(szTmp); //# 主变绕组温度点位 WINDING_TEMPERATURE = 16366 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "WINDING_TEMPERATURE", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: WINDING_TEMPERATURE parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiWindingTemp = atoi(szTmp); //# 主变油温点位 OIL_TEMPERATURE = 16405 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "OIL_TEMPERATURE", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: OIL_TEMPERATURE parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiOilTemperature = atoi(szTmp); //# 主变顶层油温点位 OIL_TOP_TEMPERATURE = 16405 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "OIL_TOP_TEMPERATURE", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: OIL_TOP_TEMPERATURE parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiOilTopTemp = atoi(szTmp); //# 主变油位点位 OIL_POSITION = 16406 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "OIL_POSITION", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: OIL_POSITION parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiOilPosition = atoi(szTmp); //# 主变油枕油位点位 OIL_OILPILLOW_OILLEVEL = 16406 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "OIL_OILPILLOW_OILLEVEL", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: OIL_OILPILLOW_OILLEVEL parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstByqCode[i].uiOilPillowLevel = atoi(szTmp); } // 获取断路器配置各项参数 for (i = 0; i < (int)g_iec_conf.iec_break_count; i++) { ST_BREAK_EQM_CODE stGisState; memset(&stGisState, 0x00, sizeof(ST_BREAK_EQM_CODE)); snprintf(szSection, sizeof(szSection), "IEC_BREAK_CODE_%02d", i + 1); memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "EQM_CODE_A", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: EQM_CODE_A parameter failed", szSection); fclose(fpIec); return false; } strcpy((char*)g_iec_conf.pstBrkCode[i].szEqmCodeA, szTmp); strcpy((char*)stGisState.szEqmCodeA, szTmp); memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "EQM_CODE_B", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: EQM_CODE_B parameter failed", szSection); fclose(fpIec); return false; } strcpy((char*)g_iec_conf.pstBrkCode[i].szEqmCodeB, szTmp); strcpy((char*)stGisState.szEqmCodeB, szTmp); memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "EQM_CODE_C", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: EQM_CODE_C parameter failed", szSection); fclose(fpIec); return false; } strcpy((char*)g_iec_conf.pstBrkCode[i].szEqmCodeC, szTmp); strcpy((char*)stGisState.szEqmCodeC, szTmp); // 断开状态点位,开关的遥信点位 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "STATE_SIGNAL", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: STATE_SIGNAL parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstBrkCode[i].uiStateSadr = atoi(szTmp); stGisState.uiStateSadr = atoi(szTmp); // 断开电压点位 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "ABORT_VOLTAGE", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: ABORT_VOLTAGE parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstBrkCode[i].uiAbortVoltage = atoi(szTmp); stGisState.uiAbortVoltage = atoi(szTmp); // 断开电流点位 memset(szTmp, 0x00, sizeof(szTmp)); if ((iRet = iGetString(szSection, "ABORT_CURRENT", szTmp, sizeof(szTmp))) < 0) { vPrtLogMsg(LOG_ERROR, iRet, "get %s: ABORT_CURRENT parameter failed", szSection); fclose(fpIec); return false; } g_iec_conf.pstBrkCode[i].uiAbortCurrent = atoi(szTmp); stGisState.uiAbortCurrent = atoi(szTmp); mutex_lock(g_map_gis_state_mutex); // 断路器遥信状态下,对应其电流电压点位 g_map_gis_state.insert(map::value_type(stGisState.uiStateSadr, stGisState)); mutex_unlock(g_map_gis_state_mutex); } fclose(fpIec); // 根据配置,建立点表地址匹配关系map for (i = 0; i < (int)g_iec_conf.iec_byq_count; i++) { // 主变高压侧电流电压匹配关系 ST_SADR_MATCH stAdr; memset(&stAdr, 0x00, sizeof(ST_SADR_MATCH)); stAdr.eqm_type = 1; stAdr.count = 2; stAdr.psadr = (ST_MATCH_LIST*)calloc(stAdr.count, sizeof(ST_MATCH_LIST)); stAdr.psadr[0].group = 1; // 高压侧电流、电压组 stAdr.psadr[0].btype = 1; // 高压侧电流 stAdr.psadr[0].sadr = g_iec_conf.pstByqCode[i].uiHighCurrent; stAdr.psadr[1].group = 1; // 高压侧电流、电压组 stAdr.psadr[1].btype = 2; // 高压侧电压 stAdr.psadr[1].sadr = g_iec_conf.pstByqCode[i].uiHighVoltage; setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiHighVoltage, &stAdr); setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiHighCurrent, &stAdr); if (stAdr.psadr) free(stAdr.psadr); stAdr.psadr = NULL; // 主变低压侧电流电压匹配关系 stAdr.psadr = (ST_MATCH_LIST*)calloc(stAdr.count, sizeof(ST_MATCH_LIST)); stAdr.psadr[0].group = 2; // 低压侧电流、电压组 stAdr.psadr[0].btype = 1; //低压侧电流 stAdr.psadr[0].sadr = g_iec_conf.pstByqCode[i].uiLowCurrent; stAdr.psadr[1].group = 2; // 低压侧电流、电压组 stAdr.psadr[1].btype = 2; //低压侧电压 stAdr.psadr[1].sadr = g_iec_conf.pstByqCode[i].uiLowVoltage; setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiLowVoltage, &stAdr); setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiLowCurrent, &stAdr); if (stAdr.psadr) free(stAdr.psadr); stAdr.psadr = NULL; // 运行工况 stAdr.eqm_type = 1; stAdr.count = 13; stAdr.psadr = (ST_MATCH_LIST*)calloc(stAdr.count, sizeof(ST_MATCH_LIST)); stAdr.psadr[0].group = 3; // 运行工况组 stAdr.psadr[0].btype = 1; // 进口水压力 stAdr.psadr[0].sadr = g_iec_conf.pstByqCode[i].uiCoolWaterPressEntry; stAdr.psadr[1].group = 3; // 运行工况组 stAdr.psadr[1].btype = 2; // 出口水压力 stAdr.psadr[1].sadr = g_iec_conf.pstByqCode[i].uiCoolWaterPressOuter; stAdr.psadr[2].group = 3; // 运行工况组 stAdr.psadr[2].btype = 3; // 主变本体油位数 stAdr.psadr[2].sadr = g_iec_conf.pstByqCode[i].uiOilPosition; stAdr.psadr[3].group = 3; // 运行工况组 stAdr.psadr[3].btype = 4; // 主变本体油温数 stAdr.psadr[3].sadr = g_iec_conf.pstByqCode[i].uiOilTemperature; stAdr.psadr[4].group = 3; // 运行工况组 stAdr.psadr[4].btype = 5; // 进口水温度 stAdr.psadr[4].sadr = g_iec_conf.pstByqCode[i].uiCoolWaterTempEntry; stAdr.psadr[5].group = 3; // 运行工况组 stAdr.psadr[5].btype = 6; // 出口水温度 stAdr.psadr[5].sadr = g_iec_conf.pstByqCode[i].uiCoolWaterTempOuter; stAdr.psadr[6].group = 3; // 运行工况组 stAdr.psadr[6].btype = 7; // 进口油压力 stAdr.psadr[6].sadr = g_iec_conf.pstByqCode[i].uiOilPressEntry; stAdr.psadr[7].group = 3; // 运行工况组 stAdr.psadr[7].btype = 8; // 出口油压力 stAdr.psadr[7].sadr = g_iec_conf.pstByqCode[i].uiOilPressOuter; stAdr.psadr[8].group = 3; // 运行工况组 stAdr.psadr[8].btype = 9; // 进口油温度 stAdr.psadr[8].sadr = g_iec_conf.pstByqCode[i].uiOilTempEntry; stAdr.psadr[9].group = 3; // 运行工况组 stAdr.psadr[9].btype = 10; // 出口油温度 stAdr.psadr[9].sadr = g_iec_conf.pstByqCode[i].uiOilTempOuter; stAdr.psadr[10].group = 3; // 运行工况组 stAdr.psadr[10].btype = 11; // 油枕油位 stAdr.psadr[10].sadr = g_iec_conf.pstByqCode[i].uiOilPillowLevel; stAdr.psadr[11].group = 3; // 运行工况组 stAdr.psadr[11].btype = 12; // 顶层油温度 stAdr.psadr[11].sadr = g_iec_conf.pstByqCode[i].uiOilTopTemp; stAdr.psadr[12].group = 3; // 运行工况组 stAdr.psadr[12].btype = 13; // 绕组温度 stAdr.psadr[12].sadr = g_iec_conf.pstByqCode[i].uiWindingTemp; setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiCoolWaterPressEntry, &stAdr); setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiCoolWaterPressOuter, &stAdr); setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiOilPosition, &stAdr); setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiOilTemperature, &stAdr); setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiCoolWaterTempEntry, &stAdr); setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiCoolWaterTempOuter, &stAdr); setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiOilPressEntry, &stAdr); setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiOilPressOuter, &stAdr); setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiOilTempEntry, &stAdr); setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiOilTempOuter, &stAdr); setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiOilPillowLevel, &stAdr); setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiOilTopTemp, &stAdr); setSadrMatchRelations(g_iec_conf.pstByqCode[i].uiWindingTemp, &stAdr); if (stAdr.psadr) free(stAdr.psadr); stAdr.psadr = NULL; } for (i = 0; i < (int)g_iec_conf.iec_break_count; i++) { ST_SADR_MATCH stAdr; memset(&stAdr, 0x00, sizeof(ST_SADR_MATCH)); stAdr.eqm_type = 2; stAdr.count = 2; stAdr.psadr = (ST_MATCH_LIST*)calloc(stAdr.count, sizeof(ST_MATCH_LIST)); stAdr.psadr[0].group = 4; stAdr.psadr[0].btype = 1; // 断开电流 stAdr.psadr[0].sadr = g_iec_conf.pstBrkCode[i].uiAbortCurrent; stAdr.psadr[1].group = 4; stAdr.psadr[1].btype = 2; // 断开电压 stAdr.psadr[1].sadr = g_iec_conf.pstBrkCode[i].uiAbortVoltage; setSadrMatchRelations(g_iec_conf.pstBrkCode[i].uiAbortVoltage, &stAdr); setSadrMatchRelations(g_iec_conf.pstBrkCode[i].uiAbortCurrent, &stAdr); if (stAdr.psadr) free(stAdr.psadr); stAdr.psadr = NULL; } return true; } // 打印IEC104配置参数 static void showIEC104Conf() { int i = 0; vPrtLogMsg(LOG_DEBUG, RET_OK, "---> IEC104_CONF: iec_byq_count = %d, iec_break_count = %d", g_iec_conf.iec_byq_count, g_iec_conf.iec_break_count); vPrtLogMsg(LOG_DEBUG, RET_OK, "---> IEC104_CONF: yx_start_addr = %d-(0x%04x)", g_iec_conf.yx_start_addr, g_iec_conf.yx_start_addr); vPrtLogMsg(LOG_DEBUG, RET_OK, "---> IEC104_CONF: yx_stop_addr = %d-(0x%04x)", g_iec_conf.yx_stop_addr, g_iec_conf.yx_stop_addr); vPrtLogMsg(LOG_DEBUG, RET_OK, "---> IEC104_CONF: jb_start_addr = %d-(0x%04x)", g_iec_conf.jb_start_addr, g_iec_conf.jb_start_addr); vPrtLogMsg(LOG_DEBUG, RET_OK, "---> IEC104_CONF: jb_stop_addr = %d-(0x%04x)", g_iec_conf.jb_stop_addr, g_iec_conf.jb_stop_addr); vPrtLogMsg(LOG_DEBUG, RET_OK, "---> IEC104_CONF: yc_start_addr = %d-(0x%04x)", g_iec_conf.yc_start_addr, g_iec_conf.yc_start_addr); vPrtLogMsg(LOG_DEBUG, RET_OK, "---> IEC104_CONF: yc_stop_addr = %d-(0x%04x)", g_iec_conf.yc_stop_addr, g_iec_conf.yc_stop_addr); for (i = 0; i < (int)g_iec_conf.iec_byq_count; i++) vPrtLogMsg(LOG_DEBUG, RET_OK, "---> IEC104_CONF: BYQ_%02d Eqm_code = %s [%d,%d,%d,%d---%d,%d,%d,%d]", i+1, g_iec_conf.pstByqCode[i].szEqmCode, g_iec_conf.pstByqCode[i].uiHighVoltage, g_iec_conf.pstByqCode[i].uiHighCurrent, g_iec_conf.pstByqCode[i].uiLowVoltage, g_iec_conf.pstByqCode[i].uiLowCurrent, g_iec_conf.pstByqCode[i].uiCoolWaterPressEntry, g_iec_conf.pstByqCode[i].uiCoolWaterPressOuter, g_iec_conf.pstByqCode[i].uiOilTemperature, g_iec_conf.pstByqCode[i].uiOilPosition); for (i = 0; i < (int)g_iec_conf.iec_break_count; i++) vPrtLogMsg(LOG_DEBUG, RET_OK, "---> IEC104_CONF: GIS_%02d Eqm_code(A,B,C) = (%s,%s,%s [%d,%d])", i+1, g_iec_conf.pstBrkCode[i].szEqmCodeA, g_iec_conf.pstBrkCode[i].szEqmCodeB, g_iec_conf.pstBrkCode[i].szEqmCodeC, g_iec_conf.pstBrkCode[i].uiAbortVoltage, g_iec_conf.pstBrkCode[i].uiAbortCurrent); // 显示点表地址匹配关系map vPrtLogMsg(LOG_DEBUG, RET_OK, "---> g_map_sadr: size= %d", g_map_sadr.size()); } void InitIECENV() { memset(&g_IecCtrl, 0x00, sizeof(ST_IEC104_CTRL)); g_IecCtrl.t0 = (int)g_TConfig.getTimeout0(); g_IecCtrl.t1 = (int)g_TConfig.getTimeout1(); g_IecCtrl.t2 = (int)g_TConfig.getTimeout2(); g_IecCtrl.t3 = (int)g_TConfig.getTimeout3(); g_IecCtrl.k = (int)g_TConfig.getK(); g_IecCtrl.w = (int)g_TConfig.getW(); g_IecCtrl.timer_S_Ackflag = true; g_IecCtrl.timer_U_Testflag = true; // 初始化为真,如果过程中有超时,置为false g_IecCtrl.m_gis_change = false; g_IecCtrl.time_action = time(NULL); // 总召间隔时间更新 } void IEC104EnvLoad() { mutex_create(g_list_pack_mutex); mutex_create(g_list_dbset_mutex); mutex_create(g_sendno_mutex); mutex_create(g_list_origin_mutex); mutex_create(g_list_origin_mutex_new); mutex_create(g_list_busi_data_mutex); mutex_create(g_list_pingce_mutex); mutex_create(g_list_warn_mutex); g_list_pack.clear(); g_list_dbset.clear(); g_list_origin.clear(); g_list_origin_new.clear(); g_list_busi_data.clear(); g_list_pingce.clear(); g_list_warn.clear(); InitIECENV(); iGetIEC104Conf(); //InitIECPointTable(); #ifdef _DEBUG showIEC104Conf(); #endif } void IEC104EnvFree() { mutex_close(g_list_pack_mutex); mutex_close(g_list_dbset_mutex); mutex_close(g_sendno_mutex); mutex_close(g_list_origin_mutex); mutex_close(g_list_origin_mutex_new); mutex_close(g_list_busi_data_mutex); mutex_close(g_list_pingce_mutex); mutex_close(g_list_warn_mutex); g_list_pack.clear(); g_list_dbset.clear(); g_list_origin.clear(); g_list_pingce.clear(); g_list_warn.clear(); } // last action time. void UpdateLastTime() { mutex_lock(g_IecCtrl_mutex); g_IecCtrl.last_time = time(NULL); mutex_unlock(g_IecCtrl_mutex); } // 添加报文到解析队列 void AddParserList(unsigned char *pbuf, int bufLen) { ST_RECVPKG stPack; ST_APCI *pstAPCI = (ST_APCI*)pbuf; memset(&stPack, 0x00, sizeof(ST_RECVPKG)); stPack.usISUType = (pstAPCI->cntl1 & 0x03); if (stPack.usISUType == 0 || stPack.usISUType == 2) { stPack.usSendNo = 2 + ((pstAPCI->cntl2 << 8) | pstAPCI->cntl1); // 发送序号 stPack.usRecvNo = (pstAPCI->cntl4 << 8) | pstAPCI->cntl3; // 接收序号 } else if (stPack.usISUType == 3) { stPack.usRecvNo = (pstAPCI->cntl4 << 8) | pstAPCI->cntl3; // 接收序号 } stPack.pszBuff = (unsigned char*)calloc(1, bufLen + 1); if (stPack.pszBuff == NULL) { vPrtLogMsg(LOG_WARNG, RET_CALLOC_FAIL, "calloc failed."); return; } memcpy(stPack.pszBuff, pbuf, bufLen); stPack.iLength = bufLen; mutex_lock(g_list_pack_mutex); g_list_pack.push_front(stPack); mutex_unlock(g_list_pack_mutex); } //ST_IEC104_DATA //添加到入库队列 // pkgtype= 类型:1-运行工况 2:断路器数据 3:变压器负荷数据 static void addDbSetList(char *pdata, int length, char ctype) { int i = 0; ST_DB_DATA stSetData; memset(&stSetData, 0x00, sizeof(ST_DB_DATA)); stSetData.pData = (unsigned char*)calloc(1, length); if (stSetData.pData == NULL) { vPrtLogMsg(LOG_WARNG, RET_CALLOC_FAIL, "calloc failed."); return; } memcpy(stSetData.pData, pdata, length); stSetData.ctype = (ctype & 0xff); //类型:1 - 运行工况 2 : 断路器数据 3 : 变压器负荷数据 stSetData.iLength = length; mutex_lock(g_list_dbset_mutex); g_list_dbset.push_front(stSetData); mutex_unlock(g_list_dbset_mutex); } // 添加告警数据队列 static void addWarningTableList(ST_IECPOINT_TABLE &stData) { int i = 0; ST_IECPOINT_TABLE stSetData; memset(&stSetData, 0x00, sizeof(ST_DB_DATA)); memcpy(&stSetData, &stData, sizeof(ST_IECPOINT_TABLE)); mutex_lock(g_list_warn_mutex); g_list_warn.push_front(stSetData); mutex_unlock(g_list_warn_mutex); } // 添加断路器断开状态数据队列 static void addGisDataList(ST_IECPOINT_TABLE &stData) { int i = 0; ST_IECPOINT_TABLE stSetData; memset(&stSetData, 0x00, sizeof(ST_DB_DATA)); memcpy(&stSetData, &stData, sizeof(ST_IECPOINT_TABLE)); mutex_lock(g_list_pingce_mutex); g_list_pingce.push_front(stSetData); mutex_unlock(g_list_pingce_mutex); } // 添加原始数据入库队列 static void addOriginDataList(ST_IECPOINT_TABLE &stData) { int i = 0; ST_IECPOINT_TABLE stSetData; memset(&stSetData, 0x00, sizeof(ST_DB_DATA)); memcpy(&stSetData, &stData, sizeof(ST_IECPOINT_TABLE)); mutex_lock(g_list_origin_mutex); g_list_origin.push_front(stSetData); mutex_unlock(g_list_origin_mutex); } // 添加原始数据入库队列 static void addOriginDataListNew(const IEC_OBJVAL_NEW &stData) { // int i = 0; // IEC_OBJVAL_NEW stSetData; // memset(&stSetData, 0x00, sizeof(IEC_OBJVAL_NEW)); // memcpy(&stSetData, &stData, sizeof(IEC_OBJVAL_NEW)); mutex_lock(g_list_origin_mutex_new); g_list_origin_new.push_front(stData); mutex_unlock(g_list_origin_mutex_new); } // 获取发送序列号 void vAutoSendSeqNo(int b) { mutex_lock(g_sendno_mutex); if (g_IecCtrl.usSendNo > 16384) g_IecCtrl.usSendNo = 0; else g_IecCtrl.usSendNo += b; mutex_unlock(g_sendno_mutex); } // TX U-Format Message (APCI only) int SendMsgFormatU(int cmd) { int iRet = -1; if (g_Tcp.tcpIsConnected(g_IecCtrl.sockid)) { ST_APCI header; header.start = 0x68; header.len = 0x04; header.cntl1 = 0x03 | cmd; // U-Format header.cntl2 = 0; header.cntl3 = 0; // g_IecCtrl.usRecvNo & 0xFE; header.cntl4 = 0; //(g_IecCtrl.usRecvNo >> 8) & 0xFF; iRet = g_Tcp.tcpSendBuffer(g_IecCtrl.sockid, (const char*)&header, sizeof(ST_APCI)); if (iRet == ErrException) { vPrtLogMsg(LOG_ERROR, iRet, "send mesg failed, sockid:%d msg:%s will close socket", g_IecCtrl.sockid, strerror(errno)); g_Tcp.clear_tcp_buffer(g_IecCtrl.sockid, MAX_SBUFF_TCP); g_Tcp.tcpCloseSocket(g_IecCtrl.sockid); g_IecCtrl.isConnect = false; } //g_IecCtrl.usSendNo++; vPrtLogHex(LOG_PACK, g_IecCtrl.sockid, PRT_PACK_SEND, (unsigned char*)&header, sizeof(ST_APCI)); } return iRet; } // 发送S格式报文 int SendMsgFormatS(unsigned short sendno) { if (!g_IecCtrl.isConnect || g_IecCtrl.sockid <= 0) { vPrtLogMsg(LOG_WARNG, RET_FAIL, "send S package, No socket connection, send cancel.sockid=%d isConn=%d", g_IecCtrl.sockid, g_IecCtrl.isConnect); return 0; } ST_APCI header; int iRet = -1; header.start = 0x68; header.len = 0x04; header.cntl1 = 0x01; // S-Format header.cntl2 = 0x00; //S格式确认包,cnt1=0x01, cnt2=0x00,是固定不变的。 header.cntl3 = sendno & 0xFE; // 应答对端的接收序列号 header.cntl4 = (sendno >> 8) & 0xFF; //header.cntl1 = (g_IecCtrl.RxCounter & 0xFE); // S-Format //header.cntl2 = (g_IecCtrl.RxCounter >> 8) & 0xFF; //S格式确认包,cnt1=0x01, cnt2=0x00,是固定不变的。 //header.cntl3 = (g_IecCtrl.TxCounter & 0xFE); // S-Format //header.cntl4 = (g_IecCtrl.TxCounter >> 8) & 0xFF; //S格式确认包,cnt1=0x01, cnt2=0x00,是固定不变的。 if ((iRet = g_Tcp.tcpSendBuffer(g_IecCtrl.sockid, (const char*)&header, sizeof(ST_APCI))) < 0) { vPrtLogMsg(LOG_WARNG, iRet, "send Format S failed with error: %s, errno=%d will close socket", strerror(errno), errno); g_Tcp.clear_tcp_buffer(g_IecCtrl.sockid, MAX_SBUFF_TCP); g_Tcp.tcpCloseSocket(g_IecCtrl.sockid); g_IecCtrl.isConnect = false; return iRet; } //g_IecCtrl.usSendNo++; vPrtLogHex(LOG_PACK, g_IecCtrl.sockid, PRT_PACK_SEND, (unsigned char*)&header, sizeof(ST_APCI)); return iRet; } // TX I-Format Message (always contains ASDU) int SendMsgFormatI(unsigned char *msgbuf, unsigned int len) { if (!g_IecCtrl.isConnect || g_IecCtrl.sockid <= 0) { vPrtLogMsg(LOG_WARNG, RET_FAIL, "send I package, No socket connection, send cancel.sockid=%d isConn=%d", g_IecCtrl.sockid, g_IecCtrl.isConnect); return 0; } char buf[1024]; int iRet = -1; ST_APCI *header = (ST_APCI*)buf; vAutoSendSeqNo(1); // 发送序列号增1 header->start = 0x68; header->len = 0x04 + len; header->cntl1 = g_IecCtrl.usSendNo & 0xFE; // I-Format header->cntl2 = ((g_IecCtrl.usSendNo >> 8) & 0xFF); header->cntl3 = (g_IecCtrl.usRecvNo & 0xFE); // I-Format header->cntl4 = ((g_IecCtrl.usRecvNo >> 8) & 0xFF); memcpy(buf + sizeof(ST_APCI), msgbuf, len); if ((iRet = g_Tcp.tcpSendBuffer(g_IecCtrl.sockid, (const char*)buf, len + sizeof(ST_APCI))) < 0) { vPrtLogMsg(LOG_WARNG, iRet, "send Format I failed with error: %s, errno=%d will close socket", strerror(errno), errno); g_Tcp.clear_tcp_buffer(g_IecCtrl.sockid, MAX_SBUFF_TCP); g_Tcp.tcpCloseSocket(g_IecCtrl.sockid); g_IecCtrl.isConnect = false; return iRet; } // g_IecCtrl.usSendNo++; vPrtLogHex(LOG_PACK, g_IecCtrl.sockid, PRT_PACK_SEND, (unsigned char*)buf, len + sizeof(ST_APCI)); return iRet; } int Interrogate(int asdu, int group) { ST_ASDU msg; msg.header.type = 0x64; // interrogation command msg.header.qual = 0x01; // number of elements msg.header.tx_cause1 = 0x06; // activation msg.header.tx_cause2 = 0x00; msg.header.commom_asdu1 = asdu & 0xFF; msg.header.commom_asdu2 = (asdu >> 8) & 0xFF; // 貌似少了3个字节的信息体地址 // group information msg.data[0] = 0x00; msg.data[1] = 0x00; msg.data[2] = 0x00; msg.data[3] = 20 + group; return SendMsgFormatI((unsigned char*)&msg, 10); } /*************************************************************************** ** 函数名:thread_listen_proc 启动服务线程 ** 参数: 无 ** ** 返回: 无 ***************************************************************************/ void* thread_listen_proc(void * arg) { int server_fd, accept_fd; vPrtLogMsg(LOG_DEBUG, 0, "thread_listen_proc = %d startup...", GETTID()); //从链路启动服务 server_fd = g_Tcp.tcpOpenServer(g_TConfig.getLocalAddr(), g_TConfig.getLocalPort()); if (server_fd <= 0) { vPrtLogMsg(LOG_ERROR, server_fd, "Local server:%s:%d startup failed.", g_TConfig.getLocalAddr(), g_TConfig.getLocalPort()); g_Running = 0; return NULL; } g_Tcp.tcpSetServerfd(server_fd); mutex_lock(g_IecCtrl_mutex); g_IecCtrl.listenid = server_fd; mutex_unlock(g_IecCtrl_mutex); while (g_Running) { pthread_testcancels(); accept_fd = g_Tcp.tcpAcceptSocket(server_fd); if (accept_fd < 0) { /* mutex_lock(g_IecCtrl_mutex); g_Tcp.tcpCloseSocket(g_IecCtrl.sockid); g_IecCtrl.last_time = 0; g_IecCtrl.sockid = -1; g_IecCtrl.isConnect = false; mutex_unlock(g_IecCtrl_mutex); _SLEEP(1000); */ // vPrtLogMsg(LOG_DEBUG, errno,"slave link waitting connect...accept_fd=%d", accept_fd); continue; } mutex_lock(g_IecCtrl_mutex); if (g_Tcp.tcpIsConnected(g_IecCtrl.sockid)) { mutex_unlock(g_IecCtrl_mutex); vPrtLogMsg(LOG_DEBUG, errno,"Previous link is connected, won't accept accept_fd=%d", accept_fd); _SLEEP(1000); continue; } g_IecCtrl.last_time = time(NULL); g_IecCtrl.last_yx_time = time(NULL); g_IecCtrl.last_yc_time = time(NULL); g_IecCtrl.sockid = accept_fd; g_IecCtrl.isConnect = true; mutex_unlock(g_IecCtrl_mutex); pthread_t thread_handle_minor_recv = -1; pthread_t thread_handle_minor_active = -1; _SLEEP(3000); // 给主链路时间,来处理登录应答. #ifndef _WIN32 pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // 创建一个分离子线程 #endif g_Tcp.tcpSetSockID(accept_fd); vPrtLogMsg(LOG_DEBUG, errno, "connect link the recv socket fd is: %d", g_IecCtrl.sockid); ht_pthread_create_background(&thread_handle_minor_recv, thread_recv_proc, NULL); ht_pthread_create_background(&thread_handle_minor_active, thread_active_proc, NULL); #ifndef _WIN32 pthread_detach(thread_handle_minor_recv); pthread_detach(thread_handle_minor_active); #endif _SLEEP(1000); } g_Tcp.tcpCloseSocket(server_fd); vPrtLogMsg(LOG_DEBUG, errno, "shutdown accept addr=%s:%d, socket_id: %d", g_TConfig.getLocalAddr(), g_TConfig.getLocalPort(), server_fd); return NULL; } // 添加104子站服务不能连接的告警消息 void vSetIEC104StationsWarnMesg() { int i = 0; char eqm_code[64] = { 0 }, szuuid[64] = { 0 }; char szSql[DEF_BUFFER_1K] = { 0 }; CDBMySQL *pdbHandle = CDBMySQL::Instance(); if (!pdbHandle) { return; } vGetHostTimeFmt(g_IecCtrl.m_iec_warn_time); for (i = 0; i < (int)g_iec_conf.iec_byq_count; i++) { getuuid(szuuid, sizeof(szuuid)); strcpy(eqm_code, (const char*)g_iec_conf.pstByqCode[i].szEqmCode); snprintf(szSql,sizeof(szSql), "INSERT INTO busi_eqm_warning(id,eq_type,gz_type,warning_msg,warning_time,create_time," "del_flag,site_id,main_tree_id,run_state) " "VALUES('%s','1', '9', '104子站服务异常断开,请检查服务!', '%s', SYSDATE(), '1', '%s', '%s','0')", szuuid,g_IecCtrl.m_iec_warn_time, g_iec_conf.site_id, eqm_code); vPrtLogMsg(LOG_DEBUG, RET_OK, "insert IECService Warning: %s", szSql); if (!pdbHandle->InsertRecord((const char *)szSql)) { vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO busi_eqm_warning message failed,SQL:%s", szSql); } // 插入告警详细表 char szSubUuid[64] = { 0 }; char szWarninfo[512] = { 0 }; getuuid(szSubUuid, sizeof(szSubUuid)); memset(szSql, 0x00, sizeof(szSql)); snprintf(szWarninfo, sizeof(szWarninfo), "{\"sadr\":\"\",\"thresholdValue\":\"\",\"currRealValue\":\"\",\"equipmentStatus\":\"\",\"collectDate\":\"%s\",\"ipaddr\":\"%s\",\"port\":\"%d\",\"msgInfo\":\"%s\",\"phase\":\"\"}", g_IecCtrl.m_iec_warn_time, g_TConfig.getRemoteAddr(), g_TConfig.getRemotePort(),"IEC104服务链路"); snprintf(szSql, sizeof(szSql), "INSERT INTO busi_eqm_warning_info(id,warning_id,warning_info) " "VALUES('%s','%s','%s')", szSubUuid, szuuid, szWarninfo); if (!pdbHandle->InsertRecord((const char *)szSql)) { vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO busi_eqm_warning_info message failed,SQL:%s", szSql); } } } // 删除104子站服务不能连接的告警消息 void vDelIEC104StationsWarnMesg() { int i = 0; char eqm_code[64] = { 0 }; char szSql[DEF_BUFFER_1K] = { 0 }; CDBMySQL *pdbHandle = CDBMySQL::Instance(); if (!pdbHandle) { return; } for (i = 0; i < (int)g_iec_conf.iec_byq_count; i++) { strcpy(eqm_code, (const char*)g_iec_conf.pstByqCode[i].szEqmCode); if (strlen(g_IecCtrl.m_iec_warn_time) > 0 ) snprintf(szSql, sizeof(szSql), "update busi_eqm_warning set del_flag='2', deal_status='1',processing_time=sysdate(),deal_msg='system service auto resume.'," "processing_user='system' where site_id='%s' and eq_type='1' and gz_type='9' and main_tree_id='%s' and warning_time='%s' and " "warning_msg='104子站服务异常断开,请检查服务!' ", g_iec_conf.site_id, eqm_code, g_IecCtrl.m_iec_warn_time); else snprintf(szSql, sizeof(szSql), "update busi_eqm_warning set del_flag='2', deal_status='1',processing_time=sysdate(),deal_msg='system service auto resume.'," "processing_user='system' where site_id='%s' and eq_type='1' and gz_type='9' and main_tree_id='%s' and " "warning_msg='104子站服务异常断开,请检查服务!' ", g_iec_conf.site_id, eqm_code); vPrtLogMsg(LOG_DEBUG, RET_OK, "update IECService Warning: %s", szSql); if (!pdbHandle->UpdateRecord((const char *)szSql)) { vPrtLogMsg(LOG_ERROR, RET_FAIL, "update busi_eqm_warning message failed,SQL:%s", szSql); } } } /*************************************************************************** ** function name : thread_linkmgr_proc ** deacription : link manager thread ** parameter : none ** return code : NULL ***************************************************************************/ void *thread_client_proc(void *arg) { bool bWarn = true; vPrtLogMsg(LOG_DEBUG, 0, "thread_client_proc = %d startup...", GETTID()); g_IecCtrl.b_Signal = false; g_IecCtrl.m_gis_fault_count = 0; // g_IecCtrl.m_gis_count = 0; while (g_Running) { pthread_testcancels(); if (g_Tcp.tcpIsConnected(g_IecCtrl.sockid) && g_IecCtrl.isConnect) { _SLEEP(5000); // 5秒钟检查一次链路是否正常 continue; } else if (g_IecCtrl.sockid > 0) { mutex_lock(g_IecCtrl_mutex); g_Tcp.tcpCloseSocket(g_IecCtrl.sockid); g_IecCtrl.last_time = 0; g_IecCtrl.sockid = -1; g_IecCtrl.isConnect = false; InitIECENV(); mutex_unlock(g_IecCtrl_mutex); } vPrtLogMsg(LOG_DEBUG, 0, "Connect to server:%s:%d start...", g_TConfig.getRemoteAddr(), g_TConfig.getRemotePort()); //创建客户端 g_IecCtrl.sockid = g_Tcp.tcpConnect(g_TConfig.getRemoteAddr(), g_TConfig.getRemotePort(), 30); // t0 = 30s if (g_IecCtrl.sockid <= 0) { vPrtLogMsg(LOG_ERROR, g_IecCtrl.sockid, "Connect to server:%s:%d failed.", g_TConfig.getRemoteAddr(), g_TConfig.getRemotePort()); if (bWarn) { vSetIEC104StationsWarnMesg(); bWarn = false; } _SLEEP(5000); continue; } mutex_lock(g_IecCtrl_mutex); g_IecCtrl.last_time = time(NULL); g_IecCtrl.isConnect = true; mutex_unlock(g_IecCtrl_mutex); SendMsgFormatU(CMD_STARTDT); // 发送激活命令 pthread_t thread_handle_minor_recv = -1; pthread_t thread_handle_minor_active = -1; g_Internal_time = time(NULL); //_SLEEP(3000) ; #ifndef _WIN32 pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // 创建一个分离子线程,接收数据线程 #endif vPrtLogMsg(LOG_DEBUG, errno, "connect link the recv socket fd is: %d", g_IecCtrl.sockid); ht_pthread_create_background(&thread_handle_minor_recv, thread_recv_proc, NULL); ht_pthread_create_background(&thread_handle_minor_active, thread_active_proc, NULL); #ifndef _WIN32 pthread_detach(thread_handle_minor_recv); pthread_detach(thread_handle_minor_active); #endif _SLEEP(1000); bWarn = true; vDelIEC104StationsWarnMesg(); // 链路自动恢复后,处理链路告警:以处理 } g_Tcp.tcpCloseSocket(g_IecCtrl.sockid); g_IecCtrl.isConnect = false; vPrtLogMsg(LOG_DEBUG, errno, "shutdown thread_client_proc, server_addr=%s:%d, socket_id: %d", g_TConfig.getRemoteAddr(), g_TConfig.getRemotePort(), g_IecCtrl.sockid); return NULL; } /*************************************************************************** ** function name : thread_recv_proc ** deacription : 104 parser thread ** parameter : none ** return code : NULL ***************************************************************************/ void* thread_recv_proc(void * arg) { unsigned char szBuf[MAX_SBUFF_TCP] = { 0 }; int recv_buflen = 0, pkgLen = 0; vPrtLogMsg(LOG_DEBUG, 0, "thread_recv_proc = %d startup, sockid=%d...", GETTID(), g_IecCtrl.sockid); while (g_Running && g_IecCtrl.isConnect) { pthread_testcancels(); memset(szBuf, 0x00, sizeof(szBuf)); recv_buflen = -1; pkgLen = 0; recv_buflen = g_Tcp.tcpRecvBuffer(g_IecCtrl.sockid, (char*)szBuf, MAX_SBUFF_TCP, 5); // t1 = 15s if (recv_buflen == ErrException || (recv_buflen == 0 && errno == 2)) { vPrtLogMsg(LOG_WARNG, errno, "socket link exceptiond, do close sockid=%d, thread_recv_proc pthread_exit.", g_IecCtrl.sockid); g_Tcp.clear_tcp_buffer(g_IecCtrl.sockid, MAX_SBUFF_TCP); mutex_lock(g_IecCtrl_mutex); g_IecCtrl.isConnect = false; g_IecCtrl.sockid = -1; mutex_unlock(g_IecCtrl_mutex); break; } else if (recv_buflen <= 0) { vPrtLogMsg(LOG_WARNG, RET_OK,"socket link recv data length: %d,sockid=%d,errno=%d, sleep and continue",recv_buflen,g_IecCtrl.sockid,errno); _SLEEP(1000); continue; } mutex_lock(g_IecCtrl_mutex); g_IecCtrl.last_time = time(NULL); mutex_unlock(g_IecCtrl_mutex); if (recv_buflen < (int)sizeof(ST_APCI)) // < 6byte { _SLEEP(1000); continue; } if (recv_buflen >= (int)sizeof(ST_APCI) && (szBuf[0] & 0xff) == CMD_START_HEAD) // 0x68H { pkgLen = 1 + 1 + (szBuf[1] & 0xff); if (recv_buflen < pkgLen) continue; } AddParserList(szBuf, pkgLen); vPrtLogHex(LOG_PACK, g_IecCtrl.sockid, PRT_PACK_RECV, (unsigned char*)szBuf, pkgLen); g_Tcp.clear_tcp_buffer(g_IecCtrl.sockid, pkgLen); } vPrtLogMsg(LOG_DEBUG, RET_OK, "link exceptiond, thread_recv_proc pthread_exit."); return NULL; } //遥控执行 void vYaoKongExe(unsigned char *msgbuf, unsigned int len) { msgbuf[2] = 0x06; msgbuf[9] = 0x01; SendMsgFormatI(msgbuf, len); } //遥控撤销 void vYaoKongUnexe(unsigned char *msgbuf, unsigned int len) { msgbuf[2] = 0x08; SendMsgFormatI(msgbuf, len); } // 遥信值入map bool bSetPointTableValueYX(unsigned char v, unsigned int adr) { IEC_OBJVAL_NEW objVal = { 0 }; objVal.stype = 1; objVal.dtime = time(NULL); objVal.ival = v; objVal.sadr = adr; addOriginDataListNew(objVal); bool is_state_opend = false; unsigned char ovl = 0; map::iterator m_pIter; mutex_lock(g_map_iec_mutex); m_pIter = g_map_iec.find(adr); if (m_pIter != g_map_iec.end()) { if (((m_pIter->second).stype & 0xff) == 0x01) { (m_pIter->second).dtime = time(NULL)-1; // 遥信量 if ((v & 0xff) != ((m_pIter->second).cval & 0xff)) { ovl = ((m_pIter->second).cval & 0xff); // 上一次的状态值 (m_pIter->second).cval = (v & 0xff); g_IecCtrl.b_Signal = true; g_IecCtrl.stime = time(NULL); // 根据配置文件GIS的点位配置,抓取断路器断开状态 if (((ovl & 0xff) == YX_STAT_CLOSE) && ((v & 0xff) == YX_STAT_OPEND)) // 原状态位合1,且新状态位0,表示断路器断开一次 { addGisDataList(m_pIter->second); // 记录一次断开数据 } if (((m_pIter->second).eqm_type & 0xff) == 0x01) { (m_pIter->second).wstate = getDevWorkState(m_pIter->second); // 刷新主变工作状态 SethDevTimeStat((m_pIter->second).sys_code, (m_pIter->second).wstate); vPrtLogMsg(LOG_DEBUG, RET_OK, "YX addr:%d(0x%04x) set val=%d, eqid=%s wstatue=%d", adr, adr, (m_pIter->second).cval, (m_pIter->second).eqm_code,(m_pIter->second).wstate); (m_pIter->second).bfault = getDevFaultState(m_pIter->second); // 刷新主变事故状态 } if (((m_pIter->second).eqm_type & 0xff) == 0x02) //刷新GIS开关开合状态 { flushDevCloseState((m_pIter->second).site_id, (m_pIter->second).eqm_code, (m_pIter->second).cval); } addOriginDataList(m_pIter->second); // 原始数据入库队列 vPrtLogMsg(LOG_DEBUG, RET_OK, "YX addr:%d(0x%04x) set val=%d", adr, adr, (m_pIter->second).cval); } } } mutex_unlock(g_map_iec_mutex); return true; } bool bSetPointTableValueYX(const std::vector& values) { /* IEC_OBJVAL_NEW objVal = { 0 }; objVal.stype = 1; objVal.dtime = time(NULL); objVal.ival = v; objVal.sadr = adr; addOriginDataListNew(objVal); */ return true; } //遥测值入map bool bSetPointTableValueYC(float v, unsigned int adr) { map::iterator m_pIter; double oldval = 0.0; mutex_lock(g_map_iec_mutex); m_pIter = g_map_iec.find(adr); if (m_pIter != g_map_iec.end()) { vPrtLogMsg(LOG_DEBUG, RET_OK, "bSetPointTableValueYC:%d(0x%04x) set style=%d added OriginDataList", adr, adr, (m_pIter->second).stype); if (((m_pIter->second).stype & 0xff) == 2) { // 遥测量 oldval = (m_pIter->second).fval; (m_pIter->second).dtime = time(NULL); (m_pIter->second).fval = getChangeUnit((m_pIter->second).unit, (m_pIter->second).sysunit, v); // 单位转换 if (((m_pIter->second).eqm_type & 0xff) == 1) (m_pIter->second).wstate = cGetByqDeviceState((m_pIter->second).eqm_code); else (m_pIter->second).wstate = cGetCurrentWorkState((m_pIter->second).eqm_code); // 获取工作状态 if (strlen((char*)(m_pIter->second).fieldname) > 0) { addWarningTableList(m_pIter->second); } #ifdef _DEF_DB_CHANGERATE #if 0 if (g_IecCtrl.b_Signal) { vPrtLogMsg(LOG_WARNG, RET_OK, "YC addr:%d(0x%04x) set val=%.4f, eqid=%s wstatue=%d", adr, adr, (m_pIter->second).fval, (m_pIter->second).eqm_code, (m_pIter->second).wstate); addPingCeTableList(m_pIter->second); g_IecCtrl.b_Signal = false; } else if (bCompare(oldval, (m_pIter->second).fval, (m_pIter->second).devrate) && !g_IecCtrl.b_Signal) { // 计算偏差率 //vPrtLogMsg(LOG_WARNG, RET_OK, "YC addr:%d(0x%04x) set val=%.4f-%.4f-%.4f, eqid=%s wstatue=%d", adr, adr, (m_pIter->second).fval,oldval,v, (m_pIter->second).eqm_code, (m_pIter->second).wstate); vPrtLogMsg(LOG_WARNG, RET_OK, "bCompare olv=%.4f nlv=%.4f sadr=%d rate=%.2f",oldval,(m_pIter->second).fval, adr, (m_pIter->second).devrate); addPingCeTableList(m_pIter->second); } if ((time(NULL) - g_Internal_time) >= (g_iec_conf.save_internal)) { // 间隔时间保存数据 vPrtLogMsg(LOG_WARNG, RET_OK, "(time(NULL) - g_Internal_time) =%d internal=%d", (time(NULL) - g_Internal_time), g_iec_conf.save_internal); addPingCeTableList(m_pIter->second); g_Internal_time = time(NULL); } #endif #endif if ((m_pIter->second).isget == 1 && bCompare(oldval, (m_pIter->second).fval, (m_pIter->second).devrate)) // 是否提取 { addOriginDataList(m_pIter->second); // 原始数据入库队列 vPrtLogMsg(LOG_DEBUG, RET_OK, "YC addr:%d(0x%04x) set val=%.4f added OriginDataList", adr, adr, (m_pIter->second).fval); } //vPrtLogMsg(LOG_DEBUG, RET_OK, "YC addr:%d(0x%04x) set val=%.4f", adr, adr, (m_pIter->second).fval); } } mutex_unlock(g_map_iec_mutex); return true; } bool bSetPointTableValueYC(const std::vector& values) { // Save the origin data into database first for (std::vector::const_iterator it = values.begin(); it != values.end(); ++it) { addOriginDataListNew(*it); } if (g_TConfig.shouldParseBusiData() != 0) { // time_t ts = 0; std::map::const_iterator itPoint; bool assigned = false; map::iterator itCachedDev; std::string sql; list::iterator itBusiData; mutex_lock(g_map_iec_mutex_new); for (std::vector::const_iterator it = values.begin(); it != values.end(); ++it) { if (it->stype == 1) { continue; } itPoint = g_map_iec_new.find(it->sadr); if (itPoint == g_map_iec_new.end() || strlen((const char*)itPoint->second.fieldName) == 0) { continue; } itCachedDev = g_map_dev_data.find(itPoint->second.sensor_id); if (itCachedDev == g_map_dev_data.end()) { continue; } assigned = AssignValueToDeviceData(itCachedDev->second, *it); if (assigned) { if (itCachedDev->second.assignedFields == itCachedDev->second.fields.size()) { sql = BuildSqlForDeviceData(itCachedDev->second); ResetCachedDeviceData(itCachedDev->second); mutex_lock(g_list_busi_data_mutex); itBusiData = g_list_busi_data.insert(g_list_busi_data.end(), std::string()); itBusiData->swap(sql); mutex_unlock(g_list_busi_data_mutex); vPrtLogMsg(LOG_DEBUG, 0, "Insert Busi Data into Table %s, sensor_id=%u", (const char*)itCachedDev->second.device->tableName, itCachedDev->second.device->sensor_id); } } } mutex_unlock(g_map_iec_mutex_new); } /* IEC_OBJVAL_NEW objVal = { 0 }; objVal.stype = 2; objVal.dtime = time(NULL); objVal.fval = v; objVal.sadr = adr; addOriginDataListNew(objVal); */ return true; } // I-Formar message decodification I格式帧解码 // msgbuf : asdu_header + asdu_body // len : asdu length int DecodeMsgFormatI(unsigned char *msgbuf, unsigned int len, unsigned short sendno) { ST_ASDU_HEADER *header = NULL; ST_OBJVAL stObj[DEF_BUFFER_256]; unsigned char num = 0, cause = 0, n = 0; bool seq = false; int asdu = 0, idx = 0; unsigned int pos = 0; unsigned int adr; //ASDU = type(1) + limit(1) + cause(2) + gaddr(2) + objaddr(3) + data(1) + data(1) + ... memset(stObj, 0x00, sizeof(ST_OBJVAL)*DEF_BUFFER_256); /* 可变结构限定词 = VARIABLE STRUCTURE QUALIFIER :=CP8{ number、SQ } number = N = 数目 := UI7[1..7]<0..127> <0> :=应用服务数据单元不含信息对象 <1..127>:=应用服务数据单元信息元素(单个信息元素或同类信息元素组合)的数目 SQ = 单个或者顺序 := BS1[8]<0..1> <0> :=寻址同一种类型的许多信息对象中单个的信息元素或者信息元素的集合 <1> :=寻址 ASDU 单个信息对象中顺序的单个信息元素信息元素的同类集合 SQ<0>和 N<0..127>∶ = 信息对象的数目 I (一个地址+一个元素)*N SQ<1>和 N<0..127>∶ = 每个应用服务数据单元中单个对象的信息元素或者信息元素的 集合的数目 j (一个地址,后接连续 N 个元素) SQ 位规定寻址后续信息对象或单个信息元素 / 信息元素集合的方法。 SQ := 0 由信息对象地址寻址的单个信息元素或信息元素集合。应用服务数据单 元可以由一个或者多个同类的信息对象所组成。数目 N 是一个二进制数,它定义了信息对 象的数目。 SQ := 1 单个信息元素或者信息元素同类集合的序列(即同一种格式测量值)由信 息对象地址来寻址(见 IEC 60870 - 5 - 3 中的 5.1.5), 信息对象地址是顺序单个信息元素或者信 息元素集合的第一个信息元素或者集合的地址。后续单个信息元素或者信息元素集合的地 址是从这个地址起顺序加 1。数目 N 是一个二进制数,它定义了单个信息元素或者信息元 素集合的数目。在顺序单个信息元素或者信息元素集合的情况下每个应用服务数据单元仅 安排一个信息对象. */ header = (ST_ASDU_HEADER*)msgbuf; num = header->qual & 0x7F; // number of objects. 数据元素个数 if (header->qual & 0x80) // sequence of objects ? 限定词,第一位:1=报文包含信息数据,0=不含信息数据 seq = true; /* 传送原因 = CAUSE OF TRANSMISSION := CP16{ Cause, P / N, T, Originator Address(opt) } 其中 Cause :=UI6[1..6]<0..63> <0> := 未定义 <1..63> :=传送原因序号 <1..47> :=本配套标准的标准定义(兼容范围)见表 14 <48..63> := 专用范围 P/N ∶ = BS1[7]<0..1> <0> ∶ = 肯定确认 <1> ∶ = 否定确认 T=test := BS1[8]<0..1> <0>:=未试验 <1>:=试验 Originator address = 源发者地址 := UI8[9..16] <0>:=缺省值 <1..255> :=源发者地址号 */ cause = header->tx_cause1; // cause of tx.传送原因[1] /* 公共地址 :=UI16[1..16]<0..65535> 其中 <0> :=未用 <1..65534> :=站地址 <65535> :=全局地址 */ asdu = header->commom_asdu2 << 8; asdu |= header->commom_asdu1; if (asdu != g_iec_conf.iec_global_addr) { vPrtLogMsg(LOG_ERROR, RET_FAIL, "Recv Common Address=0x%04x(%d), Dest Common Address=0x%04x(%d), Plase Checking Config!", asdu, asdu,g_iec_conf.iec_global_addr,g_iec_conf.iec_global_addr); } vPrtLogMsg(LOG_DEBUG, RET_OK, "ASDU Common Address=0x%04x(%d) TypeID=%d Count=%d Cause=%d(0x%02x) seq=%d", asdu, asdu, header->type, num, cause, cause, seq); // type identification // 第一个八位位组为类型标识(图 11), 它定义了后续信息对象的结构、类型和格式。 // 类型标识定义如下: // 类型标识=TYPE IDENTIFICATION:=UI8[1..8]<1..255> // bit 8 7 6 5 4 3 2 1 // 信息对象是否带时标由标识类型的不同序号来区分。 // 控制站将舍弃那些类型标识未被定义的应用服务数据单元 // 类型标识值<0>未用,在本配套标准中定义了 1 至 127 的值,128 至 255 未定义。136 // 至 255 可以由此标准的使用者彼此独立的进行定义,仅当使用具有类型标识号为 1 至 127 // 的范围的应用服务数据单元才能达到全部互操作。 std::vector ycItems; IEC_OBJVAL_NEW ycItem = { 2, 0 }; time_t ts = time(NULL); switch (header->type & 0xff) { case 1: // Single-point information SIQ104 *pi; if (seq) // 有序数据,即信息体地址[3]+data[1]+data[1]+... { SP104 *ps = (SP104*)&msgbuf[sizeof(ST_ASDU_HEADER)]; adr = ps->addr2 << 16 | ps->addr1 << 8 | ps->addr0; vPrtLogMsg(LOG_DEBUG, RET_OK, "type=%d SP_%d: val:%d Valid: %d Blocked: %d", header->type, adr, ps->siq.spi, ps->siq.iv, ps->siq.bl); bSetPointTableValueYX(ps->siq.spi, adr); /* ycItem.stype = 1; ycItem.dtime = ts; ycItem.sadr = adr; ycItem.ival = ps->siq.spi; ycItems.push_back(ycItem); */ pos = sizeof(ST_ASDU_HEADER)+sizeof(SP104); while (pos < len) { adr++; pi = (SIQ104*)&msgbuf[pos]; // bSetPointTableValueYX(pi->spi, adr); /* ycItem.stype = 1; ycItem.dtime = ts; ycItem.sadr = adr; ycItem.ival = pi->spi; ycItems.push_back(ycItem); */ if (pi->spi) vPrtLogMsg(LOG_DEBUG, RET_OK, "type=%d SP_%d: val:%d Valid: %d Blocked: %d", header->type, adr, pi->spi, pi->iv, pi->bl); pos++; } if (cause == 3) SendMsgFormatS(sendno); // 突发上送之后发送S帧确认 } else { // 数据格式,即信息体地址[3]+data[1]+信息体地址[3]+data[1]+信息体地址[3]+data[1]+... pos = sizeof(ST_ASDU_HEADER); while (pos < len) { SP104 *ps = (SP104*)&msgbuf[pos]; adr = ps->addr2 << 16 | ps->addr1 << 8 | ps->addr0; bSetPointTableValueYX(ps->siq.spi, adr); /* ycItem.stype = 1; ycItem.dtime = ts; ycItem.sadr = adr; ycItem.ival = ps->siq.spi; ycItems.push_back(ycItem); */ vPrtLogMsg(LOG_DEBUG, RET_OK, "type=%d SP_%d: val:%d Valid: %d Blocked: %d", header->type, adr, ps->siq.spi, ps->siq.iv, ps->siq.bl); pos += sizeof(SP104); } } break; case 9: // 短整数,测量值,归一化值 pos = sizeof(ST_ASDU_HEADER); if (seq) { // 连续的值序列,常见于总召报文,即:3位信息地址+[2字节的值+1字节的品质位]+[2字节的值+1字节的品质位]+[2字节的值+1字节的品质位]... SH104 *pf = (SH104*)&msgbuf[pos]; adr = pf->addr2 << 16 | pf->addr1 << 8 | pf->addr0; short *val = (short*)&pf->val[0]; bSetPointTableValueYC(*val, adr); ycItem.stype = 2; ycItem.dtime = ts; ycItem.sadr = adr; ycItem.fval = *val; ycItems.push_back(ycItem); vPrtLogMsg(LOG_DEBUG, RET_OK, "type=%d SFP_%d(0x%04x): val:%d OFlow: %d Valid: %d Blocked: %d", header->type, adr, adr, *val, pf->qds.ov, pf->qds.iv, pf->qds.bl); pos += sizeof(SH104); adr++; while (pos < len) { SHP104 *pfv = (SHP104*)&msgbuf[pos]; short *val = (short*)&pfv->val[0]; bSetPointTableValueYC(*val, adr); ycItem.stype = 2; ycItem.dtime = ts; ycItem.sadr = adr; ycItem.fval = *val; ycItems.push_back(ycItem); if (*val) vPrtLogMsg(LOG_DEBUG, RET_OK, "type=%d SFP_%d(0x%04x): val:%d OFlow: %d Valid: %d Blocked: %d", header->type, adr, adr, *val, pfv->qds.ov, pfv->qds.iv, pfv->qds.bl); pos += sizeof(SHP104); adr++; } } else { // 当有变化量时,连续的值序列,即:3位信息地址+[2字节的值+1字节的品质位]+3位信息地址+[2字节的值+1字节的品质位]+... while (pos < len) { SH104 *pf = (SH104*)&msgbuf[pos]; adr = pf->addr2 << 16 | pf->addr1 << 8 | pf->addr0; short *val = (short*)&pf->val[0]; bSetPointTableValueYC(*val, adr); ycItem.stype = 2; ycItem.dtime = ts; ycItem.sadr = adr; ycItem.fval = *val; ycItems.push_back(ycItem); vPrtLogMsg(LOG_DEBUG, RET_OK, "type=%d SFP_%d(0x%04x): val:%d OFlow: %d Valid: %d Blocked: %d", header->type, adr, adr, *val, pf->qds.ov, pf->qds.iv, pf->qds.bl); pos += sizeof(SH104); } } break; case 13: // Measure value, short floating point value 短浮点数测量值 pos = sizeof(ST_ASDU_HEADER); if (seq) { // 连续的值序列,常见于总召报文,即:3位信息地址+[4字节的值+1字节的品质位]+[4字节的值+1字节的品质位]+[4字节的值+1字节的品质位]... SFP104 *pf = (SFP104*)&msgbuf[pos]; adr = pf->addr2 << 16 | pf->addr1 << 8 | pf->addr0; float *val = (float*)&pf->val[0]; bSetPointTableValueYC(*val, adr); ycItem.stype = 2; ycItem.dtime = ts; ycItem.sadr = adr; ycItem.fval = *val; ycItems.push_back(ycItem); vPrtLogMsg(LOG_DEBUG, RET_OK, "type=%d SFP_%d(0x%04x): val:%-.4f OFlow: %d Valid: %d Blocked: %d", header->type, adr, adr, *val, pf->qds.ov, pf->qds.iv, pf->qds.bl); pos += sizeof(SFP104); adr++; while (pos < len) { SFP104V *pfv = (SFP104V*)&msgbuf[pos]; float *val = (float*)&pfv->val[0]; bSetPointTableValueYC(*val, adr); ycItem.stype = 2; ycItem.dtime = ts; ycItem.sadr = adr; ycItem.fval = *val; ycItems.push_back(ycItem); vPrtLogMsg(LOG_DEBUG, RET_OK, "type=%d SFP_%d(0x%04x): val:%-.4f OFlow: %d Valid: %d Blocked: %d", header->type, adr, adr, *val, pfv->qds.ov, pfv->qds.iv, pfv->qds.bl); pos += sizeof(SFP104V); adr++; } } else { // 当有变化量时,连续的值序列,即:3位信息地址+[4字节的值+1字节的品质位]+3位信息地址+[4字节的值+1字节的品质位]+... while (pos < len) { SFP104 *pf = (SFP104*)&msgbuf[pos]; adr = pf->addr2 << 16 | pf->addr1 << 8 | pf->addr0; float *val = (float*)&pf->val[0]; bSetPointTableValueYC(*val, adr); ycItem.stype = 2; ycItem.dtime = ts; ycItem.sadr = adr; ycItem.fval = *val; ycItems.push_back(ycItem); vPrtLogMsg(LOG_DEBUG, RET_OK, "type=%d SFP_%d(0x%04x): val:%-.4f OFlow: %d Valid: %d Blocked: %d", header->type, adr, adr, *val, pf->qds.ov, pf->qds.iv, pf->qds.bl); pos += sizeof(SFP104); } } break; case 30: // Single-point information with time tag CP56Time2a 带CP56时标的单点信息 pos = sizeof(ST_ASDU_HEADER); while (pos < len) { SP104_T *ps = (SP104_T*)&msgbuf[pos]; adr = ps->addr2 << 16 | ps->addr1 << 8 | ps->addr0; CP56Time t56(ps->time); char buf[32]; t56.GetTimeString(buf, sizeof(buf)); bSetPointTableValueYX(ps->siq.spi, adr); /* ycItem.stype = 1; ycItem.dtime = ts; ycItem.sadr = adr; ycItem.ival = ps->siq.spi; ycItems.push_back(ycItem); */ vPrtLogMsg(LOG_DEBUG, RET_OK, "type=%d SP_%d: val:%d Valid: %d Blocked: %d time:%s", header->type, adr, ps->siq.spi, ps->siq.iv, ps->siq.bl, buf); pos += sizeof(SP104_T); } if (cause == 3) SendMsgFormatS(sendno); // 突发上送之后发送S帧确认 break; case 36: // Measure value, short float point value w/CP56Time2a 带CP56时标的短浮点测量值 pos = sizeof(ST_ASDU_HEADER); while (pos < len) { SFP104_T *pf = (SFP104_T*)&msgbuf[pos]; adr = pf->addr2 << 16 | pf->addr1 << 8 | pf->addr0; float *val = (float*)&pf->val[0]; bSetPointTableValueYC(*val, adr); CP56Time t56(pf->time); ycItem.stype = 2; ycItem.dtime = t56.GetTime(); ycItem.sadr = adr; ycItem.fval = *val; ycItems.push_back(ycItem); char buf[32]; t56.GetTimeString(buf, sizeof(buf)); vPrtLogMsg(LOG_DEBUG, RET_OK, "type=%d SFP_%d: val:%-.4f OFlow: %d Valid: %d Blocked: %d time:%s", header->type, adr, *val, pf->qds.ov, pf->qds.iv, pf->qds.bl, buf); pos += sizeof(SFP104_T); } break; case 45: if (cause == 7 && !g_IecCtrl.is_yk_ack) // 收到遥控返校 { vYaoKongExe(msgbuf, len);// 遥控执行 g_IecCtrl.is_yk_ack = true; } else if (cause == 7 && g_IecCtrl.is_yk_ack) { vYaoKongUnexe(msgbuf, len); // 遥控撤销 g_IecCtrl.is_yk_ack = false; } break; case 70: //站端初始化结束 pos = sizeof(ST_ASDU_HEADER); // 跳过ASDU的头,size=6byte idx = 0; while (pos < len) { memcpy(&stObj[idx].objaddr, msgbuf + pos, 3); // 信息对象地址,3字节 stObj[idx].objaddr = ntohi(stObj[idx].objaddr); // 转高低位 pos += 3; if (pos >= len) break; stObj[idx].objval = (msgbuf[pos] & 0xff); // 对象值, 0:电源合 1:电源分 idx++; pos++; } vPrtLogMsg(LOG_DEBUG, RET_OK, "End of Initialization"); break; case 100: // 总召唤命令 if (cause == 7) // 激活确认 { if (g_TConfig.shouldParseBusiData() != 0) { ResetAllCachedDeviceData(); } vPrtLogMsg(LOG_DEBUG, RET_OK, "Recv Activation Confirmation, %d.", msgbuf[9] - 20); } else if (cause == 10) // 激活结束 { g_IecCtrl.time_action = ts; // time(NULL); // SendMsgFormatS(sendno); // 总召唤结束发送S帧确认 if (g_TConfig.shouldParseBusiData() != 0) { ResetAllCachedDeviceData(); } vPrtLogMsg(LOG_DEBUG, RET_OK, "Recv Activation Termination, %d", msgbuf[9] - 20); } else vPrtLogMsg(LOG_DEBUG, RET_OK, "Recv Command:%d ,Unknown.", msgbuf[9] - 20); break; default: vPrtLogMsg(LOG_WARNG, RET_OK, "Not Implemented!,type=%d", header->type); break; } if (!ycItems.empty()) { bSetPointTableValueYC(ycItems); } return RET_OK; } // 发送召唤激活 int SendMsgFormatIAction(unsigned char cmd) { int iRet = -1; ST_IEC_APDU stPack; if (g_Tcp.tcpIsConnected(g_IecCtrl.sockid)) { memset(&stPack, 0x00, sizeof(ST_IEC_APDU)); stPack.apci.start = 0x68; stPack.apci.len = 0x0e; stPack.apci.cntl1 = 0; // g_IecCtrl.usSendNo & 0xFF; stPack.apci.cntl2 = 0;// (g_IecCtrl.usSendNo >> 8) & 0xFF; stPack.apci.cntl3 = g_IecCtrl.usRecvNo & 0xFE; stPack.apci.cntl4 = (g_IecCtrl.usRecvNo >> 8) & 0xFF; stPack.asdu.header.type = cmd; stPack.asdu.header.qual = 0x01; stPack.asdu.header.tx_cause1 = 0x06; stPack.asdu.header.tx_cause2 = 0x00; stPack.asdu.header.commom_asdu1 = (g_iec_conf.iec_global_addr & 0xFF); stPack.asdu.header.commom_asdu2 = (g_iec_conf.iec_global_addr >> 8) & 0xFF; stPack.asdu.data[3] = 0x14; // 全召 iRet = g_Tcp.tcpSendBuffer(g_IecCtrl.sockid, (const char*)&stPack, stPack.apci.len + 2); if (iRet == ErrException) { vPrtLogMsg(LOG_ERROR, iRet, "send mesg failed, sockid:%d msg:%s will close socket", g_IecCtrl.sockid, strerror(errno)); g_Tcp.clear_tcp_buffer(g_IecCtrl.sockid, MAX_SBUFF_TCP); g_Tcp.tcpCloseSocket(g_IecCtrl.sockid); g_IecCtrl.isConnect = false; } g_IecCtrl.time_action = -1; // 总召间隔时间更新 vPrtLogHex(LOG_PACK, g_IecCtrl.sockid, PRT_PACK_SEND, (unsigned char*)&stPack, iRet); } return iRet; } void DecodeMsgFormatU(ST_APCI *p) { switch (p->cntl1 & 0xfc) // 判断是否是U帧 { case CMD_STARTDT: // U启动 SendMsgFormatU(CMD_STARTC); break; case CMD_STOPDT: // U停止 SendMsgFormatU(CMD_STOPC); break; case CMD_TESTFR: // && !this->GetIsResponseUTest()) // U测试 SendMsgFormatU(CMD_TESTC); break; case 0x08: // 启动确认位:=1 vPrtLogMsg(LOG_DEBUG, RET_OK, "Send Activation"); SendMsgFormatIAction(CMD_CTL_64H); // 发送总召激活 break; default: break; } } // S-Formar message decodification S格式帧解码 void DecodeMsgFormatS(unsigned char *msgbuf, unsigned int len) { int Index; ST_IEC_APDU stPkg; memset(&stPkg, 0x00, sizeof(ST_IEC_APDU)); printf("\nFormatS"); Index = 0; /* NsIec104Struct.SendBuffer[0]=0x68; NsIec104Struct.SendBuffer[1]=0x04; NsIec104Struct.SendBuffer[2]=0x0b; NsIec104Struct.SendBuffer[3]=0x00; NsIec104Struct.SendBuffer[4]=0x00; NsIec104Struct.SendBuffer[5]=0x00; NsIec104Struct.ReceiveHimNumber[0]=NsIec104Struct.ReceiveBuffer[2]; NsIec104Struct.ReceiveHimNumber[1]=NsIec104Struct.ReceiveBuffer[3]; if((NsIec104Struct.SendLength = send(NsIec104Struct.NsNewSocketId,&NsIec104Struct.SendBuffer[0],6,0x0)) < 0) { perror ("Client Write Error"); } printf("\nwrite=%d",NsIec104Struct.SendLength); */ } /*************************************************************************** ** function name : thread_parser_proc ** deacription : 104 parser thread ** parameter : none ** return code : NULL ***************************************************************************/ void * thread_parser_proc(void * arg) { int len = 0, j = 0; ST_RECVPKG pData; vPrtLogMsg(LOG_DEBUG, 0, "thread_parser_proc = %d startup...", GETTID()); while (g_Running) { pthread_testcancels(); memset(&pData, 0x00, sizeof(ST_RECVPKG)); mutex_lock(g_list_pack_mutex); if (g_list_pack.empty() || g_list_pack.size() <= 0) { mutex_unlock(g_list_pack_mutex); _SLEEP(MAX_SLEEP_EMPTY * 10); continue; } memcpy(&pData, &(g_list_pack.back()), sizeof(ST_RECVPKG)); // 由尾取出 if (pData.pszBuff == NULL) { mutex_unlock(g_list_pack_mutex); _SLEEP(MAX_SLEEP_EMPTY * 10); continue; } g_list_pack.pop_back(); // 由尾删除 mutex_unlock(g_list_pack_mutex); // 解析104报文 if (pData.iLength >= MIN_APDU_LENGTH && (pData.pszBuff[0] & 0xff) == CMD_START_HEAD) // 0x68H { ST_APCI *pstAPCI = (ST_APCI*)pData.pszBuff; g_IecCtrl.usISUType = (pstAPCI->cntl1 & 0x03); g_IecCtrl.usSendNo = (pstAPCI->cntl2 << 8) | pstAPCI->cntl1; // 发送序号 g_IecCtrl.usRecvNo = (pstAPCI->cntl4 << 8) | pstAPCI->cntl3; // 接收序号 if (g_IecCtrl.usISUType == 0 || g_IecCtrl.usISUType == 2) // I Format package { g_IecCtrl.timer_S_Ackflag = false; // 收到I格式帧的时候置为false, 超时的时候置为true. g_IecCtrl.RxCounter = g_IecCtrl.usSendNo++; g_IecCtrl.LastAckTx = g_IecCtrl.usRecvNo; SendMsgFormatS(pData.usSendNo); // 应答 DecodeMsgFormatI(pData.pszBuff + sizeof(ST_APCI), pData.iLength - sizeof(ST_APCI), pData.usSendNo); // 解析报文 } else if (g_IecCtrl.usISUType == 1) // S Format package { //DecodeMsgFormatS(pData.pszBuff + sizeof(ST_APCI), pData.iLength - sizeof(ST_APCI)); } else if (g_IecCtrl.usISUType == 3) // U Format package { DecodeMsgFormatU(pstAPCI); // U Format package g_IecCtrl.usRecvNo = (pstAPCI->cntl4 << 8) | pstAPCI->cntl3; g_IecCtrl.LastAckTx = g_IecCtrl.usRecvNo; } g_IecCtrl.timer_U_Testflag = false; // 接收到I S U格式的帧都需要重置,表示t3内已经接收到报文 } free(pData.pszBuff); pData.pszBuff = NULL; } return NULL; } // IEC原始数据入库 void dbSet_iec_origin(char pszSql[][256], int count) { CDBMySQL *pdbHandle = CDBMySQL::Instance(); if (!pdbHandle) return; vPrtLogMsg(LOG_DEBUG, RET_OK, "insert iec_origin_data start, cont: %d", count); if (!pdbHandle->InsertRecordBitch(pszSql, count)) { vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO iec_origin_data message failed."); } vPrtLogMsg(LOG_DEBUG, RET_OK, "insert iec_origin_data complater, insert top cont: %d", count); } /*************************************************************************** ** function name : thread_origin_proc ** deacription : 104 origin data save database thread ** parameter : none ** return code : NULL ***************************************************************************/ void * thread_origin_proc(void * arg) { int count = 0, n = 0; ST_IECPOINT_TABLE pData; char szSql[512] = { 0 }, szWaringTime[32] = { 0 }; MYSQL *pMySql = NULL; vPrtLogMsg(LOG_DEBUG, 0, "thread_origin_proc = %d startup...", GETTID()); while (g_Running) { pthread_testcancels(); memset(&pData, 0x00, sizeof(ST_IECPOINT_TABLE)); mutex_lock(g_list_origin_mutex); count = g_list_origin.size(); n = 0; if (g_list_origin.empty() || g_list_origin.size() <= 0) { mutex_unlock(g_list_origin_mutex); _SLEEP(MAX_SLEEP_EMPTY * 10); continue; } //if (time(NULL) - g_IecCtrl.last_yc_time <= g_iec_conf.save_internal) // 超过设定保存时间间隔时 //{ // g_list_origin.clear(); // mutex_unlock(g_list_origin_mutex); // _SLEEP(MAX_SLEEP_EMPTY * 10); // continue; //} //g_IecCtrl.last_yc_time = time(NULL); CDBMySQL *pdbHandle = CDBMySQL::Instance(); if (!pdbHandle) { mutex_unlock(g_list_origin_mutex); _SLEEP(MAX_SLEEP_EMPTY * 5); continue; } pMySql = pdbHandle->GetIdleMySql(); if (pMySql == NULL) { mutex_unlock(g_list_origin_mutex); vPrtLogMsg(LOG_WARNG, RET_FAIL, "GetIdleMySql handle failed."); _SLEEP(MAX_SLEEP_EMPTY); continue; } pdbHandle->dbAutoCommit(pMySql, false); for (int n = 0; n < (count > 500 ? 500 : count); n++) { memcpy(&pData, &(g_list_origin.back()), sizeof(ST_IECPOINT_TABLE)); // 由尾取出 g_list_origin.pop_back(); // 由尾删除 memset(szSql, 0x00, sizeof(szSql)); vTranHostTimeFmt(pData.dtime, szWaringTime); if ((pData.stype & 0xff) == 1) // 遥信 { snprintf(szSql, sizeof(szSql), "INSERT into iec_origin_data(id, site_id, site_tree_id,system_code,d_time,state,stype,sadr,sadrval) " "VALUES(guuid(), '%s','%s', '%s','%s', '%d', '%d', '%d', '%d')", pData.site_id, pData.eqm_code, pData.sys_code, szWaringTime, pData.wstate, pData.stype, pData.sadr, pData.cval); } else { // 遥测 snprintf(szSql, sizeof(szSql), "INSERT into iec_origin_data(id, site_id, site_tree_id,system_code,d_time,state,stype,sadr,sadrval) " "VALUES(guuid(), '%s','%s', '%s','%s', '%d','%d', '%d', '%.4f')", pData.site_id, pData.eqm_code, pData.sys_code, szWaringTime, pData.wstate, pData.stype, pData.sadr, pData.fval); } pdbHandle->AddInsertRecord(pMySql, szSql); } pdbHandle->dbCommit(pMySql); pdbHandle->dbAutoCommit(pMySql, true); pdbHandle->SetIdleMysql(pMySql); mutex_unlock(g_list_origin_mutex); _SLEEP(MAX_SLEEP_EMPTY * 10); } return NULL; } /*************************************************************************** ** function name : thread_origin_proc_new ** deacription : 104 origin data save database thread ** parameter : none ** return code : NULL ***************************************************************************/ void * thread_origin_proc_new(void * arg) { int count = 0, n = 0; IEC_OBJVAL_NEW pData; char szSql[512] = { 0 }, szWaringTime[32] = { 0 }; MYSQL *pMySql = NULL; g_IecCtrl.last_origin_time = time(NULL); vPrtLogMsg(LOG_DEBUG, 0, "thread_origin_proc_new = %d startup...", GETTID()); while (g_Running) { pthread_testcancels(); memset(&pData, 0x00, sizeof(ST_IECPOINT_TABLE)); mutex_lock(g_list_origin_mutex_new); count = g_list_origin_new.size(); n = 0; if (g_list_origin_new.empty() || g_list_origin_new.size() <= 0) { mutex_unlock(g_list_origin_mutex_new); _SLEEP(MAX_SLEEP_EMPTY * 10); continue; } //if (time(NULL) - g_IecCtrl.last_yc_time <= g_iec_conf.save_internal) // 超过设定保存时间间隔时 //{ // g_list_origin_new.clear(); // mutex_unlock(g_list_origin_mutex_new); // _SLEEP(MAX_SLEEP_EMPTY * 10); // continue; //} //g_IecCtrl.last_yc_time = time(NULL); CDBMySQL *pdbHandle = CDBMySQL::Instance(); if (!pdbHandle) { mutex_unlock(g_list_origin_mutex_new); _SLEEP(MAX_SLEEP_EMPTY * 5); continue; } pMySql = pdbHandle->GetIdleMySql(); if (pMySql == NULL) { mutex_unlock(g_list_origin_mutex_new); vPrtLogMsg(LOG_WARNG, RET_FAIL, "GetIdleMySql handle failed."); _SLEEP(MAX_SLEEP_EMPTY); continue; } pdbHandle->dbAutoCommit(pMySql, false); for (int n = 0; n < (count > 500 ? 500 : count); n++) { memcpy(&pData, &(g_list_origin_new.back()), sizeof(IEC_OBJVAL_NEW)); // 由尾取出 g_list_origin_new.pop_back(); // 由尾删除 memset(szSql, 0x00, sizeof(szSql)); vTranHostTimeFmt(pData.dtime, szWaringTime); if (pData.stype == 1) // 遥信 { snprintf(szSql, sizeof(szSql), "INSERT INTO niec_origin_data(d_time,stype,sadr,ival) " "VALUES('%s', '%d', '%d', '%u')", szWaringTime, pData.stype, pData.sadr, pData.ival); } else { // 遥测 snprintf(szSql, sizeof(szSql), "INSERT INTO niec_origin_data(d_time,stype,sadr,fval) " "VALUES('%s', '%d', '%d', '%.4f')", szWaringTime, pData.stype, pData.sadr, pData.fval); } pdbHandle->AddInsertRecord(pMySql, szSql); } pdbHandle->dbCommit(pMySql); pdbHandle->dbAutoCommit(pMySql, true); time_t now = time(NULL); if (now - g_IecCtrl.last_origin_time >= g_iec_conf.orgin_data_save_internal) // 超过设定保存时间间隔时 { g_IecCtrl.last_origin_time = now; memset(szSql, 0x00, sizeof(szSql)); vTranHostTimeFmt((now - g_iec_conf.orgin_data_save_internal), szWaringTime); snprintf(szSql, sizeof(szSql), "DELETE FROM niec_origin_data WHERE d_time<'%s' ", szWaringTime); pdbHandle->AddInsertRecord(pMySql, szSql); } pdbHandle->SetIdleMysql(pMySql); mutex_unlock(g_list_origin_mutex_new); _SLEEP(MAX_SLEEP_EMPTY * 10); } return NULL; } /*************************************************************************** ** function name : thread_busi_data_proc ** deacription : 104 business data save database thread ** parameter : none ** return code : NULL ***************************************************************************/ void * thread_busi_data_proc(void * arg) { int count = 0, n = 0; ST_IECPOINT_TABLE pData; char szSql[512] = { 0 }, szWaringTime[32] = { 0 }; std::string sql; MYSQL *pMySql = NULL; vPrtLogMsg(LOG_DEBUG, 0, "thread_busi_data_proc = %d startup...", GETTID()); while (g_Running) { pthread_testcancels(); memset(&pData, 0x00, sizeof(ST_IECPOINT_TABLE)); mutex_lock(g_list_busi_data_mutex); count = g_list_busi_data.size(); n = 0; if (g_list_busi_data.empty() || g_list_busi_data.size() <= 0) { mutex_unlock(g_list_busi_data_mutex); _SLEEP(MAX_SLEEP_EMPTY * 10); continue; } CDBMySQL *pdbHandle = CDBMySQL::Instance(); if (!pdbHandle) { mutex_unlock(g_list_busi_data_mutex); _SLEEP(MAX_SLEEP_EMPTY * 5); continue; } pMySql = pdbHandle->GetIdleMySql(); if (pMySql == NULL) { mutex_unlock(g_list_busi_data_mutex); vPrtLogMsg(LOG_WARNG, RET_FAIL, "GetIdleMySql handle failed."); _SLEEP(MAX_SLEEP_EMPTY); continue; } pdbHandle->dbAutoCommit(pMySql, false); for (int n = 0; n < (count > 500 ? 500 : count); n++) { sql.swap(g_list_busi_data.back()); g_list_busi_data.pop_back(); // Remove the tail // memset(szSql, 0x00, sizeof(szSql)); pdbHandle->AddInsertRecord(pMySql, sql.c_str()); } pdbHandle->dbCommit(pMySql); pdbHandle->dbAutoCommit(pMySql, true); pdbHandle->SetIdleMysql(pMySql); mutex_unlock(g_list_busi_data_mutex); _SLEEP(MAX_SLEEP_EMPTY * 10); } return NULL; } /*************************************************************************** ** function name : iGetSadrMatchRecord ** deacription : 104 addr point match list ** parameter : none ** return code : NULL ** relations table: ht_iec104.conf ***************************************************************************/ int iGetSadrMatchRecord(unsigned int sadr, ST_SADR_MATCH &adrList) { if(sadr <= 0) return 0 ; map::iterator m_pIter; mutex_lock(g_map_sadr_mutex); m_pIter = g_map_sadr.find(sadr); if (m_pIter == g_map_sadr.end()) { mutex_unlock(g_map_sadr_mutex); return 0; } adrList.psadr = (ST_MATCH_LIST*)calloc(m_pIter->second.count, sizeof(ST_MATCH_LIST)); if (adrList.psadr == NULL) { vPrtLogMsg(LOG_WARNG, RET_FAIL, "calloc failed."); mutex_unlock(g_map_sadr_mutex); return 0; } adrList.count = (m_pIter->second).count; adrList.eqm_type = (m_pIter->second).eqm_type; for (int i = 0; i < (int)adrList.count; i++) { adrList.psadr[i].btype = (m_pIter->second).psadr[i].btype; adrList.psadr[i].group = (m_pIter->second).psadr[i].group; adrList.psadr[i].sadr = (m_pIter->second).psadr[i].sadr; } mutex_unlock(g_map_sadr_mutex); return adrList.count; } // 获取指定地址关系的组号记录 static bool bGetSadrMatchRecord(int gorup, ST_SADR_MATCH &adrList) { map::iterator m_pIter; mutex_lock(g_map_sadr_mutex); for (m_pIter = g_map_sadr.begin(); m_pIter != g_map_sadr.end(); m_pIter++) { for (int i = 0; i < (int)(m_pIter->second).count; i++) { if ((int)((m_pIter->second).psadr[i].group) == gorup) { adrList.psadr = (ST_MATCH_LIST*)calloc((m_pIter->second).count, sizeof(ST_MATCH_LIST)); if (adrList.psadr == NULL) { vPrtLogMsg(LOG_WARNG, RET_FAIL, "calloc failed."); mutex_unlock(g_map_sadr_mutex); return false; } adrList.count = (m_pIter->second).count; adrList.eqm_type = (m_pIter->second).eqm_type; for (int i = 0; i < (int)adrList.count; i++) { adrList.psadr[i].btype = (m_pIter->second).psadr[i].btype; adrList.psadr[i].group = (m_pIter->second).psadr[i].group; adrList.psadr[i].sadr = (m_pIter->second).psadr[i].sadr; } mutex_unlock(g_map_sadr_mutex); return true; } } } mutex_unlock(g_map_sadr_mutex); return false; } // 提取数据 static bool bGetValueBySadr(ST_IECPOINT_TABLE &stPoint) { map::iterator m_pIter; mutex_lock(g_map_iec_mutex); m_pIter = g_map_iec.find(stPoint.sadr); if (m_pIter == g_map_iec.end()) { mutex_unlock(g_map_iec_mutex); return false; } memcpy(&stPoint, &m_pIter->second, sizeof(ST_IECPOINT_TABLE)); mutex_unlock(g_map_iec_mutex); return true; } //初始化运行工况数据 void initRunState(ST_IEC_BYQREAD_TABLE &stRunState, int dInitValue) { stRunState.dcurJkyl[0] = dInitValue; // 冷却水进口压力值 stRunState.dcurCkyl[0] = dInitValue; // 冷却水出口压力值 stRunState.dCoolWaterTempEntry[0] = dInitValue; // 冷却水进口温度 stRunState.dCoolWaterTempOuter[0] = dInitValue; // 冷却水出口温度 stRunState.dOilPressEntry[0] = dInitValue; // 变压器油进口油压力(MPa) stRunState.dOilPressOuter[0] = dInitValue; // 变压器油出口油压力(MPa) stRunState.dOilTempEntry[0] = dInitValue; // 变压器油进口温度 stRunState.dOilTempOuter[0] = dInitValue; // 变压器油出口温度 stRunState.dOilTemperature[0] = dInitValue; //主变本体油温点位 stRunState.dOilPosition[0] = dInitValue; //主变本体油位点位 stRunState.dOilTopTemp[0] = dInitValue; //主变顶层油温点位 stRunState.dOilPillowLevel[0] = dInitValue; //主变油枕油位点位 stRunState.dWindingTemp[0] = dInitValue; //主变绕组温度点位 } //// 运行工况数据有效性转换 //char * double2String(double value, double dInitValue, char *pStr, int iStrLen) //{ // memset(pStr, 0x00, iStrLen); // if (value != dInitValue) sprintf(pStr, "%.4f", value); // return pStr; //} void calcHigthVolCurr(double &vol, double &curr) { double dvol = vol; double dcurr = curr; vPrtLogMsg(LOG_WARNG, RET_OK, "vol = %.4f cur=%.4f", vol,curr); //double dHvol = ((525000 * 1.732) / 3); // 高压侧电压=((额定电压*根号3)/3)=单相的电压值 double dHvol = (525000 / 1.732); // 高压侧电压=((额定电压*根号3)/3)=单相的电压值 curr = (dvol*dcurr) / dHvol; // 高压侧电流=(低压侧单相低压*低压侧单相电流)/高压侧电压 vol = dHvol; } // 组织变压器评测数据,iec_bydwork_param static void vBuildByqWorkParam(ST_IECPOINT_TABLE &stIec,ST_SADR_MATCH &adrList) { double dInitValue = -9999.0f; ST_IEC_BYQWORK_TABLE stWork; ST_IEC_BYQREAD_TABLE stRunState; ST_IEC_GISBREAK_TABLE stGis; // 数据入库 char szSql[DEF_BUFFER_1K] = { 0 }; char sTime[24] = { 0 }, eTime[24] = { 0 }; memset(&stWork, 0x00, sizeof(ST_IEC_BYQWORK_TABLE)); memset(&stGis, 0x00, sizeof(ST_IEC_GISBREAK_TABLE)); memset(&stRunState, 0x00, sizeof(ST_IEC_BYQREAD_TABLE)); initRunState(stRunState, 0x00); CDBMySQL *pdbHandle = CDBMySQL::Instance(); if (!pdbHandle) return; int group = 0; time_t st = 0; //vPrtLogMsg(LOG_WARNG, RET_OK, "---------adrList.count:%d----------",adrList.count); for (int i = 0; i < (int)adrList.count; i++) { memset(&stIec, 0x00, sizeof(ST_IECPOINT_TABLE)); if (adrList.psadr[i].sadr <= 0) continue; // 0时,表示104配置文件中没有此点表地址 stIec.sadr = adrList.psadr[i].sadr ; if (false == bGetValueBySadr(stIec)) continue; if (adrList.psadr[i].sadr == stIec.sadr) { group = adrList.psadr[i].group; switch (group) { case 1: // 主变高压侧电流电压组 case 2: // 主变低压侧电流电压组 if (adrList.psadr[i].btype == 1) stWork.current = stIec.fval; else if (adrList.psadr[i].btype == 2) stWork.voltage = stIec.fval; if(strlen((const char *)stWork.eqm_code) <=0) strncpy((char *)stWork.eqm_code, (char *)stIec.eqm_code, strlen((const char *)stIec.eqm_code)); if (strlen((const char *)stWork.site_id) <= 0) strncpy((char *)stWork.site_id, (char *)stIec.site_id, strlen((const char *)stIec.site_id)); if (strlen((const char *)stWork.system_code) <= 0) strncpy((char *)stWork.system_code, (char *)stIec.sys_code, strlen((const char *)stIec.sys_code)); stWork.state = cGetByqDeviceState(stIec.eqm_code); // 获取工作状态 if (st <= 0) { st = GetDevTimeStat(stIec.sys_code, &stWork.state) ; vTranHostTimeFmt(st, sTime); } vTranHostTimeFmt(st, sTime); g_IecCtrl.stime = time(NULL); vTranHostTimeFmt(g_IecCtrl.stime, eTime); #ifdef _DEF_HMF_VOLTAGE // 根据低压侧的电压电流及额定高压侧电压,计算高压侧电流 if (((stWork.state & 0xff) == 1) && (stWork.voltage >0 && stWork.current > 0)) { calcHigthVolCurr(stWork.voltage, stWork.current); // 高压侧电压=((额定电压*根号3)/3)=单相的电压值 } #endif //if (g_IecCtrl.stime > 0) { // if (strlen(sTime) <= 0) // { // vTranHostTimeFmt(g_IecCtrl.stime, sTime); // g_IecCtrl.stime = time(NULL); // vTranHostTimeFmt(g_IecCtrl.stime, eTime); // } //} //else { // g_IecCtrl.stime = time(NULL); // if (strlen(sTime) <= 0) vTranHostTimeFmt(g_IecCtrl.stime, sTime); // vTranHostTimeFmt(time(NULL), eTime); //} stWork.is_fault = cGetByqDeviceFaultState(stIec.eqm_code); // 获取事故状态 break; case 3: // 主变运行工况组 if (adrList.psadr[i].btype == 1) sprintf(stRunState.dcurJkyl,"%.4f",stIec.fval); // 进口水压力 else if (adrList.psadr[i].btype == 2) sprintf(stRunState.dcurCkyl, "%.4f", stIec.fval); // 出口水压力 else if (adrList.psadr[i].btype == 3) sprintf(stRunState.dOilPosition, "%.4f", stIec.fval); // 主变油位数 else if (adrList.psadr[i].btype == 4) sprintf(stRunState.dOilTemperature, "%.4f", stIec.fval); // 主变油温数 else if (adrList.psadr[i].btype == 5) sprintf(stRunState.dCoolWaterTempEntry,"%.4f",stIec.fval); // 进口水温度 else if (adrList.psadr[i].btype == 6) sprintf(stRunState.dCoolWaterTempOuter, "%.4f", stIec.fval); // 出口水温度 else if (adrList.psadr[i].btype == 7) sprintf(stRunState.dOilPressEntry, "%.4f", stIec.fval); // 进口油压力 else if (adrList.psadr[i].btype == 8) sprintf(stRunState.dOilPressOuter, "%.4f", stIec.fval); // 出口油压力 else if (adrList.psadr[i].btype == 9) sprintf(stRunState.dOilTempEntry, "%.4f", stIec.fval); // 进口油温度 else if (adrList.psadr[i].btype == 10) sprintf(stRunState.dOilTempOuter, "%.4f", stIec.fval); // 出口油温度 else if (adrList.psadr[i].btype == 11) sprintf(stRunState.dOilPillowLevel, "%.4f", stIec.fval);// 油枕油位 else if (adrList.psadr[i].btype == 12) sprintf(stRunState.dOilTopTemp, "%.4f", stIec.fval); // 顶层油温度 else if (adrList.psadr[i].btype == 13) sprintf(stRunState.dWindingTemp, "%.4f", stIec.fval); // 绕组温度 if (stRunState.chkTime <= 0) stRunState.chkTime = stIec.dtime; else stRunState.chkTime = (stRunState.chkTime < stIec.dtime ? stRunState.chkTime : stIec.dtime); if (strlen((const char *)stRunState.eqm_code) <= 0) strncpy((char *)stRunState.eqm_code, (char *)stIec.eqm_code, strlen((const char *)stIec.eqm_code)); if (strlen((const char *)stRunState.site_id) <= 0) strncpy((char *)stRunState.site_id, (char *)stIec.site_id, strlen((const char *)stIec.site_id)); if (strlen((const char *)stRunState.system_code) <= 0) strncpy((char *)stRunState.system_code, (char *)stIec.sys_code, strlen((const char *)stIec.sys_code)); stRunState.wstate = cGetByqDeviceState(stIec.eqm_code); // 获取工作状态; break; case 4: // 断路器电流电压组 if (adrList.psadr[i].btype == 1) stGis.abort_current = stIec.fval; // 断开电流 else if (adrList.psadr[i].btype == 2) stGis.abort_voltage = stIec.fval; // 断开电压 if (strlen((const char *)stGis.eqm_code) <= 0) strncpy((char *)stGis.eqm_code, (char *)stIec.eqm_code, strlen((const char *)stIec.eqm_code)); if (strlen((const char *)stGis.site_id) <= 0) strncpy((char *)stGis.site_id, (char *)stIec.site_id, strlen((const char *)stIec.site_id)); if (strlen((const char *)stGis.system_code) <= 0) strncpy((char *)stGis.system_code, (char *)stIec.sys_code, strlen((const char *)stIec.sys_code)); if (stGis.d_time <= 0) stGis.d_time = stIec.dtime; else stGis.d_time = (stGis.d_time < stIec.dtime ? stGis.d_time : stIec.dtime); // stGis.wstate = cGetByqDeviceState(stIec.eqm_code); // 获取工作状态; stGis.wstate = cGetCurrentWorkState(stIec.eqm_code); stGis.faild_rate = 0; stGis.is_fault = stIec.bfault; stGis.is_close = 1; // getGisOpenCloseState(stIec.site_id, stIec.eqm_code); break; default:; } } } // for test //vGetHostTimeFmtBeforBay(sTime, 1); //_SLEEP(1000); //vGetHostTimeFmtBeforBay(eTime, 1); // switch (group) { case 1: // 主变高压侧电流电压组 case 2: // 主变低压侧电流电压组 snprintf(szSql, sizeof(szSql), "INSERT INTO iec_bydwork_param(id,site_id,eqm_code,system_code,stype,start_time,stop_time," "higth_voltage,higth_current, record_date, ins_date) " "VALUES(guuid(),'%s', '%s','%s', '%d', '%s', '%s', %.4f, %.4f, SYSDATE(), SYSDATE())", stWork.site_id, stWork.eqm_code, stWork.system_code, stWork.state, sTime, eTime, stWork.voltage, stWork.current); vPrtLogMsg(LOG_DEBUG, RET_OK, "iec_bydwork_param: %s", szSql); break; case 3: // 主变运行工况组 // 原始数据入库 vTranHostTimeFmt(stRunState.chkTime, sTime); memset(szSql, 0x00, sizeof(szSql)); snprintf(szSql, sizeof(szSql), "INSERT INTO transformer_run_status(id, main_tree_id, system_code, work_status, d_time, oil_temperature, oil_position," "cooling_entry_pressure, cooling_exit_pressure, coolingwater_inlet_temperature,coolingwater_outlet_temperature," "circulating_oil_inlet_pressure,circulating_oil_outlet_pressure,top_oil_temperature,oilpillow_oillevel," "winding_temperature,circulating_oil_inlet_temperature,circulating_oil_out_temperature,site_id) " // "VALUES(guuid(),'%s','%s','%d','%s', '%.4f', '%.4f', '%.4f', '%.4f','%.4f', '%.4f', '%.4f', '%.4f','%.4f', '%.4f', '%.4f','%s')", "VALUES(guuid(),'%s','%s','%d','%s', '%s', '%s', '%s', '%s','%s', '%s', '%s', '%s','%s', '%s', '%s','%s','%s','%s')", stRunState.eqm_code, stRunState.system_code, stRunState.wstate, sTime, stRunState.dOilTemperature, stRunState.dOilPosition, stRunState.dcurJkyl, stRunState.dcurCkyl, stRunState.dCoolWaterTempEntry, stRunState.dCoolWaterTempOuter, stRunState.dOilPressEntry, stRunState.dOilPressOuter, stRunState.dOilTopTemp, stRunState.dOilPillowLevel, stRunState.dWindingTemp, stRunState.dOilTempEntry, stRunState.dOilTempOuter, stRunState.site_id); vPrtLogMsg(LOG_DEBUG, RET_OK, "transformer_run_status: %s", szSql); break; case 4: // 断路器电流电压组 memset(szSql, 0x00, sizeof(szSql)); vTranHostTimeFmt(stGis.d_time, sTime); snprintf(szSql, sizeof(szSql), "INSERT INTO iec_breaker_param(id,site_id,eqm_code,system_code,d_time,work_state,abort_current,abort_voltage,faild_rate," "is_fault,is_break,ins_date) " "VALUES(guuid(),'%s', '%s', '%s','%s','%d',%.4f, %.4f, %.4f, '%d', '%d',SYSDATE())", stGis.site_id, stGis.eqm_code, stGis.system_code, sTime, stGis.wstate, stGis.abort_current, stGis.abort_voltage, stGis.faild_rate, stGis.is_fault, stGis.is_close); vPrtLogMsg(LOG_DEBUG, RET_OK, "iec_breaker_param: %s", szSql); break; default:; } if (!pdbHandle->InsertRecord((const char *)szSql)) { vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO SQL message failed,SQL:%s", szSql); } //vPrtLogMsg(LOG_WARNG, RET_FAIL, "INSERT INTO SQL message failed,SQL:%s", szSql); } // 保存断路器断开数据记录 static void saveGisData(ST_BREAK_EQM_CODE &stGisRecord, unsigned char cState, time_t dtime) { ST_IEC_GISBREAK_TABLE stGis; ST_IECPOINT_TABLE stIec; char szSql[DEF_BUFFER_1K] = { 0 }, szTime[32] = { 0 }; CDBMySQL *pdbHandle = CDBMySQL::Instance(); if (!pdbHandle) return; memset(&stGis, 0x00, sizeof(ST_IEC_GISBREAK_TABLE)); memset(&stIec, 0x00, sizeof(ST_IECPOINT_TABLE)); stIec.sadr = stGisRecord.uiAbortCurrent; if (true == bGetValueBySadr(stIec)) // 获取电流值 stGis.abort_current = stIec.fval; memset(&stIec, 0x00, sizeof(ST_IECPOINT_TABLE)); stIec.sadr = stGisRecord.uiAbortVoltage; if (true == bGetValueBySadr(stIec)) // 获取电压值 stGis.abort_voltage = stIec.fval; strncpy((char *)stGis.eqm_code, (char *)stIec.eqm_code, strlen((const char *)stIec.eqm_code)); strncpy((char *)stGis.site_id, (char *)stIec.site_id, strlen((const char *)stIec.site_id)); strncpy((char *)stGis.system_code, (char *)stIec.sys_code, strlen((const char *)stIec.sys_code)); stGis.wstate = cGetCurrentWorkState(stIec.eqm_code); stGis.faild_rate = 0; stGis.is_fault = 0; stGis.is_close = cState; vTranHostTimeFmt(dtime, szTime); snprintf(szSql, sizeof(szSql), "INSERT INTO iec_breaker_param(id,site_id,eqm_code,system_code,d_time,work_state,abort_current,abort_voltage,faild_rate," "is_fault,is_break,ins_date) " "VALUES(guuid(),'%s', '%s', '%s','%s','%d',%.4f, %.4f, %.4f, '%d', '%d',SYSDATE())", stGis.site_id, stGis.eqm_code, stGis.system_code, szTime, stGis.wstate, stGis.abort_current, stGis.abort_voltage, stGis.faild_rate, stGis.is_fault, stGis.is_close); if (!pdbHandle->InsertRecord((const char *)szSql)) { vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO SQL message failed,SQL:%s", szSql); } } /*************************************************************************** ** function name : thread_gis_hold_proc ** deacription : 记录断路器断开时的电流电压及状态 ** parameter : none ** return code : NULL ** relations table: iec_break_param ***************************************************************************/ void * thread_gis_hold_proc(void * arg) { ST_IECPOINT_TABLE pData; ST_BREAK_EQM_CODE stGisRecord; map::iterator m_pIter; vPrtLogMsg(LOG_DEBUG, 0, "thread_gis_hold_proc = %d startup...", GETTID()); while (g_Running) { pthread_testcancels(); memset(&pData, 0x00, sizeof(ST_IECPOINT_TABLE)); mutex_lock(g_list_pingce_mutex); if (g_list_pingce.empty() || g_list_pingce.size() <= 0) { mutex_unlock(g_list_pingce_mutex); _SLEEP(MAX_SLEEP_EMPTY * 10); continue; } memcpy(&pData, &(g_list_pingce.back()), sizeof(ST_IECPOINT_TABLE)); // 由尾取出 g_list_pingce.pop_back(); // 由尾删除 mutex_unlock(g_list_pingce_mutex); // 根据遥信的点位地址,获取该点对应的电流电压点位及其数据 mutex_lock(g_map_gis_state_mutex); memset(&stGisRecord, 0x00, sizeof(ST_BREAK_EQM_CODE)); m_pIter = g_map_gis_state.find(pData.sadr); if (m_pIter == g_map_gis_state.end()) { vPrtLogMsg(LOG_WARNG, RET_FAIL, "yx_asdr=%d can not config info, do not nothing", pData.sadr); continue; } memcpy(&stGisRecord, &(m_pIter->second), sizeof(ST_BREAK_EQM_CODE)); mutex_lock(g_map_gis_state_mutex); saveGisData(stGisRecord, pData.cval, pData.dtime); } return NULL; } /*************************************************************************** ** function name : thread_pingce_proc ** deacription : 104 pingce data save database thread ** parameter : none ** return code : NULL ** relations table: iec_bydwork_param,iec_breaker_param,transformer_run_status ***************************************************************************/ #ifdef _DEF_DB_CHANGERATE void * thread_pingce_proc(void * arg) { ST_IECPOINT_TABLE pData; ST_SADR_MATCH adrList; vPrtLogMsg(LOG_DEBUG, 0, "thread_pingce_proc = %d startup...", GETTID()); while (g_Running) { pthread_testcancels(); #if 0 memset(&pData, 0x00, sizeof(ST_IECPOINT_TABLE)); mutex_lock(g_list_pingce_mutex); if (g_list_pingce.empty() || g_list_pingce.size() <= 0) { mutex_unlock(g_list_pingce_mutex); _SLEEP(MAX_SLEEP_EMPTY * 10); continue; } memcpy(&pData, &(g_list_pingce.back()), sizeof(ST_IECPOINT_TABLE)); // 由尾取出 g_list_pingce.pop_back(); // 由尾删除 mutex_unlock(g_list_pingce_mutex); #endif // 发生信号有变化且发生时间>0时,立即提取数据,加入数据入库队列中 if (!g_IecCtrl.b_Signal && (time(NULL) - g_Internal_time < g_iec_conf.save_internal)) { // 超过设定保存时间间隔时 _SLEEP(100); continue; } if (!g_IecCtrl.isConnect) { _SLEEP(100); continue; } g_IecCtrl.b_Signal = false; g_Internal_time = time(NULL); memset(&pData, 0x00, sizeof(ST_IECPOINT_TABLE)); memset(&adrList, 0x00, sizeof(ST_SADR_MATCH)); for (int i = 0; i < (int)g_iec_conf.iec_byq_count; i++) { for(int group = 2; group <= 3; group++) { switch(group) { case 1: // //pData.sadr = g_iec_conf.pstByqCode[i].uiHighCurrent; //uiLowCurrent //break; case 2: //pData.sadr = g_iec_conf.pstByqCode[i].uiLowCurrent; //uiLowCurrent if (1 == cGetByqDeviceState(g_iec_conf.pstByqCode[i].szEqmCode)) // 获取工作状态 pData.sadr = g_iec_conf.pstByqCode[i].uiHighCurrent; //uiHighCurrent 发电时取高压侧电流电压 else pData.sadr = g_iec_conf.pstByqCode[i].uiLowCurrent; //uiLowCurrent 抽水/空闲时取低压侧电流电压 break; case 3: pData.sadr = g_iec_conf.pstByqCode[i].uiWindingTemp; //uiLowCurrent break; default: { pData.sadr = 0 ; continue; } } if (iGetSadrMatchRecord(pData.sadr, adrList) > 0) { vBuildByqWorkParam(pData, adrList); if (adrList.psadr) { free((void *)adrList.psadr); adrList.psadr = NULL; } } pData.sadr = 0 ; } } for (int i = 0; i < (int)g_iec_conf.iec_break_count; i++) { pData.sadr = g_iec_conf.pstBrkCode[i].uiAbortCurrent; if (iGetSadrMatchRecord(pData.sadr, adrList) > 0) { vBuildByqWorkParam(pData, adrList); if (adrList.psadr) { free((void *)adrList.psadr); adrList.psadr = NULL; } } pData.sadr = 0; } } return NULL; } #else /*************************************************************************** ** function name : thread_pingce_proc ** deacription : 104 pingce data save database thread ** parameter : none ** return code : NULL ** relations table: iec_bydwork_param,iec_breaker_param,transformer_run_status ***************************************************************************/ void * thread_pingce_proc(void * arg) { ST_IECPOINT_TABLE pData; ST_SADR_MATCH adrList; time_t interTime = time(NULL); _SLEEP(3000); vPrtLogMsg(LOG_DEBUG, 0, "thread_pingce_proc = %d startup...", GETTID()); while (g_Running) { pthread_testcancels(); // 发生信号有变化且发生时间>0时,立即提取数据,加入数据入库队列中 if (!g_IecCtrl.b_Signal && (time(NULL) - interTime < g_iec_conf.save_internal)) { // 超过设定保存时间间隔时 _SLEEP(100); continue; } if (!g_IecCtrl.isConnect) { _SLEEP(100); continue; } g_IecCtrl.b_Signal = false; interTime = time(NULL); for (int i = 1; i < 5; i++) { memset(&adrList, 0x00, sizeof(ST_SADR_MATCH)); if (!bGetSadrMatchRecord(i, adrList)) continue; vPrtLogMsg(LOG_WARNG, RET_FAIL, "get addr match relations, group=%d", i); vBuildByqWorkParam(pData, adrList); if (adrList.psadr) { free((void *)adrList.psadr); adrList.psadr = NULL; } } } return NULL; } #endif /*************************************************************************** ** function name : thread_warn_proc ** deacription : 104 warn data save database thread ** parameter : none ** return code : NULL ***************************************************************************/ void * thread_warn_proc(void * arg) { int count = 0, n = 0; double warn_val = 0.0f; // 告警值 bool isWarn = false; ST_IECPOINT_TABLE pData; char szSql[1024] = { 0 }, szWaringTime[32] = { 0 }; char szWarninfo[256] = { 0 }, szMsg[24] = { 0 }; // 告警信息 vPrtLogMsg(LOG_DEBUG, 0, "thread_warn_proc = %d startup...", GETTID()); while (g_Running) { pthread_testcancels(); memset(&pData, 0x00, sizeof(ST_IECPOINT_TABLE)); mutex_lock(g_list_warn_mutex); count = g_list_warn.size(); n = 0; if (g_list_warn.empty() || g_list_warn.size() <= 0) { mutex_unlock(g_list_warn_mutex); _SLEEP(MAX_SLEEP_EMPTY * 10); continue; } CDBMySQL *pdbHandle = CDBMySQL::Instance(); if (!pdbHandle) { mutex_unlock(g_list_warn_mutex); _SLEEP(MAX_SLEEP_EMPTY * 5); continue; } isWarn = false; memcpy(&pData, &(g_list_warn.back()), sizeof(ST_IECPOINT_TABLE)); // 由尾取出 g_list_warn.pop_back(); // 由尾删除 mutex_unlock(g_list_warn_mutex); memset(szSql, 0x00, sizeof(szSql)); // 获取告警值 warn_val = getThresholdValuse((const char*)pData.eqm_code, (const char*)pData.fieldname, pData.wstate); if (warn_val <= 0) { vPrtLogMsg(LOG_WARNG, RET_FAIL, "Noset asdr=%d warn_val=%.4f nval=%.4f eqm_code=%s wstate=%d warn_field=%s", pData.sadr, warn_val, pData.fval, pData.eqm_code, pData.wstate, pData.fieldname); continue; // 告警值为0时,无效 } vPrtLogMsg(LOG_DEBUG, RET_OK, "findmatch warninfo, asdr=%d warn_val=%.4f nval=%.4f eqm_code=%s wstate=%d warn_field=%s", pData.sadr, warn_val, pData.fval, pData.eqm_code, pData.wstate, pData.fieldname); // 判断是否有告警 if (pData.warnFlag == 1) // 大于预警值时报警 { if (pData.fval > warn_val && pData.fval != HT_INVALID_VALUE) { isWarn = true; vTranHostTimeFmt(pData.dtime, szWaringTime); strcpy(szMsg, "超标"); } } else if (pData.warnFlag == 2) // 小于预警值时报警 { if (pData.fval < warn_val && pData.fval != HT_INVALID_VALUE) { isWarn = true; vTranHostTimeFmt(pData.dtime, szWaringTime); strcpy(szMsg, "未达标"); } } if (isWarn) { char szUuid[64] = { 0 }; getuuid(szUuid, sizeof(szUuid)); // 插入告警表 snprintf(szSql, sizeof(szSql), "INSERT INTO busi_eqm_warning(id,eq_type,gz_type,warning_msg,warning_time,create_time,del_flag,site_id,main_tree_id,run_state) " "VALUES('%s','1', '9', '%s%s:%.4f', '%s', SYSDATE(), '1', '%s', '%s','%d')", szUuid, pData.poidesc, szMsg, pData.fval, szWaringTime, pData.site_id, pData.eqm_code,pData.wstate); if (!pdbHandle->InsertRecord((const char *)szSql)) { vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO busi_eqm_warning message failed,SQL:%s", szSql); } vPrtLogMsg(LOG_DEBUG, RET_OK, "INSERT INTO busi_eqm_warning message,SQL:%s", szSql); // 插入告警详细表 char szSubUuid[64] = { 0 }; getuuid(szSubUuid, sizeof(szSubUuid)); memset(szSql, 0x00, sizeof(szSql)); snprintf(szWarninfo, sizeof(szWarninfo), "{\"sadr\":\"%d\",\"thresholdValue\":\"%.4f\",\"currRealValue\":\"%.4f\",\"equipmentStatus\":\"%d\",\"collectDate\":\"%s\",\"ipaddr\":\"\",\"port\":\"\",\"msgInfo\":\"%s\",\"phase\":\"\"}", pData.sadr, warn_val, pData.fval,pData.wstate, szWaringTime,pData.poidesc); snprintf(szSql, sizeof(szSql), "INSERT INTO busi_eqm_warning_info(id,warning_id,warning_info) VALUES('%s','%s','%s')",szSubUuid, szUuid, szWarninfo); if (!pdbHandle->InsertRecord((const char *)szSql)) { vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO busi_eqm_warning_info message failed,SQL:%s", szSql); } vPrtLogMsg(LOG_DEBUG, RET_OK, "INSERT INTO busi_eqm_warning_info message,SQL:%s", szSql); } } return NULL; } // 负荷数据数据入库 void dbSet_iec_bydwork_param(ST_IEC_BYQWORK_TABLE *pstWork) { /* bool isChange = false; // 数据是否和最近一次的发生变化了 map::iterator m_pIter; if (!pstWork->eqm_code && strlen((char*)pstWork->eqm_code) <= 0) { vPrtLogMsg(LOG_WARNG, RET_FAIL, "dbSet_iec_bydwork_param: eqm_code is null,please check config file or coding."); return; } mutex_lock(g_map_byq_mutex); m_pIter = g_map_byq.find((char*)pstWork->eqm_code); if (m_pIter != g_map_byq.end()) { if (pstWork->current > 0 && pstWork->current != (m_pIter->second).stLastData.current) { isChange = true; // 数据是否和最近一次的发生变化了 (m_pIter->second).stLastData.current = pstWork->current; //覆盖最近一次的数据 } else pstWork->current = (m_pIter->second).stLastData.current; // 沿用最近一次的数据 if (pstWork->voltage > 0 && pstWork->voltage != (m_pIter->second).stLastData.voltage) { isChange = true; // 数据是否和最近一次的发生变化了 (m_pIter->second).stLastData.voltage = pstWork->voltage; } else pstWork->voltage = (m_pIter->second).stLastData.voltage; if ((pstWork->stype & 0xff) > 0x00) { if ((pstWork->stype & 0xff) == (m_pIter->second).stLastData.stype) pstWork->start_time = (m_pIter->second).stLastData.start_time; // 状态未发生变化,则开始时间沿用之前的时间 else { (m_pIter->second).stLastData.stype = (pstWork->stype & 0xff); // 状态发生了变化 pstWork->start_time = time(NULL); (m_pIter->second).stLastData.start_time = time(NULL); isChange = true; } } else { pstWork->stype = (m_pIter->second).stLastData.stype; // 状态=0时,无效值,沿用上一次的状态。 pstWork->start_time = (m_pIter->second).stLastData.start_time; } #ifdef _SITE_ID_TYPE_INT if (pstWork->site_id <= 0) pstWork->site_id = (m_pIter->second).SiteID; #else if (strlen((const char*)pstWork->site_id) <= 0) strcpy((char*)pstWork->site_id , (const char*)((m_pIter->second).SiteID)); #endif pstWork->stop_time = time(NULL); */ // if (isChange) // 数据未有变化,无需入库操作 // if ((pstWork->state & 0xff) != 0x03) // { // // 数据入库 // char szSql[DEF_BUFFER_1K] = { 0 }; // char sTime[21] = { 0 }, eTime[21] = { 0 }; // CDBMySQL *pdbHandle = CDBMySQL::Instance(); // if (!pdbHandle) return; // // vTranHostTimeFmt(pstWork->start_time, sTime); // vTranHostTimeFmt(pstWork->stop_time, eTime); //#ifdef _SITE_ID_TYPE_INT // sprintf(szSql, "INSERT INTO iec_bydwork_param(site_id,eqm_code,stype,start_time,stop_time," // "higth_voltage,higth_current, record_date, ins_date) " // "VALUES(%d, '%s', %d, '%s', '%s', %.2f, %.2f, SYSDATE(), SYSDATE())", // pstWork->site_id, pstWork->eqm_code, pstWork->state, sTime, eTime, pstWork->voltage, pstWork->current); //#else // snprintf(szSql, sizeof(szSql), "INSERT INTO iec_bydwork_param(site_id,eqm_code,stype,start_time,stop_time," // "higth_voltage,higth_current, record_date, ins_date) " // "VALUES('%s', '%s', %d, '%s', '%s', %.2f, %.2f, SYSDATE(), SYSDATE())", // pstWork->site_id, pstWork->eqm_code, pstWork->state, sTime, eTime, pstWork->voltage, pstWork->current); //#endif // vPrtLogMsg(LOG_DEBUG, RET_OK, "iec_bydwork_param: %s", szSql); // if (!pdbHandle->InsertRecord((const char *)szSql)) { // vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO iec_bydwork_param message failed,SQL:%s", szSql); // } // } //} //mutex_unlock(g_map_byq_mutex); return; } // 运行工况数据入库 //void dbSet_transformer_read_table(ST_IEC_BYQREAD_TABLE *pstRung) //{ // bool isChange = false; // 数据是否和最近一次的发生变化了 // bool bcurYWei = false, bcurYWen = false, bcurJkyl = false, bcurCkyl = false; // map::iterator m_pIter; // if (!pstRung->eqm_code && strlen((char*)pstRung->eqm_code) <= 0) { // vPrtLogMsg(LOG_WARNG, RET_FAIL, "dbSet_transformer_read_table: eqm_code is null,please check config file or coding."); // return; // } // mutex_lock(g_map_byq_mutex); // m_pIter = g_map_byq.find((char*)pstRung->eqm_code); // if (m_pIter != g_map_byq.end()) // { /* //#ifdef _SITE_ID_TYPE_INT // if (pstRung->site_id <= 0) // pstRung->site_id = (m_pIter->second).SiteID; //#else // if (strlen((const char*)pstRung->site_id) <= 0) // strcpy((char*)pstRung->site_id, (const char*)((m_pIter->second).SiteID)); //#endif // if (pstRung->dcurYWei > 0 && pstRung->dcurYWei != (m_pIter->second).stLastData.dcurYWei) { // (m_pIter->second).stLastData.dcurYWei = pstRung->dcurYWei; // isChange = true; // } // else pstRung->dcurYWei = (m_pIter->second).stLastData.dcurYWei; // // if (pstRung->dcurYWen > 0 && pstRung->dcurYWen != (m_pIter->second).stLastData.dcurYWen) { // (m_pIter->second).stLastData.dcurYWen = pstRung->dcurYWen; //覆盖最近一次的数据 // isChange = true; // 发生变化了,需入库 // } // else pstRung->dcurYWen = (m_pIter->second).stLastData.dcurYWen; // // if (pstRung->dcurJkyl > 0 && pstRung->dcurJkyl != (m_pIter->second).stLastData.dcurJkyl) { // (m_pIter->second).stLastData.dcurJkyl = pstRung->dcurJkyl; //覆盖最近一次的数据 // isChange = true; // 发生变化了,需入库 // } // else pstRung->dcurJkyl = (m_pIter->second).stLastData.dcurJkyl; // // if (pstRung->dcurCkyl > 0 && pstRung->dcurCkyl != (m_pIter->second).stLastData.dcurCkyl) { // (m_pIter->second).stLastData.dcurCkyl = pstRung->dcurCkyl; //覆盖最近一次的数据 // isChange = true; // 发生变化了,需入库 // } // else pstRung->dcurCkyl = (m_pIter->second).stLastData.dcurCkyl; // if (!isChange) return; // 数据未有变化,无需入库操作 // */ // vPrtLogMsg(LOG_DEBUG, RET_OK, "eqm_code:%s Warn_YWei:%.2f Warn_YWen:%.2f Warn_Ckyl:%.2f Warn_Jkyl:%.2f", // pstRung->eqm_code, (m_pIter->second).dYWei, (m_pIter->second).dYWen, (m_pIter->second).dCkyl, (m_pIter->second).dJkyl); // vPrtLogMsg(LOG_DEBUG, RET_OK, "eqm_code:%s Curr_YWei:%.2f Curr_YWen:%.2f Curr_Ckyl:%.2f Curr_Jkyl:%.2f", // pstRung->eqm_code, pstRung->dcurYWei, pstRung->dcurYWen, pstRung->dcurCkyl, pstRung->dcurJkyl); // // 告警判断 // if (pstRung->dcurYWei > (m_pIter->second).dYWei) bcurYWei = true; // if (pstRung->dcurYWen > (m_pIter->second).dYWen) bcurYWen = true; // if (pstRung->dcurJkyl < (m_pIter->second).dJkyl) bcurJkyl = true; // 压力值小于预警值时报警 // if (pstRung->dcurCkyl < (m_pIter->second).dCkyl) bcurCkyl = true; // 压力值小于预警值时报警 // // // 数据入库 // char szSql[DEF_BUFFER_1K] = { 0 }, szTime[21] = { 0 }; // CDBMySQL *pdbHandle = CDBMySQL::Instance(); // if (!pdbHandle) { // mutex_unlock(g_map_byq_mutex); // return; // } // // 实时在线缓存表更新数据 // snprintf(szSql, sizeof(szSql), "update transformer_read_table_cache set d_time=SYSDATE(),oil_temperature='%.2f'," // "oil_position = '%.2f', cooling_entry_pressure = '%.2f', cooling_exit_pressure = '%.2f', site_eqm_code = '%s' " // "where site_id = '%s' and eqmid = '%s'", // pstRung->dcurYWen, pstRung->dcurYWei, pstRung->dcurJkyl, pstRung->dcurCkyl, pstRung->eqm_code, pstRung->site_id, pstRung->eqm_code); // vPrtLogMsg(LOG_DEBUG, RET_OK, "transformer_read_table_cache: %s", szSql); // if (!pdbHandle->UpdateRecord((const char *)szSql)) { // vPrtLogMsg(LOG_ERROR, RET_FAIL, "UPDATE transformer_read_table_cache failed,SQL:%s", szSql); // memset(szSql, 0x00, sizeof(szSql)); // snprintf(szSql, sizeof(szSql), "INSERT INTO transformer_read_table_cache(eqmid,d_time,oil_temperature,oil_position,cooling_entry_pressure," // "cooling_exit_pressure,site_id,site_eqm_code) " // "VALUES('%s',SYSDATE(), '%.2f', '%.2f', '%.2f', '%.2f', '%s','%s')", // pstRung->eqm_code, pstRung->dcurYWen, pstRung->dcurYWei, pstRung->dcurJkyl, pstRung->dcurCkyl, pstRung->site_id, pstRung->eqm_code); // vPrtLogMsg(LOG_DEBUG, RET_OK, "transformer_read_table_cache: %s", szSql); // if (!pdbHandle->InsertRecord((const char *)szSql)) { // vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO transformer_read_table_cache message failed,SQL:%s", szSql); // } // } // // 原始数据入库 // memset(szSql, 0x00, sizeof(szSql)); // snprintf(szSql, sizeof(szSql), "INSERT INTO transformer_read_table(eqmid,d_time,oil_temperature,oil_position,cooling_entry_pressure," // "cooling_exit_pressure,site_id) " // "VALUES('%s',SYSDATE(), '%.2f', '%.2f', '%.2f', '%.2f', '%s')", // pstRung->eqm_code, pstRung->dcurYWen, pstRung->dcurYWei, pstRung->dcurJkyl, pstRung->dcurCkyl, pstRung->site_id); // vPrtLogMsg(LOG_DEBUG, RET_OK, "transformer_read_table: %s", szSql); // if (!pdbHandle->InsertRecord((const char *)szSql)) { // vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO transformer_read_table message failed,SQL:%s", szSql); // } // vTranHostTimeFmt(pstRung->chkTime, szTime); // // // 报警入库 // if (bcurYWei) { // 油位告警 //#ifdef _SITE_ID_TYPE_INT // sprintf(szSql, "INSERT INTO busi_eqm_warning(eq_type,gz_type,warning_msg,warning_time,create_time,del_flag,site_id," // "eqm_code) " // "VALUES('1', '9', '主变油位超标:%.2f(L)', '%s', SYSDATE(), '0', '%d', '%s')", // pstRung->dcurYWei, szTime, pstRung->site_id, pstRung->eqm_code); //#else // snprintf(szSql, sizeof(szSql), "INSERT INTO busi_eqm_warning(eq_type,gz_type,warning_msg,warning_time,create_time,del_flag,site_id," // "eqm_code) " // "VALUES('1', '9', '主变油位超标:%.2f(L)', '%s', SYSDATE(), '0', '%s', '%s')", // pstRung->dcurYWei, szTime, pstRung->site_id, pstRung->eqm_code); //#endif // vPrtLogMsg(LOG_DEBUG, RET_OK, "dbInsertWaring: %s", szSql); // if (!pdbHandle->InsertRecord((const char *)szSql)) { // vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO busi_eqm_warning message failed,SQL:%s", szSql); // } // } // if (bcurYWen) { // 油温告警 //#ifdef _SITE_ID_TYPE_INT // sprintf(szSql, "INSERT INTO busi_eqm_warning(eq_type,gz_type,warning_msg,warning_time,create_time,del_flag,site_id," // "eqm_code) " // "VALUES('1', '9', '主变油温超标:%.2f(℃)', '%s', SYSDATE(), '0', '%d', '%s')", // pstRung->dcurYWen, szTime, pstRung->site_id, pstRung->eqm_code); //#else // snprintf(szSql, sizeof(szSql), "INSERT INTO busi_eqm_warning(eq_type,gz_type,warning_msg,warning_time,create_time,del_flag,site_id," // "eqm_code) " // "VALUES('1', '9', '主变油温超标:%.2f(℃)', '%s', SYSDATE(), '0', '%s', '%s')", // pstRung->dcurYWen, szTime, pstRung->site_id, pstRung->eqm_code); //#endif // vPrtLogMsg(LOG_DEBUG, RET_OK, "dbInsertWaring: %s", szSql); // if (!pdbHandle->InsertRecord((const char *)szSql)) { // vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO busi_eqm_warning message failed,SQL:%s", szSql); // } // } // if (bcurJkyl) { // 进口压力告警 //#ifdef _SITE_ID_TYPE_INT // sprintf(szSql, "INSERT INTO busi_eqm_warning(eq_type,gz_type,warning_msg,warning_time,create_time,del_flag,site_id," // "eqm_code) " // "VALUES('1', '9', '主变冷却水进口压力未达标:%.2f(MPa)', '%s', SYSDATE(), '0', '%d', '%s')", // pstRung->dcurJkyl, szTime, pstRung->site_id, pstRung->eqm_code); //#else // snprintf(szSql, sizeof(szSql), "INSERT INTO busi_eqm_warning(eq_type,gz_type,warning_msg,warning_time,create_time,del_flag,site_id," // "eqm_code) " // "VALUES('1', '9', '主变冷却水进口压力未达标:%.2f(MPa)', '%s', SYSDATE(), '0', '%s', '%s')", // pstRung->dcurJkyl, szTime, pstRung->site_id, pstRung->eqm_code); //#endif // vPrtLogMsg(LOG_DEBUG, RET_OK, "dbInsertWaring: %s", szSql); // if (!pdbHandle->InsertRecord((const char *)szSql)) { // vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO busi_eqm_warning message failed,SQL:%s", szSql); // } // } // if (bcurCkyl) { // 出口压力告警 //#ifdef _SITE_ID_TYPE_INT // sprintf(szSql, "INSERT INTO busi_eqm_warning(eq_type,gz_type,warning_msg,warning_time,create_time,del_flag,site_id," // "eqm_code) " // "VALUES('1', '9', '主变冷却水出口压力未达标:%.2f(MPa)', '%s', SYSDATE(), '0', '%d', '%s')", // pstRung->dcurCkyl, szTime, pstRung->site_id, pstRung->eqm_code); //#else // snprintf(szSql, sizeof(szSql), "INSERT INTO busi_eqm_warning(eq_type,gz_type,warning_msg,warning_time,create_time,del_flag,site_id," // "eqm_code) " // "VALUES('1', '9', '主变冷却水出口压力未达标:%.2f(MPa)', '%s', SYSDATE(), '0', '%s', '%s')", // pstRung->dcurCkyl, szTime, pstRung->site_id, pstRung->eqm_code); //#endif // vPrtLogMsg(LOG_DEBUG, RET_OK, "dbInsertWaring: %s", szSql); // if (!pdbHandle->InsertRecord((const char *)szSql)) { // vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO busi_eqm_warning message failed,SQL:%s", szSql); // } // } // } // mutex_unlock(g_map_byq_mutex); // return; //} //void dbSet_iec_breaker_param(ST_IEC_GISBREAK_TABLE *pData) //{ // // 数据入库 // char szSql[DEF_BUFFER_1K] = { 0 }; // char sTime[21] = { 0 }, eTime[21] = { 0 }; // CDBMySQL *pdbHandle = CDBMySQL::Instance(); // if (!pdbHandle) return; // // vTranHostTimeFmt(pData->d_time, sTime); //#ifdef _SITE_ID_TYPE_INT // snprintf(szSql,sizeof(szSql), "INSERT INTO iec_breaker_param(site_id,gis_code,eqm_code,abort_current,abort_voltage,faild_rate," // "record_date,ins_date, is_fault,is_break) " // "VALUES(%d, '%s', '%s', %.2f, %.2f, %.2f, '%s',SYSDATE(), '%d','%d')", // pData->site_id, pData->eqm_code, pData->eqm_code, pData->abort_current, pData->abort_voltage, pData->faild_rate, // sTime, pData->is_fault,pData->is_close); //#else // snprintf(szSql, sizeof(szSql), "INSERT INTO iec_breaker_param(site_id,gis_code,eqm_code,abort_current,abort_voltage,faild_rate," // "record_date,ins_date, is_fault,is_break) " // "VALUES('%s', '%s', '%s', %.2f, %.2f, %.2f, '%s',SYSDATE(), '%d','%d')", // pData->site_id, pData->eqm_code, pData->eqm_code, pData->abort_current, pData->abort_voltage, pData->faild_rate, // sTime, pData->is_fault, pData->is_close); //#endif // vPrtLogMsg(LOG_DEBUG, RET_OK, "iec_breaker_param: %s", szSql); // if (!pdbHandle->InsertRecord((const char *)szSql)) { // vPrtLogMsg(LOG_ERROR, RET_FAIL, "INSERT INTO iec_breaker_param message failed,SQL:%s", szSql); // } // return; //} // 刷新设备运行状态:1:发电、2:抽水、3:空闲 unsigned char getDevWorkState(ST_IECPOINT_TABLE &stIec) { bool b_byq_close = false, b_byq_fd = false, b_byq_cs = false; unsigned char cstate = 0; int s = 0; //对于一个主变设备的状态检索,最多找到3个遥信量即可,不必检索所有的map列表 unsigned char szMEqmCode[DEF_EQM_CODE_SIZE] = { 0 }; // 主变ID // 先根据设备类型区分出是主变设备/GIS设备 if ((stIec.eqm_type & 0xff) != 1) // GIS设备 { //根据隶属关系表,获取主设备id if (!bGetMasterEqmCodeBySubEqmCode(stIec.site_id, stIec.eqm_code, szMEqmCode)) { vPrtLogMsg(LOG_WARNG, RET_FAIL, "from s_eqm_code:%s find m_eqm_code, not found,please check device build relations...", stIec.eqm_code); return 0x03; // 默认置为空闲状态 } } else { strcpy((char*)szMEqmCode, (const char*)stIec.eqm_code); // 主变ID } //根据主变设备ID,找出其遥信地址,然后依据遥信量(3个)确定设备的工作状态 map::iterator m_pIter; for (m_pIter = g_map_iec.begin(); ((m_pIter != g_map_iec.end()) && (s < 3)); m_pIter++) { if (((m_pIter->second).stype & 0xff) != 1) continue; // 确定遥信量 if (((m_pIter->second).eqm_type & 0xff) != 1) continue; // 变压器设备 if (0 != stringncasecmp((const char*)((m_pIter->second).site_id), (const char*)stIec.site_id, strlen((const char*)stIec.site_id))) continue; if (0 != stringncasecmp((const char*)((m_pIter->second).eqm_code), (const char*)szMEqmCode, strlen((const char*)szMEqmCode))) continue; switch ((m_pIter->second).isget) { case 1: // 1号发电机出口开关合位 if (((m_pIter->second).cval & 0xff) == 0x01) b_byq_close = true; s++; break; case 2: // 1号机组发电换相刀闸合位 if (((m_pIter->second).cval & 0xff) == 0x01) b_byq_fd = true; s++; break; case 3: // 1号机组抽水换相刀闸合位 if (((m_pIter->second).cval & 0xff) == 0x01) b_byq_cs = true; s++; break; default:; } } // 判断开关量 if (b_byq_close) { if (b_byq_fd) cstate = 0x01; // 发电状态 else if (b_byq_cs) cstate = 0x02; // 抽水状态 else cstate = 0x03; // 空闲状态 } else cstate = 0x03; // 空闲状态 flushDevWorkState(stIec.site_id, szMEqmCode, cstate); vSetByqDeviceState(szMEqmCode, cstate); return cstate; } // 主变设备运行事故状态: 4:机组电气事故 unsigned char getDevFaultState(ST_IECPOINT_TABLE &stIec) { unsigned char isFault = 0; map::iterator m_pIter; if (stIec.eqm_type != 1) return 0; // 只有主变有事故状态. for (m_pIter = g_map_iec.begin(); m_pIter != g_map_iec.end(); m_pIter++) { if ((m_pIter->second).stype != 1) continue; // 不是遥信量 if (0 != stringncasecmp((const char*)(m_pIter->second).site_id, (const char*)stIec.site_id, strlen((const char*)stIec.site_id))) continue; if (0 != stringncasecmp((const char*)(m_pIter->second).eqm_code, (const char*)stIec.eqm_code, strlen((const char*)stIec.eqm_code))) continue; switch ((m_pIter->second).isget) { case 4: // 1号机组电气事故,1:事故 0:正常 if (((m_pIter->second).cval & 0xff) == 0x01) { isFault = 1; } default:; } } flushFaultState(stIec.site_id, stIec.eqm_code, isFault); vSetByqDeviceFaultState(stIec.eqm_code, isFault); return isFault; } // 提取运行工况数据 //static void dbGet_transformer_read_table(ST_IEC_BYQREAD_TABLE &stRung, ST_IEC_BYQWORK_TABLE &stFuHe) //{ // bool b_byq_close = false, b_byq_fd = false, b_byq_cs = false; // //bool b_gis_close = false; // float hCurr = 0, lcurr = 0, hvol = 0, lvol = 0; // map::iterator m_pIter; // mutex_lock(g_map_iec_mutex); // stFuHe.real_time = time(NULL); // //stFuHe.start_time = g_IecCtrl.stime > 0 ? g_IecCtrl.stime : time(NULL); // 开始时间 // stRung.chkTime = time(NULL); // for (m_pIter = g_map_iec.begin(); m_pIter != g_map_iec.end(); m_pIter++) // { // if (memcmp((m_pIter->second).eqm_code, stRung.eqm_code, strlen((char*)stRung.eqm_code))) continue; // if (0 != stringncasecmp((const char*)(m_pIter->second).site_id, (const char*)stRung.site_id, strlen((const char*)stRung.site_id))) continue; // switch ((m_pIter->second).sadr) // { // case 1: case 5: case 9: case 13: // 1号发电机出口开关合位 // if( ( (m_pIter->second).cval & 0xff) == 0x01) b_byq_close = true; // break; // case 2: case 6: case 10: case 14: // 1号机组发电换相刀闸合位 // if (((m_pIter->second).cval & 0xff) == 0x01) b_byq_fd = true; // break; // case 3: case 7:case 11:case 15: // 1号机组抽水换相刀闸合位 // if (((m_pIter->second).cval & 0xff) == 0x01) b_byq_cs = true; // break; // case 4: case 8: case 12: case 16: // 1号机组电气事故 // stFuHe.is_fault = ((m_pIter->second).cval & 0xff); // break; // // // GIS的遥信数据 // //case 17: case 18: case 19: // GIS开关合位B相 0:分 1:合 // // if (((m_pIter->second).cval & 0xff) == 0x01) b_gis_close = true; // // break; // // // 以下是遥测量 // case 16385: case 16406: case 16427: case 16448: //主变高压侧A相电流(A) // break; // case 16386: case 16407: case 16428: case 16449: //主变高压侧B相电流(A) // hCurr = (m_pIter->second).fval; // break; // case 16387: case 16408: case 16429: case 16450: //主变高压侧C相电流(A) // break; // // case 16388: case 16409: case 16430: case 16451: //主变高压侧A相电压(kv) // break; // case 16389: case 16410: case 16431: case 16452: //主变高压侧B相电压(kv) // hvol = ((m_pIter->second).fval * 1000); // stFuHe.voltage = ((m_pIter->second).fval * 1000); // break; // case 16390: case 16411: case 16432: case 16453: //主变高压侧C相电压(kv) // break; // // case 16391: case 16412: case 16433: case 16454: //机组出口A相电压(kv) // break; // case 16392: case 16413: case 16434: case 16455: //机组出口B相电压(kv) // lvol = ((m_pIter->second).fval * 1000); // break; // case 16393: case 16414: case 16435: case 16456: //机组出口C相电压(kv) // break; // case 16394: case 16415: case 16436: case 16457: //机组出口A相电流(A) // break; // case 16395: case 16416: case 16437: case 16458: //机组出口B相电流(A) // lcurr = (m_pIter->second).fval; // break; // case 16396: case 16417: case 16438: case 16459: //机组出口C相电流(A) // break; // case 16397: case 16418: case 16439: case 16460: //主变高压侧上层油温(℃) // stRung.dcurYWen = (m_pIter->second).fval; // break; // case 16398: case 16419: case 16440: case 16461: //主变绕组温度(℃) // break; // case 16399: case 16420: case 16441: case 16462: //主变冷却系统进口水压(MPa) // stRung.dcurJkyl = (m_pIter->second).fval; // break; // case 16400: case 16421: case 16442: case 16463: //主变冷却系统出口水压(MPa) // stRung.dcurCkyl = (m_pIter->second).fval; // break; // case 16401: case 16422: case 16443: case 16464: //主变冷却器进口水温(℃) // break; // case 16402: case 16423: case 16444: case 16465: //主变冷却器出口水温(℃) // break; // case 16403: case 16424: case 16445: case 16466: //主变冷却系统油泵进口油温(℃) // break; // case 16404: case 16425: case 16446: case 16467: //主变冷却系统油泵出口油温(℃) // break; // case 16405: case 16426: case 16447: case 16468: //主变油位值(待定?)(L) // stRung.dcurYWei = (m_pIter->second).fval; // break; // default: // //vPrtLogMsg(LOG_WARNG, RET_OK, "this YX addr:%d(0x%04x) not define.", adr, adr); // ; // } // end switch // }// end for // // mutex_unlock(g_map_iec_mutex); // // // 判断开关量 // if (b_byq_close) { // if (b_byq_fd) stFuHe.state = 0x01; // 发电状态 // else if (b_byq_cs) stFuHe.state = 0x02; // 抽水状态 // else stFuHe.state = 0x03; // 空闲状态 // } // else stFuHe.state = 0x03; // 空闲状态 // //m_pIter->second.wstate = stFuHe.state; // // mutex_unlock(g_map_iec_mutex); // switch (stFuHe.state & 0xff) // { // case 0x02: // 抽水状态 // stFuHe.current = lcurr; // 低压侧电流 // stFuHe.voltage = lvol; // 低压侧电压 // break; // case 0x03: // 空闲状态,数据无需入库 // g_IecCtrl.stime = 0; // 时间置0 // g_IecCtrl.etime = 0; // 时间置0 // break; // case 0x01: // 发电状态 // stFuHe.current = hCurr; // 高压侧电流 // stFuHe.voltage = hvol; // 高压侧电压 // break; // default:; // } // stFuHe.stop_time = time(NULL); // 结束时间 //} // //// 根据断路器的分组号,获取断路器的开关状态位 ////eqm_code : 遥信地址所配置的开关量,获取其各(A,B,C)相的开关量状态位 //// 配置文件中的各断路器A相,点表配置其开关量,入参eqm_code位A相的编号 ////unsigned char cGetGisCloseStatusByEqmCodeA(unsigned int site_id, unsigned char *eqm_code) //unsigned char cGetGisCloseStatusByEqmCodeA(htype site_id, unsigned char *eqm_code) //{ // unsigned char cStat = 0; // map::iterator m_pIter; // mutex_lock(g_map_iec_mutex); // for (m_pIter = g_map_iec.begin(); m_pIter != g_map_iec.end(); m_pIter++) // { // if (memcmp((m_pIter->second).eqm_code, eqm_code, strlen((char*)eqm_code))) continue; //#ifdef _SITE_ID_TYPE_INT // if ((m_pIter->second).site_id != site_id) continue; //#else // if (stringncasecmp((const char*)(m_pIter->second).site_id, (const char*)site_id, strlen((const char*)site_id) != 0)) continue; //#endif // switch ((m_pIter->second).sadr) // { // case 17: case 18: case 19: // GIS开关合位B相 0:分 1:合 // cStat = ((m_pIter->second).cval & 0xff); // //if (((m_pIter->second).cval & 0xff) == 0x01) b_gis_close = true; // break; // default:; // } // } // mutex_unlock(g_map_iec_mutex); // return cStat; //} //void dbGet_gis_breaker_table(ST_IEC_GISBREAK_TABLE &stGis) //{ // //bool b_gis_close = false, b_gis_fault = false; // // map::iterator m_pIter; // mutex_lock(g_map_iec_mutex); // stGis.d_time = time(NULL); // for (m_pIter = g_map_iec.begin(); m_pIter != g_map_iec.end(); m_pIter++) // { // if (memcmp((m_pIter->second).eqm_code, stGis.eqm_code, strlen((char*)stGis.eqm_code))) continue; //#ifdef _SITE_ID_TYPE_INT // if((m_pIter->second).site_id != stGis.site_id) continue; //#else // if (stringncasecmp((const char*)(m_pIter->second).site_id, (const char*)stGis.site_id, strlen((const char*)stGis.site_id) != 0)) continue; //#endif // switch ((m_pIter->second).sadr) // { // case 4: case 8: case 12: case 16: // 1号机组电气事故 // stGis.is_fault = ((m_pIter->second).cval & 0xff); // break; // // GIS的遥信数据 // case 17: case 18: case 19: // GIS开关合位B相 0:分 1:合 // stGis.is_close = ((m_pIter->second).cval & 0xff); // //if (((m_pIter->second).cval & 0xff) == 0x01) b_gis_close = true; // break; // // // 以下是遥测量 // case 16469: // 5001 - 1#电缆线A相电流(A) // case 16470: // 5001 - 1#电缆线B相电流(A) // case 16471: // 5001 - 1#电缆线C相电流(A) // stGis.abort_current = (m_pIter->second).fval; // break; // case 16472: // 5003 - 1#电缆线A相电流(A) // case 16473: // 5003 - 1#电缆线B相电流(A) // case 16474: // 5003 - 1#电缆线C相电流(A) // stGis.abort_current = (m_pIter->second).fval; // break; // case 16475: // 5051-A相电压(Kv) // case 16476: // 5051-B相电压(Kv) // case 16477: // 5051-C相电压(Kv) // stGis.abort_voltage = ((m_pIter->second).fval * 1000); // break; // case 16478: // 5051-A相电流(A) // case 16479: // 5051-B相电流(A) // case 16480: // 5051-C相电流(A) // stGis.abort_current = (m_pIter->second).fval; // break; // default: // //vPrtLogMsg(LOG_WARNG, RET_OK, "this YX addr:%d(0x%04x) not define.", adr, adr); // stGis.is_close = 0x01; //默认为合状态。 // break; // } // end switch // }// end for // if (stGis.abort_voltage <= 0) { // m_pIter = g_map_iec.find(16476); // 默认取本设备的电压值,5051-B相电压(Kv) // if (m_pIter != g_map_iec.end()) // stGis.abort_voltage = ((m_pIter->second).fval * 1000); // } // mutex_unlock(g_map_iec_mutex); // //if (g_IecCtrl.m_gis_count == 0) // // g_IecCtrl.m_gis_count = 1; // stGis.faild_rate = 0; // (float)((g_IecCtrl.m_gis_fault_count / g_IecCtrl.m_gis_count) * 100); //} /*************************************************************************** ** function name : thread_setdb_proc ** deacription : db opration thread and mysql insert... ** parameter : none ** return code : NULL ***************************************************************************/ //void *thread_setdb_proc(void *arg) //{ // vPrtLogMsg(LOG_DEBUG, 0, "thread_setdb_proc = %d startup...", GETTID()); //ST_DB_DATA stdbSet; //while (g_Running) //{ // pthread_testcancels(); // memset(&stdbSet, 0x00, sizeof(ST_DB_DATA)); // mutex_lock(g_list_dbset_mutex); // if (g_list_dbset.empty() || g_list_dbset.size() <= 0) { // mutex_unlock(g_list_dbset_mutex); // _SLEEP(MAX_SLEEP_EMPTY * 10); // continue; // } // memcpy(&stdbSet, &(g_list_dbset.back()), sizeof(ST_DB_DATA)); // 由尾取出 // if (stdbSet.pData == NULL) { // mutex_unlock(g_list_dbset_mutex); // _SLEEP(MAX_SLEEP_EMPTY * 10); // continue; // } // g_list_dbset.pop_back(); // 由尾删除 // mutex_unlock(g_list_dbset_mutex); // // 根据不同的数据类型分别入库 // switch (stdbSet.ctype) // { // case 1: // 1:运行工况数据入库 transformer_read_table // dbSet_transformer_read_table((ST_IEC_BYQREAD_TABLE*)stdbSet.pData); // //dbSet_transformer_read_table_cache((ST_IEC_BYQREAD_TABLE*)stdbSet.pData); // break; // case 2: // 2:GIS负荷数据入库 iec_breaker_param // dbSet_iec_breaker_param((ST_IEC_GISBREAK_TABLE*)stdbSet.pData); // break; // case 3: // 3:负荷数据入库 iec_bydwork_param // dbSet_iec_bydwork_param((ST_IEC_BYQWORK_TABLE*)stdbSet.pData); // break; // default: // break; // } // end switch // free(stdbSet.pData); // stdbSet.pData = NULL; //} // return NULL; //} /*************************************************************************** ** function name : thread_getdata_proc ** deacription : from g_iec_map get data and add g_list_dbset. ** parameter : none ** return code : NULL ***************************************************************************/ //void *thread_getdata_proc(void *arg) //{ // vPrtLogMsg(LOG_DEBUG, 0, "thread_getdata_proc = %d startup...", GETTID()); // int i = 0; // g_IecCtrl.lastTime = time(NULL); // _SLEEP(1000 * 5); // while (g_Running) // { // pthread_testcancels(); // // // 发生信号有变化且发生时间>0时,立即提取数据,加入数据入库队列中 // if (!((g_IecCtrl.b_Signal || g_IecCtrl.m_gis_change) || (time(NULL) - g_IecCtrl.lastTime) > (60 * 5))) // { // _SLEEP(100); // continue; // } // if (!g_IecCtrl.isConnect) { // _SLEEP(100); // continue; // } // // //g_IecCtrl.stime = 0; // g_IecCtrl.lastTime = time(NULL); // for (i = 0; i < (int)g_iec_conf.iec_byq_count; i++) // { // // 1:运行工况数据入库 transformer_read_table // ST_IEC_BYQREAD_TABLE stRung; // ST_IEC_BYQWORK_TABLE stFuHe; // memset(&stRung, 0x00, sizeof(ST_IEC_BYQREAD_TABLE)); // memset(&stFuHe, 0x00, sizeof(ST_IEC_BYQWORK_TABLE)); // strcpy((char*)stRung.site_id, (const char*)g_iec_conf.site_id); // strcpy((char*)stFuHe.site_id, (const char*)g_iec_conf.site_id); // strcpy((char*)stRung.eqm_code, (const char*)g_iec_conf.pstByqCode[i].szEqmCode); // strcpy((char*)stFuHe.eqm_code, (const char*)g_iec_conf.pstByqCode[i].szEqmCode); // if (g_iec_conf.pstByqCode[i].stime <= 0) { // g_iec_conf.pstByqCode[i].stime = time(NULL)-10; // stFuHe.start_time = time(NULL) - 10; // } // else { // stFuHe.start_time = g_iec_conf.pstByqCode[i].etime>0 ? g_iec_conf.pstByqCode[i].etime:time(NULL); // g_iec_conf.pstByqCode[i].stime = g_iec_conf.pstByqCode[i].etime; // } // dbGet_transformer_read_table(stRung, stFuHe); // // 类型:1-运行工况 2:断路器数据 3:变压器负荷数据 // addDbSetList((char*)&stRung, sizeof(ST_IEC_BYQREAD_TABLE), 0x01); // //if (stFuHe.current < 100) { // // vPrtLogMsg(LOG_WARNG, RET_OK, "%s: stype=%d,curr_val=%.2f(A) < 100(A),curr_vol:%.2f(V),not save.", // // stFuHe.eqm_code, (stFuHe.stype & 0xff), stFuHe.current, stFuHe.voltage); // // continue; // //} // if ((stFuHe.state & 0xff) == 0x01 || (stFuHe.state & 0xff) == 0x02) { // 空闲状态时的数据不入库。2019-01-08 // g_iec_conf.pstByqCode[i].etime = time(NULL); // stFuHe.stop_time = g_iec_conf.pstByqCode[i].etime; // addDbSetList((char*)&stFuHe, sizeof(ST_IEC_BYQWORK_TABLE), 0x03); // } // if ((stFuHe.state & 0xff) == 0x03) { // g_iec_conf.pstByqCode[i].stime = time(NULL); // g_iec_conf.pstByqCode[i].etime; // g_iec_conf.pstByqCode[i].etime = time(NULL); // } // } // // //if (g_IecCtrl.b_Signal || g_IecCtrl.m_gis_change) // 有主变的开关变化或gis的开关变化时。 // { // for (i = 0; i < (int)g_iec_conf.iec_break_count; i++) // { // // 2:GIS负荷数据入库 iec_breaker_param // ST_IEC_GISBREAK_TABLE stGis; // memset(&stGis, 0x00, sizeof(ST_IEC_GISBREAK_TABLE)); // strcpy((char*)stGis.site_id, (const char*)g_iec_conf.site_id); // strcpy((char*)stGis.eqm_code, (const char*)g_iec_conf.pstBrkCode[i].szEqmCodeA); // dbGet_gis_breaker_table(stGis); // // 类型:1-运行工况 2:断路器数据 3:变压器负荷数据 // //if ((stGis.is_close & 0xff) == 0x00) // addDbSetList((char*)&stGis, sizeof(ST_IEC_GISBREAK_TABLE), 0x02); // // memset(&stGis, 0x00, sizeof(ST_IEC_GISBREAK_TABLE)); //#ifdef _SITE_ID_TYPE_INT // stGis.site_id = g_iec_conf.iec_site_id; //#else // strcpy((char*)stGis.site_id, (const char*)g_iec_conf.site_id); //#endif // strcpy((char*)stGis.eqm_code, (const char*)g_iec_conf.pstBrkCode[i].szEqmCodeB); // dbGet_gis_breaker_table(stGis); // stGis.is_close = cGetGisCloseStatusByEqmCodeA(stGis.site_id, g_iec_conf.pstBrkCode[i].szEqmCodeA); // // 类型:1-运行工况 2:断路器数据 3:变压器负荷数据 // //if ((stGis.is_close & 0xff) == 0x00) // addDbSetList((char*)&stGis, sizeof(ST_IEC_GISBREAK_TABLE), 0x02); // // memset(&stGis, 0x00, sizeof(ST_IEC_GISBREAK_TABLE)); //#ifdef _SITE_ID_TYPE_INT // stGis.site_id = g_iec_conf.iec_site_id; //#else // strcpy((char*)stGis.site_id, (const char*)g_iec_conf.site_id); //#endif // strcpy((char*)stGis.eqm_code, (const char*)g_iec_conf.pstBrkCode[i].szEqmCodeC); // dbGet_gis_breaker_table(stGis); // stGis.is_close = cGetGisCloseStatusByEqmCodeA(stGis.site_id, g_iec_conf.pstBrkCode[i].szEqmCodeA); // // 类型:1-运行工况 2:断路器数据 3:变压器负荷数据 // //if ((stGis.is_close & 0xff) == 0x00) // addDbSetList((char*)&stGis, sizeof(ST_IEC_GISBREAK_TABLE), 0x02); // } // g_IecCtrl.m_gis_change = false; // } // g_IecCtrl.b_Signal = false; // _SLEEP(1000); // } // return NULL; //} /*************************************************************************** ** function name : dbGetFaildMaxValue ** deacription : link active thread ** parameter : none ** return code : NULL ***************************************************************************/ //double dbGetFaildMaxValue(const char *site_id, const char *eqm_code) //{ // double dValue = 0.0; // char szSql[1024] = { 0 }; // // CDBMySQL *pdbHandle = CDBMySQL::Instance(); // //SELECT a.site_id,b.site_code,a.eqm_code, v.ywei,v.ywen, v.jkyl,v.ckyl FROM busi_site_tree a, transformer_threshold v,busi_offline_transformer_brand b // //WHERE a.site_id=v.site_id AND a.status = 'A' AND a.type = 'a' AND b.status='A' AND a.eqm_code = v.eqm_code AND a.eqm_code = b.equipment_code AND b.equipment_code=v.eqm_code; // sprintf(szSql, "select site_id, eqm_code, higth_voltage, higth_current from iec_bydwork_param where site_id='%s' and eqm_code='%s'", site_id, eqm_code); // printf("=====%s\n", szSql); // MYSQL_RES *res = pdbHandle->SelectRecord(szSql); // if (!res) return 0.0; // // MYSQL_ROW row = NULL; // while (row = pdbHandle->GetRecord(res)) { // printf("site_id = %s eqm_code=%s type=%s\n", row[0], row[1], row[2]); // } // pdbHandle->FreeRecord(res); // printf("\n"); // return dValue; //} /*************************************************************************** ** function name : thread_Timer_proc ** deacription : Timer_proc thread ** parameter : none ** return code : NULL ***************************************************************************/ void *thread_Timer_proc(void *arg) { vPrtLogMsg(LOG_DEBUG, 0, "thread_Timer_proc = %d startup...", GETTID()); while (g_Running) { if (!g_IecCtrl.isConnect) { _SLEEP(1000); continue; } // 间隔1s time_t timeOrigin = time(NULL); // 定期总召 if ((g_IecCtrl.time_action != -1) && ((timeOrigin - g_IecCtrl.time_action) > g_iec_conf.action_interval)) { vPrtLogMsg(LOG_DEBUG, RET_OK, "Send Activation"); SendMsgFormatIAction(CMD_CTL_64H); // 发送总召激活 } _SLEEP(1000); continue; while ((time(NULL) - timeOrigin) < 1000) _SLEEP(1000); if (!g_IecCtrl.isConnect) // t0时间内连接未建立则重新连接并发送U启动帧激活数据传输 { // time-out for reconnection. g_IecCtrl.timer_t0++; // t0++ if (g_IecCtrl.timer_t0 > g_IecCtrl.t0) // TCP连接建立的超时时间(超时重新连接) { g_IecCtrl.timer_t0 = 0; g_IecCtrl.isConnect = false; //if (master->OpenLink(master->RemoteHost, master->RemotePort) == EOK) //SendMsgFormatU(CMD_STARTDT); } } else { // maximun number of frames received before master send ACK. W if ((g_IecCtrl.RxCounter - g_IecCtrl.LastAckRx) >= g_IecCtrl.w * 2) // Send_S_Msg(); // time-out of waiting ACK to Sended APDU o TestFR g_IecCtrl.timer_Confirm++; // t1:RTU(服务器)端启动U格式测试过程后等待U格式测试应答的超时时间(超时处理:断开连接) if (g_IecCtrl.timer_Confirm > g_IecCtrl.timer_t1) { if (g_IecCtrl.TxCounter - g_IecCtrl.LastAckTx > 6) { vPrtLogMsg(LOG_WARNG, 0, "Wait for U RESP timeout: TxCounter=%d LastAckTx=%d > 6, will close socket", g_IecCtrl.TxCounter, g_IecCtrl.LastAckTx); g_Tcp.tcpCloseSocket(g_IecCtrl.sockid); g_IecCtrl.isConnect = false; } // g_IecCtrl.timer_Confirmflag = true; } // time-out for no data to send, send S-frame to ack data received. OK g_IecCtrl.timer_t2++; // t2规定接收方在接收到I格式报文后,若经过t2时间未再收到新的I格式报文, // 则必须向发送方发送S格式帧对已经接收到的I格式报文进行认可,显然t2必须小于t1。 if (g_IecCtrl.timer_t2 > g_IecCtrl.t2) // (T2 < T1). S格式的超时时间 { g_IecCtrl.timer_t2 = 0; if (g_IecCtrl.timer_S_Ackflag) // 在收到I格式报文的时候置timer_S_Ack为0 SendMsgFormatS(g_IecCtrl.usSendNo); g_IecCtrl.timer_S_Ackflag = true; } // time-out for idle status, send test frame to check link state. OK // t3规定调度端或子站RTU端每接收一帧 I帧、S帧或者U帧将重新触发计时器t3,若在t3内未接收到任何报文,将向对方发送测试链路帧 g_IecCtrl.timer_t3++; if (g_IecCtrl.timer_t3 > g_IecCtrl.t3) // 没有实际的数据交换时,任何一端启动U格式测试过程的最大间隔时间 (发送测试帧) { g_IecCtrl.timer_t3 = 0; if (g_IecCtrl.timer_U_Testflag) // 接收到I S U帧都将timer_U_Test置为0 SendMsgFormatU(CMD_TESTFR); g_IecCtrl.timer_U_Testflag = true; } } } return NULL; } /*************************************************************************** ** function name : thread_active_proc ** deacription : link active thread ** parameter : none ** return code : NULL ***************************************************************************/ void *thread_active_proc(void *arg) { vPrtLogMsg(LOG_DEBUG, 0, "thread_active_proc = %d startup...", GETTID()); ST_APCI header; while (g_Running && g_IecCtrl.isConnect) { if (time(NULL) - g_IecCtrl.last_time > g_TConfig.getTimeout3()) { header.start = 0x68; header.len = 0x04; vAutoSendSeqNo(1); // 发送序列号增1 header.cntl1 = g_IecCtrl.usSendNo & 0xFF; // S-Format header.cntl2 = (g_IecCtrl.usSendNo >> 8) & 0xFF; header.cntl3 = g_IecCtrl.usRecvNo & 0xFE; header.cntl4 = (g_IecCtrl.usRecvNo >> 8) & 0xFF; g_Tcp.tcpSendBuffer(g_IecCtrl.sockid, (const char*)&header, 6); vPrtLogHex(LOG_PACK, g_IecCtrl.sockid, PRT_PACK_SEND, (unsigned char*)&header, sizeof(ST_APCI)); mutex_lock(g_IecCtrl_mutex); g_IecCtrl.last_time = time(NULL); mutex_unlock(g_IecCtrl_mutex); } //vPrtLogHex(LOG_PACK, g_IecCtrl.sockid, PRT_PACK_SEND, (unsigned char*)CMD_ACTIVE_PACKAGE, sizeof(ST_APCI)); //vPrtListCount(); _SLEEP(1000); } return NULL; } // 获取最近一次变压器的数据 //static void dbGetIECBYQLastData(ST_BYQ_CACHE &pstByq) //{ // char szSql[256] = { 0 }; // time_t stime = 0; // CDBMySQL *pdbHandle = CDBMySQL::Instance(); // if (!pdbHandle) return; // // 获取最近一次的电压、电流... //#ifdef _SITE_ID_TYPE_INT // sprintf(szSql, "select stype,start_time,stop_time,higth_voltage,higth_current from iec_bydwork_param where " // "eqm_code = '%s' and site_id=%d ORDER BY id desc limit 1", pstByq.szEqmCode, pstByq.SiteID); //#else // snprintf(szSql, sizeof(szSql), "select stype,start_time,stop_time,higth_voltage,higth_current from iec_bydwork_param where " // "eqm_code = '%s' and site_id='%s' ORDER BY id desc limit 1", pstByq.szEqmCode, pstByq.SiteID); //#endif // MYSQL_RES *res = pdbHandle->SelectRecord(szSql); // if (!res) return; // // MYSQL_ROW row = NULL; // if (row = pdbHandle->GetRecord(res)) // { // pstByq.stLastData.stype = atoi(row[0]); // // if (row[1] && strlen(row[1]) > 0) { // memset(szSql, 0x00, sizeof(szSql)); // strncpy(szSql, (const char*)row[1], strlen(row[1])); // pstByq.stLastData.start_time = strTimeFmt2int(szSql); // } // // if (row[2] && strlen(row[2]) > 0) { // memset(szSql, 0x00, sizeof(szSql)); // strncpy(szSql, (const char*)row[2], strlen(row[2])); // pstByq.stLastData.stop_time = strTimeFmt2int(szSql); // } // (row[3] && strlen(row[3])) ? (pstByq.stLastData.voltage = atof((const char*)row[3])) : 0; // (row[4] && strlen(row[4])) ? (pstByq.stLastData.current = atof((const char*)row[4])) : 0; // // } // pdbHandle->FreeRecord(res); // // // 获取最近一次的油位,油温,进出口压力值 //#ifdef _SITE_ID_TYPE_INT // sprintf(szSql, "select oil_temperature,oil_position,cooling_entry_pressure,cooling_exit_pressure " // "from transformer_read_table where " // "eqmid = '%s' and site_id=%d ORDER BY id desc limit 1", pstByq.szEqmCode, pstByq.SiteID); //#else // snprintf(szSql, sizeof(szSql), "select oil_temperature,oil_position,cooling_entry_pressure,cooling_exit_pressure " // "from transformer_read_table where " // "eqmid = '%s' and site_id='%s' ORDER BY id desc limit 1", pstByq.szEqmCode, pstByq.SiteID); //#endif // res = pdbHandle->SelectRecord(szSql); // if (!res) return; // // row = NULL; // if (row = pdbHandle->GetRecord(res)) // { // pstByq.stLastData.dcurYWen = atof(row[0]); // pstByq.stLastData.dcurYWei = atof(row[1]); // pstByq.stLastData.dcurJkyl = atof(row[2]); // pstByq.stLastData.dcurCkyl = atof(row[3]); // } // pdbHandle->FreeRecord(res); // return; //} //// 获取gis数据 //static void dbGetLastDataByEqmCode(unsigned char *pEqmcode) //{ // int i = 0; // char szSql[256] = { 0 }; // string strKey = ""; // time_t stime = 0; // CDBMySQL *pdbHandle = CDBMySQL::Instance(); // if (!pdbHandle) return; // // snprintf(szSql, sizeof(szSql), "select site_id,abort_voltage,abort_current,faild_rate,is_fault,record_date from iec_breaker_param " // "where eqm_code = '%s' ORDER BY id desc limit 1", pEqmcode); // // MYSQL_RES *res = pdbHandle->SelectRecord(szSql); // if (!res) return; // strKey = (char*)pEqmcode; // MYSQL_ROW row = NULL; // if (row = pdbHandle->GetRecord(res)) // { // ST_GIS_IEC104_DATA stGis; // memset(&stGis, 0x00, sizeof(ST_GIS_IEC104_DATA)); // // strcpy((char*)stGis.szEqmCode, (char*)pEqmcode); //#ifdef _SITE_ID_TYPE_INT // (row[0] && strlen(row[0])) ? (stGis.SiteID = atoi((const char*)row[0])) : 0; // site_id //#else // if (row[0] && strlen(row[0]) > 0) { // strncpy((char*)stGis.SiteID, row[0], strlen(row[0])); // } //#endif // (row[1] && strlen(row[1])) ? (stGis.stLastData.voltage = atof((const char*)row[1])) : 0; // (row[2] && strlen(row[2])) ? (stGis.stLastData.current = atof((const char*)row[2])) : 0; // (row[3] && strlen(row[3])) ? (stGis.stLastData.failed_rate = atof((const char*)row[3])) : 0; // (row[4] && strlen(row[4])) ? (stGis.stLastData.is_fault = atoi((const char*)row[4])) : 0; // if (row[5] && strlen(row[5]) > 0) { // memset(szSql, 0x00, sizeof(szSql)); // strncpy(szSql, (const char*)row[5], strlen(row[5])); // stGis.stLastData.record_date = strTimeFmt2int(szSql); // } // mutex_lock(g_map_gis_104_mutex); // g_map_gis_104.insert(map::value_type(strKey, stGis)); // mutex_unlock(g_map_gis_104_mutex); // } // pdbHandle->FreeRecord(res); // return; //} // 获取最近一次断路器的数据 //static void dbGetIECGISLastData() //{ // int i = 0; // for (i = 0; i < (int)g_iec_conf.iec_break_count; i++) // { // dbGetLastDataByEqmCode(g_iec_conf.pstBrkCode[i].szEqmCodeA); // dbGetLastDataByEqmCode(g_iec_conf.pstBrkCode[i].szEqmCodeB); // dbGetLastDataByEqmCode(g_iec_conf.pstBrkCode[i].szEqmCodeC); // } // return; //} // 打印GIS最近一次104上传数据 //static void vPrtIECGISLastData() //{ // map::iterator m_pIter; // m_pIter = g_map_gis_104.begin(); // vPrtLogMsg(LOG_DEBUG, RET_OK, "---------Print GIS Last Data ----------"); // while (m_pIter != g_map_gis_104.end()) // { //#ifdef _SITE_ID_TYPE_INT // vPrtLogMsg(LOG_DEBUG, RET_OK, "%-4d %-10s %.3f %.3f %.3f %1d %u", (m_pIter->second).SiteID, (m_pIter->second).szEqmCode, //#else // vPrtLogMsg(LOG_DEBUG, RET_OK, "%-s %.3f %.3f %.3f %1d %u", (m_pIter->second).szEqmCode, //#endif // (m_pIter->second).stLastData.voltage, (m_pIter->second).stLastData.current, // (m_pIter->second).stLastData.failed_rate, (m_pIter->second).stLastData.is_fault, (m_pIter->second).stLastData.record_date); // m_pIter++; // } // vPrtLogMsg(LOG_DEBUG, RET_OK, "---------- gis_last_data_size:%d-----------", g_map_gis_104.size()); // return; //} // 设置主变的油位信息体地址 bool bSetBYQPointValueByAddr(const char *pszEqmCode, float value) { unsigned int sdr = 0; for (int i = 0; i < (int)g_iec_conf.iec_byq_count; i++) { if (0 == stringncasecmp(pszEqmCode, (const char*)(g_iec_conf.pstByqCode[i].szEqmCode), strlen(pszEqmCode))) { g_IecCtrl.m_gis_change = true; // 通知,需保存一条记录 switch (i) { case 0: return bSetPointTableValueYC(value, (unsigned int)16405); case 1: return bSetPointTableValueYC(value, (unsigned int)16426); case 2: return bSetPointTableValueYC(value, (unsigned int)16447); case 3: return bSetPointTableValueYC(value, (unsigned int)16468); default: break; } } } return false; } //// 获取站点主变设备对应关系及阈值 //bool bGetByqCacheRelation(unsigned char *pszEqmCode, ST_BYQ_CACHE *pstData) //{ // if (!pszEqmCode) return false; // map::iterator m_pIter; // mutex_lock(g_map_byq_mutex); // m_pIter = g_map_byq.find((char*)pszEqmCode); // if (m_pIter != g_map_byq.end()) // { // memcpy(pstData, &(m_pIter->second), sizeof(ST_BYQ_CACHE)); // //g_map_request_mec_rsp.erase(m_pIter) ; // mutex_unlock(g_map_byq_mutex); // return true; // } // mutex_unlock(g_map_byq_mutex); // vPrtLogMsg(LOG_WARNG, RET_OK, "Can't found EqmCode:%s on BYQ cache relation table,map_size:%d", pszEqmCode, g_map_byq.size()); // return false; //} /*************************************************************************** ** function name : dbGetGISCacheData ** deacription : get gis define value & site_id-->site_code relation. ** parameter : none ** return code : NULL ***************************************************************************/ //void dbGetGISCacheData(void) //{ // char szSql[1024] = { 0 }; // // CDBMySQL *pdbHandle = CDBMySQL::Instance(); // if (!pdbHandle) return; // // snprintf(szSql, sizeof(szSql), "SELECT c.site_id,b.des, b.cac_number, b.eqm_code, c.picval FROM gis_sbjc a, gis_tree b, gis_threshold c " // "WHERE a.status = 'A' AND a.type = '6' AND b.type = '6' AND a.id = b.eqm_id AND b.eqm_code = c.eqm_code"); // // MYSQL_RES *res = pdbHandle->SelectRecord(szSql); // if (!res) return; // // MYSQL_ROW row = NULL; // while (row = pdbHandle->GetRecord(res)) // { // ST_GIS_CACHE stGis; // string strKey = ""; // memset(&stGis, 0x00, sizeof(ST_GIS_CACHE)); //#ifdef _STIE_ID_TYPE_INT // stGis.SiteID = atoi(row[0]); //#else // if (row[0] && strlen(row[0]) > 0) { // strncpy((char*)stGis.SiteID, (const char*)row[0], strlen(row[0])); // } //#endif // if (row[1] && strlen(row[1]) > 0) { // strncpy((char*)stGis.name_des, (const char*)row[1], sizeof(stGis.name_des)); // } // if (row[2] && strlen(row[2]) > 0) { // strncpy((char*)stGis.szSersorID, (const char*)row[2], sizeof(stGis.szSersorID)); // strKey = (char*)stGis.szSersorID; // } // if (row[3] && strlen(row[3]) > 0) { // strncpy((char*)stGis.szEqmCodeID, (const char*)row[3], sizeof(stGis.szEqmCodeID)); // } // (row[4] && strlen(row[4])) ? (stGis.dNum = atof((const char*)row[4])) : 0; // // mutex_lock(g_map_gis_mutex); // g_map_gis.insert(map::value_type(strKey, stGis)); // mutex_unlock(g_map_gis_mutex); // } // pdbHandle->FreeRecord(res); // vPrtLogMsg(LOG_DEBUG, RET_OK, "---get_gis_size:%d---", g_map_gis.size()); // return; //} // 获取GIS设备对应关系及阈值 //bool bGetGisCacheRelation(unsigned char *pszSersorid, ST_GIS_CACHE *pstData) //{ // if (!pszSersorid) return false; // map::iterator m_pIter; // mutex_lock(g_map_gis_mutex); // m_pIter = g_map_gis.find((char*)pszSersorid); // if (m_pIter != g_map_gis.end()) // { // memcpy(pstData, &(m_pIter->second), sizeof(ST_GIS_CACHE)); // //g_map_request_mec_rsp.erase(m_pIter) ; // mutex_unlock(g_map_gis_mutex); // return true; // } // mutex_unlock(g_map_gis_mutex); // vPrtLogMsg(LOG_WARNG, RET_OK, "Can't found SersorID:%s on GIS cache relation table,map_size:%d", pszSersorid, g_map_gis.size()); // return false; //} // 打印GIS缓存数据 //void vPrtGisCacheRelation(void) //{ // map::iterator m_pIter; // m_pIter = g_map_gis.begin(); // vPrtLogMsg(LOG_DEBUG, RET_OK, "---------Print GIS Relation----------"); // while (m_pIter != g_map_gis.end()) // { // // c.site_id, b.des, b.cac_number, b.eqm_code, c.tpsb_dl //#ifdef _SITE_ID_TYPE_INT // vPrtLogMsg(LOG_DEBUG, RET_OK, "%-4d %-.5f %18s %16s", (m_pIter->second).SiteID, //#else // vPrtLogMsg(LOG_DEBUG, RET_OK, "%-.5f %18s %16s", //#endif // (m_pIter->second).dNum, (m_pIter->second).szSersorID, (m_pIter->second).szEqmCodeID); // m_pIter++; // } // vPrtLogMsg(LOG_DEBUG, RET_OK, "---------- GIS_size:%d-----------", g_map_gis.size()); // return; //} /*************************************************************************** ** function name : dbGetBLQCacheData ** deacription : get BLQ define value & site_id-->site_code relation. ** parameter : none ** return code : NULL ***************************************************************************/ //void dbGetBLQCacheData(void) //{ // char szSql[1024] = { 0 }; // // CDBMySQL *pdbHandle = CDBMySQL::Instance(); // if (!pdbHandle) return; // // snprintf(szSql, sizeof(szSql), "SELECT c.site_id,b.des, b.cac_number, b.eqm_code, c.tpsb_dl FROM arrester_sbjc a, arrester_tree b, arrester_threshold c " // "WHERE a.status = 'A' AND a.type = '5' AND b.type = '5' AND a.id = b.eqm_id AND b.eqm_code = c.eqm_code"); // // MYSQL_RES *res = pdbHandle->SelectRecord(szSql); // if (!res) return; // // MYSQL_ROW row = NULL; // while (row = pdbHandle->GetRecord(res)) // { // ST_BLQ_CACHE stBlq; // string strKey = ""; // memset(&stBlq, 0x00, sizeof(ST_BLQ_CACHE)); //#ifdef _SITE_ID_TYPE_INT // stBlq.SiteID = atoi(row[0]); //#else // if (row[0] && strlen(row[0]) > 0) { // strncpy((char*)stBlq.SiteID, (const char*)row[0], strlen(row[0])); // } //#endif // if (row[1] && strlen(row[1]) > 0) { // strncpy((char*)stBlq.name_des, (const char*)row[1], sizeof(stBlq.name_des)); // } // if (row[2] && strlen(row[2]) > 0) { // strncpy((char*)stBlq.szSersorID, (const char*)row[2], sizeof(stBlq.szSersorID)); // strKey = (char*)stBlq.szSersorID; // } // if (row[3] && strlen(row[3]) > 0) { // strncpy((char*)stBlq.szEqmCodeID, (const char*)row[3], sizeof(stBlq.szEqmCodeID)); // } // (row[4] && strlen(row[4])) ? (stBlq.dMaxDL = atof((const char*)row[4])) : 0; // // mutex_lock(g_map_blq_mutex); // g_map_blq.insert(map::value_type(strKey, stBlq)); // mutex_unlock(g_map_blq_mutex); // } // pdbHandle->FreeRecord(res); // vPrtLogMsg(LOG_DEBUG, RET_OK, "---get_BLQ_size:%d---", g_map_blq.size()); // return; //} // 获取BLQ设备对应关系及阈值 //bool bGetBlqCacheRelation(unsigned char *pszSersorid, ST_BLQ_CACHE *pstData) //{ // if (!pszSersorid) return false; // map::iterator m_pIter; // mutex_lock(g_map_blq_mutex); // m_pIter = g_map_blq.find((char*)pszSersorid); // if (m_pIter != g_map_blq.end()) // { // memcpy(&pstData, &(m_pIter->second), sizeof(ST_BYQ_CACHE)); // //g_map_request_mec_rsp.erase(m_pIter) ; // mutex_unlock(g_map_blq_mutex); // return true; // } // mutex_unlock(g_map_blq_mutex); // vPrtLogMsg(LOG_WARNG, RET_OK, "Can't found SersorID:%s on BLQ cache relation table,map_size:%d", pszSersorid, g_map_blq.size()); // return false; //} // 打印BLQ缓存数据 //void vPrtBlqCacheRelation(void) //{ // map::iterator m_pIter; // m_pIter = g_map_blq.begin(); // vPrtLogMsg(LOG_DEBUG, RET_OK, "---------Print BLQ Relation----------"); // while (m_pIter != g_map_blq.end()) // { // // c.site_id, b.des, b.cac_number, b.eqm_code, c.tpsb_dl //#ifdef _SITE_ID_TYPE_INT // vPrtLogMsg(LOG_DEBUG, RET_OK, "%-4d %-.5f %18s %16s %s", (m_pIter->second).SiteID, //#else // vPrtLogMsg(LOG_DEBUG, RET_OK, "%-.5f %18s %16s %s", //#endif // (m_pIter->second).dMaxDL, (m_pIter->second).szSersorID, (m_pIter->second).szEqmCodeID, // (m_pIter->second).name_des); // m_pIter++; // } // vPrtLogMsg(LOG_DEBUG, RET_OK, "---------- BLQ_size:%d-----------", g_map_blq.size()); // return; //} // 统计发电、抽水时间 void vIECWorkTime() { char szSql[1024] = { 0 }; // 统计一天的发电时长(分钟) snprintf(szSql, sizeof(szSql), "select sum(TIMESTAMPDIFF(MINUTE,start_time,stop_time)) from iec_bydwork_param " "where eqm_code='SBBH1BYQ' and stype=1 " "and ins_date BETWEEN '2019-01-09 00:00:00' and '2019-01-09 23:59:59'"); //统计平均电压,电流 snprintf(szSql, sizeof(szSql), "select count(*),sum(higth_voltage),sum(higth_current),avg(higth_voltage),avg(higth_current) " "from iec_bydwork_param where eqm_code = 'SBBH1BYQ' and stype = 1 " "and ins_date >= '2019-01-09 00:00:00' and ins_date <= '2019-01-09 23:59:59' "); // select count(*), sum(temper), avg(temper) // from busi_temper_cac where type = 'A相出线' // and dtime >= '2019-01-09 00:00:00' and dtime <= '2019-01-09 23:59:59'; /* select count(*), sum(temper), avg(temper) from busi_temper_cac where type = 'B相出线' and dtime >= '2019-01-09 00:00:00' and dtime <= '2019-01-09 23:59:59' and eqm_code = 'SBBH31CWG'; --and sensor_id = 'JXHPD001A10000112'; select count(*), sum(temper), avg(temper) from busi_temper_cac where type = 'B相出线' and dtime >= '2019-01-09 00:00:00' and dtime <= '2019-01-09 23:59:59' and eqm_code = 'SBBH166CWG'; --and sensor_id = 'JXHPD001A10000112'; */ }