From 7b5c7a8c3c7b9a7c0e3f9ca7cd179dd79f31a533 Mon Sep 17 00:00:00 2001 From: Matthew Date: Tue, 7 Nov 2023 13:47:16 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=8E=E6=B3=B0=E5=AE=9E=E7=8E=B0=E7=9A=84IE?= =?UTF-8?q?C104?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 仅支持接收数据 --- etc/bak.conf | 8 + etc/ht_iec104.conf | 8 + etc/ht_service.conf | 52 ++ etc/htimg-win.conf | 15 + etc/htimg.conf | 15 + etc/rtsplist.txt | 14 + include/HTCP56Time.h | 84 ++++ include/HTCP56Time2a.h | 84 ++++ include/HTConfig.h | 179 +++++++ include/HTConst.h | 68 +++ include/HTDataStruct.h | 379 ++++++++++++++ include/HTDatabase.h | 100 ++++ include/HTError.h | 44 ++ include/HTGlobal.h | 120 +++++ include/HTHP104Table.h | 144 ++++++ include/HTIEC104.h | 97 ++++ include/HTImageBusi.h | 42 ++ include/HTInitUtils.h | 32 ++ include/HTLogger.h | 75 +++ include/HTMemCacheData.h | 110 +++++ include/HTMutex.h | 42 ++ include/HTOpencvImg.h | 548 +++++++++++++++++++++ include/HTPublic.h | 226 +++++++++ include/HTTcpSocket.h | 97 ++++ include/HTTestOpencv.h | 67 +++ include/HTThread.h | 44 ++ include/HTType.h | 69 +++ include/HTUnit.h | 24 + include/HTVersion.h | 19 + include/HXIec104.h | 179 +++++++ src/HTCP56Time.cpp | 137 ++++++ src/HTCP56Time2a.cpp | 137 ++++++ src/HTConfig.cpp | 690 ++++++++++++++++++++++++++ src/HTDatabase.cpp | 458 +++++++++++++++++ src/HTGlobal.cpp | 78 +++ src/HTIEC104.cpp | 682 +++++++++++++++++++++++++ src/HTImageBusi.cpp | 193 ++++++++ src/HTInitUtils.cpp | 105 ++++ src/HTLogger.cpp | 283 +++++++++++ src/HTMemCacheData.cpp | 794 ++++++++++++++++++++++++++++++ src/HTOpencvImg.cpp | 904 ++++++++++++++++++++++++++++++++++ src/HTPublic.cpp | 1012 ++++++++++++++++++++++++++++++++++++++ src/HTService.cpp | 449 +++++++++++++++++ src/HTTcpSocket.cpp | 518 +++++++++++++++++++ src/HTTestOpencv.cpp | 1 + src/HTThread.cpp | 114 +++++ src/HTUnit.cpp | 123 +++++ src/HXIec104.cpp | 912 ++++++++++++++++++++++++++++++++++ src/make.list | 59 +++ src/make.mak | 50 ++ src/makefile | 55 +++ src/makefile.mak | 59 +++ 52 files changed, 10798 insertions(+) create mode 100644 etc/bak.conf create mode 100644 etc/ht_iec104.conf create mode 100644 etc/ht_service.conf create mode 100644 etc/htimg-win.conf create mode 100644 etc/htimg.conf create mode 100644 etc/rtsplist.txt create mode 100644 include/HTCP56Time.h create mode 100644 include/HTCP56Time2a.h create mode 100644 include/HTConfig.h create mode 100644 include/HTConst.h create mode 100644 include/HTDataStruct.h create mode 100644 include/HTDatabase.h create mode 100644 include/HTError.h create mode 100644 include/HTGlobal.h create mode 100644 include/HTHP104Table.h create mode 100644 include/HTIEC104.h create mode 100644 include/HTImageBusi.h create mode 100644 include/HTInitUtils.h create mode 100644 include/HTLogger.h create mode 100644 include/HTMemCacheData.h create mode 100644 include/HTMutex.h create mode 100644 include/HTOpencvImg.h create mode 100644 include/HTPublic.h create mode 100644 include/HTTcpSocket.h create mode 100644 include/HTTestOpencv.h create mode 100644 include/HTThread.h create mode 100644 include/HTType.h create mode 100644 include/HTUnit.h create mode 100644 include/HTVersion.h create mode 100644 include/HXIec104.h create mode 100644 src/HTCP56Time.cpp create mode 100644 src/HTCP56Time2a.cpp create mode 100644 src/HTConfig.cpp create mode 100644 src/HTDatabase.cpp create mode 100644 src/HTGlobal.cpp create mode 100644 src/HTIEC104.cpp create mode 100644 src/HTImageBusi.cpp create mode 100644 src/HTInitUtils.cpp create mode 100644 src/HTLogger.cpp create mode 100644 src/HTMemCacheData.cpp create mode 100644 src/HTOpencvImg.cpp create mode 100644 src/HTPublic.cpp create mode 100644 src/HTService.cpp create mode 100644 src/HTTcpSocket.cpp create mode 100644 src/HTTestOpencv.cpp create mode 100644 src/HTThread.cpp create mode 100644 src/HTUnit.cpp create mode 100644 src/HXIec104.cpp create mode 100644 src/make.list create mode 100644 src/make.mak create mode 100644 src/makefile create mode 100644 src/makefile.mak diff --git a/etc/bak.conf b/etc/bak.conf new file mode 100644 index 0000000..1cef11e --- /dev/null +++ b/etc/bak.conf @@ -0,0 +1,8 @@ +/********************************************************************/ +# ht_iec104.conf +# date : 2018.09.01 +# auther : huatek by liuyx +# Copyright (C) 2018, huatek, Inc. +/********************************************************************/ +[IEC_DEVCOUNT] +# 涓诲彉璁惧鎬绘暟閲 \ No newline at end of file diff --git a/etc/ht_iec104.conf b/etc/ht_iec104.conf new file mode 100644 index 0000000..1cef11e --- /dev/null +++ b/etc/ht_iec104.conf @@ -0,0 +1,8 @@ +/********************************************************************/ +# ht_iec104.conf +# date : 2018.09.01 +# auther : huatek by liuyx +# Copyright (C) 2018, huatek, Inc. +/********************************************************************/ +[IEC_DEVCOUNT] +# 涓诲彉璁惧鎬绘暟閲 \ No newline at end of file diff --git a/etc/ht_service.conf b/etc/ht_service.conf new file mode 100644 index 0000000..1a79799 --- /dev/null +++ b/etc/ht_service.conf @@ -0,0 +1,52 @@ +/********************************************************************/ +# ht_service.conf +# date : 2018.09.01 +# auther : huatek by liuyx +# Copyright (C) 2018, huatek, Inc. +/********************************************************************/ +[HT_MONITOR] +# server monitor flag, true: monitor, false:no monitor +monitor_enable = true + +[HT_VERSION] +# server version info, max length=32(byte) +ht_server_version = 2019.06.11 + +[HT_LOCAL_HOST] +local_host_addr = 127.0.0.1 +local_tcp_port = 2404 + +[HT_REMOTE_HOST] +#remote_host_addr = 192.168.1.1 +remote_host_addr = 127.0.0.1 +remote_host_port = 2404 + +[HT_SOCKET] +max_epoll_limit = 2000 +timeout_t0 = 30 +timeout_t1 = 15 +timeout_t2 = 10 +timeout_t3 = 20 +iec_k = 8 +iec_w = 3 + +# application database config parameter +[HT_DATABASE] +db_host_addr = 192.168.128.86 +db_host_port = 3306 +db_name = hmf_0617 +db_username = root +db_password = 123456 +db_min_conn = 5 +db_max_conn = 8 + +[HT_THREAD_NUMBER] +thread_recv_num = 2 +thread_parse_num = 5 + +thread_opration_num = 3 +thread_respone_num = 2 + +[HT_LOGGER] +logger = console,debug,error,warning,package +#logger = error,warning diff --git a/etc/htimg-win.conf b/etc/htimg-win.conf new file mode 100644 index 0000000..7170042 --- /dev/null +++ b/etc/htimg-win.conf @@ -0,0 +1,15 @@ +/********************************************************************/ +# htimg.conf +# date : 2018.09.01 +# auther : huatek by liuyx +# Copyright (C) 2006-2018, huatek, Inc. +# ------------------------------------------------------------------- +# 浠〃鍗曚綅绫诲瀷鍙婂崟浣嶅畾涔夊搴斿叧绯昏〃 +# ---------------------------------------- +# 绫诲瀷 | 鍗曚綅瀹氫箟 | +# -------------+-------------------------+ +# meter_type | meter_units | +# -------------+-------------------+-----+ +# | 0 | 1 | 2 | 3 | +# = 0 +-------------------+-----+ +# (鐢垫祦) | 寰畨 | 姣畨 | 瀹 \ No newline at end of file diff --git a/etc/htimg.conf b/etc/htimg.conf new file mode 100644 index 0000000..7170042 --- /dev/null +++ b/etc/htimg.conf @@ -0,0 +1,15 @@ +/********************************************************************/ +# htimg.conf +# date : 2018.09.01 +# auther : huatek by liuyx +# Copyright (C) 2006-2018, huatek, Inc. +# ------------------------------------------------------------------- +# 浠〃鍗曚綅绫诲瀷鍙婂崟浣嶅畾涔夊搴斿叧绯昏〃 +# ---------------------------------------- +# 绫诲瀷 | 鍗曚綅瀹氫箟 | +# -------------+-------------------------+ +# meter_type | meter_units | +# -------------+-------------------+-----+ +# | 0 | 1 | 2 | 3 | +# = 0 +-------------------+-----+ +# (鐢垫祦) | 寰畨 | 姣畨 | 瀹 \ No newline at end of file diff --git a/etc/rtsplist.txt b/etc/rtsplist.txt new file mode 100644 index 0000000..9db4ba0 --- /dev/null +++ b/etc/rtsplist.txt @@ -0,0 +1,14 @@ +rtsp://192.168.1.12/stream65.sdp +rtsp://192.168.1.12/stream66.sdp +rtsp://192.168.1.12/stream67.sdp +rtsp://192.168.1.12/stream68.sdp +rtsp://192.168.1.12/stream69.sdp +rtsp://192.168.1.12/stream70.sdp +rtsp://192.168.1.12/stream71.sdp +rtsp://192.168.1.12/stream72.sdp +rtsp://192.168.1.12/stream73.sdp +rtsp://192.168.1.12/stream74.sdp +rtsp://192.168.1.12/stream75.sdp +rtsp://192.168.1.12/stream76.sdp +rtsp://192.168.1.12/stream80.sdp +rtsp://192.168.1.12/stream81.sdp diff --git a/include/HTCP56Time.h b/include/HTCP56Time.h new file mode 100644 index 0000000..8c5e2e9 --- /dev/null +++ b/include/HTCP56Time.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** File name : HTCP56Time.h +** Description : define data type +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_CP56TIME_H +#define __HT_CP56TIME_H +// +// CP56Time IEC 60870-5-104 time data type implementation +// +#pragma pack (push ,1) +#include + +#ifndef _WIN32 +typedef struct _SYSTEMTIME { + unsigned short wYear; + unsigned short wMonth; + unsigned short wDayOfWeek; + unsigned short wDay; + unsigned short wHour; + unsigned short wMinute; + unsigned short wSecond; + unsigned short wMilliseconds; +} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME; + +typedef struct _FILETIME { + unsigned long dwLowDateTime; + unsigned long dwHighDateTime; +} FILETIME, *PFILETIME, *LPFILETIME; + +#endif + + +typedef struct cp56time { + u_short msec; + u_char min :6; + u_char res1 :1; + u_char iv :1; + u_char hour :5; + u_char res2 :2; + u_char su :1; + u_char mday :5; + u_char wday :3; + u_char month :4; + u_char res3 :4; + u_char year :7; + u_char res4 :1; +} cp56time ; + + +class CP56Time +{ +private: + SYSTEMTIME stime; + bool valid; + bool genuine; + bool summer; + +public: + CP56Time(unsigned char *data); + ~CP56Time(void); + + void GetTimeString(char *buf, size_t size); + FILETIME _GetFileTime(void); + SYSTEMTIME _GetSystemTime(void); + + void ActualTimeToCP56Time(unsigned char *data); + + void TimeToCP56Time(FILETIME *ft, unsigned char *data); + void TimeToCP56Time(SYSTEMTIME *st, unsigned char *data); + + void CP56TimeToTime(unsigned char *data, FILETIME *ft); + void CP56TimeToTime(unsigned char *data, SYSTEMTIME *st); +}; +#pragma pack (pop) +#endif // end __HT_CP56TIME_H + diff --git a/include/HTCP56Time2a.h b/include/HTCP56Time2a.h new file mode 100644 index 0000000..a305c3f --- /dev/null +++ b/include/HTCP56Time2a.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** File name : HTCP56Time2a.h +** Description : define data type +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_CP56TIME2A_H +#define __HT_CP56TIME2A_H +// +// CP56Time2a IEC 60870-5-104 time data type implementation +// +#pragma pack (push ,1) +#include + +#ifndef _WIN32 +typedef struct _SYSTEMTIME { + unsigned short wYear; + unsigned short wMonth; + unsigned short wDayOfWeek; + unsigned short wDay; + unsigned short wHour; + unsigned short wMinute; + unsigned short wSecond; + unsigned short wMilliseconds; +} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME; + +typedef struct _FILETIME { + unsigned long dwLowDateTime; + unsigned long dwHighDateTime; +} FILETIME, *PFILETIME, *LPFILETIME; + +#endif + + +typedef struct cp56time2a { + u_short msec; + u_char min :6; + u_char res1 :1; + u_char iv :1; + u_char hour :5; + u_char res2 :2; + u_char su :1; + u_char mday :5; + u_char wday :3; + u_char month :4; + u_char res3 :4; + u_char year :7; + u_char res4 :1; +} cp56time2a ; + + +class CP56Time2a +{ +private: + SYSTEMTIME stime; + bool valid; + bool genuine; + bool summer; + +public: + CP56Time2a(unsigned char *data); + ~CP56Time2a(void); + + void GetTimeString(char *buf, size_t size); + FILETIME _GetFileTime(void); + SYSTEMTIME _GetSystemTime(void); + + void ActualTimeToCP56Time(unsigned char *data); + + void TimeToCP56Time2a(FILETIME *ft, unsigned char *data); + void TimeToCP56Time2a(SYSTEMTIME *st, unsigned char *data); + + void CP56Time2aToTime(unsigned char *data, FILETIME *ft); + void CP56Time2aToTime(unsigned char *data, SYSTEMTIME *st); +}; +#pragma pack (pop) +#endif // end __HT_TYPE_H + diff --git a/include/HTConfig.h b/include/HTConfig.h new file mode 100644 index 0000000..57d42f7 --- /dev/null +++ b/include/HTConfig.h @@ -0,0 +1,179 @@ +/**************************************************************************** +** File name : HTConfig.h +** Description : config parameter +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_CONFIG_H +#define __HT_CONFIG_H +#include +#include +#include +#include +// 配置文件路径 +#ifdef _WIN32 + static const char HT_CONFIG_FILE[] = "../etc/ht_service.conf"; +#else + static const char HT_CONFIG_FILE[] = "../etc/ht_service.conf" ; +#endif + +class TConfig +{ +public: + TConfig(); + virtual ~TConfig(); + + static TConfig *getInstance(); + + // 读取配置文件参数 + bool getIniConfig(); + void showConfig(); + + // 设置本地服务器IP + void setLocalAddr(char *pszAddr); + + // 获取本地服务器IP + char *getLocalAddr(); + + // 设置本地服务器端口 + void setLocalPort(unsigned short iPort); + + // 获取本地服务器端口 + unsigned short getLocalPort(); + + + // 设置远程服务器IP + void setRemoteAddr(char *pszAddr); + + // 获取远程服务器IP + char *getRemoteAddr(); + + // 设置远程服务器端口 + void setRemotePort(unsigned short iPort); + + // 获取远程服务器端口 + unsigned short getRemotePort(); + + + void setRecvThreadNumber(unsigned int n) ; // 接收线程数 + void setParseThreadNumber(unsigned int n) ; // 解析104线程数 + void setOprationThreadNumber(unsigned int n) ; // 入库线程数 + void setResponeThreadNumber(unsigned int n) ; // 应答线程数 + + unsigned int getRecvThreadNumber() ; // 接收线程数 + unsigned int getParseThreadNumber() ; // 解析104线程数 + unsigned int getOprationThreadNumber() ; // 入库线程数 + unsigned int getResponeThreadNumber() ; // 应答线程数 + + + // 配置数据库配置参数接口 + unsigned int getdbPort() ; + unsigned int getdbMaxConnect(); + unsigned int getdbMinConnect() ; + char *getdbHostIP() ; + char *getdbName() ; + char *getdbUserName() ; + char *getdbUserPass() ; + + void setdbPort(unsigned int port); + void setdbMaxConnect(unsigned int max); + void setdbMinConnect(unsigned int min); + void setdbHostIP(char *pszDBHostIP); + void setdbName(char *pszDBName); + void setdbUserName(char *pszDBUserName); + void setdbUserPass(char *pszDBUserPass); + + + // socket 相关属性参数配置 + void setFdLimit(unsigned int iCount); + unsigned int getFdLimit(); + + void setTimeout0(unsigned int t); + void setTimeout1(unsigned int t); + void setTimeout2(unsigned int t); + void setTimeout3(unsigned int t); + unsigned int getTimeout0(); + unsigned int getTimeout1(); + unsigned int getTimeout2(); + unsigned int getTimeout3(); + + void setK(unsigned int k); + unsigned int getK(); + + void setW(unsigned int w); + unsigned int getW(); + + void setLogDebug(char yes); + void setLogError(char yes); + void setLogWarning(char yes); + void setLogPack(char yes); + void setLogConsole(char yes); + void setLogMessage(char yes); + char isLogDebug(void); + char isLogError(void); + char isLogWarning(void); + char isLogPack(void); + char isLogConsole(void); + char isLogMessage(void); + + // version infomation functios + void setServerVersion(char *pver) ; + char *getServerVersion(); + + void setMonitor(bool bMonitor); + bool getMonitor(); + // 读取配置文件函数 + int iniGetString(const char *pszSection, const char *pszEntry, char *pszRetBuf, unsigned int uiBufLen); + +private: + static TConfig *p_TConfig; + + + bool b_monitor_enable ; // 监控标志 true:启用 false: 不启用 + + // server version infomations + char m_version[32+1]; // format 2013.00.100 + + // database config parameter + char m_dbHostIP[16]; + char m_dbName[16]; + char m_dbUserName[16]; + char m_dbUserPass[16]; + + unsigned int m_dbMaxConnect; + unsigned int m_dbMinConnect; + unsigned int m_dbPort; + + char m_local_addr[16]; + unsigned m_local_port; + char m_remote_addr[16] ; + unsigned int m_remote_port ; + // socket config + unsigned int m_fd_limit; + unsigned int t0,t1,t2,t3,uK,uW; + + + unsigned int m_recv_num; + unsigned int m_parse_num; + unsigned int m_opration_num; + unsigned int m_respone_num; + + + // logger + char m_logdebug; // debug logger + char m_logwarning; // warning logger + char m_logerror; // error logger + char m_logpack; // package print logger + char m_logconsole; // console print + char m_logmessage; // message print +}; + +#endif + + diff --git a/include/HTConst.h b/include/HTConst.h new file mode 100644 index 0000000..58a01c3 --- /dev/null +++ b/include/HTConst.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** File name : HTConst.h +** Description : define const +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_CONST_H +#define __HT_CONST_H + +// ASCI字符数字定义 +#define KEY0 '0' +#define KEY1 '1' +#define KEY2 '2' +#define KEY3 '3' +#define KEY4 '4' +#define KEY5 '5' +#define KEY6 '6' +#define KEY7 '7' +#define KEY8 '8' +#define KEY9 '9' + +// 数字定义 +#define KEY_0 0x00 +#define KEY_1 0x01 +#define KEY_2 0x02 +#define KEY_3 0x03 +#define KEY_4 0x04 +#define KEY_9 0x09 + +#ifndef MAX_PATH +#define MAX_PATH 260 +#endif + +// use buffer size define +#define DEF_BUFFER_32 32 +#define DEF_BUFFER_128 128 +#define DEF_BUFFER_256 256 +#define DEF_BUFFER_1K 1024 +#define DEF_BUFFER_2K 2048 +#define DEF_BUFFER_4K 4096 +#define DEF_BUFFER_8K 8192 +#define DEF_BUFFER_512K 1024*512 + +#define MAX_SLEEP_EMPTY 5 // ms + +#define CHANNEL_DOWN 1 // MEC下行通道UDP +#define CHANNEL_UP 0 // MEC上行通道UDP + +#define MAX_FLT_EXTERN 24 // 最大内部报文扩展项个数 + +// 809平台间报文类型 +#define PALT_PKG_QUERY 0 // 平台查岗 +#define PALT_PKG_MESG 1 // 平台间报文消息 + +// 来源 +#define MSG_SOURCE_MARGE 0 // 上级监管平台 +#define MSG_SOURCE_LOACL 1 // 企业平台 + +#define HT_INVALID_VALUE 0x7FFFFFFF // 无效值 + +#endif // end __HT_CONST_H + diff --git a/include/HTDataStruct.h b/include/HTDataStruct.h new file mode 100644 index 0000000..78c557f --- /dev/null +++ b/include/HTDataStruct.h @@ -0,0 +1,379 @@ +/**************************************************************************** +** File name : HTDataStruct.h +** Description : define data struct +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_DATA_STRUCT_H +#define __HT_DATA_STRUCT_H + +#pragma pack (push ,1) + +#define DEF_EQM_CODE_SIZE 32+1 // 设备编码eqm_code最大长度 +//#define _SITE_ID_TYPE_INT // 站点ID数据类型定义 + +#ifdef _SITE_ID_TYPE_INT + typedef unsigned int htype; +#else + typedef unsigned char* htype; +#endif + +typedef struct { + unsigned char status; // 链接状态 0:非正常 1:正常 + int udp_fd; // 与MEC的上行通道套接字fd + tint64 online_time; // 登陆时间 + tint64 last_time; // 离线/退出时间 + struct sockaddr_in staddr; // 对方地址 +}ST_UDP_CONN; + +// 链路管理数据结构 +typedef struct { + bool isConnect; // true: connected false: not connected + int listenid; // listen handle + int sockid; // socket connect handle + time_t last_time; // last send/recv time + + bool is_yk_ack ; // 是否收到遥控信号 + bool b_Signal; // 遥信量变化 false: 无变化 true:有变化,则需记录一条记录 + time_t stime; // 遥信信号变化时间,否则为0 + time_t etime; // 结束时间 + time_t lastTime; // 最近一次入库时间 + time_t last_yx_time; + time_t last_yc_time; + unsigned long m_gis_fault_count; // gis故障次数 + //unsigned long m_gis_count; // gis开合次数 + bool m_gis_change; // 断路器断开时,记录入库 + char m_iec_warn_time[24]; // IEC子站异常时间 + + unsigned short usSendNo; // 发送序号 + unsigned short usRecvNo; // 接收序号 + int TxCounter; + int RxCounter; + int LastAckTx; + int LastAckRx; + int t0; // time-out of connection establishment (reconnection) TCP连接建立的超时时间 + int t1; // time-out of send or test APDUs (wait ack). RTU(服务器)端启动U格式测试过程后等待U格式测试应答的超时时间 + int t2; // time-out for ack in case of no data messages (T2 < T1). S格式的超时时间 + int t3; // time-out for sending TESFR in case of long idle state. 没有实际的数据交换时,任何一端启动U格式测试过程的最大间隔时间 + int k; // maximum difference N(R) and N(S) + int w; // lastest ack after receiving W I-Format message. + unsigned short usISUType; // 0,2=I ; 1=S ; 3=U + //int timer_Connect; + int timer_t0; // T0 param + + int timer_Confirm; // associated of T1 param + int timer_t1; // T1 param + + int timer_S_Ack; // associated of T2 param + time_t timer_t2; // T2 param + bool timer_S_Ackflag; + + time_t timer_t3; // T3 param + bool timer_U_Testflag; + time_t time_action; // 总召间隔请求时间 +}ST_IEC104_CTRL; + + + +typedef struct { + unsigned char start; // 起始字节 + unsigned char len; // 帧长度 + unsigned char cntl1; // 控制域1-4 + unsigned char cntl2; + unsigned char cntl3; + unsigned char cntl4; +}ST_APCI; + +typedef struct { // 数据单元标识 + unsigned char type; // 类型标识 + unsigned char qual; // 可变结构限定词 + unsigned char tx_cause1; // 传送原因(2字节)根据主站配置 + unsigned char tx_cause2; + unsigned char commom_asdu1; // 公共地址(2字节)根据主站配置 + unsigned char commom_asdu2; +}ST_ASDU_HEADER; + +typedef struct { + ST_ASDU_HEADER header; // 数据单元标识 + unsigned char data[243]; // 信息体 +}ST_ASDU; + + +typedef struct { + ST_APCI apci; + ST_ASDU asdu; +}ST_IEC_APDU; + +typedef struct +{ + int iLength ; // 接收长度 + unsigned short usISUType; // 0,2=I ; 1=S ; 3=U + unsigned short usSendNo; // 发送序号 + unsigned short usRecvNo; // 接收序号 + unsigned char *pszBuff; // 接收数据 +}ST_RECVPKG ; +/* +typedef struct { + unsigned short usISUType ; // 0,2=I ; 1=S ; 3=U + unsigned short usLen ; // data length + + unsigned short usSendNo; // 发送序号 + unsigned short usRecvNo; // 接收序号 + unsigned int LastAckSendNo; // last send number + unsigned int LastAckRecvNo; // last recv number + + ST_ASDU_HEADER stAsduHead; // ASDU Header + unsigned int uiInfoAddr; // info body addr,3(byte) + unsigned int uiLastAckTx; // last respone send number + + +}ST_IEC104_INFO; +*/ +// single point information w/quality +struct SIQ104{ + unsigned char spi : 1, // off=0 / on=1 + rs1 : 1, // reserve + rs2 : 1, // reserve + rs3 : 1, // reserve + bl : 1, // not blocked=0 / blocked=1 + sb : 1, // not substituted=0 / substituted=1 + nt : 1, // topical=0 / not topical=1 + iv : 1; // valid=0 / not valid=1 +}; + +// quality descriptor +struct QDS104{ + unsigned char ov : 1, // no overflow=0 / overflow=1 + rs1 : 1, // reserve + rs2 : 1, // reserve + rs3 : 1, // reserve + bl : 1, // not blocked=0 / blocked=1 + sb : 1, // not substituted=0 / substituted=1 + nt : 1, // topical=0 / not topical=1 + iv : 1; // valid=0 / not valid=1 +}; + +// single point value +struct SP104{ + unsigned char addr0; + unsigned char addr1; + unsigned char addr2; + struct SIQ104 siq; +}; + +// single point value w/time tag CP56Time2a +struct SP104_T{ + unsigned char addr0; + unsigned char addr1; + unsigned char addr2; + struct SIQ104 siq; + unsigned char time[7]; +}; + +// short floating point value +struct SFP104{ + unsigned char addr0; + unsigned char addr1; + unsigned char addr2; + //float value; + unsigned char val[4]; + struct QDS104 qds; +}; +// short floating point value +struct SFP104V{ + unsigned char val[4]; + struct QDS104 qds; +}; + +// short point value +struct SH104{ + unsigned char addr0; + unsigned char addr1; + unsigned char addr2; + unsigned char val[2]; + struct QDS104 qds; +}; +// short point value +struct SHP104{ + unsigned char val[2]; + struct QDS104 qds; +}; + +// short floating point value w/time tag CP56Time2a +struct SFP104_T{ + unsigned char addr0; + unsigned char addr1; + unsigned char addr2; + unsigned char val[4]; + struct QDS104 qds; + unsigned char time[7]; +}; + +// GIS负荷计算表结构定义iec_break_param +typedef struct { + unsigned char site_id[DEF_EQM_CODE_SIZE]; // 站点ID + unsigned char eqm_code[DEF_EQM_CODE_SIZE]; // 设备编码 + unsigned char system_code[DEF_EQM_CODE_SIZE]; // 设备编码 + unsigned char wstate; // 工作状态 1:发电 2:抽水 3:空闲 + unsigned char is_close; // 断开状态 0:分 1:合 + unsigned char is_fault; // 是否故障 1:故障 0:正常 + float faild_rate; // 发生故障率% + time_t d_time; // 发生时间 + double abort_current; // 断开电流(A) + double abort_voltage; // 断开电压(V) +}ST_IEC_GISBREAK_TABLE; + + +// 变压器负荷计算表结构定义iec_bydwork_param +typedef struct { + unsigned char site_id[DEF_EQM_CODE_SIZE]; // 站点ID + unsigned char eqm_code[DEF_EQM_CODE_SIZE]; // 设备编码 + unsigned char system_code[DEF_EQM_CODE_SIZE]; // 设备编码 + unsigned char state; // 状态类型: 1-发电状态 2:抽水状态 3:空闲状态 + unsigned char is_fault; // 主变是否故障 1:故障 0:正常 + time_t start_time; // 发电/抽水开始时间 + time_t stop_time; // 发电/抽水结束时间 + time_t real_time; // 发生时间 + double voltage; // 高/低压出口电压(kV) + double current; // 高/低压出口电流(A) +}ST_IEC_BYQWORK_TABLE; + +// 变压器运行工况表结构定义transformer_read_table +typedef struct { + unsigned char site_id[DEF_EQM_CODE_SIZE]; // 站点ID + unsigned char eqm_code[DEF_EQM_CODE_SIZE]; // 设备编码 + unsigned char system_code[DEF_EQM_CODE_SIZE]; // 设备编码 + unsigned char wstate; // 工作状态:1-发电状态 2:抽水状态 3:空闲状态 + time_t chkTime; // 监测时间 +#if 0 + double dcurJkyl; // 冷却水进口压力值 + double dcurCkyl; // 冷却水出口压力值 + double dCoolWaterTempEntry; // 冷却水进口温度 + double dCoolWaterTempOuter; // 冷却水出口温度 + + //2020-05-23 add + double dOilPressEntry; // 变压器油进口油压力(MPa) + double dOilPressOuter; // 变压器油出口油压力(MPa) + double dOilTempEntry; // 变压器油进口温度 + double dOilTempOuter; // 变压器油出口温度 + + double dOilTemperature; //主变本体油温点位 + double dOilPosition; //主变本体油位点位 + double dOilTopTemp; //主变顶层油温点位 + double dOilPillowLevel; //主变油枕油位点位 + double dWindingTemp; //主变绕组温度点位 +#else + char dcurJkyl[16]; // 冷却水进口压力值 + char dcurCkyl[16]; // 冷却水出口压力值 + char dCoolWaterTempEntry[16]; // 冷却水进口温度 + char dCoolWaterTempOuter[16]; // 冷却水出口温度 + + char dOilPressEntry[16]; // 变压器油进口油压力(MPa) + char dOilPressOuter[16]; // 变压器油出口油压力(MPa) + char dOilTempEntry[16]; // 变压器油进口温度 + char dOilTempOuter[16]; // 变压器油出口温度 + + char dOilTemperature[16]; //主变本体油温点位 + char dOilPosition[16]; //主变本体油位点位 + char dOilTopTemp[16]; //主变顶层油温点位 + char dOilPillowLevel[16]; //主变油枕油位点位 + char dWindingTemp[16]; //主变绕组温度点位 +#endif +}ST_IEC_BYQREAD_TABLE; + +// 入库队列 +typedef struct +{ + unsigned char ctype; // 类型:1-运行工况 2:断路器数据 3:变压器数据 + unsigned int iLength; // 数据长度 + unsigned char *pData; // 数据ST_MASRTE_PARAM |ST_BREAKER_PARAM|ST_WORK_PARAM +}ST_DB_DATA; + +// 变压器工作数据,通过104获取。 +typedef struct { + unsigned char stype; // 状态类型: 1-发电状态 2:抽水状态 3:空闲状态 + time_t start_time; // 发电/抽水开始时间 + time_t stop_time; // 发电/抽水结束时间 + double voltage; // 高/低压出口电压(v) + double current; // 高/低压出口电流(A) + double dcurYWei; // 最近油位值 + double dcurYWen; // 最近油温值 + double dcurJkyl; // 最近冷却水进口压力值 + double dcurCkyl; // 最近冷却水出口压力值 +}ST_IEC104_BYQ_DATA; + + +// 变压器设备对应关系、阈值缓存记录 +//typedef struct { +//#ifdef _SITE_ID_TYPE_INT +// unsigned int SiteID; // 站点ID +//#else +// unsigned char SiteID[DEF_EQM_CODE_SIZE]; // 站点ID +//#endif +// unsigned char szSiteCode[DEF_EQM_CODE_SIZE]; // 物理站点唯一编码 +// unsigned char szEqmCode[DEF_EQM_CODE_SIZE]; // 系统设备唯一编码 +// unsigned char szSersorID[20]; // sersorid唯一编码 +// double dYWei; // 油位阈值 +// double dYWen; // 油温阈值 +// double dJkyl; // 冷却水进口压力阈值 +// double dCkyl; // 冷却水出口压力阈值 +// ST_IEC104_BYQ_DATA stLastData; // 变压器最近一次104上传的数据 +//}ST_BYQ_CACHE; + + +// 断路器104数据结构 +//typedef struct { +// unsigned char is_fault; // 是否故障 1:否 2:是 +// time_t record_date; // 发生时间 +// double voltage; // 断开电压(V) +// double current; // 断开电流(A) +// double failed_rate; // %电流故障百分比% +//}ST_IEC104_GIS_DATA; + +// GIS设备对应关系、阈值缓存记录 +//typedef struct { +//#ifdef _SITE_ID_TYPE_INT +// unsigned int SiteID; // 站点ID +//#else +// unsigned char SiteID[DEF_EQM_CODE_SIZE]; // 站点ID +//#endif +// unsigned char szEqmCode[DEF_EQM_CODE_SIZE]; // 设备唯一编码 +// ST_IEC104_GIS_DATA stLastData; // 断路器最近一次104上传的数据 +//}ST_GIS_IEC104_DATA; + +// GIS设备外挂对应关系、阈值缓存记录 +//typedef struct { +//#ifdef _SITE_ID_TYPE_INT +// unsigned int SiteID; // 站点ID +//#else +// unsigned char SiteID[DEF_EQM_CODE_SIZE]; // 站点ID +//#endif +// unsigned char szSersorID[20]; // sersorid唯一编码 +// unsigned char szEqmCodeID[18]; // 设备唯一编码 +// unsigned char name_des[128]; // 设备名称,描述 +// double dNum ; // GIS放电电流(mA) +//}ST_GIS_CACHE; + +// BLQ设备对应关系、阈值缓存记录 +//typedef struct { +//#ifdef _SITE_ID_TYPE_INT +// unsigned int SiteID; // 站点ID +//#else +// unsigned char SiteID[DEF_EQM_CODE_SIZE]; // 站点ID +//#endif +// unsigned char szSersorID[20]; // sersorid唯一编码 +// unsigned char szEqmCodeID[18]; // 设备唯一编码 +// unsigned char name_des[128]; // 设备名称,描述 +// double dMaxDL; // 避雷器放电电流图片识别阈值 +//}ST_BLQ_CACHE; + + +#pragma pack (pop) +#endif // end + diff --git a/include/HTDatabase.h b/include/HTDatabase.h new file mode 100644 index 0000000..1cbc49d --- /dev/null +++ b/include/HTDatabase.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** File name : HTDatabase.h +** Description : define database api +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_DATABASE_H +#define __HT_DATABASE_H + +#include "HTPublic.h" +#include "HTDataStruct.h" +#include "mysql.h" + +#ifdef _WIN32 +//#pragma comment(lib,"ociliba.lib") +#pragma comment(lib,"libmysql.lib") +#endif + +typedef std::list CONNECTION_HANDLE_LIST; +typedef std::list::iterator ITER_CONNECTION_HANDLE_LIST; + +#define CONNECTION_NUM 10 //同时打开的连接数 + +class CDBMySQL +{ +public: + CDBMySQL(); + CDBMySQL(const char *host, const char *user, const char *password, const char *db, unsigned int port=3306); + virtual ~CDBMySQL(); + +public: + + bool dbConnectPool(); //连接数据库 + void dbFreeConnectPool() ; //释放链接资源 + + bool dbAutoCommit(MYSQL *pMysql, bool bStart); // 开始事务处理 + bool dbCommit(MYSQL *pMysql); + bool InsertRecordBitch(const char pszSql[][256], int count); + bool AddInsertRecord(MYSQL *pHandle, const char *szSql); + + MYSQL_RES* SelectRecord(const char *szSql); //选择记录,返回结果集 + bool SelectDB(const char *szDB); //选择数据库 + bool UpdateRecord(const char *szSql); //更新记录 + bool InsertRecord(const char *szSql); //插入记录 + bool DelRecord(const char *szSql); //删除记录 + + bool IsEnd(MYSQL_RES *myquery); //是否最后 + void SeekData(MYSQL_RES *myquery, int offset); //查找指定数据 + void FreeRecord(MYSQL_RES *myquery); //释放结果集 + unsigned int GetFieldNum(MYSQL_RES *myquery); //得到字段数 + MYSQL_ROW GetRecord(MYSQL_RES *myquery); //得到结果(一个记录) + my_ulonglong GetRowNum(MYSQL_RES *myquery); //得到记录数 + char* getLastError(MYSQL* pMySql); //输出错误信息 + + char* GetState(); //服务器状态 + char* GetServerInfo(); //服务器信息 + int GetProtocolInfo(); //协议信息 + char* GetHostInfo(); //主机信息 + char* GetClientInfo(); //客户机信息 + char* GetFieldName(MYSQL_RES *myquery, int FieldNum); //字段名 + + bool LockTable(const char *TableName, const char *Priority); //对特定表加锁 + bool UnlockTable(); //解锁 + bool SetCharset(); + //int CreateDB(char *db); //创建数据库,返回错误信息 + //int DropDB(char *db); //删除数据库,返回错误信息 + + MYSQL* GetIdleMySql(); //提取一个空闲句柄供使用 + void SetIdleMysql(MYSQL* pMySql); //从使用队列中释放一个使用完毕的句柄,插入到空闲队列 + static CDBMySQL* Instance(); + +public: + //MYSQL m_mysql; //数据库连接句柄 + MYSQL_ROW m_row; //记录集(单行) + MYSQL_FIELD *m_field; //字段信息(结构体) + + //创建两个队列 + CONNECTION_HANDLE_LIST m_lsBusyList; //正在使用的连接句柄 + CONNECTION_HANDLE_LIST m_lsIdleList; //未使用的连接句柄 + + mutex m_csList; + +private: + static CDBMySQL* p_dbHandle ; + + char m_host[20]; //主机 + char m_user[20]; //用户名 + char m_password[20]; //密码 + char m_db[20]; //数据库名 + unsigned int m_port; //端口 + unsigned int m_min; // 链接数 +}; + +#endif // __HT_DATABASE_H diff --git a/include/HTError.h b/include/HTError.h new file mode 100644 index 0000000..d6fb84e --- /dev/null +++ b/include/HTError.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** File name : HTError.h +** Description : define error code +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_ERROR_H +#define __HT_ERROR_H + +#define RET_OK 0 +#define RET_FAIL -1 +#define RET_IPPORT_INVALID -2 // IP地址或端口无效 +#define RET_UDP_BIND_PORT -3 // UDP绑定端口错误 +#define RET_LENGTH_INVALID -4 // 数据长度无效 +#define RET_VALUE_INVALID -5 // 域值无效 +#define RET_TYPE_INVALID -6 // 业务类型无效 +#define RET_CALLOC_FAIL -7 // 申请内存失败 +#define RET_SUB_ID_INVALID -8 // 域ID标识无效/不支持的ID标识码 +#define RET_CALL_OCI_FAILED -9 // OCI调用失败 +#define RET_NOT_FOUND_RECORD -10 // 无原请求业务流水 +#define RET_ERROR_AUTHID -11 // 无效接入码 +#define RET_UDP_STATUS_EXP -12 // UDP链接状态异常 +#define RET_NOT_EXTERN_PACK -13 // 无扩展报文 +#define RET_NOT_FOUND_ACCESSID -14 // 没有检索到接入码 +#define RET_TERM_NOT_ONLINE -15 // 终端不在线 +#define RET_SUB_COMMAND_INVALID -16 // 采集数据的子命令无效 +#define RET_MAJOR_CONN_ERR -17 // TCP主链路状态错误 +#define RET_NOT_FILE_EXIST -18 // 文件不存在 +#define RET_NOT_DATA -19 // 采集行驶记录无数据 +#define RET_SET_ERROR_PIC -20 // 插入拍照下发指令记录失败 +#define RET_SERVER_ID_ERR -21 // 连接服务器名称无效 +#define RET_JT809_VERSION -22 // 数据库配置了无效的JT809协议版本号 +#define RET_JT808_VERSION -23 // 808内部报文协议类型无效 +#define RET_JT809_CRC_ERROR -24 // CRC16校验错误 +#define RET_LINK_CHECK_ERROR -25 // 链路校验码错误 +#define RET_RECORD_ORG_ID_NULL -26 // 记录仪ID或企业ID为空 +#endif // end __HT_ERROR_H + diff --git a/include/HTGlobal.h b/include/HTGlobal.h new file mode 100644 index 0000000..08dabba --- /dev/null +++ b/include/HTGlobal.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** File name : HTGolbal.h +** Description : global variable define +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#pragma warning (disable:4786) +#ifndef __HT_GLOBAL_H +#define __HT_GLOBAL_H + +#include "HTType.h" +#include "HTConst.h" +#include "HTMutex.h" +#include "HTPublic.h" +#include "HTLogger.h" +#include "HTConfig.h" +#include "HTDatabase.h" +#include "HTDataStruct.h" +#include "HTHP104Table.h" +#include "HTMemCacheData.h" +#include "HTInitUtils.h" +#include "HTCP56Time.h" +#include "HTError.h" +#include "HTTcpSocket.h" +#include "HTIEC104.h" +#include "HTThread.h" +#include "HTImageBusi.h" +#include "HTOpencvImg.h" +#include "HTTestOpencv.h" +#include "HTUnit.h" +#include "HTVersion.h" + +#include +#include +#include +#include + +#define _HT_OPENCV_APP // 图片分析处理程序 +#define _HT_IEC104_APP // IEC104通讯程序 +#define _DEF_HMF_VOLTAGE // 黑麋峰高压侧电流计算 +#define _DEF_DB_CHANGERATE // 启用偏差率入库功能,否则以设定的间隔时间入库 + + +using namespace std; +//#define _CRT_SECURE_NO_WARNINGS 1 + + +extern int g_Running; +extern TConfig g_TConfig; +extern TTcpSocket g_Tcp; + +extern ST_IEC104_CTRL g_IecCtrl; // socket linker info and status +extern mutex g_IecCtrl_mutex; // socket linker on mutex + +extern map g_map_work; // 主变工作状态缓存 +extern mutex g_map_work_mutex; // 主变工作状态缓存队列锁 + +//extern map g_map_byq; // 变压器缓存数据 +extern map g_map_thres_byq; // 变压器缓存数据 +extern mutex g_map_byq_mutex; // 变压器缓存数据信息队列锁 + +//extern map g_map_gis; // GIS缓存数据 +//extern mutex g_map_gis_mutex; // GIS缓存数据信息队列锁 + +extern multimap g_map_relation; // 主设备与外挂设备关系 +extern mutex g_map_relation_mutex; // GIS缓存数据信息队列锁 + +//extern map g_map_gis_104; // GIS最近一次104上传数据缓存 +//extern mutex g_map_gis_104_mutex; + +//extern map g_map_blq; // BLQ缓存数据 +//extern mutex g_map_blq_mutex; // BLQ缓存数据信息队列锁 + +extern map g_map_iec; // 104报文解析缓存数据 +extern mutex g_map_iec_mutex; // 104报文解析缓存数据信息队列锁 + +extern map g_map_sadr; // 点表匹配关系 +extern mutex g_map_sadr_mutex; + +extern map g_map_img_thres; // 图片识别阈值 +extern mutex g_map_img_thres_mutex; + +//extern list g_list_monitor; // 监控消息数据队列 +//extern mutex g_list_monitor_mutex; +extern map g_map_dev_time_stat; +extern mutex g_map_dev_time_stat_mutex; + +extern map g_map_gis_state; // 断路器状态位与电流电压关系匹配表 +extern mutex g_map_gis_state_mutex; + +extern int g_seqno; // 与MEC之间交换的流水号 +extern mutex g_seq_mutex; // 流水号 + +extern pthread_t thread_handle_monitor; // 监控线程句柄 + +extern pthread_t thread_handle_parse; // 104报文解析线程 +//extern pthread_t thread_handle_setdb; // 入库线程 +//extern pthread_t thread_handle_getdata; // 数据提取线程 +extern pthread_t thread_handle_timer; // 应答线程 + +extern pthread_t thread_handle_client; // 客户端链接线程 +extern pthread_t thread_handle_warning; // 报警处理及入库线程句柄 +extern pthread_t thread_handle_origin; // 原始数据如何线程句柄 +extern pthread_t thread_handle_pingce; // IEC104评测数据入库线程句柄 +extern pthread_t thread_handle_gishold; // 断路器断开数据入库线程句柄 + +extern pthread_t thread_handle_active; // 心跳线程 +extern pthread_t thread_handle_linkmgr; // 链路管理线程 +extern pthread_t thread_handle_cache; // 内存同步线程句柄 +extern pthread_t thread_handle_opecvimg; // 图片识别线程句柄 + + +#endif // end __HT_GLOBAL_H + diff --git a/include/HTHP104Table.h b/include/HTHP104Table.h new file mode 100644 index 0000000..710df95 --- /dev/null +++ b/include/HTHP104Table.h @@ -0,0 +1,144 @@ +/**************************************************************************** +** File name : HTHP104Table.h +** Description : define data struct +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HP104_TABLE +#define __HP104_TABLE + +static const char IEC_CONFIMG_FILE[] = "../etc/ht_iec104.conf"; + +#pragma pack (push ,1) + +// 一个单元的信息体 +typedef struct { + int count; // 索引,0开始 + unsigned int objaddr; // 信息对象地址(3) + unsigned int objval; // 值域 +}ST_OBJVAL; + +// 变压器设备唯一编码 +typedef struct _BYQ_EQM_CODE { + unsigned char szEqmCode[DEF_EQM_CODE_SIZE]; // 设备编码,16位 + unsigned int uiHighVoltage; //发电状态: 主变高压侧电压点位 + unsigned int uiHighCurrent; //发电状态: 主变高压侧电流点位 + unsigned int uiLowVoltage; //抽水、空闲状态: 主变低压侧电压点位 + unsigned int uiLowCurrent; //抽水、空闲状态: 主变低压侧电流点位 + + unsigned int uiCoolWaterPressEntry; //主变冷却水进口压力点位 + unsigned int uiCoolWaterPressOuter; //主变冷却水出口压力点位 + unsigned int uiCoolWaterTempEntry; //主变冷却水进口温度点位 + unsigned int uiCoolWaterTempOuter; //主变冷却水出口温度点位 + + unsigned int uiOilPressEntry; //主变油进口压力点位 + unsigned int uiOilPressOuter; //主变油出口压力点位 + unsigned int uiOilTempEntry; //主变油进口温度点位 + unsigned int uiOilTempOuter; //主变油出口温度点位 + + unsigned int uiOilTemperature; //主变本体油温点位 + unsigned int uiOilPosition; //主变本体油位点位 + unsigned int uiOilTopTemp; //主变顶层油温点位 + unsigned int uiOilPillowLevel; //主变油枕油位点位 + unsigned int uiWindingTemp; //主变绕组温度点位 + + time_t stime; + time_t etime; +}ST_BYQ_EQM_CODE; + +// 设备工作时间及状态记录 +typedef struct _DEVICE_TIME_STAT { + unsigned char sys_code[DEF_EQM_CODE_SIZE]; // sys_code,主设备ID,对应busi_site_tree.system_code + unsigned char desct[DEF_BUFFER_256]; // sys_code,主设备ID,对应busi_site_tree.system_code + time_t usTime; // 最近一次记录时间 + unsigned char wstate; // 工作状态:1-发电状态 2:抽水状态 3:空闲状态 +}ST_DEVICE_TIME_STAT; + +// 断路器设备唯一编码 +typedef struct _BREAK_EQM_CODE { + unsigned char szEqmCodeA[DEF_EQM_CODE_SIZE]; // 设备编码,16位 + unsigned char szEqmCodeB[DEF_EQM_CODE_SIZE]; // 设备编码,16位 + unsigned char szEqmCodeC[DEF_EQM_CODE_SIZE]; // 设备编码,16位 + unsigned int uiStateSadr; //断开状态点位地址 对应值含义=1:合 0:开 + unsigned int uiAbortVoltage; //断开电压点位 + unsigned int uiAbortCurrent; //断开电流点位 +}ST_BREAK_EQM_CODE; + + +// IEC104协议基础配置信息 +typedef struct _IEC104_CONF +{ + unsigned int save_internal; // 104时间保存间隔时间(s) + unsigned int iec_byq_count; // 变压器数量 + unsigned int iec_break_count; // 断路器数量 + unsigned char site_id[DEF_EQM_CODE_SIZE]; // 站点ID + unsigned short iec_global_addr; // 公共地址 + unsigned int yx_start_addr; // YX 0x0001- 遥信起始地址, 十进制数 + unsigned int yx_stop_addr; // YX 0x1000- 遥信结束地址, 十进制数 + unsigned int jb_start_addr; // JB 0x1001- 继电保护起始地址, 十进制数 + unsigned int jb_stop_addr; // JB 0x4000- 继电保护结束地址, 十进制数 + unsigned int yc_start_addr; // YC 0x4001- 遥测起始地址, 十进制数 + unsigned int yc_stop_addr; // YC 0x5000- 遥测起始地址, 十进制数 + ST_BYQ_EQM_CODE *pstByqCode; // 变压器设备系统唯一编码 + ST_BREAK_EQM_CODE *pstBrkCode; // 断路器设备系统唯一编码 +}ST_IEC104_CONF; + + +// 点表地址匹配关系 +typedef struct { + unsigned int group; // 组号 + unsigned int btype; // 电流、电压...... + unsigned int sadr; // 相关联的其他sadr列表 +}ST_MATCH_LIST; +typedef struct{ + //unsigned char eqm_code[DEF_EQM_CODE_SIZE]; // 设备编码 + unsigned char eqm_type; // 1:主变 2:GIS 3:测温 4:避雷器 + unsigned int count; // *psadr的数量 + ST_MATCH_LIST *psadr; //ST_MATCH_LIST[] +}ST_SADR_MATCH; + +// 解析104报文的值缓存区、点表配置信息,表iec_point_conf +typedef struct _IECPOINT_TABLE +{ + unsigned char stype; // 地址类型 1:遥信 2:遥测 + unsigned char cval; // 遥信值 + unsigned int sno; // 起始地址偏移量 + unsigned int sadr; // 信息体地址,map.key + double fval; // 遥测值 + unsigned char site_id[DEF_EQM_CODE_SIZE]; // 站点ID + unsigned char eqm_code[DEF_EQM_CODE_SIZE]; // eqm_code,主设备ID,对应busi_site_tree.id + unsigned char sys_code[DEF_EQM_CODE_SIZE]; // sys_code,主设备ID,对应busi_site_tree.system_code + unsigned char fieldname[DEF_EQM_CODE_SIZE * 2]; // 阈值字段名称,transformer_runing_status_threshold表字段 + unsigned char isget; // 评测字段提取标志,YX:{1=总开关状态 2=发电状态 3=抽水状态 4=事故状态} YC:{1=提取 0:不提取} + unsigned short unit; // 104协议数据单位 + unsigned short sysunit; // 系统固定的字段单位,参与评测数据 + double devrate; // 偏差率,当值在±之间时,保存数据 + unsigned char eqm_type; // 设备类型 1:主变 2:GIS 3:测温 4:避雷器 + unsigned char warnFlag; // 告警判断, =1:>预警值时告警 =2:<预警值时告警(压力) 油位如何告警(最低/高)? + time_t dtime; // 告警时间 + unsigned char wstate; // 工作状态:1-发电状态 2:抽水状态 3:空闲状态 + unsigned char bfault; // 主变事故状态:0-正常 1-事故状态 + unsigned char poidesc[DEF_BUFFER_256]; // 点表字段描述 +}ST_IECPOINT_TABLE; + +/* isget: +1:冷却水进口压力 2:冷却水出口压力 3:冷却水进口温度 4:冷却水出口温度 +5:油泵进口油温 6:油泵出口油温 7:高压侧上层油温 8:主变绕组温度 +9:主变本体油位 10:主变油枕油位 11:主变高/低压出口电压 12:主变高/低压出口电流 +13:机组出口相电压 14:机组出口相电流 15:GIS电缆电压 16:GIS电缆电流 17:机组电气事故 +18:变压器运行负荷 19: GIS负荷 + +// unit: +1:kV(千伏) 2:V(伏) 3:kA(千安) 4:A(安) 5:mA(毫安) 6:℃(度) 7:Pa(帕) 8:KPa(千帕) 9:MPa(兆帕) 10:pF(皮法) +11:pC(皮库仑) 12:dB(分贝) 13:μL(微升) 14:L(升) 15:m/s(米/秒) 16:rpm&r/min(转/分钟) +*/ + +#pragma pack (pop) +#endif // end + diff --git a/include/HTIEC104.h b/include/HTIEC104.h new file mode 100644 index 0000000..9192f4c --- /dev/null +++ b/include/HTIEC104.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** File name : HTIEC104.h +** Description : define 104 struct +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_IEC104_H +#define __HT_IEC104_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define CMD_START_HEAD 0x68 + + // 激活命令 +#define CMD_STARTDT 0x04 +#define CMD_STOPDT 0x10 +#define CMD_TESTFR 0x40 + + // 确认命令 +#define CMD_STARTC 0x08 +#define CMD_STOPC 0x20 +#define CMD_TESTC 0x80 + +//总召指令 +#define CMD_CTL_64H 0x64 // type=总召激活 + + +#define MIN_APDU_LENGTH 6 // min lengtg = 6byte, APCI +#define MAX_ASDU_LENGTH 249 + +#define YX_STAT_OPEND 0 // 开关状态: 0--开闸 +#define YX_STAT_CLOSE 1 // 开关状态: 1--合闸 + + +// 心跳 +#define CMD_ACTIVE_PACKAGE "\x68\x04\x40\x00\x00\x00" + + +class CIEC104 +{ +public: + CIEC104() ; + ~CIEC104() ; +private: +protected: +}; +void IEC104EnvFree(); +void IEC104EnvLoad(); +void UpdateLastTime(); + +void *thread_listen_proc(void *arg); +void *thread_client_proc(void *arg); +void *thread_warn_proc(void *arg); +void *thread_origin_proc(void *arg); +void * thread_pingce_proc(void * arg); + +void *thread_recv_proc(void *arg) ; +void *thread_active_proc(void *arg); +void *thread_parser_proc(void *arg); +void *thread_Timer_proc(void *arg); +void *thread_cache_proc(void *arg) ; // 同步内存数据线程 +//void *thread_setdb_proc(void *arg); // 数据入库线程 +//void *thread_getdata_proc(void *arg); +void *thread_origin_proc(void *arg); // 原始数据入库现场 +void *thread_gis_hold_proc(void * arg); + +// 刷新机组的工作状态,1:发电、2:抽水、3:空闲 +unsigned char getDevWorkState(ST_IECPOINT_TABLE &stIec); +unsigned char getDevFaultState(ST_IECPOINT_TABLE &stIec); +// +////// 获取BYQ设备对应关系及阈值 +//bool bGetByqCacheRelation(unsigned char *pszSersorid, ST_BYQ_CACHE *pstData); +//// +////// 获取GIS设备对应关系及阈值 +//bool bGetGisCacheRelation(unsigned char *pszSersorid, ST_GIS_CACHE *pstData); +//// +////// 获取BLQ设备对应关系及阈值 +//bool bGetBlqCacheRelation(unsigned char *pszSersorid, ST_BLQ_CACHE *pstData); + +bool bSetBYQPointValueByAddr(const char *pszEqmCode, float value); + +#ifdef __cplusplus +} +#endif + + +#endif // end + diff --git a/include/HTImageBusi.h b/include/HTImageBusi.h new file mode 100644 index 0000000..cf74e63 --- /dev/null +++ b/include/HTImageBusi.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** File name : HTImageBusi.h +** Description : define memory data struct +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_IMAGE_BUSI_H +#define __HT_IMAGE_BUSI_H +#pragma pack (push ,1) + +//图片识别阈值缓存区 +typedef struct +{ + unsigned char site_id[DEF_EQM_CODE_SIZE]; // 站点ID + unsigned char eqm_code[DEF_EQM_CODE_SIZE]; // 主设备编码/主变/GIS/避雷器 + unsigned char system_code[DEF_EQM_CODE_SIZE];// 系统设备编码 + unsigned char sensor_id[DEF_EQM_CODE_SIZE]; // Sensor Code,map key + unsigned char desc[DEF_BUFFER_256]; // 对应sensor code的描述 + unsigned char eqm_type; // 设备类型 1:主变 2:GIS 3:测温柜 4:避雷器 + //unsigned char wstate; // 工作状态 1:发电状态 2:抽水状态 3:空闲状态 + unsigned char phase; // 相位 O:全相 1:A相 2:B相 3:C相 + double value[3]; // 阈值,index=0:发电状态阈值 =1:抽水状态阈值 =2:空闲状态阈值 +}ST_IMG_THRESHOLD; + + +// 加载图片阈值 +void vLoadImageThreshold(); +void vPrtImageThreshold(void); + +// 根据sensor_id,获取阈值 +bool getImageThresholdValuse(const char *sensor_id, ST_IMG_THRESHOLD &pstThresdhold); + + +#pragma pack (pop) +#endif // end + diff --git a/include/HTInitUtils.h b/include/HTInitUtils.h new file mode 100644 index 0000000..09824ee --- /dev/null +++ b/include/HTInitUtils.h @@ -0,0 +1,32 @@ +/**************************************************************************** +** File name : HTInitUtils.h +** Description : Defines service initialization API +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_INIT_UTILS_H +#define __HT_INIT_UTILS_H + +#ifdef __cplusplus +extern "C" { +#endif + +// 初始化服务运行环境 +int loadServiceEvent(); +void reloadServiceEvent(int platform_id); +int unLoadServiceEvent(); + +int get_seqno(void); + + +#ifdef __cplusplus +} +#endif +#endif // end __HT_INIT_UTILS_H + diff --git a/include/HTLogger.h b/include/HTLogger.h new file mode 100644 index 0000000..859eff7 --- /dev/null +++ b/include/HTLogger.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** File name : HTLogger.h +** Description : logger function define +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_LOGGER_H +#define __HT_LOGGER_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +// logger config parameter +#ifdef _WIN32 + static const char *DEF_LOG_PATH_NAME = "..\\log" ; //日志文件目录名 + static const char *DEF_RUN_INFO_PATH = "..\\run" ; // 服务运行状态日志目录 +#else + static const char *DEF_LOG_PATH_NAME = "../log" ; //日志文件目录名 + static const char *DEF_RUN_INFO_PATH = "../run" ; // 服务运行状态日志目录 +#endif + +// 打印报文类型,日志 +#define PRT_PACK_SEND 0 // 打印发送报文类型 +#define PRT_PACK_RECV 1 // 打印接收报文类型 +#define PRT_PACK_DATA 2 // 打印报文 + +#define DEF_LOG_FILESZIE 1048576*50 /* logfile size define 50M byte */ + +#ifdef LOG_DEBUG +#undef LOG_DEBUG +#endif +#define __LOG_DEBUG 0 // 跟踪日志 +#define LOG_DEBUG __LINE__, _FILE_, __LOG_DEBUG + +#ifdef LOG_WARNG +#undef LOG_WARNG +#endif +#define __LOG_WARNG 1 // 告警日志 +#define LOG_WARNG __LINE__, _FILE_, __LOG_WARNG + +#ifdef LOG_ERROR +#undef LOG_ERROR +#endif +#define __LOG_ERROR 2 // 错误日志 +#define LOG_ERROR __LINE__, _FILE_, __LOG_ERROR + +#ifdef LOG_PACK +#undef LOG_PACK +#endif +#define __LOG_PACK 3 // 报文日志 +#define LOG_PACK __LINE__, _FILE_, __LOG_PACK + +// 日志记录相关函数 +void vInitLogMutex(void); +void vFreeLogMutex(void); + +void vPrtLogMsg(int line, const char *pszFileName, char logLevel, int iCode, ...); +void vPrtLogHex(int line, const char *pszFileName, char logLevel, int sockid, /* unsigned short msg_id, */ + char pszMsgType, unsigned char *pusMsg,int uiMsgLen); + + + + +#ifdef __cplusplus +} +#endif +#endif // __HT_LOGGER_H + diff --git a/include/HTMemCacheData.h b/include/HTMemCacheData.h new file mode 100644 index 0000000..99f9eec --- /dev/null +++ b/include/HTMemCacheData.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** File name : HTMemCacheData.h +** Description : define memory data struct +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_MEM_CACHE_DATA_H +#define __HT_MEM_CACHE_DATA_H +#pragma pack (push ,1) + + +// 变压器三种工作状态下的阈值,运行工况阈值的字典 +typedef struct +{ + double value; // 阈值 + char field[64]; // 阈值字段名称,对应阈值表中的字段名称 +}ST_STAT_FIELD; + +#define MAX_RUN_STATUS_COUNT 15 // 一个主变的最大运行工况阈值数量 +typedef struct { + int fnum; // 阈值个数 + ST_STAT_FIELD stField[MAX_RUN_STATUS_COUNT]; +}ST_STAT_THRESHOLD; + +// 变压器运行工况阈值缓存信息体 +typedef struct{ + unsigned char site_id[DEF_EQM_CODE_SIZE]; // 站点ID + unsigned char eqm_code[DEF_EQM_CODE_SIZE]; // 主设备ID,对应表busi_site_tree.id,map.key + unsigned char system_code[DEF_EQM_CODE_SIZE]; // 系统设备编码,strkey + unsigned char dev_name[DEF_EQM_CODE_SIZE * 2]; // 设备名称 + unsigned char wstate; // 当前设备工作状态 1-发电状态 2:抽水状态 3:空闲状态 + ST_STAT_THRESHOLD stThreashod[3]; // 0-发电状态 1:抽水状态 2:空闲状态 +}ST_BYQ_RUN_STATE_THRESHOLD; + +// 主变与其他主设备关联关系 +typedef struct{ + unsigned char site_id[DEF_EQM_CODE_SIZE]; // 站点ID + unsigned char m_eqm_code[DEF_EQM_CODE_SIZE]; // 主设备ID,对应表busi_site_tree.id. + unsigned char s_eqm_code[DEF_EQM_CODE_SIZE]; // 主设备ID,对应表busi_site_tree.id,map.key + unsigned char s_sys_code[DEF_EQM_CODE_SIZE]; // 从设备ID,对应表busi_site_tree.id,map.key + unsigned char s_eqm_type; // 设备类型 1:主变 2:GIS 3:测温 4:避雷器 + unsigned char wstate; // 主变+GIS,工作状态 1-发电状态 2:抽水状态 3:空闲状态 + unsigned char bClose; // GIS的开合状态0:分 1:合 + unsigned char bfault; // 主变事故状态:0-正常 1-事故状态 +}ST_DEV_RELATION; + +// 主变id工作状态列表 +typedef struct{ + unsigned char site_id[DEF_EQM_CODE_SIZE]; // 站点ID + unsigned char eqm_code[DEF_EQM_CODE_SIZE]; // 主设备ID,对应表busi_site_tree.id. + unsigned char eqm_name[DEF_BUFFER_128]; // 设备名称 + unsigned char wstate; // 主变+GIS,工作状态 1-发电状态 2:抽水状态 3:空闲状态 + unsigned char bfault; // 主变事故状态:0-正常 1-事故状态 +}ST_BYQWORK_STATUS; + +// 是否有报警 +//bool isWarnning(unsigned char *site_id, unsigned char *sys_code, int state, unsigned int saddr, double val); +bool isWarnning(ST_IECPOINT_TABLE &stPointt, double val); + +// 获取系统设定的阈值 +double getThresholdValuse(const char *eqm_code, const char *pFiledName, int jobState); + +// 根据s_eqm_code获取对应的主变设备编码 +bool bGetMasterEqmCodeBySubEqmCode(unsigned char *site_id, unsigned char *s_eqm_code, unsigned char *m_eqm_code); + + +// 刷新主变设备/GIS/避雷器运行状态 +void flushDevWorkState(unsigned char *site_id, unsigned char *m_eqm_code, unsigned char state); + +//刷新主变设备机组事故状态 state=false:正常 true:事故 +bool flushFaultState(unsigned char *site_id, unsigned char *m_eqm_code, unsigned char state); + +// 刷新GIS开关状态 +bool flushDevCloseState(unsigned char *site_id, unsigned char *s_eqm_code, unsigned char state); + +// 获取GIS的开关状态 +unsigned char getGisOpenCloseState(unsigned char *site_id, unsigned char *s_eqm_code); + +//从隶属关系map中,获取设备工作状态 +//返回0:无效状态-没有找到该设备/设备无关联关系存在 +unsigned char cGetCurrentWorkState(/*unsigned char *pszSite_id,*/ unsigned char *pszEqm_code); + + + + +/*************************************************************************/ +// 设置主变工作状态 +void vSetByqDeviceState(unsigned char *pszEqm_code, unsigned char state); + +// 获取工作状态 +unsigned char cGetByqDeviceState(unsigned char *pszEqm_code); + +// 设置主变事故状态 +void vSetByqDeviceFaultState(unsigned char *pszEqm_code, unsigned char state); + +// 获取事故状态 +unsigned char cGetByqDeviceFaultState(unsigned char *pszEqm_code); + +void SethDevTimeStat(unsigned char *sys_code, unsigned char ws); +time_t GetDevTimeStat(unsigned char *sys_code, unsigned char *ws); + +#pragma pack (pop) +#endif // end + diff --git a/include/HTMutex.h b/include/HTMutex.h new file mode 100644 index 0000000..69b255b --- /dev/null +++ b/include/HTMutex.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** File name : HTMutex.cpp +** Description : define mutex type +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_MUTEX_H +#define __HT_MUTEX_H + +#ifndef _WIN32 //for unix + #define mutex pthread_mutex_t + #define mutex_create(X) pthread_mutex_init(&X, NULL) + #define mutex_close(X) pthread_mutex_destroy(&X) + #define mutex_lock(X) pthread_mutex_lock(&X) + #define mutex_unlock(X) pthread_mutex_unlock(&X) +#else //for winX + #define mutex HANDLE + #define mutex_create(X) X = CreateMutex(NULL, FALSE, NULL) + #define mutex_close(X) CloseHandle(X) + #define mutex_lock(X) WaitForSingleObject(X, INFINITE) + #define mutex_unlock(X) ReleaseMutex(X) +#endif + +// delay tims, millisecond(ms) +#ifndef _WIN32 //for unix + #define _SLEEP(X) usleep(X * 1000) +#else //for winX + #define _SLEEP(X) Sleep(X) //ms +#endif + +#ifdef _WIN32 //for unix +#define snprintf _snprintf +#endif + +#endif // end __HT_MUTEX_H + diff --git a/include/HTOpencvImg.h b/include/HTOpencvImg.h new file mode 100644 index 0000000..51c9526 --- /dev/null +++ b/include/HTOpencvImg.h @@ -0,0 +1,548 @@ +/**************************************************************************** +** File name : HTOpencvImg.h +** Description : define Opencv function +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_OPENCV_IMG_H +#define __HT_OPENCV_IMG_H +#pragma warning(disable: 4819) +#include +#include "HTGlobal.h" +//#include "opencv/cv.h" +#include "opencv2/opencv.hpp" +#include "opencv2/core/core.hpp" +#include "opencv2/highgui/highgui.hpp" +#include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" +#include "opencv2/ml.hpp" +#include "opencv2/objdetect.hpp" + +//#define _HT_OPENCV_TEST_ENV // 测试环境,产生随机数作为分析表的数据 + +#pragma pack (push ,1) + +//OpencvDirTraverse.cpp : Defines the entry point for the console application. +#ifdef _WIN32 +#pragma comment(lib,"opencv_world300d.lib") +//#pragma comment(lib,"opencv_ts300d.lib") +#endif + +using namespace std; +using namespace cv; + +#if (defined _WIN32) || (defined _WIN64) +static const char HT_CONFIMG_FILE[] = "..\\etc\\htimg-win.conf"; +#else +static const char HT_CONFIMG_FILE[] = "../etc/htimg.conf"; +#endif + +#define eps 0.0000000001 +#define PI acos(-1.0) +//#define MAX_FILE_SIZE 8294454 // 图片文件大小(字节) +//#define MAX_FILE_SIZE 177400 +//#define _IM_SHOW // 显示图片 +//#define _IMG_MIDILL_SAVE // 保存最终变换图片 + +typedef struct _CONF_IMG { + //[CAMERA_01] + int seqno; // 序列号,001-999之间 + unsigned char eqm_type[2]; // 主设备类型, T-主变 G-GIS B-避雷器 + unsigned char site_id[DEF_EQM_CODE_SIZE]; // 站点ID + unsigned char eqm_code[DEF_EQM_CODE_SIZE]; // 主设备编码 + unsigned char sys_code[DEF_EQM_CODE_SIZE]; // 主设备系统编码 + unsigned char table_type[32]; // 仪表类型名称 + unsigned char name[32]; //# 拍摄对象名称,变压器放电拍照设备 + unsigned char sersorid[DEF_EQM_CODE_SIZE]; //# 设备的sersor_id, 与数据库一一对应 + unsigned int base_angle; //# 仪表基准度数, 180° 或360° + unsigned char meter_type; //# 仪表的数据单位类型, 0:电流 1 : 压力 2 : 容量(油位) 3: 温度 + unsigned char meter_units; //# 对应于meter_type的单位 + unsigned char direct_Clockwise;// 仪表读数的方向, 正时针 = 1 反时针 = 0 + double dInitVal; // 初始值 + unsigned int max_pointer_len; //# 最大指针长度(mm), 20mm~200mm, 默认:100 + unsigned char img_path[MAX_PATH]; // 图片文件路径及类型: ../img01/*.* or ../img01/*.jpg ... + unsigned char img_bak[MAX_PATH]; // 图片文件备份路径../img01/bak ... + bool is_replace; //true: 覆盖原文件,不保留原文件,文件名不变;false: 保留原文件,并将截图文件命名为 xxx_cut.xxx + //# 截图区域配置 + int s_height; //# 起始行 / 高度 / Y / H / rows + int e_height; //# 结束行 / 高度 / Y / H / rows + int s_width; //# 起始列 / 宽度 / X / W / cols + int e_width; //# 结束列 / 宽度 / X / W / cols + int img_min_size; // 图片文件最小字节数 +}ST_OPENCV_CONF; + + +typedef struct _YB_TYPE { + int len; // 线长度 + double du; // 角度 + double val; // 对应的值 +}ST_YB_TYPE; + +static const ST_YB_TYPE g_YB_3EX5050[] = +{ + { 156, 139.00, 0 }, + { 156, 127.00, 1 }, + { 156, 116.00, 2 }, + { 156, 105.00, 3 }, + { 156, 90.00, 10 }, + { 156, 75.00, 20 }, + { 156, 52.00, 30 }, + { -1, 0, 0 } +}; +static const ST_YB_TYPE g_YB_JSY10[] = +{ + { 306, 90.00, 0 }, + { 306, 54.00, 1 }, + { 306, 18.00, 2 }, + { 306, 342.00, 3 }, + { 306, 306.00, 4 }, + { 306, 270.00, 5 }, + { 306, 234.00, 6 }, + { 306, 198.00, 7 }, + { 306, 162.00, 8 }, + { 306, 126.00, 9 }, + { -1, 0, 0 } +}; + +static const ST_YB_TYPE g_YB_YZFTH[] = +{ + { 220, 45.00, 10.00 }, + { 220, 47.70, 9.90 }, + { 220, 50.40, 9.80 }, + { 220, 53.10, 9.70 }, + { 220, 55.80, 9.60 }, + { 220, 58.50, 9.50 }, + { 220, 61.20, 9.40 }, + { 220, 63.90, 9.30 }, + { 220, 66.60, 9.20 }, + { 220, 69.30, 9.10 }, + { 220, 72.00, 9.00 }, + { 220, 74.70, 8.90 }, + { 220, 77.40, 8.80 }, + { 220, 80.10, 8.70 }, + { 220, 82.80, 8.60 }, + { 220, 85.50, 8.50 }, + { 220, 88.20, 8.40 }, + { 220, 90.90, 8.30 }, + { 220, 93.60, 8.20 }, + { 220, 96.30, 8.10 }, + { 220, 99.00, 8.00 }, + { 220, 101.70, 7.90 }, + { 220, 104.40, 7.80 }, + { 220, 107.10, 7.70 }, + { 220, 109.80, 7.60 }, + { 220, 112.50, 7.50 }, + { 220, 115.20, 7.40 }, + { 220, 117.90, 7.30 }, + { 220, 120.60, 7.20 }, + { 220, 123.30, 7.10 }, + { 220, 126.00, 7.00 }, + { 220, 128.70, 6.90 }, + { 220, 131.40, 6.80 }, + { 220, 134.10, 6.70 }, + { 220, 136.80, 6.60 }, + { 220, 139.50, 6.50 }, + { 220, 142.20, 6.40 }, + { 220, 144.90, 6.30 }, + { 220, 147.60, 6.20 }, + { 220, 150.30, 6.10 }, + { 220, 153.00, 6.00 }, + { 220, 155.70, 5.90 }, + { 220, 158.40, 5.80 }, + { 220, 161.10, 5.70 }, + { 220, 163.80, 5.60 }, + { 220, 166.50, 5.50 }, + { 220, 169.20, 5.40 }, + { 220, 171.90, 5.30 }, + { 220, 174.60, 5.20 }, + { 220, 177.30, 5.10 }, + { 220, 180.00, 5.00 }, + { 220, 182.70, 4.90 }, + { 220, 185.40, 4.80 }, + { 220, 188.10, 4.70 }, + { 220, 190.80, 4.60 }, + { 220, 193.50, 4.50 }, + { 220, 196.20, 4.40 }, + { 220, 198.90, 4.30 }, + { 220, 201.60, 4.20 }, + { 220, 204.30, 4.10 }, + { 220, 207.00, 4.00 }, + { 220, 209.70, 3.90 }, + { 220, 212.40, 3.80 }, + { 220, 215.10, 3.70 }, + { 220, 217.80, 3.60 }, + { 220, 220.50, 3.50 }, + { 220, 223.20, 3.40 }, + { 220, 225.90, 3.30 }, + { 220, 228.60, 3.20 }, + { 220, 231.30, 3.10 }, + { 220, 234.00, 3.00 }, + { 220, 236.70, 2.90 }, + { 220, 239.40, 2.80 }, + { 220, 242.10, 2.70 }, + { 220, 244.80, 2.60 }, + { 220, 247.50, 2.50 }, + { 220, 250.20, 2.40 }, + { 220, 252.90, 2.30 }, + { 220, 255.60, 2.20 }, + { 220, 258.30, 2.10 }, + { 220, 261.00, 2.00 }, + { 220, 263.70, 1.90 }, + { 220, 266.40, 1.80 }, + { 220, 269.10, 1.70 }, + { 220, 271.80, 1.60 }, + { 220, 274.50, 1.50 }, + { 220, 277.20, 1.40 }, + { 220, 279.90, 1.30 }, + { 220, 282.60, 1.20 }, + { 220, 285.30, 1.10 }, + { 220, 288.00, 1.00 }, + { 220, 290.70, 0.90 }, + { 220, 293.40, 0.80 }, + { 220, 296.10, 0.70 }, + { 220, 298.80, 0.60 }, + { 220, 301.50, 0.50 }, + { 220, 304.20, 0.40 }, + { 220, 306.90, 0.30 }, + { 220, 309.60, 0.20 }, + { 220, 312.30, 0.10 }, + { 220, 315.00, 0.00 }, + { -1, 0, 0 } +}; + +// 150摄氏度的油温表读数 +static const ST_YB_TYPE g_YB_WSS150[] = +{ + { 183, 225.00, 0.00 }, + { 183, 219.60, 3.00 }, + { 183, 214.20, 6.00 }, + { 183, 208.80, 9.00 }, + { 183, 203.40, 12.00 }, + { 183, 198.00, 15.00 }, + { 183, 192.60, 18.00 }, + { 183, 187.20, 21.00 }, + { 183, 181.80, 24.00 }, + { 183, 176.40, 27.00 }, + { 183, 171.00, 30.00 }, + { 183, 165.60, 33.00 }, + { 183, 160.20, 36.00 }, + { 183, 154.80, 39.00 }, + { 183, 149.40, 42.00 }, + { 183, 144.00, 45.00 }, + { 183, 138.60, 48.00 }, + { 183, 133.20, 51.00 }, + { 183, 127.80, 54.00 }, + { 183, 122.40, 57.00 }, + { 183, 117.00, 60.00 }, + { 183, 111.60, 63.00 }, + { 183, 106.20, 66.00 }, + { 183, 100.80, 69.00 }, + { 183, 95.40, 72.00 }, + { 183, 90.00, 75.00 }, + { 183, 84.60, 78.00 }, + { 183, 79.20, 81.00 }, + { 183, 73.80, 84.00 }, + { 183, 68.40, 87.00 }, + { 183, 63.00, 90.00 }, + { 183, 57.60, 93.00 }, + { 183, 52.20, 96.00 }, + { 183, 46.80, 99.00 }, + { 183, 41.40, 102.00 }, + { 183, 36.00, 105.00 }, + { 183, 30.60, 108.00 }, + { 183, 25.20, 111.00 }, + { 183, 19.80, 114.00 }, + { 183, 14.40, 117.00 }, + { 183, 9.00, 120.00 }, + { 183, 3.60, 123.00 }, + { 183, 358.20, 126.00 }, + { 183, 325.80, 129.00 }, + { 183, 347.40, 132.00 }, + { 183, 342.00, 135.00 }, + { 183, 336.60, 138.00 }, + { 183, 331.20, 141.00 }, + { 183, 325.80, 144.00 }, + { 183, 320.40, 147.00 }, + { 183, 315.00, 150.00 }, + { -1, 0, 0 } +}; +// 100摄氏度的温度表读数 +static const ST_YB_TYPE g_YB_WSS100[] = +{ + { 183, 225.00, 0.00 }, + { 183, 219.60, 2.00 }, + { 183, 214.20, 4.00 }, + { 183, 208.80, 6.00 }, + { 183, 203.40, 8.00 }, + { 183, 198.00, 10.00 }, + { 183, 192.60, 12.00 }, + { 183, 187.20, 14.00 }, + { 183, 181.80, 16.00 }, + { 183, 176.40, 18.00 }, + { 183, 171.00, 20.00 }, + { 183, 165.60, 22.00 }, + { 183, 160.20, 24.00 }, + { 183, 154.80, 26.00 }, + { 183, 149.40, 28.00 }, + { 183, 144.00, 30.00 }, + { 183, 138.60, 32.00 }, + { 183, 133.20, 34.00 }, + { 183, 127.80, 36.00 }, + { 183, 122.40, 38.00 }, + { 183, 117.00, 40.00 }, + { 183, 111.60, 42.00 }, + { 183, 106.20, 44.00 }, + { 183, 100.80, 46.00 }, + { 183, 95.40, 48.00 }, + { 183, 90.00, 50.00 }, + { 183, 84.60, 52.00 }, + { 183, 79.20, 54.00 }, + { 183, 73.80, 56.00 }, + { 183, 68.40, 58.00 }, + { 183, 63.00, 60.00 }, + { 183, 57.60, 62.00 }, + { 183, 52.20, 64.00 }, + { 183, 46.80, 66.00 }, + { 183, 41.40, 68.00 }, + { 183, 36.00, 70.00 }, + { 183, 30.60, 72.00 }, + { 183, 25.20, 74.00 }, + { 183, 19.80, 76.00 }, + { 183, 14.40, 78.00 }, + { 183, 9.00, 80.00 }, + { 183, 3.60, 82.00 }, + { 183, 361.80, 84.00 }, + { 183, 356.40, 86.00 }, + { 183, 351.00, 88.00 }, + { 183, 345.60, 90.00 }, + { 183, 340.20, 92.00 }, + { 183, 334.80, 94.00 }, + { 183, 329.40, 96.00 }, + { 183, 324.00, 98.00 }, + { 180, 318.60, 100.00 }, + { -1, 0, 0 } +}; +// 1.6MPa压力表读数 +static const ST_YB_TYPE g_YB_OCR17NI12MO2_16[] = +{ + { 183, 225.00, 0.00 }, + { 183, 221.63, 0.02 }, + { 183, 218.25, 0.04 }, + { 183, 214.88, 0.06 }, + { 183, 211.50, 0.08 }, + { 183, 208.13, 0.10 }, + { 183, 204.75, 0.12 }, + { 183, 201.38, 0.14 }, + { 183, 198.00, 0.16 }, + { 183, 194.63, 0.18 }, + { 183, 191.25, 0.20 }, + { 183, 187.88, 0.22 }, + { 183, 184.50, 0.24 }, + { 183, 181.13, 0.26 }, + { 183, 177.75, 0.28 }, + { 183, 174.38, 0.30 }, + { 183, 171.00, 0.32 }, + { 183, 167.63, 0.34 }, + { 183, 164.25, 0.36 }, + { 183, 160.88, 0.38 }, + { 183, 157.50, 0.40 }, + { 183, 154.13, 0.42 }, + { 183, 150.75, 0.44 }, + { 183, 147.38, 0.46 }, + { 183, 144.00, 0.48 }, // 144.74 - 0.5 + { 183, 140.63, 0.50 }, + { 183, 137.25, 0.52 }, + { 183, 133.88, 0.54 }, + { 183, 130.50, 0.56 }, + { 183, 127.13, 0.58 }, + { 183, 123.75, 0.60 }, + { 183, 120.38, 0.62 }, + { 183, 117.00, 0.64 }, + { 183, 113.63, 0.66 }, + { 183, 110.25, 0.68 }, + { 183, 106.88, 0.70 }, + { 183, 103.50, 0.72 }, + { 183, 100.13, 0.74 }, + { 183, 96.75, 0.76 }, + { 183, 93.38, 0.78 }, + { 183, 90.00, 0.80 }, + { 183, 86.63, 0.82 }, + { 183, 83.25, 0.84 }, + { 183, 79.88, 0.86 }, + { 183, 76.50, 0.88 }, + { 183, 73.13, 0.90 }, + { 183, 69.75, 0.92 }, + { 183, 66.38, 0.94 }, + { 183, 63.00, 0.96 }, + { 183, 59.63, 0.98 }, + { 183, 56.25, 1.00 }, + { 183, 52.88, 1.02 }, + { 183, 49.50, 1.04 }, + { 183, 46.13, 1.06 }, + { 183, 42.75, 1.08 }, + { 183, 39.38, 1.10 }, + { 183, 36.00, 1.12 }, + { 183, 32.63, 1.14 }, + { 183, 29.25, 1.16 }, + { 183, 25.88, 1.18 }, + { 183, 22.50, 1.20 }, + { 183, 19.13, 1.22 }, + { 183, 15.75, 1.24 }, + { 183, 12.38, 1.26 }, + { 183, 9.00, 1.28 }, + { 183, 5.63, 1.30 }, + { 183, 2.25, 1.32 }, + { 183, 361.13, 1.34 }, + { 183, 357.75, 1.36 }, + { 183, 354.38, 1.38 }, + { 183, 351.00, 1.40 }, + { 183, 347.63, 1.42 }, + { 183, 344.25, 1.44 }, + { 183, 340.88, 1.46 }, + { 183, 337.50, 1.48 }, + { 183, 334.13, 1.50 }, + { 183, 330.75, 1.52 }, + { 183, 327.38, 1.54 }, + { 183, 324.00, 1.56 }, + { 183, 320.63, 1.58 }, + { 180, 317.25, 1.60 }, + { -1, 0, 0 } +}; + +// 2.5MPa压力表读数 +static const ST_YB_TYPE g_YB_OCR17NI12MO2_25[] = +{ + { 183, 225.00, 0.00 }, + { 183, 219.60, 0.05 }, + { 183, 214.20, 0.10 }, + { 183, 208.80, 0.15 }, + { 183, 203.40, 0.20 }, + { 183, 198.00, 0.25 }, + { 183, 192.60, 0.30 }, + { 183, 187.20, 0.35 }, + { 183, 181.80, 0.40 }, + { 183, 176.40, 0.45 }, + { 183, 171.00, 0.50 }, + { 183, 165.60, 0.55 }, + { 183, 160.20, 0.60 }, + { 183, 154.80, 0.65 }, + { 183, 149.40, 0.70 }, + { 183, 144.00, 0.75 }, + { 183, 138.60, 0.80 }, + { 183, 133.20, 0.85 }, + { 183, 127.80, 0.90 }, + { 183, 122.40, 0.95 }, + { 183, 117.00, 1.00 }, + { 183, 111.60, 1.05 }, + { 183, 106.20, 1.10 }, + { 183, 100.80, 1.15 }, + { 183, 95.40, 1.20 }, + { 183, 90.00, 1.25 }, + { 183, 84.60, 1.30 }, + { 183, 79.20, 1.35 }, + { 183, 73.80, 1.40 }, + { 183, 68.40, 1.45 }, + { 183, 63.00, 1.50 }, + { 183, 57.60, 1.55 }, + { 183, 52.20, 1.60 }, + { 183, 46.80, 1.65 }, + { 183, 41.40, 1.70 }, + { 183, 36.00, 1.75 }, + { 183, 30.60, 1.80 }, + { 183, 25.20, 1.85 }, + { 183, 19.80, 1.90 }, + { 183, 14.40, 1.95 }, + { 183, 9.00, 2.00 }, + { 183, 3.60, 2.05 }, + { 183, 361.80, 2.10 }, + { 183, 356.40, 2.15 }, + { 183, 351.00, 2.20 }, + { 183, 345.60, 2.25 }, + { 183, 340.20, 2.30 }, + { 183, 334.80, 2.35 }, + { 183, 329.40, 2.40 }, + { 183, 324.00, 2.45 }, + { 183, 318.60, 2.50 }, + { -1, 0, 0 } +}; +#pragma pack (pop) + + +//181 - 0 = 181 +//530 - +//495 +//224 +//135 +//123 +//92 + + +//自定义直线 +class MyLine +{ +public: + int id; //编号 + int k; //倾斜角[0-360) + int l; //长度 +public: + MyLine(int ID = 0, int K = 0, int L = 0){ id = ID, k = K, l = L; } //构造函数 + + bool operator<(const MyLine &A) { return k < A.k; } //重定义小于号 + + void print(){ printf("id: %3d k: %3d° l: %3d\n", id, k, l); }//输出函数 +}; + + +//显示图片 +void showImg(const char *title, Mat &img); + +//点到线段的距离 +double DistancetoSegment(Point P, Point A, Point B); +//向量模长 +double Length(Point A); + +double gtest(double du, double base, int linelen); // for test + +// 读取仪表指针数值 +//double dReadPointValue(const char *tbale_type, const char *jpg_file, double base); +double dReadPointValue_JSY10(ST_OPENCV_CONF *stConf, const char *jpg_file); +double dReadPointValue_3EX5050(ST_OPENCV_CONF *stConf, const char *jpg_file); +//double dReadPointValue_YZF250TH_T4(ST_OPENCV_CONF *stConf, const char *jpg_file); +double dReadPointValues(ST_OPENCV_CONF *stConf, const char *jpg_file); +//double dGetReadValueOfYZFTH(double du, double base, int linelen); + +/* +pPath : path, eg: /usr/local/img/*.jpg +: "D:\\Photo and Video\\destop1\\*.jpg"; +*/ +int iGetImgFileList(const char *pPath, std::vector & image_files); + +// 播放视频流 +int showRtspVideoStream(const char* rtsp_url); +int showRtspVideoStreams(const char *rtsp_url); + +// 截取图片指定区域并保存 +// isReplace = true: 覆盖原文件,不保留原文件,文件名不变 +// = false: 保留原文件,并将截图文件命名为 xxx_cut.xxx +//int vCutImageSave(char* path_filename, int shigh, int ehigh, int swidth, int ewidth, bool isReplace); +int vCutImageSave(ST_OPENCV_CONF *stConf, char* path_filename); + +// 仪表盘的单位转换 +double dChangeUnits(unsigned char *sersorid, double inVal); + +// 图片识别处理线程 +void* thread_opencv_proc(void * arg); + +bool bBakFilename(char *filename, char *pBakPath); + + +double dReadPointValue_Wss411_150_T1(ST_OPENCV_CONF *stConf, const char *jpg_file); + +#endif // !__HT_OPENCV_IMG_H_ + diff --git a/include/HTPublic.h b/include/HTPublic.h new file mode 100644 index 0000000..925ccf3 --- /dev/null +++ b/include/HTPublic.h @@ -0,0 +1,226 @@ +/**************************************************************************** +** File name : HTPublic.h +** Description : define common api +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_PUBLIC_H +#define __HT_PUBLIC_H + +#ifdef _WIN32 +#pragma comment(lib,"ws2_32.lib") +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* timespec{} for pselect() */ +#include +#include +#include +#include /* for nonblocking */ +#include +#include +#include "HTType.h" + +using namespace std; + +#ifdef _WIN32 + #include + #include + #include + #include + #include + #include +#else + #include + #include + #include + #include + #include + #include + #include + #include /* sockaddr_in{} and other Internet defns */ + #include /* inet(3) functions */ + #include + #include + #include + #include + #include + #include + #include + #include + #include +#endif + +/* +#if defined(__linux__) && defined(__NR_gettid) +#define GETTID() syscall(__NR_gettid) +#else +#define GETTID() getpid() +#endif +*/ +#ifdef _WIN32 +#define GETTID() GetCurrentThreadId() // 获取线程ID +#define GETPID() GetCurrentProcessId() // 获取主进程ID +#else +#define GETTID() syscall(__NR_gettid) +#define GETPID() getpid() // 获取主进程ID +#endif + +#define DEF_PID_FILE "../run/pid_file.pid" // 程序主进程ID文件 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +void vSetPid(); +int iGetPid(); + +// 时间函数 +void vGetHostTime (char *pszTime) ; +time_t vGetHostTimeFmt (char *pszTime) ; +time_t vGetHostTimeFmtBeforBay(char *pszTime, int beforbay); +void vTranHostTimeFmt (time_t t, char *pszTime); +time_t strTime2int(char *pszTime); +time_t strTimeFmt2int(char *pszTime); +void getCurrentBefor360Hour(char *pstime, char *petime); +time_t vGeOneDayTimeFmt(char *pSTime, char *pETime); +void vFormatTimes(char *pszInTimeStr, char *pszOutFormatTime); +time_t getUTCLongTime (void) ; +void getUTCFmtTime (char *pszTime) ; +void UTC2FmtTime (time_t utc, char *pszTime) ; +void UTC2LocalTime (time_t utc, char *pszTime) ; +void diffTimes(unsigned int c, char *pszTime); +unsigned int uiTime (void) ; +int getCurrTimeDiff(unsigned char *bcd_t) ; + +time_t local2Utc(unsigned char *pTime, int iLen); +time_t local2UtcTime(time_t localTime); + +int getuuid(char *str, int inlen); + +void vGetHostTimeOnMillsecond(char *pszTime); // 获取时间,YYYYMMDDHH24MISS:MLSS +time_t vGetHostTimeFmtOnMillsecond(char *pszTime); // 获取时间,YYYY-MM-DD HH24:MI:SS+MLSS + +unsigned int getWarnID(unsigned char *pTime, int iLen, unsigned int id); + + +// 目录操作函数 +int iDirOrFileExist(const char *pszName); +int iBuildDirent(const char *pName); +int iSplitNumberFiled(char *pstr, char node, int no); +int iSplitStringFiled(char *pstr, char node, char no, char *pFiled); +int get_file_size(const char *path); +int getFileCreateTime(const char *path, char *pCreateTime); + +bool bSplitFilenameByFullPath(char *pFullPath, char *pPrantPath, char *pFilename, char *pExt); +// 将Linux文件路径转为Windows的路径格式 +void Unix2WindowPath(char *pszPath); +void Window2UnixPath(char *pszPath); +void getGnssData(unsigned char *p_date); +void getGnssTime(unsigned char *p_time); +void setPostionDate(unsigned char *pDate, unsigned char *pTime); +void setPostionTime(unsigned char *pDate, unsigned char *pTime); + +int iTrimVersionHeadChar(char *strver); +void LRTrim(unsigned char *str); +int RigthTrim(unsigned char *str); +int LeftTrim(unsigned char *str); +void MiddleTrim(unsigned char *str); +bool isStringDigit(char *pstr); + +int stringcasecmp(const char *ps1, const char *ps2); +int stringncasecmp(const char *ps1, const char *ps2, int length); + +int bits_check(unsigned char *map, int field_no); + +void getDateFromTime(char* p_time,char* p_date); +void getTimeFromTime(char* p_time,char* p_times); + +void bcd_to_asc(unsigned char *pusFrom, unsigned int uiFromLen,unsigned char *pusTo); +void asc_to_bcd(unsigned char *pusFrom, unsigned int uiFromLen, unsigned char *pusTo); + +unsigned int htoni(unsigned int us); +unsigned int ntohi(unsigned int us); +double getRandByTime(); + +#ifdef ntohll +utint64 ntohll(utint64 arg64) ; +#endif +#ifdef htonll +utint64 htonll(utint64 arg64) ; +#endif +unsigned int int64To32(utint64 u64); +void LocalTime2Bcd(char *pLocalTime, char *pBcd); + +int getStringLen(unsigned char *pstr, int length); +int getHexString(unsigned char *str, int length, unsigned char *pstr); + +/************************************************************************* +Function : 32位整数转二进制字符串 +Param in : + num : source uint +Param out : + pBin : object strings.(min length = 32) +Return Code : none +*************************************************************************/ +void uint32_binstr(unsigned int num, char* pBin); + +/************************************************************************* +Function : 64位整数转二进制字符串 +Param in : + num : source uint +Param out : + pBin : object strings.(min length = 64) +Return Code : none +*************************************************************************/ +void uint64_binstr(utint64 num, char* pBin); + +/************************************************************************* +Function : 二进制字符串转32位整数 +Param in : + pBin : source bin string(eg. 1010101001111), need '\0' end. +Param out : + : none +Return Code : uint32 interger +*************************************************************************/ +unsigned int binstr_uint32(char *pBin); + +/************************************************************************* +Function : 二进制字符串转64位整数 +Param in : + pBin : source bin string(eg. 1010101001111), need '\0' end. +Param out : + : none +Return Code : utint64 interger +*************************************************************************/ +utint64 binstr_uint64(char *pBin); + +/************************************************************************* +Function : 字符串反转 +Param in : + str : source string(eg. 1010101001111), need '\0' end. + len : source length +Param out : + : str +Return Code : str, null is faild +*************************************************************************/ +char* strSwap(char* szT,int len); + +#ifdef __cplusplus +} +#endif +#endif // end __HT_PUBLIC_H + diff --git a/include/HTTcpSocket.h b/include/HTTcpSocket.h new file mode 100644 index 0000000..1674e90 --- /dev/null +++ b/include/HTTcpSocket.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** File name : HTTcpSocket.h +** Description : define common api for tcp socket +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_TCP_SOCKET_H +#define __HT_TCP_SOCKET_H + +#include "HTPublic.h" +//#include + +static const int MAX_SEND_INFO = 512; //最大发送包长度 +static const int MAX_SBUFF_TCP = 2048; //发送最大包长度 +// static const int MAX_DATA_INFO = 1024; //数据包做大长度 + +#ifdef _WIN32 +#ifndef ECONNRESET +#define ECONNRESET WSAECONNRESET //errno= 104 = Connection reset by peer +#endif +#endif + +#ifndef INVALID_HANDLE +#define INVALID_HANDLE -1 // 无效句柄 +#endif + +/* socket listen number */ +#define LISTENQ 20 +#define MAX_TEMP_BUFFER_SIZE 2048 + +/* error code define */ +#define ErrOpenServer -1000 /* Open Server Fail */ +#define ErrSockParam -1001 /* Socket Param error */ +#define ErrSendFail -1002 /* send data fail or socket exception*/ +#define ErrRecvTimeOut -1003 /* recv data time out */ +#define ErrRecvFail -1004 /* recv data fail */ +#define ErrOpenFile -1005 /* open dest file fail */ +#define ErrSetSockOpt -1006 /* set socket options */ +#define ErrBindFail -1007 /* set socket bind fail*/ +#define ErrGetPeerIP -1008 /* Get PeerIP Fail */ +#define ErrListenFail -1009 /* socket listen error */ +#define ErrTimeStrFmt -1020 /* Input time string error */ +#define ErrEintr -1021 /* Interrupted system call,EINTR*/ +#define ErrException -1022 /* socket exceptions close */ + + +class TTcpSocket +{ +public: + void clear_tcp_buffer(int socket_fd, int nbytes); + + bool tcpIsConnected(int sockid); + + // 根据sockid获取源地址和源端口 + int getPeerInfo(int sockid, unsigned char *sip, unsigned short *sport); + int getLocalSocketInfo(int sockid, unsigned char *sip, unsigned short *sport); + + int tcpRecvBuffer(int sockid, char* pBuffer,int nMaxLength, int timeout=6); + int tcpSendBuffer(int sockid, const char *pBuffer, int length); + + int tcpAcceptSocket(int sockid); + int tcpCloseSocket(int sockfd); + int tcpOpenServer(const char *ip,unsigned short port); + int tcpSetlinger(int sockid); + int tcpSetNodelay(int sockid) ; + int tcpConnect(const char *pszIP, short port, int iTimeout); + void tcpSetServerfd(int fd); + void tcpSetSockID(int fd); + int tcpGetServerfd(); + int tcpGetSockID(); + + TTcpSocket(); + virtual ~TTcpSocket(); + + //长连接测试函数 + //bool tcpClient_Keep() ; +private: + #ifndef _WIN32 + void SetSocketMode(int sockid,int iMode=O_NONBLOCK) ; //O_NONBLOCK=04000 + #else + void SetSocketMode(int sockid,int iMode=04000) ; //O_NONBLOCK=04000 + #endif +private: + unsigned short m_tcpPort; + bool m_tcpConnected; + int m_sockid; + int m_server_fd; +}; + +#endif // end __HT_TCP_SOCKET_H + diff --git a/include/HTTestOpencv.h b/include/HTTestOpencv.h new file mode 100644 index 0000000..80d1c93 --- /dev/null +++ b/include/HTTestOpencv.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** File name : HTTestOpencv.h +** Description : define Opencv Test function +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_TESTOPENCV__H +#define __HT_TESTOPENCV__H +#pragma warning(disable: 4819) + +#include "HTGlobal.h" +#include "opencv2/opencv.hpp" +#include "opencv/cv.h" +#include "opencv2/core/core.hpp" +#include "opencv2/highgui/highgui.hpp" +#include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/imgcodecs.hpp" + +#pragma pack (push ,1) + +//OpencvDirTraverse.cpp : Defines the entry point for the console application. +#ifdef _WIN32 +#pragma comment(lib,"opencv_world300d.lib") +#endif + +using namespace std; +using namespace cv; + +#pragma pack (pop) + + +int HTCanny(char *filename); +// 图片矫正 +void ImageRecify(const char* pInFileName); + +void ImgRotate(const char *img_file); + +void SendMessageOne(char *rtsp_url); + +// 鼠标选取区域,实现截图功能并保持图片 +void vCutPicture(char *filename); + +// 检测矩形 +int iCheckFangXiang(char *filename); + +//检测圆方法 +int iCheckCircles(char *filename); + +//检测直线方法 +int iCheckLine(char *filename); + + +void CannyThreshold(int, void*); +void vHoughLines(int, void*); +void HTImgAnalys(const char *img_file); + + +void vInitPress_OCR17NI12MO2_16(); + +#endif // !__HT_OPENCV_IMG_H_ + diff --git a/include/HTThread.h b/include/HTThread.h new file mode 100644 index 0000000..e933ad0 --- /dev/null +++ b/include/HTThread.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** File name : HTThread.h +** Description : define service threads +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_THREAD_H +#define __HT_THREAD_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + + // 线程接口定义 +int HTInitThreadHandle(void); +void HTFreeThreadHandle(void); +void pthread_testcancels(void); + +int ht_pthread_create_background(pthread_t *thread_handle, void *(*pfunc)(void *), void *data); + + + +// void *thread_parser_proc(void * arg); +// void *thread_opration_proc(void *arg) ; +// void *thread_respone_proc(void *arg) ; +// +// void *thread_client_proc(void * arg); +// void *thread_active_proc(void *arg) ; + + + +#ifdef __cplusplus +} +#endif + +#endif // end __HT_THREAD_H + diff --git a/include/HTType.h b/include/HTType.h new file mode 100644 index 0000000..9b2bb0a --- /dev/null +++ b/include/HTType.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** File name : HTType.h +** Description : define data type +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_TYPE_H +#define __HT_TYPE_H + +#ifdef _WIN32 + #ifndef int64 + typedef __int64 tint64; + #endif +#else + #ifndef int64 + typedef long long tint64 ; + #endif +#endif + +#ifdef _WIN32 + #ifndef utint64 + typedef unsigned __int64 utint64; + #endif +#else + #ifndef utint64 + typedef unsigned long long utint64 ; + #endif +#endif + + +#ifndef uint + typedef unsigned int uint; +#endif + +#ifndef ulong + typedef unsigned long ulong; +#endif + +#ifndef byte + typedef unsigned char byte; +#endif + +#ifndef uchar + typedef unsigned char uchar; +#endif + +#ifndef ushort + typedef unsigned short ushort; +#endif + +#ifdef _WIN32 + #ifndef pthread_t + typedef unsigned long pthread_t; + #endif +/*#else // Linux + #ifndef pthread_t + typedef pthread_t pthread_t; // bits/pthreadtypes.h typedef unsigned long int pthread_t; + #endif + */ +#endif + +#endif // end __HT_TYPE_H + diff --git a/include/HTUnit.h b/include/HTUnit.h new file mode 100644 index 0000000..3d63913 --- /dev/null +++ b/include/HTUnit.h @@ -0,0 +1,24 @@ +/**************************************************************************** +** File name : HTUnit.h +** Description : define const +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_UNIT_H +#define __HT_UNIT_H + + +// 计量单位转换 +double getChangeUnit(short Unit, short sysUnit, double val); + +bool bCompare(double ov, double nv, double rate); + + +#endif // end __HT_UNIT_H + diff --git a/include/HTVersion.h b/include/HTVersion.h new file mode 100644 index 0000000..8fad5fe --- /dev/null +++ b/include/HTVersion.h @@ -0,0 +1,19 @@ +/**************************************************************************** +** File name : HTVersion.h +** Description : define mutex type +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#ifndef __HT_VERSION_H +#define __HT_VERSION_H + +#define HT_VERSION_BUILD_ID "20200526" + +#endif // end __HT_VERSION_H + diff --git a/include/HXIec104.h b/include/HXIec104.h new file mode 100644 index 0000000..b841822 --- /dev/null +++ b/include/HXIec104.h @@ -0,0 +1,179 @@ +#ifndef __HX_IEC104_H +#define __HX_IEC104_H + +#include +#include + +#include "HTGlobal.h" + +#define NS_IEC_104_YK_BASE_PORT 16 +#define NS_IEC104_YK_PERMIT_TIME 16 + + +#define NS_IEC_104_TOTAL_YX_TIMES 9 +#define NS_IEC_104_ONCE_YX 120 +#define NS_IEC_104_ONCE_YX_BYTES 120/8 + +#define NS_IEC_104_TOTAL_YC_TIMES 16 +#define NS_IEC_104_ONCE_YC 32 + +#define NS_IEC_104_TOTAL_YM_TIMES 8 +#define NS_IEC_104_ONCE_YM 16 + +#define NS_IEC_104_MIN_LENGTH 6 +#define NS_IEC_104_HEAD 0x68 +#define NS_IEC_104_STARTDT 0x04 +#define NS_IEC_104_STOPDT 0x10 + +#define NS_IEC_104_TESTFR 0x40 +#define NS_IEC_104_QCC_POSITION 15 +#define NS_IEC_104_TIME_POSITION 15 + + + +#define NS_IEC_104_REASONBYTE 2 +#define NS_IEC_104_ASDUADDRESSBYTE 2 +#define NS_IEC_104_INFORMATIONBYTE 3 + + +/* Location Which Bytes In Receive Buffer */ +#define NS_STARTREASON 8 +#define NS_STARTASDUADDRESS 10 +#define NS_STARTINFORMATION 12 +#define NS_STARTQUALIFIER 15 +#define NS_IEC_104_GROUP_BYTE 15 + + +#define NS_IEC104_GROUP_BEGIN 21 +#define NS_IEC104_GROUP_END 36 + + + +#define NS_IEC104_YX_START_OBJECT 0x01 +#define NS_IEC104_YC_START_OBJECT 0x701 +#define NS_IEC104_YCYX_OBJECT_INDEX 0x80 + + + + +#define NS_IEC104_SENDBUFFER 256 +#define NS_IEC104_RECEIVEBUFFER 128 +#define NS_CONNECTED 0x02 +#define NS_DISCONNECTED 0x20 +#define NS_IEC104_PERMIT_TIME 30 + + +#define NS_IEC104_MAX_K 12 +#define NS_IEC104_MAX_W 8 +#define NS_IEC104_MAX_GROUP 30 + +#define NS_IEC104_MAX_YC 512 +#define NS_IEC104_CHANGE_YC_CYCLE 16 +#define NS_IEC104_ONCE_YC_COUNT 32 + +#define OFF false + + +typedef struct NS_IEC_104_NS_ +{ + struct sockaddr_in ServerAddress; + int NsNewSocketId; + unsigned char LinkState; + unsigned long LinkValidTime; + unsigned char Card; + short Port; + + unsigned char ReceiveBuffer[NS_IEC104_RECEIVEBUFFER]; + unsigned char SendBuffer[NS_IEC104_SENDBUFFER]; + short SendLength; + short ReceiveLength; + unsigned short ReceiveIndex; + short ReceiveIndexLength; + + unsigned char ApciCode; + + unsigned char TransmitReason[2]; + unsigned char CommonAsduAddress[2]; + unsigned char InformationObject[4]; + unsigned char FormatType; + unsigned char UCommand; + unsigned char ReceiveHimNumber[2]; + unsigned short SendMeNumber; + unsigned short ApduLength; + unsigned char AsduType; + unsigned char AsduQualifier; + unsigned char Qcc; + unsigned char FreezeSign; + unsigned char PulseGroup; + + unsigned char TimeSave[8]; + + unsigned char Table; + unsigned short HasSendNumber; + unsigned short NeedSendNumber; + unsigned short LeftSendNumber; + unsigned short K; + unsigned short W; + + + unsigned short ReceiveYkId; + unsigned char YkCellAction; + unsigned short YkCellNumber; + unsigned short YkKgNumber; + unsigned char YkNowState; + unsigned short MediaNumber; + unsigned char YkError; + unsigned char YkYtType; + unsigned char YkStartSign; + unsigned long YkStartTime; + unsigned short SystemState; + unsigned char DataBuff[160]; + unsigned char SetTimeFlag; + + unsigned char GroupSendBuffer[NS_IEC104_MAX_GROUP][NS_IEC104_SENDBUFFER]; + unsigned short GroupSendLength[NS_IEC104_MAX_GROUP]; + + short YcLastValue[NS_IEC104_MAX_YC]; + unsigned char YcNap[NS_IEC104_MAX_YC]; + unsigned char YcChangeCycle; + unsigned short YcLibIndex; + unsigned short YcChangeCount; + unsigned char CosSign; + unsigned char NetRunSign; + unsigned char SetNetSign; + + unsigned char TableNo; + /*unsigned short XYxNum; + + unsigned short XYmNum;*/ + unsigned short XYcNum; + unsigned short XYcCycleNum; + +} NS_IEC104_MAIN; + +#define NS_IEC104_USE_CYCLE 5 + +typedef struct _CYCLE +{ + time_t LastTime; + time_t TimeNap ; + time_t TimeSign; + +}NS_SEND_TIME_NAP; + +typedef struct _SYS_DATE +{ + unsigned short NsYxTableNumber; + unsigned short NsYmTableNumber; + unsigned short NsYcTableNumber; +}NS_SYSTEM_DATA_MODE ; + + +NS_IEC104_MAIN NsIec104Struct; +static NS_SEND_TIME_NAP NsIec104Cycle[NS_IEC104_USE_CYCLE]; +static unsigned short NsIec104Nap[NS_IEC104_USE_CYCLE]={/*5*/120,15,20,25,30}; + + +#endif + + \ No newline at end of file diff --git a/src/HTCP56Time.cpp b/src/HTCP56Time.cpp new file mode 100644 index 0000000..a6a38a1 --- /dev/null +++ b/src/HTCP56Time.cpp @@ -0,0 +1,137 @@ +/**************************************************************************** +** File name : CP56Time.cpp +** Description : CP56Time IEC 60870-5-104 time data type implementation +** 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 "HTGlobal.h" + +static const char *_FILE_ ="HTCP56Time.cpp"; + +// Constructor: decode CP56Time data +CP56Time::CP56Time(unsigned char *data) +{ + CP56TimeToTime(data, &stime); +} + +CP56Time::~CP56Time(void) +{ +} + +// +// return time string of CP56Time decoded +// +void CP56Time::GetTimeString(char *buf, size_t size) +{ + sprintf(buf,"%2.2d-%2.2d-%4.4d %2.2d:%2.2d:%2.2d.%3.3d", stime.wDay, + stime.wMonth, stime.wYear, stime.wHour, stime.wMinute, + stime.wSecond, stime.wMilliseconds); + return; +} + +// +// return SYSTEMTIME structure of CP56Time decoded +// +SYSTEMTIME CP56Time::_GetSystemTime(void) +{ + return stime; +} + +// +// return FILETIME structure of CP56Time decoded +// +FILETIME CP56Time::_GetFileTime(void) +{ + FILETIME ft = {0}; + //SystemTimeToFileTime(&stime, &ft); + return ft; +} + +// +// return CP56Time data of actual time. +// +void CP56Time::ActualTimeToCP56Time(unsigned char *data) +{ + SYSTEMTIME st; + //GetSystemTime(&st); + TimeToCP56Time(&st, data); +} + +// +// convert FILETIME to CP56Time +// +void CP56Time::TimeToCP56Time(FILETIME *ft, unsigned char *data) +{ + SYSTEMTIME st; + //FileTimeToSystemTime(ft, &st); + TimeToCP56Time(&st, data); +} + +// +// convert SYSTEMTIME to CP56Time +// +void CP56Time::TimeToCP56Time(SYSTEMTIME *st, unsigned char *data) +{ + unsigned int m; + m = st->wMilliseconds + 1000 * st->wSecond; + data[0] = m & 0xFF; + data[1] = (m & 0xFF00)>>8; + data[2] = st->wMinute & 0x00FF; // add valid flag and genuine flag + data[3] = st->wHour & 0x00FF; // add summer flag + data[4] = ((st->wDayOfWeek%7)&0x03)<<5 | (st->wDay&0x1F); + data[5] = st->wMonth & 0x0F; + data[6] = st->wYear - 2000; +} + +// +// convert CP56Time to FILETIME +// +void CP56Time::CP56TimeToTime(unsigned char *data, FILETIME *ft) +{ + SYSTEMTIME st; + CP56TimeToTime(data, &st); + //SystemTimeToFileTime(&st, ft); +} + +// +// convert CP56Time to SYSTEMTIME +// +void CP56Time::CP56TimeToTime(unsigned char *data, SYSTEMTIME *st) +{ + unsigned int mili = data[0] | data[1]<<8; + st->wSecond = mili / 1000; + st->wMilliseconds = mili - st->wSecond*1000; + + if(data[2] & 0x40) + genuine = true; + else + genuine = false; + + if(data[2] & 0x80) + valid = true; + else + valid = false; + + st->wMinute = data[2] & 0x3F; + st->wHour = data[3] & 0x1F; + + if(data[3] & 0x80) + summer = true; + else + summer = false; + + st->wDay = data[4] & 0x1F; + st->wDayOfWeek = (data[4] & 0xE0 ) >> 5; + if(st->wDayOfWeek) // if zero day of week not used. + st->wDayOfWeek = (st->wDayOfWeek + 1)%7; + st->wMonth = data[5] & 0x0F; + st->wYear = 2000 + (data[6] & 0x7F); + +} + diff --git a/src/HTCP56Time2a.cpp b/src/HTCP56Time2a.cpp new file mode 100644 index 0000000..1e0a013 --- /dev/null +++ b/src/HTCP56Time2a.cpp @@ -0,0 +1,137 @@ +/**************************************************************************** +** File name : CP56Time2a.cpp +** Description : CP56Time2a IEC 60870-5-104 time data type implementation +** 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 "HTGlobal.h" + +static const char *_FILE_ ="HTCP56Time2a.cpp"; + +// Constructor: decode CP56Time2a data +CP56Time2a::CP56Time2a(unsigned char *data) +{ + CP56Time2aToTime(data, &stime); +} + +CP56Time2a::~CP56Time2a(void) +{ +} + +// +// return time string of CP56Time2a decoded +// +void CP56Time2a::GetTimeString(char *buf, size_t size) +{ + sprintf(buf,"%2.2d-%2.2d-%4.4d %2.2d:%2.2d:%2.2d.%3.3d", stime.wDay, + stime.wMonth, stime.wYear, stime.wHour, stime.wMinute, + stime.wSecond, stime.wMilliseconds); + return; +} + +// +// return SYSTEMTIME structure of CP56Time2a decoded +// +SYSTEMTIME CP56Time2a::_GetSystemTime(void) +{ + return stime; +} + +// +// return FILETIME structure of CP56Time2a decoded +// +FILETIME CP56Time2a::_GetFileTime(void) +{ + FILETIME ft = {0}; + //SystemTimeToFileTime(&stime, &ft); + return ft; +} + +// +// return CP56Time2a data of actual time. +// +void CP56Time2a::ActualTimeToCP56Time(unsigned char *data) +{ + SYSTEMTIME st; + //GetSystemTime(&st); + TimeToCP56Time2a(&st, data); +} + +// +// convert FILETIME to CP56Time2a +// +void CP56Time2a::TimeToCP56Time2a(FILETIME *ft, unsigned char *data) +{ + SYSTEMTIME st; + //FileTimeToSystemTime(ft, &st); + TimeToCP56Time2a(&st, data); +} + +// +// convert SYSTEMTIME to CP56Time2a +// +void CP56Time2a::TimeToCP56Time2a(SYSTEMTIME *st, unsigned char *data) +{ + unsigned int m; + m = st->wMilliseconds + 1000 * st->wSecond; + data[0] = m & 0xFF; + data[1] = (m & 0xFF00)>>8; + data[2] = st->wMinute & 0x00FF; // add valid flag and genuine flag + data[3] = st->wHour & 0x00FF; // add summer flag + data[4] = ((st->wDayOfWeek%7)&0x03)<<5 | (st->wDay&0x1F); + data[5] = st->wMonth & 0x0F; + data[6] = st->wYear - 2000; +} + +// +// convert CP56Time2a to FILETIME +// +void CP56Time2a::CP56Time2aToTime(unsigned char *data, FILETIME *ft) +{ + SYSTEMTIME st; + CP56Time2aToTime(data, &st); + //SystemTimeToFileTime(&st, ft); +} + +// +// convert CP56Time2a to SYSTEMTIME +// +void CP56Time2a::CP56Time2aToTime(unsigned char *data, SYSTEMTIME *st) +{ + unsigned int mili = data[0] | data[1]<<8; + st->wSecond = mili / 1000; + st->wMilliseconds = mili - st->wSecond*1000; + + if(data[2] & 0x40) + genuine = true; + else + genuine = false; + + if(data[2] & 0x80) + valid = true; + else + valid = false; + + st->wMinute = data[2] & 0x3F; + st->wHour = data[3] & 0x1F; + + if(data[3] & 0x80) + summer = true; + else + summer = false; + + st->wDay = data[4] & 0x1F; + st->wDayOfWeek = (data[4] & 0xE0 ) >> 5; + if(st->wDayOfWeek) // if zero day of week not used. + st->wDayOfWeek = (st->wDayOfWeek + 1)%7; + st->wMonth = data[5] & 0x0F; + st->wYear = 2000 + (data[6] & 0x7F); + +} + diff --git a/src/HTConfig.cpp b/src/HTConfig.cpp new file mode 100644 index 0000000..ba3e870 --- /dev/null +++ b/src/HTConfig.cpp @@ -0,0 +1,690 @@ +/**************************************************************************** +** File name : HTConfig.cpp +** Description : config parameter +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +//#include "StdAfx.h" +#include "HTPublic.h" +#include "HTConst.h" +#include "HTConfig.h" +#include "HTLogger.h" + +static const char *_FILE_ = "HTConfig.cpp" ; + +TConfig::TConfig() +{ + b_monitor_enable = false ; // 监控标志 true:启用 false: 不启用 + + // database config parameter + memset(m_dbHostIP,0x00, sizeof(m_dbHostIP)); + memset(m_dbName, 0x00, sizeof(m_dbName)); + memset(m_dbUserName, 0x00, sizeof(m_dbUserName)); + memset(m_dbUserPass, 0x00, sizeof(m_dbUserPass)); + + m_dbMaxConnect = 1 ; + m_dbMinConnect = 1 ; + m_dbPort = 3306 ; + + + memset(m_remote_addr, 0x00, sizeof(m_remote_addr)); + m_remote_port = 2404 ; + // socket config + m_fd_limit = 1024 ; + + + m_recv_num = 1 ; + m_parse_num = 1 ; + m_opration_num = 1; + m_respone_num = 1 ; + +} + +TConfig::~TConfig() +{ + b_monitor_enable = false ; // 监控标志 true:启用 false: 不启用 + + // database config parameter + memset(m_dbHostIP,0x00, sizeof(m_dbHostIP)); + memset(m_dbName, 0x00, sizeof(m_dbName)); + memset(m_dbUserName, 0x00, sizeof(m_dbUserName)); + memset(m_dbUserPass, 0x00, sizeof(m_dbUserPass)); + + m_dbMaxConnect = 0 ; + m_dbMinConnect = 0 ; + m_dbPort = 3306 ; + + memset(m_remote_addr, 0x00, sizeof(m_remote_addr)); + m_remote_port = 2404 ; + + m_recv_num = 0 ; + m_parse_num = 0 ; + m_opration_num = 0; + m_respone_num = 0 ; +} + +// 设置数据库连接端口 +void TConfig::setdbPort(unsigned int port) +{ + m_dbPort= port; +} + +// 设置数据库连接端口 +unsigned int TConfig::getdbPort() +{ + return m_dbPort; +} + +// 设置数据库主机地址 +void TConfig::setdbHostIP(char *pszDBHostIP) +{ + if(!pszDBHostIP) return ; + strcpy(m_dbHostIP, pszDBHostIP); +} +// 获取数据库主机地址 +char *TConfig::getdbHostIP() +{ + return m_dbHostIP; +} + +// 设置数据库最大连接池数 +void TConfig::setdbMaxConnect(unsigned int max) +{ + m_dbMaxConnect = max; +} +// 获取数据库最大连接池数 +unsigned int TConfig::getdbMaxConnect() +{ + return m_dbMaxConnect; +} + +// 设置数据库最小连接池数 +void TConfig::setdbMinConnect(unsigned int min) +{ + m_dbMinConnect = min; +} +// 获取数据库最小连接池数 +unsigned int TConfig::getdbMinConnect() +{ + return m_dbMinConnect; +} + +// 设置数据库服务名称 +void TConfig::setdbName(char *pszDBName) +{ + if(!pszDBName) return ; + strcpy(m_dbName, pszDBName); +} +// 获取数据库服务名称 +char *TConfig::getdbName() +{ + return m_dbName; +} +// 设置数据库用户名 +void TConfig::setdbUserName(char *pszDBUserName) +{ + if(!pszDBUserName) return ; + strcpy(m_dbUserName, pszDBUserName); +} +// 获取数据库用户名 +char *TConfig::getdbUserName() +{ + return m_dbUserName; +} + +// 设置数据库用户密码 +void TConfig::setdbUserPass(char *pszDBUserPass) +{ + if(!pszDBUserPass) return ; + strcpy(m_dbUserPass, pszDBUserPass); +} +// 获取数据库用户密码 +char *TConfig::getdbUserPass() +{ + return m_dbUserPass; +} + +// 设置本地服务器IP +void TConfig::setLocalAddr(char *pszAddr) +{ + if (!pszAddr) return; + strcpy(m_local_addr, pszAddr); +} +// 获取本地服务器IP +char *TConfig::getLocalAddr() +{ + return m_local_addr; +} + +// 设置本地服务器端口 +void TConfig::setLocalPort(unsigned short iPort) +{ + m_local_port = iPort; +} + +// 获取本地服务器端口 +unsigned short TConfig::getLocalPort() +{ + return m_local_port; +} + + +// 设置远程服务器IP +void TConfig::setRemoteAddr(char *pszAddr) +{ + if(!pszAddr) return ; + strcpy(m_remote_addr, pszAddr); +} +// 获取远程服务器IP +char *TConfig::getRemoteAddr() +{ + return m_remote_addr; +} + +// 设置远程服务器端口 +void TConfig::setRemotePort(unsigned short iPort) +{ + m_remote_port = iPort; +} + +// 获取远程服务器端口 +unsigned short TConfig::getRemotePort() +{ + return m_remote_port; +} + +// socket 相关属性参数配置 +void TConfig::setFdLimit(unsigned int iCount) +{ + m_fd_limit = iCount; +} + +unsigned int TConfig::getFdLimit() +{ + return m_fd_limit; +} + +void TConfig::setK(unsigned int k) +{ + uK = k; +} +void TConfig::setW(unsigned int w) +{ + uW = w; +} +unsigned int TConfig::getK() +{ + return uK; +} +unsigned int TConfig::getW() +{ + return uW; +} +void TConfig::setTimeout0(unsigned int t) +{ + t0 = t; +} +void TConfig::setTimeout1(unsigned int t) +{ + t1 = t; +} +unsigned int TConfig::getTimeout0() +{ + return t0; +} +unsigned int TConfig::getTimeout1() +{ + return t1; +} +void TConfig::setTimeout2(unsigned int t) +{ + t2 = t; +} +unsigned int TConfig::getTimeout2() +{ + return t2; +} +void TConfig::setTimeout3(unsigned int t) +{ + t3 = t; +} +unsigned int TConfig::getTimeout3() +{ + return t3; +} + +void TConfig::setLogDebug(char yes) +{ + m_logdebug = yes; // debug logger +} +void TConfig::setLogError(char yes) +{ + m_logerror = yes; //error logger +} +void TConfig::setLogWarning(char yes) +{ + m_logwarning = yes; // warning logger +} +void TConfig::setLogPack(char yes) +{ + m_logpack = yes; // package print logger +} +void TConfig::setLogConsole(char yes) +{ + m_logconsole = yes; // console print logger +} +void TConfig::setLogMessage(char yes) +{ + m_logmessage = yes; // message print logger +} +char TConfig::isLogDebug(void) +{ + return m_logdebug; // debug logger +} +char TConfig::isLogError(void) +{ + return m_logerror; //error logger +} +char TConfig::isLogWarning(void) +{ + return m_logwarning ; // warning logger +} +char TConfig::isLogPack(void) +{ + return m_logpack ; // package print logger +} +char TConfig::isLogConsole(void) +{ + return m_logconsole; // console print logger +} +char TConfig::isLogMessage(void) +{ + return m_logmessage; // message print logger +} + +void TConfig::setServerVersion(char *pver) +{ + if(pver == NULL) { + strcpy(m_version, "000.00.000"); + return ; + } + strcpy(m_version, pver); +} +char *TConfig::getServerVersion() +{ + return m_version; +} + + +//JT/T809 服务数据交换监控 +void TConfig::setMonitor(bool status) +{ + b_monitor_enable = status; +} +bool TConfig::getMonitor() +{ + return b_monitor_enable; +} + +void TConfig::setRecvThreadNumber(unsigned int n) +{ + m_recv_num = n ; +} +unsigned int TConfig::getRecvThreadNumber() +{ + return m_recv_num ; +} + +void TConfig::setParseThreadNumber(unsigned int n) // 解析104线程数 +{ + m_parse_num = n ; +} +unsigned int TConfig::getParseThreadNumber() +{ + return m_parse_num ; +} + +void TConfig::setOprationThreadNumber(unsigned int n) // 入库线程数 +{ + m_opration_num = n ; +} +unsigned int TConfig::getOprationThreadNumber() +{ + return m_opration_num ; +} + +void TConfig::setResponeThreadNumber(unsigned int n) // 应答线程数 +{ + m_respone_num = n ; +} +unsigned int TConfig::getResponeThreadNumber() +{ + return m_respone_num ; +} +/************************************************************************* + 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 +*************************************************************************/ +int TConfig::iniGetString(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((fpIni= fopen(HT_CONFIG_FILE,"r")) == NULL) return (-1); + + /*** check section ***/ + iSectFlag= 0; + while(!feof(fpIni)) { + if (fgets(szBuf,DEF_BUFFER_1K,fpIni) == 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(fpIni)) { + if(fgets(szBuf,DEF_BUFFER_1K,fpIni) == 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 (iLen==0) return (-1); + if (iLen > (int)uiBufLen) iLen= uiBufLen; + memcpy(pszRetBuf, psz2, iLen); + *(pszRetBuf+iLen)= '\0'; + return (0); + } + fclose(fpIni); + return (-1); +} +// 加载服务配置参数 +bool TConfig::getIniConfig() +{ + int iRet = -1; + char szTmp[64]; + + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_LOGGER","logger", szTmp, sizeof(szTmp))) < 0) { + printf("get logger parameter failed, %s\n", szTmp); + } + + if(strstr(szTmp, "debug") == NULL) setLogDebug(0x00); + else setLogDebug(0x01); + + if(strstr(szTmp, "error") == NULL) setLogError(0x00); + else setLogError(0x01); + + if(strstr(szTmp, "warning") == NULL) setLogWarning(0x00); + else setLogWarning(0x01); + + if(strstr(szTmp, "package") == NULL) setLogPack(0x00); + else setLogPack(0x01); + + if(strstr(szTmp, "console") == NULL) setLogConsole(0x00); + else setLogConsole(0x01); + + if(strstr(szTmp, "message") == NULL) setLogMessage(0x00); + else setLogMessage(0x01); + + //////////////////////////////////////////////////////////////////////////// + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_MONITOR","monitor_enable", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get monitor_enable parameter failed"); + return false; + } + if(stringcasecmp(szTmp, "true") == 0) + setMonitor(true); // 启用监控报文功能 + else setMonitor(false) ; + + //////////////////////////////////////////////////////////////////////////// + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_VERSION","ht_server_version", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get ht_server_version parameter failed"); + return false; + } + setServerVersion(szTmp); + + + //////////////////////////////////////////////////////////////////////////// + // 加载数据库配置参数 + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_DATABASE","db_host_addr", szTmp, sizeof(szTmp))) < 0) { + // vPrtLogMsg(LOG_ERROR, iRet, "get db_host_addr parameter failed"); + // return false; + setdbHostIP((char*)"127.0.0.1"); + } + else setdbHostIP(szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_DATABASE","db_host_port", szTmp, sizeof(szTmp))) < 0) { + //vPrtLogMsg(LOG_ERROR, iRet, "get db_host_port parameter failed"); + //return false; + setdbPort(3306); + } + else setdbPort((unsigned int)atoi(szTmp)); + + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_DATABASE","db_name", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get db_name parameter failed"); + return false; + } + setdbName(szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_DATABASE","db_username", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get db_username parameter failed"); + return false; + } + setdbUserName(szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_DATABASE","db_password", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get db_password parameter failed"); + return false; + } + setdbUserPass(szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_DATABASE","db_min_conn", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get db_min_conn parameter failed"); + return false; + } + setdbMinConnect((unsigned int)atoi(szTmp)); + + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_DATABASE","db_max_conn", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get db_max_conn parameter failed"); + return false; + } + setdbMaxConnect((unsigned int)atoi(szTmp)); + + //////////////////////////////////////////////////////////////////////////// + // 加载服务器端参数 + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iniGetString("HT_LOCAL_HOST", "local_host_addr", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get local_host_addr parameter failed"); + return false; + } + setLocalAddr(szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); // 服务器端口 + if ((iRet = iniGetString("HT_LOCAL_HOST", "local_tcp_port", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get local_tcp_port parameter failed,set define:2404!"); + strcpy(szTmp, "2404"); + //return false; + } + setLocalPort((unsigned int)atoi(szTmp)); + + // 加载服务器端参数 + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_REMOTE_HOST","remote_host_addr", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get remote_host_addr parameter failed"); + return false; + } + setRemoteAddr(szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); // 服务器端口 + if((iRet = iniGetString("HT_REMOTE_HOST","remote_host_port", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get remote_host_port parameter failed,set define:2404!"); + strcpy(szTmp, "2404") ; + //return false; + } + setRemotePort((unsigned int)atoi(szTmp)); + + //////////////////////////////////////////////////////////////////////////// + // socket 相关属性参数配置 + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_SOCKET","max_epoll_limit", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get max_epoll_limit parameter failed"); + return false; + } + setFdLimit((unsigned int)atoi(szTmp)); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iniGetString("HT_SOCKET", "timeout_t0", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get timeout_t0 parameter failed"); + return false; + } + setTimeout0((unsigned int)atoi(szTmp)); + + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_SOCKET","timeout_t1", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get timeout_t1 parameter failed"); + return false; + } + setTimeout1((unsigned int)atoi(szTmp)); + + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_SOCKET","timeout_t2", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get timeout_t2 parameter failed"); + return false; + } + setTimeout2((unsigned int)atoi(szTmp)); + + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_SOCKET","timeout_t3", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get timeout_t3 parameter failed"); + return false; + } + setTimeout3((unsigned int)atoi(szTmp)); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iniGetString("HT_SOCKET", "iec_k", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get iec_k parameter failed"); + return false; + } + setK((unsigned int)atoi(szTmp)); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iniGetString("HT_SOCKET", "iec_w", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get iec_w parameter failed"); + return false; + } + setW((unsigned int)atoi(szTmp)); + //////////////////////////////////////////////////////////////////////////// + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_THREAD_NUMBER","thread_recv_num", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get thread_recv_num parameter failed"); + return false; + } + setRecvThreadNumber((unsigned int)atoi(szTmp)); + + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_THREAD_NUMBER","thread_parse_num", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get thread_parse_num parameter failed"); + return false; + } + setParseThreadNumber((unsigned int)atoi(szTmp)); + + memset(szTmp, 0x00, sizeof(szTmp)); + if((iRet = iniGetString("HT_THREAD_NUMBER","thread_opration_num", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get thread_opration_num parameter failed"); + return false; + } + setOprationThreadNumber((unsigned int)atoi(szTmp)); + + memset(szTmp, 0x00, sizeof(szTmp)); // + if((iRet = iniGetString("HT_THREAD_NUMBER","thread_respone_num", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get thread_respone_num parameter failed"); + return false; + } + setResponeThreadNumber((unsigned int)atoi(szTmp)); + + return true; +} + +void TConfig::showConfig() +{ +// vPrtLogMsg(LOG_DEBUG, 0, "local_server_name=%s local_host_addr=%s local_tcp_port=%d\n" +// "db_host_addr=%s db_port=%d db_name=%s db_username=%s db_password=%s\n" +// "db_min_conn=%d db_max_conn=%d max_epoll_limit=%d loacl_active_interval=%d\n" +// "local_tcp_recv_timeout=%d local_udp_recv_timeout=%d\n" +// //"gov_user_name=%s gov_user_pass=%s gov_host_addr=%s gov_tcp_port=%d gov_tcp_recv_timeout=%d", +// "gov_tcp_recv_timeout=%d", +// m_LocalName, m_LocalAddr, m_LocalTcpPort, +// m_dbHostIP,m_dbPort,m_dbName,m_dbUserName,m_dbUserPass,m_dbMinConnect,m_dbMaxConnect, +// m_fd_limit,m_active_interval,m_tcp_recv_timeout,m_udp_recv_timeout, +// //m_GovUserName,m_GovUserPass,m_GovHostAddr,m_GovTcpPort,m_GovTcpRecvTimeout); +// m_GovTcpRecvTimeout); +} diff --git a/src/HTDatabase.cpp b/src/HTDatabase.cpp new file mode 100644 index 0000000..b582142 --- /dev/null +++ b/src/HTDatabase.cpp @@ -0,0 +1,458 @@ +/**************************************************************************** +** File name : HTDatabase.cpp +** Description : mysql database member function +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#include "HTGlobal.h" +#include "HTDatabase.h" +static const char *_FILE_ = "HTDatabase.cpp" ; + +CDBMySQL::CDBMySQL() +{ + strcpy(m_host,g_TConfig.getdbHostIP()); + strcpy(m_db, g_TConfig.getdbName()); + strcpy(m_user,g_TConfig.getdbUserName()); + strcpy(m_password,g_TConfig.getdbUserPass()); + m_port = g_TConfig.getdbPort(); + m_min = g_TConfig.getdbMinConnect(); + mutex_create(m_csList); +} + +CDBMySQL::CDBMySQL(const char *host, const char *user, const char *password, const char *db, unsigned int port/* =3306 */) +{ + strcpy(m_host, host); + strcpy(m_user, user); + strcpy(m_password, password); + strcpy(m_db, db); + m_port = port; + m_min = g_TConfig.getdbMinConnect(); + mutex_create(m_csList); +} + +CDBMySQL::~CDBMySQL() +{ + dbFreeConnectPool(); +} + +CDBMySQL* CDBMySQL::Instance() +{ + if(p_dbHandle == NULL) + { + try { + p_dbHandle = new CDBMySQL(); + } + catch(...) { + vPrtLogMsg(LOG_WARNG, RET_FAIL, "CDBMySQL::Instance exceptions."); + } + } + return p_dbHandle; +} +void CDBMySQL::dbFreeConnectPool() +{ + ITER_CONNECTION_HANDLE_LIST iter; + for (iter=m_lsBusyList.begin(); iter != m_lsBusyList.end(); iter++) + { + mysql_close((*iter)); + } + + for (iter=m_lsIdleList.begin(); iter != m_lsIdleList.end(); iter++) + { + mysql_close((*iter)); + } + mysql_library_end(); + mutex_close(m_csList); +} + +bool CDBMySQL::dbConnectPool() +{ + try + { + vPrtLogMsg(LOG_DEBUG,0, "connect database:%s/%s@%s -h %s:%d start...", m_user,m_password,m_db,m_host,m_port); + for (int i=0; i < (int)m_min; ++i) + { + char value = 1; + MYSQL *pMySql = mysql_init((MYSQL*)NULL); + //mysql_options(pMySql, MYSQL_SET_CHARSET_NAME, "gbk"); + mysql_options(pMySql, MYSQL_OPT_RECONNECT, (char *)&value); //设置自动连接 + if (pMySql != NULL) + { + if (!mysql_real_connect(pMySql,m_host,m_user,m_password,m_db,m_port,NULL,0)) + { + vPrtLogMsg(LOG_ERROR,errno, "connect database:%s/%s@%s -h %s:%d failed! err:%s", m_user,m_password,m_db,m_host,m_port, getLastError(pMySql)); + return false; + } + mysql_set_character_set(pMySql, "GBK"); + m_lsIdleList.push_back(pMySql); + } + else{ + vPrtLogMsg(LOG_ERROR,errno, "connect database:%s/%s@%s -h %s:%d failed! err:%s", m_user,m_password,m_db,m_host,m_port, getLastError(pMySql)); + } + } + } + catch (...) + { + vPrtLogMsg(LOG_ERROR,errno, "connect database:%s/%s@%s -h %s:%d failed!", m_user,m_password,m_db,m_host,m_port); + return false; + } + return true; +} + +MYSQL* CDBMySQL::GetIdleMySql() +{ + MYSQL* pMySql = NULL; + + mutex_lock(m_csList); + if (m_lsIdleList.size() > 0) + { + pMySql = m_lsIdleList.front(); + if (pMySql ) { + m_lsIdleList.pop_front(); + m_lsBusyList.push_back(pMySql); + mysql_ping(pMySql); // 检查连接是否正常 + } + } + else + { + pMySql = NULL; + } + mutex_unlock(m_csList); + return pMySql; +} + +void CDBMySQL::SetIdleMysql(MYSQL* pMySql) +{ + mutex_lock(m_csList); + if (pMySql) { + if (m_lsBusyList.size() > 0) + m_lsBusyList.remove(pMySql); + m_lsIdleList.push_back(pMySql); + } + mutex_unlock(m_csList); +} +//bStart = false : close auto commit +// = true : open auto commit +bool CDBMySQL::dbAutoCommit(MYSQL *pMysql, bool bStart) // 开始事务处理 +{ + return mysql_autocommit(pMysql, bStart) ? false : true; +} + +bool CDBMySQL::dbCommit(MYSQL *pMysql) +{ + return mysql_commit(pMysql) ? false : true; +} + +MYSQL_RES* CDBMySQL::SelectRecord(const char *szSql) +{ + MYSQL *pMySql = GetIdleMySql(); + if (pMySql == NULL) + { + return NULL; + } + if(mysql_query(pMySql,szSql)) + { + vPrtLogMsg(LOG_ERROR,errno, "SelectRecord failed! SQL:[%s] err:%s", szSql, getLastError(pMySql)); + SetIdleMysql(pMySql); + return NULL; + } + MYSQL_RES *myquery = NULL; + if(!(myquery = mysql_store_result(pMySql))) { + vPrtLogMsg(LOG_ERROR,errno, "SelectRecord failed! SQL:[%s] err:%s", szSql, getLastError(pMySql)); + myquery = NULL; + } + SetIdleMysql(pMySql); + + return myquery; +} + + +bool CDBMySQL::InsertRecordBitch(const char pszSql[][256], int count) +{ + bool bRet = false; + + MYSQL *pMySql = GetIdleMySql(); + if (pMySql == NULL) + { + return false; + } + dbAutoCommit(pMySql, false); // 开始批量提交事务 + //mysql_query(pMySql, "START TRANSACTION"); // 开启事务, 如果没有开启事务,那么效率会变得非常低下! + // return 0: successed !0: failed + for (int n = 0; n < count; n++) + { + if (!mysql_query(pMySql, pszSql[n])) + { + bRet = true; + } + else { + vPrtLogMsg(LOG_ERROR, errno, "InsertRecordBitch failed! ERROR SQL[%d]:[%s] err:%s", n+1, pszSql[n], getLastError(pMySql)); + } + } + dbCommit(pMySql); + dbAutoCommit(pMySql, true); // 结束批量提交事务 + SetIdleMysql(pMySql); + + return bRet; +} + + +bool CDBMySQL::AddInsertRecord(MYSQL *pHandle, const char *szSql) +{ + bool bRet = false; + + // return 0: successed !0: failed + if (!mysql_query(pHandle, szSql)) + { + bRet = true; + } + else { + vPrtLogMsg(LOG_ERROR, errno, "AddInsertRecord failed! SQL:[%s] err:%s", szSql, getLastError(pHandle)); + } + + return bRet; +} + +bool CDBMySQL::InsertRecord(const char *szSql) +{ + bool bRet = false; + + MYSQL *pMySql = GetIdleMySql(); + if (pMySql == NULL) + { + return false; + } + // return 0: successed !0: failed + if(!mysql_query(pMySql,szSql)) + { + bRet = true; + } + else { + vPrtLogMsg(LOG_ERROR,errno, "InsertRecord failed! SQL:[%s] err:%s", szSql, getLastError(pMySql)); + } + SetIdleMysql(pMySql); + + return bRet; +} + +bool CDBMySQL::UpdateRecord(const char *szSql) +{ + bool bRet = false; + + MYSQL *pMySql = GetIdleMySql(); + if (pMySql == NULL) + { + return false; + } + if(!mysql_query(pMySql,szSql)) + { + bRet = true; + } + else { + vPrtLogMsg(LOG_ERROR,errno, "UpdateRecord failed! SQL:[%s] err:%s", szSql, getLastError(pMySql)); + } + SetIdleMysql(pMySql); + + return bRet; +} + +bool CDBMySQL::DelRecord(const char *szSql) +{ + bool bRet = false; + MYSQL *pMySql = GetIdleMySql(); + if (pMySql == NULL) + { + return false; + } + if(!mysql_query(pMySql,szSql)) + { + bRet = true; + } + else { + vPrtLogMsg(LOG_ERROR,errno, "DelRecord failed! SQL:[%s] err:%s", szSql, getLastError(pMySql)); + } + SetIdleMysql(pMySql); + + return bRet; +} + +bool CDBMySQL::SelectDB(const char *szDB) +{ + bool bRet = false; + + MYSQL *pMySql = GetIdleMySql(); + + if (pMySql == NULL) return false; + + if (mysql_select_db(pMySql,szDB)) { + vPrtLogMsg(LOG_ERROR,errno, "SelectDB failed! dbname:[%s] err:%s", szDB, getLastError(pMySql)); + bRet = false; + } + else bRet = true; + + SetIdleMysql(pMySql); + + return bRet; +} + +my_ulonglong CDBMySQL::GetRowNum(MYSQL_RES *myquery) +{ + return mysql_num_rows(myquery); +} + +MYSQL_ROW CDBMySQL::GetRecord(MYSQL_RES *myquery) +{ + m_row = mysql_fetch_row(myquery); + + return m_row; +} + +unsigned int CDBMySQL::GetFieldNum(MYSQL_RES *myquery) +{ + return mysql_num_fields(myquery); +} + +void CDBMySQL::FreeRecord(MYSQL_RES *myquery) +{ + mysql_free_result(myquery); +} + +//int CDBMySQL::CreateDB(char *db) +//{ +// return mysql_create_db(&m_mysql,db); +//} + +void CDBMySQL::SeekData(MYSQL_RES *myquery, int offset) +{ + mysql_data_seek(myquery,offset); +} + + +char * CDBMySQL::getLastError(MYSQL *pMySql) +{ + return const_cast(mysql_error(pMySql)); +} + +bool CDBMySQL::IsEnd(MYSQL_RES *myquery) +{ + return (mysql_eof(myquery)?true:false); +} + +char* CDBMySQL::GetFieldName(MYSQL_RES *myquery, int FieldNum) +{ + m_field = mysql_fetch_field_direct(myquery, FieldNum); + + return m_field->name; +} + +char * CDBMySQL::GetClientInfo() +{ + return const_cast(mysql_get_client_info()); +} + +char* CDBMySQL::GetHostInfo() +{ + char *p = NULL; + MYSQL *pMySql = GetIdleMySql(); + if (pMySql == NULL) + { + return NULL; + } + p = const_cast(mysql_get_host_info(pMySql)); + SetIdleMysql(pMySql); + return p ; +} + +int CDBMySQL::GetProtocolInfo() +{ + int iRet = 0; + MYSQL *pMySql = GetIdleMySql(); + if (pMySql == NULL) + { + return 0; + } + iRet = mysql_get_proto_info(pMySql); + SetIdleMysql(pMySql); + + return iRet; +} + +char* CDBMySQL::GetServerInfo() +{ + static char szRet[1024] = {0}; + + MYSQL *pMySql = GetIdleMySql(); + if (pMySql == NULL) + { + return NULL; + } + strcpy(szRet, const_cast(mysql_get_server_info(pMySql))); + SetIdleMysql(pMySql); + + return szRet; +} + +char* CDBMySQL::GetState() +{ + MYSQL *pMySql = GetIdleMySql(); + if (pMySql == NULL) return NULL; + + static char szRet[1024] = {0} ; + strcpy(szRet,const_cast(mysql_stat(pMySql))); + SetIdleMysql(pMySql); + + return szRet; +} + +bool CDBMySQL::SetCharset() +{ + bool bRet = false; + //char szSql[50] = {0}; + + //strcpy(szSql, "set names gb2312"); + MYSQL *pMySql = GetIdleMySql(); + if (pMySql == NULL) return false; + if(mysql_set_character_set(pMySql, "GBK")) + //if (mysql_query(pMySql, szSql)) + bRet = true; + SetIdleMysql(pMySql); + + return bRet; +} + +//LOCK TABLES tbl1 READ, tbl2 WRITE +bool CDBMySQL::LockTable(const char *TableName, const char *Priority) +{ + bool bRet = false; + char szSql[50] = {0} ; + + sprintf(szSql, "LOCK TABLES %s %s", TableName, Priority); + MYSQL *pMySql = GetIdleMySql(); + if (pMySql == NULL) return false; + + if (mysql_query(pMySql, szSql)) + bRet = true; + SetIdleMysql(pMySql); + + return bRet; +} + +bool CDBMySQL::UnlockTable() +{ + bool bRet = false; + MYSQL *pMySql = GetIdleMySql(); + + if (pMySql == NULL) return false; + + if(mysql_query(pMySql,"UNLOCK TABLES")) bRet = true; + + SetIdleMysql(pMySql); + + return bRet; +} + diff --git a/src/HTGlobal.cpp b/src/HTGlobal.cpp new file mode 100644 index 0000000..2ea43f8 --- /dev/null +++ b/src/HTGlobal.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** File name : FLTGlobal.h +** Description : global variable define +** Create date : 2012.10.10 +** 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 +****************************************************************************/ +#pragma warning (disable:4786) +//#include "StdAfx.h" +#include "HTGlobal.h" + +TConfig g_TConfig ; +TTcpSocket g_Tcp; +int g_Running; + +ST_IEC104_CTRL g_IecCtrl; // socket linker info and status +mutex g_IecCtrl_mutex; // socket linker on mutex + +int g_seqno; // 与MEC之间交换的流水号 +mutex g_seq_mutex; // 流水号 + +map g_map_work; // 主变工作状态缓存 +mutex g_map_work_mutex; // 主变工作状态缓存队列锁 + +//map g_map_byq; // 变压器缓存数据 +map g_map_thres_byq; +mutex g_map_byq_mutex; // 变压器缓存数据信息队列锁 + +//map g_map_gis; // GIS缓存数据 +//mutex g_map_gis_mutex; // GIS缓存数据信息队列锁 + +multimap g_map_relation; // 主设备与外挂设备关系 +mutex g_map_relation_mutex; // GIS缓存数据信息队列锁 + +//map g_map_gis_104; // GIS最近一次104上传数据缓存 +//mutex g_map_gis_104_mutex; + +//map g_map_blq; // BLQ缓存数据 +//mutex g_map_blq_mutex; // BLQ缓存数据信息队列锁 + +map g_map_iec; // 104点表报文解析缓存数据 +mutex g_map_iec_mutex; // 104报文解析缓存数据信息队列锁 + +map g_map_sadr; // 点表匹配关系 +mutex g_map_sadr_mutex; + +map g_map_img_thres; // 图片识别阈值 +mutex g_map_img_thres_mutex; + +map g_map_dev_time_stat; +mutex g_map_dev_time_stat_mutex; + +map g_map_gis_state; // 断路器状态位与电流电压关系匹配表 +mutex g_map_gis_state_mutex; + + +pthread_t thread_handle_parse; // 104报文解析线程 +//pthread_t thread_handle_setdb; // 入库线程 +pthread_t thread_handle_timer; // 超时监测线程 +//pthread_t thread_handle_getdata; // 数据提取线程 + +pthread_t thread_handle_client; // 客户端链接线程 +pthread_t thread_handle_warning; // 报警处理及入库线程句柄 +pthread_t thread_handle_origin; // 原始数据如何线程句柄 +pthread_t thread_handle_pingce; // IEC104评测数据入库线程句柄 +pthread_t thread_handle_gishold; // 断路器断开数据入库线程句柄 + +pthread_t thread_handle_active; // 心跳线程 +pthread_t thread_handle_linkmgr; // 链路管理线程 +pthread_t thread_handle_cache; // 内存同步线程句柄 + +pthread_t thread_handle_opecvimg; // 图片识别线程句柄 + diff --git a/src/HTIEC104.cpp b/src/HTIEC104.cpp new file mode 100644 index 0000000..283684b --- /dev/null +++ b/src/HTIEC104.cpp @@ -0,0 +1,682 @@ +/**************************************************************************** +** 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_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配置. + // 打开配置文件,准备加载配置参数 + 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 = (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); + + // 获取公共地址配置 + 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(L \ No newline at end of file diff --git a/src/HTImageBusi.cpp b/src/HTImageBusi.cpp new file mode 100644 index 0000000..d6918b0 --- /dev/null +++ b/src/HTImageBusi.cpp @@ -0,0 +1,193 @@ +/**************************************************************************** +** File name : HTImageBusi.cpp +** Description : define memory data struct +** 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 "HTGlobal.h" +//#include "HTIEC104.h" +//#include "HTMemCacheData.h" + +static const char *_FILE_ = "HTImageBusi.cpp"; + + +/*************************************************************************** +** function name : getImageThreshold +** deacription : get image define value +** parameter : none +** return code : NULL +***************************************************************************/ +static void getImageThreshold(char *szSql) +{ + int wstate = 0; + double value = 0.0f; + CDBMySQL *pdbHandle = CDBMySQL::Instance(); + if (!pdbHandle) return; + + MYSQL_RES *res = pdbHandle->SelectRecord(szSql); + if (!res) return; + + MYSQL_ROW row = NULL; + while (row = pdbHandle->GetRecord(res)) + { + ST_IMG_THRESHOLD stThreshold; + string strKey = ""; + + memset(&stThreshold, 0x00, sizeof(ST_IMG_THRESHOLD)); + memset(&stThreshold.value, 0xff, sizeof(double) * 3); + + if (row[0] && strlen(row[0]) > 0) { + strncpy((char*)stThreshold.sensor_id, (const char*)row[0], sizeof(stThreshold.sensor_id)); + strKey = row[0]; + } + + if (row[1] && strlen(row[1]) > 0) { + strncpy((char*)stThreshold.site_id, (const char*)row[1], sizeof(stThreshold.site_id)); + } + + if (row[2] && strlen(row[2]) > 0) { + stThreshold.phase = row[2][0]; + } + if (row[3] && strlen(row[3]) > 0) { + strncpy((char*)stThreshold.desc, (const char*)row[3], sizeof(stThreshold.desc)); + } + if (row[4] && strlen(row[4]) > 0) { + strncpy((char*)stThreshold.eqm_code, (const char*)row[4], sizeof(stThreshold.eqm_code)); + } + + //工作状态:1 - 发电状态 2:抽水状态 3:空闲状态 + if (row[5] && strlen(row[5]) > 0) { + wstate = atoi((const char*)row[5]); + } + if (row[6] && strlen(row[6]) > 0) { + value = atof((const char*)row[6]); + } + else value = HT_INVALID_VALUE; + + if (row[7] && strlen(row[7]) > 0) { + stThreshold.eqm_type = (unsigned char)atoi((const char*)row[7]); + } + if (row[8] && strlen(row[8]) > 0) { + strncpy((char*)stThreshold.system_code, (const char*)row[8], sizeof(stThreshold.system_code)); + } + map::iterator m_pIter; + mutex_lock(g_map_img_thres_mutex); + m_pIter = g_map_img_thres.find((char*)stThreshold.sensor_id); + if (m_pIter != g_map_img_thres.end()) + { + switch (wstate) + { + case 1: + (m_pIter->second).value[0] = value; + break; + case 2: + (m_pIter->second).value[1] = value; + break; + case 3: + (m_pIter->second).value[2] = value; + break; + default:; + } + } + else { + if (wstate == 1) stThreshold.value[0] = value; + else if (wstate == 2) stThreshold.value[1] = value; + else if (wstate == 3) stThreshold.value[2] = value; + g_map_img_thres.insert(map::value_type(strKey, stThreshold)); + } + mutex_unlock(g_map_img_thres_mutex); + } + pdbHandle->FreeRecord(res); + return; +} +// 加载图片阈值,包括变压器、GIS、避雷器三大主设备 +void vLoadImageThreshold() +{ + char szSql[DEF_BUFFER_1K+512] = { 0 }; + + // 加载变压器图片阈值 + snprintf(szSql, sizeof(szSql), "SELECT sensor.sensor_code, sensor.site_id, sensor.position, sensor.position_des, tree.id AS m_eqm_code," + "t.work_status, t.threshold, t.type, tree.system_code " + "FROM photo_threshold t, busi_site_tree tree, busi_transformer_sub_tree sub, busi_transformer_sensor sensor " + "WHERE t.main_tree_id = tree.id AND sub.equipment_id = tree.id AND t.sensor_code = sensor.sensor_code " + "AND sensor.equipment_id = sub.id and tree.status = '1'and sub.status = '1'and sensor.status = '1' " + "AND sub.equipment_type = '051' AND tree.equipment_type = '111' " + "ORDER BY sensor.sensor_code,t.work_status"); + getImageThreshold(szSql); + + // 加载GIS图片阈值 + snprintf(szSql, sizeof(szSql), "SELECT sensor.sensor_code, sensor.site_id, sensor.position, sensor.position_des, tree.id AS m_eqm_code," + "t.work_status, t.threshold, t.type, tree.system_code " + "FROM photo_threshold t, busi_site_tree tree, busi_gis_sub_tree sub, busi_gis_sensor sensor " + "WHERE t.main_tree_id = tree.id AND sub.equipment_id = tree.id AND t.sensor_code = sensor.sensor_code " + "AND sensor.equipment_id = sub.id and tree.status = '1'and sub.status = '1'and sensor.status = '1' " + "AND sub.equipment_type = '061' AND tree.equipment_type = '211' " + "ORDER BY sensor.sensor_code,t.work_status"); + getImageThreshold(szSql); + + // 加载避雷器图片阈值 + snprintf(szSql, sizeof(szSql), "SELECT sensor.sensor_code, sensor.site_id, sensor.position, sensor.position_des, tree.id AS m_eqm_code," + "t.work_status, t.threshold, t.type, tree.system_code " + "FROM photo_threshold t, busi_site_tree tree, busi_arrester_sub_tree sub, busi_arrester_sensor sensor " + "WHERE t.main_tree_id = tree.id AND sub.equipment_id = tree.id AND t.sensor_code = sensor.sensor_code " + "AND sensor.equipment_id = sub.id and tree.status = '1'and sub.status = '1'and sensor.status = '1' " + "AND sub.equipment_type = '051' AND tree.equipment_type = '411' " + "ORDER BY sensor.sensor_code,t.work_status"); + getImageThreshold(szSql); + // 加载其他类图片阈值 + snprintf(szSql, sizeof(szSql), "SELECT sensor.sensor_code, sensor.site_id, sensor.position, sensor.position_des, tree.id AS m_eqm_code," + "t.work_status, t.threshold, t.type, tree.system_code " + "FROM photo_threshold t, busi_site_tree tree, busi_other_sub_tree sub, busi_other_sensor sensor " + "WHERE t.main_tree_id = tree.id AND sub.equipment_id = tree.id AND t.sensor_code = sensor.sensor_code " + "AND sensor.equipment_id = sub.id and tree.status = '1'and sub.status = '1'and sensor.status = '1' " + "AND sub.equipment_type = '031' AND tree.equipment_type = '511' " + "ORDER BY sensor.sensor_code,t.work_status"); + getImageThreshold(szSql); + +} + +void vPrtImageThreshold(void) +{ + map::iterator m_pIter; + m_pIter = g_map_img_thres.begin(); + vPrtLogMsg(LOG_DEBUG, RET_OK, "---------Print Image Threshold Tables----------"); + vPrtLogMsg(LOG_DEBUG, RET_OK, "site_id\t\t\t\t eqm_code\t\t\t system_code\t T sensor_id value(1,2,3)"); + while (m_pIter != g_map_img_thres.end()) + { + vPrtLogMsg(LOG_DEBUG, RET_OK, "%-s %s %s %d %s [%.2f,%.2f,%.2f]", + (m_pIter->second).site_id, (m_pIter->second).eqm_code, (m_pIter->second).system_code, + (m_pIter->second).eqm_type, (m_pIter->second).sensor_id, + (m_pIter->second).value[0], (m_pIter->second).value[1], (m_pIter->second).value[2]); + m_pIter++; + } + vPrtLogMsg(LOG_DEBUG, RET_OK, "---------- Image_Threshold_size:%d-----------", g_map_img_thres.size()); + return; +} + + +// 根据sensor_id,获取阈值 +bool getImageThresholdValuse(const char *sensor_id, ST_IMG_THRESHOLD &pstThresdhold) +{ + map::iterator m_pIter; + double val = 0.0f; + mutex_lock(g_map_img_thres_mutex); + m_pIter = g_map_img_thres.find((char*)sensor_id); + if (m_pIter != g_map_img_thres.end()) + { + memcpy(&pstThresdhold, &(m_pIter->second), sizeof(ST_IMG_THRESHOLD)); + mutex_unlock(g_map_img_thres_mutex); + return true; + } + mutex_unlock(g_map_img_thres_mutex); + return false; +} + + + + diff --git a/src/HTInitUtils.cpp b/src/HTInitUtils.cpp new file mode 100644 index 0000000..1577df9 --- /dev/null +++ b/src/HTInitUtils.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** File name : HTInitUtils.cpp +** Description : Defines service initialization API +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#include "HTGlobal.h" +#include "HTInitUtils.h" + +static const char *_FILE_ = "HTInitUtils.cpp" ; + +// make and get a globle seq number +int get_seqno(void) +{ + int iseq = 0; + mutex_lock(g_seq_mutex); + iseq = ++g_seqno ; + if(g_seqno >= 255 ) + g_seqno = 0; + mutex_unlock(g_seq_mutex); + return iseq; +} + +int loadServiceEvent() +{ + // 初始化日志共享资源锁 + vInitLogMutex(); // 初始化log文件锁与句柄 + mutex_create(g_seq_mutex); + mutex_create(g_IecCtrl_mutex); + mutex_create(g_map_byq_mutex); + //mutex_create(g_map_gis_mutex); + //mutex_create(g_map_blq_mutex); + //mutex_create(g_map_gis_104_mutex); + mutex_create(g_map_iec_mutex); + mutex_create(g_map_relation_mutex); + mutex_create(g_map_sadr_mutex); + mutex_create(g_map_img_thres_mutex); + mutex_create(g_map_work_mutex); + mutex_create(g_map_dev_time_stat_mutex); + mutex_create(g_map_gis_state_mutex); + memset(&g_IecCtrl, 0x00, sizeof(ST_IEC104_CTRL)); + g_Running = 1 ; // 服务启动标志 + g_TConfig.getIniConfig(); + IEC104EnvLoad(); + if(!CDBMySQL::Instance()->dbConnectPool()) { + vFreeLogMutex(); // 释放log文件锁与句柄 + mutex_close(g_seq_mutex); + mutex_close(g_IecCtrl_mutex); + mutex_close(g_map_byq_mutex); + //mutex_close(g_map_gis_mutex); + //mutex_close(g_map_blq_mutex); + //mutex_close(g_map_gis_104_mutex); + mutex_close(g_map_iec_mutex); + mutex_close(g_map_relation_mutex); + mutex_close(g_map_sadr_mutex); + mutex_close(g_map_img_thres_mutex); + mutex_close(g_map_work_mutex); + mutex_close(g_map_dev_time_stat_mutex); + mutex_close(g_map_gis_state_mutex); + IEC104EnvFree(); + g_Running = 0 ; + return RET_FAIL; + } + return RET_OK; +} + +// 重新从数据库加载配置 +void reloadServiceEvent(int platform_id) +{ + //TDatabase* g_TDatabase = NULL; + //g_TDatabase = TDatabase::Instance(); +} + +int unLoadServiceEvent() +{ + CDBMySQL::Instance()->dbFreeConnectPool(); + g_Running = 0 ; + HTFreeThreadHandle(); + // 释放日志共享资源锁 + + mutex_close(g_seq_mutex); + mutex_close(g_IecCtrl_mutex); + mutex_close(g_map_byq_mutex); + // mutex_close(g_map_gis_mutex); + // mutex_close(g_map_blq_mutex); + //mutex_close(g_map_gis_104_mutex); + mutex_close(g_map_iec_mutex); + mutex_close(g_map_relation_mutex); + mutex_close(g_map_sadr_mutex); + mutex_close(g_map_img_thres_mutex); + mutex_close(g_map_work_mutex); + mutex_close(g_map_dev_time_stat_mutex); + mutex_close(g_map_gis_state_mutex); + IEC104EnvFree(); + return RET_OK; +} + + + diff --git a/src/HTLogger.cpp b/src/HTLogger.cpp new file mode 100644 index 0000000..31d21c3 --- /dev/null +++ b/src/HTLogger.cpp @@ -0,0 +1,283 @@ +/**************************************************************************** +** File name : FLTLogger.cpp +** Description : logger function define +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +**************************************************************************** + + ++++++++++ 关于64位整数的打印说明 ++++++++++ + (1) windows os + printf("int_64 = %I64d\n", int64); -- 打印有符号64位整数 + printf("int_64 = %I64u\n", int64); -- 打印无符号64位整数 + + (2) Linux os + printf("int_64 = %lld\n", int64); -- 打印有符号64位整数 + printf("int_64 = %llu\n", int64); -- 打印无符号64位整数 + +****************************************************************************/ +//#include "StdAfx.h" +#include "HTGlobal.h" +#include "HTPublic.h" +#include "HTLogger.h" + +static const char *_FILE_="HTLogger.cpp"; +static char g_logger_time[15] ; // 日志文件名称时间(YYYYMMDD) + +/* mutex define */ +static mutex mutex_Debug ; //跟踪日志 +static FILE *g_fp; +/**************************************************************** +** Description : 初始化日志文件句柄锁 +** param in : None +** : +** param out : None +** return code : None +****************************************************************/ +void vInitLogMutex(void) +{ + char szFile[DEF_BUFFER_256]; + + mutex_create(mutex_Debug); + + // 创建日志文件并打开文件 + memset(szFile, 0x00, sizeof(szFile)) ; + memset(g_logger_time, 0x00, sizeof(g_logger_time)); // 记录当前日志文件的时间(YYYYMMDD) + vGetHostTime(g_logger_time) ; + + #ifdef _WIN32 + sprintf(szFile,"%s\\debug%.8s.log", DEF_LOG_PATH_NAME,g_logger_time) ; + #else + sprintf(szFile,"%s/debug%.8s.log",DEF_LOG_PATH_NAME, g_logger_time) ; + #endif + if(iDirOrFileExist(DEF_LOG_PATH_NAME) != 0) { + //文件或目录不存在时, 创建文件或目录 + if(iBuildDirent(DEF_LOG_PATH_NAME) != 0) { + printf("line:%d file:%s Create Directory:[%s] failed.\n",__LINE__,_FILE_, DEF_LOG_PATH_NAME); + return; + } + } + g_fp = fopen((const char*)szFile, (const char*)"a+"); + if(NULL == g_fp) { + printf("line:%d file:%s Can't open file:[%s] failed.\n",__LINE__,_FILE_, szFile); + return; + } + if(iDirOrFileExist(DEF_RUN_INFO_PATH) != 0) { + //文件或目录不存在时, 创建文件或目录 + if((iBuildDirent(DEF_RUN_INFO_PATH)) != 0) { + vPrtLogMsg(LOG_ERROR, errno, "Create Directory:[%s] failed,%s.", DEF_RUN_INFO_PATH,strerror(errno)); + return; + } + } +} +/**************************************************************** +** Description : 释放日志文件句柄锁 +** param in : None +** : +** param out : None +** return code : None +****************************************************************/ +void vFreeLogMutex(void) +{ + mutex_close(mutex_Debug); + if(g_fp) fclose(g_fp); +} + +/********************************************************************** +** Description : 打印错误日志 +** param in : iLine -- 行号 +** : *szFileName -- 文件名 +** : *szErrMsg -- 错误信息 +** : iCode -- 报文代码 或 错误码 +** param out : None +** return code : +** : None +** : None +**********************************************************************/ +void vPrtLogMsg(int line, const char *pszFileName, char logLevel, int iCode, /* const char *pszMsg,*/ ...) +{ + char szTime[30],szFile[DEF_BUFFER_128]; // 128 + char *p=NULL, szBuf[DEF_BUFFER_2K+1]; + va_list vl ; + + if(logLevel == __LOG_DEBUG ) { + if(g_TConfig.isLogDebug() == 0x00 /*&& g_TConfig.isLogConsole() == 0x00 && g_TConfig.isLogMessage() == 0x00 */) return; + } + else if(logLevel == __LOG_WARNG) { + if(g_TConfig.isLogWarning() == 0x00 /*&& g_TConfig.isLogConsole() == 0x00 && g_TConfig.isLogMessage() == 0x00 */) return; + } + else if(logLevel == __LOG_ERROR) { + if(g_TConfig.isLogError() == 0x00 /*&& g_TConfig.isLogConsole() == 0x00 && g_TConfig.isLogMessage() == 0x00 */) return; + } + + if(g_fp == NULL) return ; + mutex_lock(mutex_Debug); //lock + + //fseek(g_fp, 0l, SEEK_END) ; + vGetHostTime(szTime) ; + // if( ftell(g_fp) >= DEF_LOG_FILESZIE) { // 日志大小已经制定字节数时备份文件,并重新打开新文件 + if( memcmp(szTime, g_logger_time, 8) != 0x00 ) { // 检查日志文件的时间是否为同一天,不是同一天时,重新产生新一天的日志文件名称 + fclose(g_fp) ; + + char szNFile[DEF_BUFFER_256]; + memset(szNFile, 0x00, sizeof(szNFile)) ; + #ifdef _WIN32 + sprintf(szNFile, "%s\\debug%.12s.bak", DEF_LOG_PATH_NAME,szTime) ; + sprintf(szFile, "%s\\debug%.8s.log", DEF_LOG_PATH_NAME,szTime) ; + #else + sprintf(szNFile, "%s/debug%.12s.bak", DEF_LOG_PATH_NAME,szTime) ; + sprintf(szFile, "%s/debug%.8s.log",DEF_LOG_PATH_NAME, szTime) ; + #endif + rename(szFile, szNFile) ; + if((g_fp = fopen(szFile,"a+")) == NULL) { + mutex_unlock(mutex_Debug); //unlock + printf("line:%d file:%s Can't open file:[%s] failed.\n",__LINE__,_FILE_, szFile); + return ; + } + strncpy(g_logger_time, szTime, 14); // 记录最近一次变更过的时间(YYYYMMDD) + } + memset(szTime,0,sizeof(szTime)) ; + memset(szBuf, 0x00, sizeof(szBuf)); + + vGetHostTimeFmt(szTime); + + if(logLevel == __LOG_DEBUG) { // 跟踪日志 + //if(g_TConfig.isLogConsole() == 0x00) + fprintf(g_fp,"[%s] [DEBUG]-%ld Line:%d %s --> RetCode:%d ",szTime, GETTID(),line, pszFileName, iCode); + sprintf(szBuf,"[%s] [DEBUG]-%ld Line:%d %s --> RetCode:%d ",szTime, GETTID(),line, pszFileName, iCode); + } + else if(logLevel == __LOG_WARNG) { // 告警日志 + //if(g_TConfig.isLogConsole() == 0x00) + fprintf(g_fp,"[%s] [WARNING]-%ld Line:%d %s --> RetCode:%d ",szTime, GETTID(),line, pszFileName, iCode); + sprintf(szBuf,"[%s] [WARNING]-%ld Line:%d %s --> RetCode:%d ",szTime, GETTID(),line, pszFileName, iCode); + } + else if(logLevel == __LOG_ERROR) { // 错误日志 + //if(g_TConfig.isLogConsole() == 0x00) + fprintf(g_fp,"[%s] [ERROR]-%ld Line:%d %s --> RetCode:%d ",szTime, GETTID(),line, pszFileName, iCode); + sprintf(szBuf,"[%s] [ERROR]-%ld Line:%d %s --> RetCode:%d ",szTime, GETTID(),line, pszFileName, iCode); + } + if(g_TConfig.isLogConsole() == 0x01) { // 屏幕输出 + printf("%s ", szBuf) ; + } + va_start(vl, iCode); + + while((p = va_arg(vl, char *))) { + #ifdef _WIN32 + _vsnprintf(szBuf, sizeof(szBuf), p, vl); + #else + vsnprintf(szBuf, sizeof(szBuf), p, vl); + #endif + break; + } + va_end(vl); + if(g_TConfig.isLogConsole() == 0x01) { // 屏幕输出 + printf("%s\n", szBuf) ; + } + fprintf(g_fp,"%s\n",szBuf); + fflush(g_fp); + + mutex_unlock(mutex_Debug); //unlock +} +/************************************************************************* +** Description : 打印日志文件(16进制数据报文的打印) +** param in : iLine -- 打印的出处,行号 +** : *szFileName -- 文件名 +** : *pszTitle -- 主题提示信息 +** : *pusMsg -- 报文数据 +** : uiMsgLen -- 报文长度 +** param out : None +** return code : None +************************************************************************/ +void vPrtLogHex(int line, const char *pszFileName,char logLevel, int sockid, /* unsigned short msg_id, */ + const char pszMsgType, unsigned char *pusMsg,int uiMsgLen) +{ + int i, j; + char szBuf1[80+1], szBuf2[80+1]; + char szTime[20+1], szHex[3+1]; + char szFile[DEF_BUFFER_256]; + char szTitle[1024]={0}; + + if(g_TConfig.isLogPack() == 0x00) return ; + + if(g_fp == NULL) return ; + mutex_lock(mutex_Debug); //lock + + //fseek(g_fp, 0l, SEEK_END) ; + vGetHostTime(szTime) ; + if( memcmp(szTime, g_logger_time, 8) != 0x00) { // 检查日志文件的时间是否为同一天,不是同一天时,重新产生新一天的日志文件名称 + // if(ftell(g_fp) >= DEF_LOG_FILESZIE) { + fclose(g_fp) ; + + char szNFile[DEF_BUFFER_256]; + memset(szNFile, 0x00, sizeof(szNFile)) ; + #ifdef _WIN32 + sprintf(szNFile, "%s\\debug%.12s.bak", DEF_LOG_PATH_NAME,szTime) ; + sprintf(szFile, "%s\\debug%.8s.log",DEF_LOG_PATH_NAME, szTime) ; + #else + sprintf(szNFile, "%s/debug%.12s.bak", DEF_LOG_PATH_NAME,szTime) ; + sprintf(szFile, "%s/debug%.8s.log",DEF_LOG_PATH_NAME, szTime) ; + #endif + rename(szFile, szNFile) ; + if((g_fp = fopen(szFile,"a+")) == NULL) { + mutex_unlock(mutex_Debug); //unlock + printf("line:%d file:%s Can't open file:[%s] failed.\n",__LINE__, _FILE_, szFile); + return ; + } + strncpy(g_logger_time, szTime,14); // 记录最近一次变更过的时间(YYYYMMDD) + } + vGetHostTimeFmt( szTime ) ; /* 获取系统时间 */ + if(pszMsgType == PRT_PACK_SEND) { + fprintf(g_fp, "[%s] [DEBUG]-%ld Line:%d %s --> [SendData] sockid:%d length:%d\n",szTime, GETTID(),line,pszFileName,sockid,uiMsgLen); + sprintf(szTitle, "[%s] [DEBUG]-%ld Line:%d %s --> [SendData] sockid:%d length:%d\n",szTime, GETTID(),line,pszFileName,sockid,uiMsgLen); + } + else if(pszMsgType == PRT_PACK_RECV) { + fprintf(g_fp, "[%s] [DEBUG]-%ld Line:%d %s --> [RecvData] sockid:%d length:%d\n",szTime, GETTID(),line,pszFileName,sockid,uiMsgLen); + sprintf(szTitle, "[%s] [DEBUG]-%ld Line:%d %s --> [RecvData] sockid:%d length:%d\n",szTime, GETTID(),line,pszFileName,sockid,uiMsgLen); + } + else { + fprintf(g_fp, "[%s] [DEBUG]-%ld Line:%d %s --> [PrntData] sockid:%d length:%d\n",szTime, GETTID(),line,pszFileName,sockid,uiMsgLen); + sprintf(szTitle, "[%s] [DEBUG]-%ld Line:%d %s --> [PrntData] sockid:%d length:%d\n",szTime, GETTID(),line,pszFileName,sockid,uiMsgLen); + } + if(g_TConfig.isLogConsole() == 0x01) { // 屏幕输出 + printf("%s", szTitle); + } + sprintf(szTitle, "[%s] [DEBUG]-%ld Line:%d %s", szTime,GETTID(),line,pszFileName) ; + + for(i=0; i= (uiMsgLen%16) ) + break; + sprintf(szHex, "%02X ", pusMsg[j]&0xFF); + strcat(szBuf1, szHex); + if(j==7) + strcat(szBuf1, " "); + if(pusMsg[j]>0x20 && pusMsg[j]<0x0ff) + szBuf2[j] = pusMsg[j]; + else + szBuf2[j] = '_'; + } + for(; j<16; j++) + { + if(j==7) + strcat(szBuf1, " "); + strcat(szBuf1, " "); + } + fprintf(g_fp, "%s --> %s %s\n", szTitle, szBuf1, szBuf2); + if(g_TConfig.isLogConsole() == 0x01) { // 屏幕输出 + printf("%s --> %s %s\n", szTitle, szBuf1, szBuf2); + } + } + fflush(g_fp); // 写入文件 + mutex_unlock(mutex_Debug); //unlock +} + diff --git a/src/HTMemCacheData.cpp b/src/HTMemCacheData.cpp new file mode 100644 index 0000000..4eeea38 --- /dev/null +++ b/src/HTMemCacheData.cpp @@ -0,0 +1,794 @@ +/**************************************************************************** +** File name : HTMemCacheData.cpp +** Description : define memory data struct +** 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 "HTGlobal.h" +#include "HTIEC104.h" +#include "HTMemCacheData.h" + +static const char *_FILE_ = "HTMemData.cpp"; + + +/*************************************************************************** +** function name : vLoadBYQThresholdTable +** deacription : get byq define value & site_id-->site_code relation. +** parameter : none +** return code : NULL +***************************************************************************/ +static void vLoadBYQThresholdTable(bool is_load) +{ + char szSql[1024] = { 0 }; + int wstate = 0; + CDBMySQL *pdbHandle = CDBMySQL::Instance(); + if (!pdbHandle) return; + + snprintf(szSql, sizeof(szSql), "select t1.name,t1.site_id,t1.system_code,t.main_tree_id,t.work_status," + "t.coolingwater_inlet_pressure, t.coolingwater_outlet_pressure, t.coolingwater_inlet_temperature, t.coolingwater_outlet_temperature," + "t.circulating_oil_inlet_pressure,t.circulating_oil_outlet_pressure, t.winding_temperature, t.oilpillow_oillevel, t.transformer_Ontology_oillevel," + "t.oil_temperature, t.top_oil_temperature,t.circulating_oil_inlet_temperature,t.circulating_oil_out_temperature " + "from busi_site_tree t1, transformer_runing_status_threshold t " + "where t1.id = t.main_tree_id and t1.status = '1' and t1.site_id = t.site_id " + "order BY t1.system_code"); + + MYSQL_RES *res = pdbHandle->SelectRecord(szSql); + if (!res) return; + + MYSQL_ROW row = NULL; + while (row = pdbHandle->GetRecord(res)) + { + ST_BYQ_RUN_STATE_THRESHOLD stByq; + int idx = 0; + ST_STAT_THRESHOLD stThreshold; + string strKey = ""; + memset(&stByq, 0x00, sizeof(ST_BYQ_RUN_STATE_THRESHOLD)); + memset(&stThreshold, 0x00, sizeof(ST_STAT_THRESHOLD)); + + if (row[0] && strlen(row[0]) > 0) { + strncpy((char*)stByq.dev_name, (const char*)row[0], sizeof(stByq.dev_name)); + } + + if (row[1] && strlen(row[1]) > 0) { + strncpy((char*)stByq.site_id, (const char*)row[1], sizeof(stByq.site_id)); + } + + if (row[2] && strlen(row[2]) > 0) { + strncpy((char*)stByq.system_code, (const char*)row[2], sizeof(stByq.system_code)); + //strKey = (char*)stByq.system_code; + } + if (row[3] && strlen(row[3]) > 0) { + strncpy((char*)stByq.eqm_code, (const char*)row[3], sizeof(stByq.eqm_code)); // main_tree_id源自表busi_site_tree.id + strKey = (char*)stByq.eqm_code; + } + + //工作状态:1 - 发电状态 2:抽水状态 3:空闲状态 + if (row[4] && strlen(row[4]) > 0) { + wstate = atoi((const char*)row[4]); + } + + //stThreshold.wstate = wstate; + if (row[5] && strlen(row[5]) > 0) { + strcpy(stThreshold.stField[idx].field, "coolingwater_inlet_pressure"); + stThreshold.stField[idx++].value = atof((const char*)row[5]); // 冷却水进口压力 + } + else { + strcpy(stThreshold.stField[idx].field, "coolingwater_inlet_pressure"); + stThreshold.stField[idx++].value = HT_INVALID_VALUE; // 冷却水进口压力 + } + + if (row[6] && strlen(row[6]) > 0) { + strcpy(stThreshold.stField[idx].field, "coolingwater_outlet_pressure"); + stThreshold.stField[idx++].value = atof((const char*)row[6]); // 冷却水出口压力 + } + else { + strcpy(stThreshold.stField[idx].field, "coolingwater_outlet_pressure"); + stThreshold.stField[idx++].value = HT_INVALID_VALUE; // 冷却水出口压力 + } + if (row[7] && strlen(row[7]) > 0) { + strcpy(stThreshold.stField[idx].field, "coolingwater_inlet_temperature"); + stThreshold.stField[idx++].value = atof((const char*)row[7]); // 冷却水进口温度 + } + else { + strcpy(stThreshold.stField[idx].field, "coolingwater_inlet_temperature"); + stThreshold.stField[idx++].value = HT_INVALID_VALUE; // 冷却水进口温度 + } + if (row[8] && strlen(row[8]) > 0) { + strcpy(stThreshold.stField[idx].field, "coolingwater_outlet_temperature"); + stThreshold.stField[idx++].value = atof((const char*)row[8]); // 冷却水出口温度 + } + else { + strcpy(stThreshold.stField[idx].field, "coolingwater_outlet_temperature"); + stThreshold.stField[idx++].value = HT_INVALID_VALUE; // 冷却水出口温度 + } + if (row[9] && strlen(row[9]) > 0) { + strcpy(stThreshold.stField[idx].field, "circulating_oil_inlet_pressure"); + stThreshold.stField[idx++].value = atof((const char*)row[9]); // 循环油进口压力 + } + else { + strcpy(stThreshold.stField[idx].field, "circulating_oil_inlet_pressure"); + stThreshold.stField[idx++].value = HT_INVALID_VALUE; // 循环油进口压力 + } + if (row[10] && strlen(row[10]) > 0) { + strcpy(stThreshold.stField[idx].field, "circulating_oil_outlet_pressure"); + stThreshold.stField[idx++].value = atof((const char*)row[10]); // 循环油出口压力 + } + else { + strcpy(stThreshold.stField[idx].field, "circulating_oil_outlet_pressure"); + stThreshold.stField[idx++].value = HT_INVALID_VALUE; // 循环油出口压力 + } + if (row[11] && strlen(row[11]) > 0) { + strcpy(stThreshold.stField[idx].field, "winding_temperature"); + stThreshold.stField[idx++].value = atof((const char*)row[11]); // 绕组温度 + } + else { + strcpy(stThreshold.stField[idx].field, "winding_temperature"); + stThreshold.stField[idx++].value = HT_INVALID_VALUE; // 绕组温度 + } + if (row[12] && strlen(row[12]) > 0) { + strcpy(stThreshold.stField[idx].field, "oilpillow_oillevel"); + stThreshold.stField[idx++].value = atof((const char*)row[12]); // 油枕油位 + } + else { + strcpy(stThreshold.stField[idx].field, "oilpillow_oillevel"); + stThreshold.stField[idx++].value = HT_INVALID_VALUE; // 油枕油位 + } + if (row[13] && strlen(row[13]) > 0) { + strcpy(stThreshold.stField[idx].field, "transformer_Ontology_oillevel"); + stThreshold.stField[idx++].value = atof((const char*)row[13]); // 变压器本体油位 + } + else { + strcpy(stThreshold.stField[idx].field, "transformer_Ontology_oillevel"); + stThreshold.stField[idx++].value = HT_INVALID_VALUE; // 变压器本体油位 + } + if (row[14] && strlen(row[14]) > 0) { + strcpy(stThreshold.stField[idx].field, "oil_temperature"); + stThreshold.stField[idx++].value = atof((const char*)row[14]); // 变压器本体油温 + } + else { + strcpy(stThreshold.stField[idx].field, "oil_temperature"); + stThreshold.stField[idx++].value = HT_INVALID_VALUE; // 变压器本体油温 + } + if (row[15] && strlen(row[15]) > 0) { + strcpy(stThreshold.stField[idx].field, "top_oil_temperature"); + stThreshold.stField[idx++].value = atof((const char*)row[15]); // 顶层油温 + } + else { + strcpy(stThreshold.stField[idx].field, "top_oil_temperature"); + stThreshold.stField[idx++].value = HT_INVALID_VALUE; // 顶层油温 + } + if (row[16] && strlen(row[16]) > 0) { + strcpy(stThreshold.stField[idx].field, "circulating_oil_inlet_temperature"); + stThreshold.stField[idx++].value = atof((const char*)row[16]); // 变压器油进口油温度(℃) + } + else { + strcpy(stThreshold.stField[idx].field, "circulating_oil_inlet_temperature"); + stThreshold.stField[idx++].value = HT_INVALID_VALUE; // 变压器油进口油温度(℃) + } + if (row[17] && strlen(row[17]) > 0) { + strcpy(stThreshold.stField[idx].field, "circulating_oil_out_temperature"); + stThreshold.stField[idx++].value = atof((const char*)row[17]); // 变压器油出口油温度(℃) + } + else { + strcpy(stThreshold.stField[idx].field, "circulating_oil_out_temperature"); + stThreshold.stField[idx++].value = HT_INVALID_VALUE; // 变压器油出口油温度(℃) + } + stThreshold.fnum = idx; + if (idx >= MAX_RUN_STATUS_COUNT) { + vPrtLogMsg(LOG_WARNG, RET_OK, "Onec devices max threshold count:%d, current count:%d", MAX_RUN_STATUS_COUNT,idx); + stThreshold.fnum = MAX_RUN_STATUS_COUNT - 1; + } + + map::iterator m_pIter; + mutex_lock(g_map_byq_mutex); + m_pIter = g_map_thres_byq.find((char*)stByq.eqm_code); + if (m_pIter != g_map_thres_byq.end()) + { + switch (wstate) + { + case 1: + memcpy(&(m_pIter->second).stThreashod[0], &stThreshold, sizeof(ST_STAT_THRESHOLD)); + break; + case 2: + memcpy(&(m_pIter->second).stThreashod[1], &stThreshold, sizeof(ST_STAT_THRESHOLD)); + break; + case 3: + memcpy(&(m_pIter->second).stThreashod[2], &stThreshold, sizeof(ST_STAT_THRESHOLD)); + break; + default:; + } + } + else { + switch (wstate) + { + case 1: + memcpy(&stByq.stThreashod[0], &stThreshold, sizeof(ST_STAT_THRESHOLD)); + break; + case 2: + memcpy(&stByq.stThreashod[1], &stThreshold, sizeof(ST_STAT_THRESHOLD)); + break; + case 3: + memcpy(&stByq.stThreashod[2], &stThreshold, sizeof(ST_STAT_THRESHOLD)); + break; + default:; + } + g_map_thres_byq.insert(map::value_type(strKey, stByq)); + } + mutex_unlock(g_map_byq_mutex); + } + pdbHandle->FreeRecord(res); + return; +} + +static void vPrtBYQThresholdTable(void) +{ + map::iterator m_pIter; + m_pIter = g_map_thres_byq.begin(); + vPrtLogMsg(LOG_DEBUG, RET_OK, "---------Print BYQ Threshold Tables----------"); + vPrtLogMsg(LOG_DEBUG, RET_OK, "site_id\t\t\t\t eqm_code\t\t\t system_code\t ST dev_name"); + while (m_pIter != g_map_thres_byq.end()) + { + vPrtLogMsg(LOG_DEBUG, RET_OK, "%-s %s %s %c %s", + (m_pIter->second).site_id, (m_pIter->second).eqm_code, (m_pIter->second).system_code, + ((m_pIter->second).wstate == 0 ? 0x2f : 0x30+(m_pIter->second).wstate), (m_pIter->second).dev_name); + m_pIter++; + } + vPrtLogMsg(LOG_DEBUG, RET_OK, "---------- BYQ_Threshold_size:%d-----------", g_map_thres_byq.size()); + return; +} + +// 根据运行工况的字典名称,获取阈值 +double getThresholdValuse(const char *eqm_code, const char *pFiledName, int jobState) +{ + ST_BYQ_RUN_STATE_THRESHOLD stByq; + map::iterator m_pIter; + double val = 0.0f; + if (jobState <= 0) { + vPrtLogMsg(LOG_WARNG, RET_FAIL, "Check Device Statue:%d(invalid)", jobState); + return val; + } + mutex_lock(g_map_byq_mutex); + m_pIter = g_map_thres_byq.find((char*)eqm_code); + if (m_pIter == g_map_thres_byq.end()) + { + mutex_unlock(g_map_byq_mutex); + return val; + } + memcpy(&stByq, &m_pIter->second, sizeof(ST_BYQ_RUN_STATE_THRESHOLD)); + mutex_unlock(g_map_byq_mutex); + + int i = 0; + while (i < stByq.stThreashod[jobState-1].fnum) + { + if (stringncasecmp( (const char*)stByq.stThreashod[jobState-1].stField[i].field, (const char*)pFiledName, strlen((const char*)pFiledName)) == 0) + { + return stByq.stThreashod[jobState - 1].stField[i].value == HT_INVALID_VALUE ? 0 : stByq.stThreashod[jobState - 1].stField[i].value; + } + i++; + } + return val; +} + +//加载IEC104点表数据 +static void vLoadIECPointTable() +{ + char szSql[512] = { 0 }; + + CDBMySQL *pdbHandle = CDBMySQL::Instance(); + if (!pdbHandle) return; + snprintf(szSql, sizeof(szSql), "select p.site_id, p.site_tree_id, p.stype, p.sadr, p.sno,p.isget,p.unit," + "p.sysunit,p.devrate,p.thresholdfield,p.desct," + "SUBSTR(t.equipment_type from 1 for 1) as eqm_type,p.warnflag,t.system_code " + "from iec_points_conf p, busi_site_tree t " + "where p.sadr > 0 and p.state ='1' and t.id=p.site_tree_id and t.status='1' " + "ORDER BY p.site_id, p.site_tree_id, p.sadr"); + MYSQL_RES *res = pdbHandle->SelectRecord(szSql); + if (!res) return; + + MYSQL_ROW row = NULL; + while (row = pdbHandle->GetRecord(res)) + { + ST_IECPOINT_TABLE stPoint; + ST_DEVICE_TIME_STAT stDevStat; + memset(&stPoint, 0x00, sizeof(ST_IECPOINT_TABLE)); + memset(&stDevStat, 0x00, sizeof(ST_DEVICE_TIME_STAT)); + if (row[0] && strlen(row[0]) > 0) + { + strncpy((char*)stPoint.site_id, (const char*)row[0], sizeof(stPoint.site_id)); + } + if (row[1] && strlen(row[1]) > 0) { + strncpy((char*)stPoint.eqm_code, (const char*)row[1], sizeof(stPoint.eqm_code)); + } + + if (row[2] && strlen(row[2]) > 0) { + stPoint.stype = atoi(row[2]); + } + if (row[3] && strlen(row[3]) > 0) { + stPoint.sadr = atoi(row[3]); + } + if (row[4] && strlen(row[4]) > 0) { + stPoint.sno = atoi(row[4]); + } + if (row[5] && strlen(row[5]) > 0) { + stPoint.isget = (unsigned char)atoi(row[5]); + } + if (row[6] && strlen(row[6]) > 0) { + stPoint.unit = (unsigned short)atoi(row[6]); + } + if (row[7] && strlen(row[7]) > 0) { + stPoint.sysunit = (unsigned short)atoi(row[7]); + } + if (row[8] && strlen(row[8]) > 0) { + stPoint.devrate = atof(row[8]); + } + if (row[9] && strlen(row[9]) > 0) { + strncpy((char*)stPoint.fieldname, row[9], sizeof(stPoint.fieldname)); + } + if (row[10] && strlen(row[10]) > 0) { + strncpy((char*)stPoint.poidesc, row[10], sizeof(stPoint.poidesc)); + strncpy((char*)stDevStat.desct, row[10], sizeof(stDevStat.desct)); + } + if (row[11] && strlen(row[11]) > 0) { + stPoint.eqm_type = (unsigned char)atoi(row[11]); + } + if (row[12] && strlen(row[12]) > 0) { + stPoint.warnFlag = (unsigned char)atoi(row[12]); + } + if (row[13] && strlen(row[13]) > 0) { + strncpy((char*)stPoint.sys_code, (const char*)row[13], sizeof(stPoint.sys_code)); + strncpy((char*)stDevStat.sys_code, (const char*)row[13], sizeof(stDevStat.sys_code)); + } + mutex_lock(g_map_iec_mutex); + map::iterator m_pIter; + m_pIter = g_map_iec.find(stPoint.sadr); + if (m_pIter == g_map_iec.end()) + { + stPoint.bfault = 0; // 初始状态0,无事故 + stPoint.wstate = 3; // 默认为空闲状态 + g_map_iec.insert(map::value_type(stPoint.sadr, stPoint)); + } + else { + // 保留原数据 + stPoint.bfault = (m_pIter->second).bfault; + stPoint.wstate = (((m_pIter->second).wstate) & 0xff); + stPoint.cval = (((m_pIter->second).cval) & 0xff); + stPoint.fval = (m_pIter->second).fval; + stPoint.dtime = (m_pIter->second).dtime; + //覆盖更新数据 + memcpy(&(m_pIter->second), &stPoint, sizeof(ST_IECPOINT_TABLE)); + } + mutex_unlock(g_map_iec_mutex); + if (stPoint.eqm_type == 1) { + mutex_lock(g_map_dev_time_stat_mutex); + map::iterator m_pIters; + m_pIters = g_map_dev_time_stat.find((char*)stDevStat.sys_code); + if (m_pIters == g_map_dev_time_stat.end()) + { + stDevStat.usTime = time(NULL); // 初始时间 + stDevStat.wstate = 3; // 默认为空闲状态 + g_map_dev_time_stat.insert(map::value_type((char*)stDevStat.sys_code, stDevStat)); + } + mutex_unlock(g_map_dev_time_stat_mutex); + } + } + pdbHandle->FreeRecord(res); + return; +} + +// 刷新设备更新时间 +void SethDevTimeStat(unsigned char *sys_code, unsigned char ws) +{ + mutex_lock(g_map_dev_time_stat_mutex); + map::iterator m_pIters; + m_pIters = g_map_dev_time_stat.find((char*)sys_code); + if (m_pIters != g_map_dev_time_stat.end()) + { + //(m_pIters->second).usTime = time(NULL); + (m_pIters->second).wstate = ws; // 默认为空闲状态 + } + mutex_unlock(g_map_dev_time_stat_mutex); +} +// 获取状态时间 +time_t GetDevTimeStat(unsigned char *sys_code, unsigned char *ws) +{ + time_t usTime = 0; + mutex_lock(g_map_dev_time_stat_mutex); + map::iterator m_pIters; + m_pIters = g_map_dev_time_stat.find((char*)sys_code); + if (m_pIters != g_map_dev_time_stat.end()) + { + if ((m_pIters->second).usTime == 0) { + (m_pIters->second).usTime = time(NULL); // 初始时间 + } + else { + usTime = (m_pIters->second).usTime; + (m_pIters->second).usTime = time(NULL)+1; + } + if ((m_pIters->second).wstate == 0) { + (m_pIters->second).wstate = 3; // 默认为空闲状态 + } + *ws = (m_pIters->second).wstate ; + } + mutex_unlock(g_map_dev_time_stat_mutex); + return usTime; +} + +// 打印时间 +void vPrtTimeStat() +{ + char sTime[32] = { 0 }; + map::iterator m_pIter; + mutex_lock(g_map_dev_time_stat_mutex); + m_pIter = g_map_dev_time_stat.begin(); + vPrtLogMsg(LOG_WARNG, RET_OK, "---------Print time and state Table Config----------"); + vPrtLogMsg(LOG_WARNG, RET_OK, " sys_code\t\t\t time \t\t stat \t desc"); + while (m_pIter != g_map_dev_time_stat.end()) + { + vTranHostTimeFmt((m_pIter->second).usTime, sTime); + vPrtLogMsg(LOG_WARNG, RET_OK, "--> %s %s %c %s", (m_pIter->second).sys_code, + sTime, ((m_pIter->second).wstate + 0x30), (m_pIter->second).desct); + m_pIter++; + } + vPrtLogMsg(LOG_WARNG, RET_OK, "---------- Point time and state :%d-----------", g_map_dev_time_stat.size()); + mutex_unlock(g_map_dev_time_stat_mutex); + return; + +} +// 打印点表配置信息 +static void vPrtIECPointTable() +{ + map::iterator m_pIter; + mutex_lock(g_map_iec_mutex); + m_pIter = g_map_iec.begin(); + vPrtLogMsg(LOG_WARNG, RET_OK, "---------Print IEC104 Point Table Config Relation----------"); + vPrtLogMsg(LOG_WARNG, RET_OK, "sys_code\t\t\t\t\tsadr\t\t value G rate(%%) EQM_T desc"); + while (m_pIter != g_map_iec.end()) + { + //vPrtLogMsg(LOG_WARNG, RET_OK, "--> %s %s %05d(0x%04x) %03d %.4f %c %.2f %d %s", (m_pIter->second).sys_code, + vPrtLogMsg(LOG_WARNG, RET_OK, "--> %s %s %05d(0x%04x) %.4f %c %.2f %d %s", (m_pIter->second).sys_code, + ((m_pIter->second).stype == 1 ? "YX" : "YC"), + (m_pIter->second).sadr, (m_pIter->second).sadr, + // (m_pIter->second).sno, + ((m_pIter->second).stype == 1) ? ((m_pIter->second).cval & 0xff) : (m_pIter->second).fval, + ((m_pIter->second).isget == 0 ? 0x2f : (m_pIter->second).isget+0x30), (m_pIter->second).devrate, + (m_pIter->second).eqm_type, (m_pIter->second).poidesc); + m_pIter++; + } + vPrtLogMsg(LOG_WARNG, RET_OK, "---------- Point Table_size:%d-----------", g_map_iec.size()); + mutex_unlock(g_map_iec_mutex); + return; +} + +//加载主变设备ID列表,用于缓存主变设备工作状态,1:发电 2:抽水 3:空闲 +static void vLoadByqDeviceStateTable() +{ + char szSql[512] = { 0 }; + CDBMySQL *pdbHandle = CDBMySQL::Instance(); + if (!pdbHandle) return; + snprintf(szSql, sizeof(szSql), "select site_id,id,name from busi_site_tree t where equipment_type='111' and status='1' ORDER BY name"); + MYSQL_RES *res = pdbHandle->SelectRecord(szSql); + if (!res) return; + + string strKey = ""; + MYSQL_ROW row = NULL; + map::iterator m_pIter; + while (row = pdbHandle->GetRecord(res)) + { + ST_BYQWORK_STATUS stWstate; + memset(&stWstate, 0x00, sizeof(ST_BYQWORK_STATUS)); + if (row[0] && strlen(row[0]) > 0) + { + strncpy((char*)stWstate.site_id, (const char*)row[0], sizeof(stWstate.site_id)); + } + if (row[1] && strlen(row[1]) > 0) + { + strncpy((char*)stWstate.eqm_code, (const char*)row[1], sizeof(stWstate.eqm_code)); + strKey = row[1]; + } + if (row[2] && strlen(row[2]) > 0) { + strncpy((char*)stWstate.eqm_name, (const char*)row[2], sizeof(stWstate.eqm_name)); + } + mutex_lock(g_map_work_mutex); + bool isAdd = false; + m_pIter = g_map_work.find(strKey); + if (m_pIter != g_map_work.end()) + { + strcpy((char*)(m_pIter->second).site_id, (const char*)stWstate.site_id); + strcpy((char*)(m_pIter->second).eqm_code, (const char*)stWstate.eqm_code); + strcpy((char*)(m_pIter->second).eqm_name, (const char*)stWstate.eqm_name); + } + else{ + stWstate.bfault = 0; + stWstate.wstate = 3; + g_map_work.insert(map::value_type(strKey, stWstate)); + } + mutex_unlock(g_map_work_mutex); + } + pdbHandle->FreeRecord(res); + return; +} +// 打印变压器工作状态 +static void vPrtByqDeviceStateTable() +{ + int i = 0; + map::iterator m_pIter; + mutex_lock(g_map_work_mutex); + vPrtLogMsg(LOG_DEBUG, RET_OK, "---------Print byq work state Table ----------"); + vPrtLogMsg(LOG_DEBUG, RET_OK, " index site_id\t\t\t\t eqm_code\t\t\t wstate\t fault\teqm_name"); + m_pIter = g_map_work.begin(); + while (m_pIter != g_map_work.end()) + { + vPrtLogMsg(LOG_DEBUG, RET_OK, "--> %d %s %s %d %s %s", i + 1, + (m_pIter->second).site_id, + (m_pIter->second).eqm_code, + (m_pIter->second).wstate, + ((m_pIter->second).bfault == 0 ? "Normal" : "Fault"), + (m_pIter->second).eqm_name); //0:分 1 : 合 + m_pIter++; i++; + } + vPrtLogMsg(LOG_DEBUG, RET_OK, "---------- Print byq work state, size:%d-----------", g_map_work.size()); + mutex_unlock(g_map_work_mutex); + return; +} +// 设置主变工作状态 +void vSetByqDeviceState(unsigned char *pszEqm_code, unsigned char state) +{ + map::iterator m_pIter; + mutex_lock(g_map_work_mutex); + m_pIter = g_map_work.find((char*)pszEqm_code); + if (m_pIter != g_map_work.end()) + { + (m_pIter->second).wstate = state; + } + mutex_unlock(g_map_work_mutex); +} + +// 获取工作状态 +unsigned char cGetByqDeviceState(unsigned char *pszEqm_code) +{ + unsigned char state = 3; + map::iterator m_pIter; + mutex_lock(g_map_work_mutex); + m_pIter = g_map_work.find((char*)pszEqm_code); + if (m_pIter != g_map_work.end()) + { + state = ((m_pIter->second).wstate & 0xff); + } + mutex_unlock(g_map_work_mutex); + return state; +} + +// 设置主变事故状态 +void vSetByqDeviceFaultState(unsigned char *pszEqm_code, unsigned char state) +{ + map::iterator m_pIter; + mutex_lock(g_map_work_mutex); + m_pIter = g_map_work.find((char*)pszEqm_code); + if (m_pIter != g_map_work.end()) + { + (m_pIter->second).bfault = state; + } + mutex_unlock(g_map_work_mutex); +} + +// 获取主变事故状态 +unsigned char cGetByqDeviceFaultState(unsigned char *pszEqm_code) +{ + unsigned char state = 3; + map::iterator m_pIter; + mutex_lock(g_map_work_mutex); + m_pIter = g_map_work.find((char*)pszEqm_code); + if (m_pIter != g_map_work.end()) + { + state = ((m_pIter->second).bfault & 0xff); + } + mutex_unlock(g_map_work_mutex); + return state; +} + +//加载设备关系表 +static void vLoadDeviceRelationsTable() +{ + char szSql[512] = { 0 }; + CDBMySQL *pdbHandle = CDBMySQL::Instance(); + if (!pdbHandle) return; + snprintf(szSql, sizeof(szSql), "select t.site_id,b.transformer_id, b.equipment_id,SUBSTR(t.equipment_type from 1 for 1) as eqm_type, " + "t.system_code " + "from busi_equipment_relationship b, busi_site_tree t " + "where t.status = '1' and b.equipment_id = t.id " + "ORDER BY t.site_id"); //,b.transformer_id + MYSQL_RES *res = pdbHandle->SelectRecord(szSql); + if (!res) return; + + string strKey = ""; + MYSQL_ROW row = NULL; + multimap::iterator m_pIter; + while (row = pdbHandle->GetRecord(res)) + { + ST_DEV_RELATION stRelation; + memset(&stRelation, 0x00, sizeof(ST_DEV_RELATION)); + if (row[0] && strlen(row[0]) > 0) + { + strncpy((char*)stRelation.site_id, (const char*)row[0], sizeof(stRelation.site_id)); + } + if (row[1] && strlen(row[1]) > 0) + { + strncpy((char*)stRelation.m_eqm_code, (const char*)row[1], sizeof(stRelation.m_eqm_code)); + } + if (row[2] && strlen(row[2]) > 0) { + strncpy((char*)stRelation.s_eqm_code, (const char*)row[2], sizeof(stRelation.s_eqm_code)); + strKey = row[2]; + } + if (row[3] && strlen(row[3]) > 0) { + stRelation.s_eqm_type = atoi((const char*)row[3]); + } + if (row[4] && strlen(row[4]) > 0) { + strncpy((char*)stRelation.s_sys_code, (const char*)row[4], sizeof(stRelation.s_sys_code)); + } + stRelation.bClose = 1; + stRelation.bfault = 0; + stRelation.wstate = 3; + mutex_lock(g_map_relation_mutex); + bool isAdd = false; + m_pIter = g_map_relation.find(strKey); + if (m_pIter != g_map_relation.end()) + { + for (int k = 0; k != (int)g_map_relation.count(strKey); k++, m_pIter++) + { + if ((0 == stringncasecmp((const char*)stRelation.site_id,(const char*)((m_pIter->second).site_id),strlen((const char*)(m_pIter->second).site_id))) && + (0 == stringncasecmp((const char*)stRelation.m_eqm_code, (const char*)((m_pIter->second).m_eqm_code), strlen((const char*)(m_pIter->second).m_eqm_code)))) + { + isAdd = true; + break; + } + } + if (!isAdd) { + g_map_relation.insert(multimap::value_type(strKey, stRelation)); + } + } + else g_map_relation.insert(multimap::value_type(strKey, stRelation)); + mutex_unlock(g_map_relation_mutex); + } + pdbHandle->FreeRecord(res); + return; +} + +// 打印设备关系表 +static void vPrtDeviceRelationsTable() +{ + int i = 0; + multimap::iterator m_pIter; + mutex_lock(g_map_relation_mutex); + vPrtLogMsg(LOG_DEBUG, RET_OK, "---------Print device Relations Table Config ----------"); + vPrtLogMsg(LOG_DEBUG, RET_OK, " index m_eqm_code\t\t\ts_eqm_code\t\t\t sType wstate\tfault\tclose\t"); + m_pIter = g_map_relation.begin(); + while (m_pIter != g_map_relation.end()) + { + vPrtLogMsg(LOG_DEBUG, RET_OK, "--> %d %s %s %d \t%d\t%s\t%s", i + 1, + // (m_pIter->second).site_id, + (m_pIter->second).m_eqm_code, + (m_pIter->second).s_sys_code, + (m_pIter->second).s_eqm_type, + (m_pIter->second).wstate, + ((m_pIter->second).bfault == 0 ? "Normal" : "Fault"), + ((m_pIter->second).bClose == 0 ? "Opend" : "Close")); //0:分 1 : 合 + m_pIter++; i++; + } + vPrtLogMsg(LOG_DEBUG, RET_OK, "---------- Point Print device Relations_size:%d-----------", g_map_relation.size()); + mutex_unlock(g_map_relation_mutex); + return; + //方式1 + /*int k; + multimap::iterator m; + m = m_map.find(s); + for (k = 0; k != m_map.count(s); k++, m++) + cout << m->first << "--" << m->second << endl; +*/ +} + +// 根据s_eqm_code获取对应的主变设备编码 +bool bGetMasterEqmCodeBySubEqmCode(unsigned char *site_id, unsigned char *s_eqm_code, unsigned char *m_eqm_code) +{ + bool isFind = false; + multimap::iterator m_pIter; + mutex_lock(g_map_relation_mutex); + m_pIter = g_map_relation.find((char*)s_eqm_code); + if (m_pIter != g_map_relation.end()) + { + for (int c = 0; c < (int)g_map_relation.count((const char*)s_eqm_code); c++, m_pIter++) + { + if (0 != stringncasecmp( + (const char*)site_id, + (const char*)((m_pIter->second).site_id), + strlen((const char*)(m_pIter->second).site_id))) continue; + + strcpy((char*)m_eqm_code, (const char*)((m_pIter->second).m_eqm_code)); + isFind = true; + break; + } + } + mutex_unlock(g_map_relation_mutex); + return isFind; +} + +// 设置运行状态 +void flushDevWorkState(unsigned char *site_id, unsigned char *m_eqm_code, unsigned char state) +{ + map::iterator m_pIter; + mutex_lock(g_map_relation_mutex); + for (m_pIter = g_map_relation.begin(); m_pIter != g_map_relation.end(); m_pIter++) + { + if (0 != stringncasecmp( + (const char*)site_id, + (const char*)((m_pIter->second).site_id), + strlen((const char*)(m_pIter->second).site_id))) continue; + if (0 != stringncasecmp( + (const char*)m_eqm_code, + (const char*)((m_pIter->second).m_eqm_code), + strlen((const char*)(m_pIter->second).m_eqm_code))) continue; + (m_pIter->second).wstate = state; + } + mutex_unlock(g_map_relation_mutex); + return ; +} + +//设备机组事故状态 state=false:正常 true:事故 +bool flushFaultState(unsigned char *site_id, unsigned char *m_eqm_code, unsigned char state) +{ + map::iterator m_pIter; + mutex_lock(g_map_relation_mutex); + for (m_pIter = g_map_relation.begin(); m_pIter != g_map_relation.end(); m_pIter++) + { + if (0 != stringncasecmp( + (const char*)site_id, + (const char*)((m_pIter->second).site_id), + strlen((const char*)(m_pIter->second).site_id))) continue; + if (0 != stringncasecmp( + (const char*)m_eqm_code, + (const char*)((m_pIter->second).m_eqm_code), + strlen((const char*)(m_pIter->second).m_eqm_code))) continue; + (m_pIter->second).bfault = state; + } + mutex_unlock(g_map_relation_mutex); + return true; +} +// 刷新GIS的开关状态 +bool flushDevCloseState(unsigned char *site_id, unsigned char *s_eqm_code, unsigned char state) +{ + map::iterator m_pIter; + mutex_lock(g_map_relation_mutex); + m_pIter = g_map_relation.find((char*)s_eqm_code); + if (m_pIter != g_map_relation.end()) + { + for (int c = 0; c < (int)g_map_relation.count((char*)s_eqm_code); c++, m_pIter++) + { + if (0 != stringncasecmp( + (const char*)site_id, + (const char*)((m_pIter->second).site_id), + strlen((const char*)(m_pIter->second).site_id))) continue; + (m_pIter->second).bClose = state; + } + } + mutex_unlock(g_map_relation_mutex); + return true; +} +// 获取GIS的开关状态 +unsigned char getGisOpenCloseState(unsigned char *site_id, unsigned char *s_eqm_code) +{ + unsigned char isClose = 1; + map::iterator m_pIter; + mutex_lock(g_map_relation_mutex); + m_pIter = g_map_relation.find((char*)s_eqm_code); + if (m_pIter != g_map_relation.end()) + { + for (int c = 0; c < (int)g_map_relation.count((char*)s_eqm_code); c++, m_pIter++) + { + if (0 != stringncasecmp( + (const char*)site_id, + (const \ No newline at end of file diff --git a/src/HTOpencvImg.cpp b/src/HTOpencvImg.cpp new file mode 100644 index 0000000..b72b27c --- /dev/null +++ b/src/HTOpencvImg.cpp @@ -0,0 +1,904 @@ +/**************************************************************************** +** File name : HTOpencvImg.cpp +** Description : define Opencv function +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#include "HTOpencvImg.h" + +static const char *_FILE_ = "HTOpencvImg.cpp"; +static FILE *fpIni = NULL; // opencv config file handle. +static map g_conf_img; + +/************************************************************************* +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 (fpIni == NULL) { + if ((fpIni = fopen(HT_CONFIG_FILE, "r")) == NULL) + return (-1); + } + fseek(fpIni, 0, SEEK_SET); + /*** check section ***/ + iSectFlag = 0; + while (!feof(fpIni)) { + if (fgets(szBuf, DEF_BUFFER_1K, fpIni) == 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(fpIni)) { + if (fgets(szBuf, DEF_BUFFER_1K, fpIni) == 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 (-1); + if (iLen > (int)uiBufLen) iLen = uiBufLen; + memcpy(pszRetBuf, psz2, iLen); + *(pszRetBuf + iLen) = '\0'; + return (0); + } + //fclose(fpIni); + return (-1); +} + +// 加载图片配置文件数据 +bool iGetOpencvConf() +{ + int iRet = -1, icount = 0, img_size = 0; + char szTmp[512], szSection[128], szSite_id[DEF_EQM_CODE_SIZE] = { 0 }; + string strKey; + + // 打开配置文件,准备加载配置参数 + if (fpIni == NULL) { + if ((fpIni = fopen(HT_CONFIMG_FILE, "r")) == NULL) { + vPrtLogMsg(LOG_ERROR, errno, "open config file: %s failed.", HT_CONFIMG_FILE); + return NULL; + } + } + + // 获取站点ID + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString("SITE_CODE", "site_id", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get site_id parameter failed"); + fclose(fpIni); + return false; + } + strcpy((char*)szSite_id, szTmp); + + // 获取站点ID + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString("COMMON_CONF", "img_file_min_size", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get img_file_min_size parameter failed"); + fclose(fpIni); + return false; + } + img_size = atoi(szTmp); + + // 获取配置项的个数 + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString("CAMERA_COUNT", "CameraCount", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get CameraCount parameter failed"); + fclose(fpIni); + return false; + } + icount = atoi(szTmp); + vPrtLogMsg(LOG_DEBUG, 0, "get opencv config count: %d", icount); + + for (int i = 0; i < icount; i++) + { + ST_OPENCV_CONF stConf; + memset(&stConf, 0x00, sizeof(ST_OPENCV_CONF)); + strcpy((char*)stConf.site_id, szSite_id); // 站点id + stConf.img_min_size = img_size; + + snprintf(szSection, sizeof(szSection),"CAMERA_%03d", i + 1); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "eqm_type", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: eqm_type parameter failed", szSection); + fclose(fpIni); + return false; + } + stConf.eqm_type[0] = (szTmp[0] & 0xff); + + 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(fpIni); + return false; + } + strcpy((char*)stConf.eqm_code, szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "system_code", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: system_code parameter failed", szSection); + fclose(fpIni); + return false; + } + strcpy((char*)stConf.sys_code, szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "table_type", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: table_type parameter failed", szSection); + fclose(fpIni); + return false; + } + strcpy((char*)stConf.table_type, szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "name", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: name parameter failed", szSection); + fclose(fpIni); + return false; + } + strcpy((char*)stConf.name, szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "sersorid", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: sersorid parameter failed", szSection); + fclose(fpIni); + return false; + } + strcpy((char*)stConf.sersorid, szTmp); + strKey = szTmp; + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "base_angle", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: base_angle parameter failed", szSection); + fclose(fpIni); + return false; + } + stConf.base_angle = (unsigned int)atoi(szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "meter_type", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: meter_type parameter failed", szSection); + fclose(fpIni); + return false; + } + stConf.meter_type = (unsigned char)atoi(szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "meter_units", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: meter_units parameter failed", szSection); + fclose(fpIni); + return false; + } + stConf.meter_units = (unsigned char)atoi(szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "direct_Clockwise", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: direct_Clockwise parameter failed", szSection); + fclose(fpIni); + return false; + } + stConf.direct_Clockwise = (unsigned char)atoi(szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "init_value", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: init_value parameter failed", szSection); + fclose(fpIni); + return false; + } + stConf.dInitVal = (double)atof(szTmp); + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "max_pointer_len", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: max_pointer_len parameter failed", szSection); + fclose(fpIni); + return false; + } + stConf.max_pointer_len = (unsigned int)atoi(szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "img_path", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: img_path parameter failed", szSection); + fclose(fpIni); + return false; + } + strcpy((char*)stConf.img_path, szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "img_bak", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: img_bak parameter failed", szSection); + fclose(fpIni); + return false; + } + strcpy((char*)stConf.img_bak, szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "is_replace", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get is_replace parameter failed"); + return false; + } + if (stringcasecmp(szTmp, "true") == 0) + stConf.is_replace = true; // 替换原文件 + else stConf.is_replace = false; + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "s_height", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: s_height parameter failed", szSection); + fclose(fpIni); + return false; + } + stConf.s_height = atoi(szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "e_height", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: e_height parameter failed", szSection); + fclose(fpIni); + return false; + } + stConf.e_height = atoi(szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "s_width", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: s_width parameter failed", szSection); + fclose(fpIni); + return false; + } + stConf.s_width = atoi(szTmp); + + memset(szTmp, 0x00, sizeof(szTmp)); + if ((iRet = iGetString(szSection, "e_width", szTmp, sizeof(szTmp))) < 0) { + vPrtLogMsg(LOG_ERROR, iRet, "get %s: e_width parameter failed", szSection); + fclose(fpIni); + return false; + } + stConf.e_width = atoi(szTmp); + stConf.seqno = i + 1; + g_conf_img.insert(map::value_type(strKey, stConf)); + } + fclose(fpIni); + return true; +} +// 从文件名截取sersorid +static bool bGetSersorIDOfFilename(char *filename, char *sersorid, char *pExt) +{ + char *p = NULL, *s = NULL, *t = NULL; + // 文件名格式:sersorID_time.jpg 或 ../img/sersorid_time.jpg + if (filename && strlen(filename) >= 17) { + p = filename + strlen((const char*)filename); + while (*p != '\\' && *p != '/' && p != filename) { + if (*p == '.') t = p + 1; // 扩展名位置 + if (*p == '_') s = p; // 分隔符_位置 + p--; + } + if (t) { + strcpy(pExt, t); + pExt[strlen(pExt)] = 0x00; + } + if (s) { + memcpy(sersorid, p + 1, s - p - 1); + sersorid[s - p - 1] = 0x00; + } + return true; + } + return false; +} +// 移动文件到指定目录(备份文件) +bool bBakFilename(char *filename, char *pBakPath) +{ + char *p = NULL, *s = NULL, *t = NULL; + char szCmd[1024] = { 0 }; + // 文件名格式:sersorID_time.jpg 或 ../img/sersorid_time.jpg + if (filename && pBakPath) + { + if (iDirOrFileExist(pBakPath)) + iBuildDirent(pBakPath); +#ifdef _WIN32 + snprintf(szCmd, sizeof(szCmd), "move %s %s", filename, pBakPath); +#else + snprintf(szCmd, sizeof(szCmd),"mv %s %s", filename, pBakPath); +#endif + system(szCmd); + return true; + } + return false; +} +// 显示图片 +void showImg(const char *title, Mat &img) +{ +#ifdef _IM_SHOW + imshow(title, img); + waitKey(0); +#endif +} + +int dcmp(double x) +{ + if (fabs(x) < eps) return 0; + else return x < 0 ? -1 : 1; +} + +//向量点积 +double Dot(Point A, Point B) +{ + return A.x*B.x + A.y*B.y; +} + +//向量模长 +double Length(Point A) +{ + return sqrt(Dot(A, A)); +} + +//向量叉积 +double Cross(Point A, Point B) +{ + return A.x*B.y - A.y*B.x; +} +//点到线段的距离 +double DistancetoSegment(Point P, Point A, Point B) +{ + if (A == B)return Length(P - A); + Point v1 = B - A, v2 = P - A, v3 = P - B; + if (dcmp(Dot(v1, v2))<0) return Length(v2); + else if (dcmp(Dot(v1, v3))>0) return Length(v3); + else return (fabs(Cross(v1, v2)) / Length(v1)); +} + + +/* 获取指定目录下的*.xxx文件 +pPath : path, eg: /usr/local/img/*.jpg +: "D:\\Photo and Video\\destop1\\*.jpg"; +*/ +int iGetImgFileList(const char *pPath, std::vector & image_files) +{ + cv::String pattern_jpg = (char*)pPath; + + //std::vector image_files; + try{ + cv::glob(pattern_jpg, image_files); + if (image_files.size() == 0) { + //std::cout << "No image files[jpg]" << std::endl; + return 0; + } + return (int)image_files.size(); + } + catch (cv::Exception &e) + { + printf("Get ImgFile List exception,msg:%s\n", e.err.c_str()); + } + return 0; +} + +//下面是以海康威视的某款网络摄像头为例,使用 OpenCV 的 VideoCapture 类来显示实时视频 +// rtsp://[username]:[password]@[ip]:[port]/[codec]/[channel]/[subtype]/av_stream +// 1) username 用户名,常用 admin +// 2) password 密码,常用 12345 +// 3) ip 摄像头IP,如 192.0.0.64 +// 4) port 端口号,默认为 554 +// 5) codec 视频编码模式,有 h264、MPEG - 4、mpeg4 等 +// 6) channel 通道号,起始为1,例如通道1,则为 ch1 +// 7) subtype 码流类型,主码流为 main,辅码流为 sub +int showRtspVideoStream(const char* rtsp_url) +{ + // "rtsp://admin:a1234567@192.168.5.186:554/MPEG-4/ch1/main/av_stream"; + String rtsp_addr = rtsp_url; + + VideoCapture cap(rtsp_addr); + if (!cap.isOpened()) return -1; + + // cap.open(rtsp_addr); + Mat frame; + for (;;) { + cap >> frame; + if (frame.empty()) break; + imshow("Video Stream", frame); + if (waitKey(10) == 'q') break; + } + cap.release(); // 关闭视频流。 + return 0; +} + +// 播放视频流 +int showRtspVideoStreams(const char *rtsp_url) +{ + //打开视频文件:其实就是建立一个VideoCapture结构 + VideoCapture capture(rtsp_url); + //检测是否正常打开:成功打开时,isOpened返回ture + if (!capture.isOpened()) { + cout << "fail to open!" << endl; + return 0; + } + + //获取整个帧数 + long totalFrameNumber = (long)capture.get(CV_CAP_PROP_FRAME_COUNT); + cout << "整个视频共" << totalFrameNumber << "帧" << endl; + + //设置开始帧() + long frameToStart = 300; + //capture.set( CV_CAP_PROP_POS_FRAMES, frameToStart); + cout << "从第" << frameToStart << "帧开始读" << endl; + + //设置结束帧 + int frameToStop = 400; + + if (frameToStop < frameToStart) + { + cout << "结束帧小于开始帧,程序错误,即将退出!" << endl; + return -1; + } + else + { + cout << "结束帧为:第" << frameToStop << "帧" << endl; + } + + //获取帧率 + double rate = capture.get(CV_CAP_PROP_FPS); + cout << "帧率为:" << rate << endl; + + //定义一个用来控制读取视频循环结束的变量 + bool stop = false; + //承载每一帧的图像 + Mat frame; + //显示每一帧的窗口 + namedWindow("Extracted frame"); + //两帧间的间隔时间: + int delay = 1000 / (int)rate; + + //利用while循环读取帧 + //currentFrame是在循环体中控制读取到指定的帧后循环结束的变量 + long currentFrame = frameToStart; + + //滤波器的核 + int kernel_size = 3; + Mat kernel = Mat::ones(kernel_size, kernel_size, CV_32F) / (float)(kernel_size*kernel_size); + + while (!stop) + { + //读取下一帧 + if (!capture.read(frame)) + { + cout << "读取视频失败" << endl; + return -1; + } + //这里加滤波程序 + imshow("Extracted frame", frame); + //filter2D(frame, frame, -1, kernel); + + //imshow("after filter", frame); + //cout << "正在读取第" << currentFrame << "帧" << endl; + //waitKey(int delay=0)当delay ≤ 0时会永远等待;当delay>0时会等待delay毫秒 + //当时间结束前没有按键按下时,返回值为-1;否则返回按键 + + int c = waitKey(delay); + //按下ESC或者到达指定的结束帧后退出读取视频 + if ((char)c == 27 /*|| currentFrame > frameToStop*/) + { + stop = true; + } + //按下按键后会停留在当前帧,等待下一次按键 + if (c >= 0) + { + waitKey(0); + } + currentFrame++; + } + //关闭视频文件 + capture.release(); + return 0; +} +// 截取图片指定区域并保存 +// isReplace = true: 覆盖原文件,不保留原文件,文件名不变 +// = false: 保留原文件,并将截图文件命名为 xxx_cut.xxx +int vCutImageSave(ST_OPENCV_CONF *stConf, char* path_filename) +{ + char szDest[MAX_PATH] = { 0 }, ext[8] = { 0 }; + int shigh, ehigh, swidth, ewidth; + Mat image; + try{ + image = imread(path_filename); + } + catch (cv::Exception &e) + { + printf("imread exception,msg:%s\n", e.err.c_str()); + return RET_FAIL; + } + int w = image.cols; // 列数 + int h = image.rows; // 行数 + vPrtLogMsg(LOG_DEBUG, RET_OK, "file:%s, source high=%d width=%d", path_filename, h, w); + + shigh = stConf->s_height; + ehigh = stConf->e_height; + swidth = stConf->s_width; + ewidth = stConf->e_width; + if (shigh > h) shigh = 10; // 起始高度>总高度时,起始高度=10 + if (ehigh > h) ehigh = h; // 结束高度>总高度时,结束高度=h + if (swidth > w) swidth = 10; // 结束宽度>总宽度时,起始宽度=10 + if (ewidth > w) ewidth = w; // 结束宽度>总宽度时,结束宽度=w + //showImg("SRC:", image); + // 0列-h-y 27列-w-x + // 0行 +-------------------------+ + // 1行 | | + // 2行 | | + // 3行 | | + // 4行 | | + // 5行 +-------------------------+ 5行,27列 + // + // Range(起始行,结束行), Range(起始列,结束列), + Mat image_roi(image, Range(shigh, ehigh), Range(swidth, ewidth)); + if (image_roi.empty()) { + vPrtLogMsg(LOG_WARNG, RET_FAIL, "cut picture:%s to high=(%d,%d) width=(%d,%d) failed.", path_filename, shigh, ehigh, swidth, ewidth); + return RET_FAIL; + } + showImg("CUT PIC:", image_roi); + if (!stConf->is_replace) + { + bGetSersorIDOfFilename(path_filename, szDest, ext); + // 保留原文件,并重命名 + snprintf(szDest, sizeof(szDest), "%s", path_filename); + memset(szDest + strlen(szDest) - strlen(ext) - 1, 0x00, sizeof(szDest)-strlen(szDest) + 1); + strcat(szDest, "_cut"); + snprintf(szDest + strlen(szDest), sizeof(szDest), ".%s", ext); + imwrite(szDest, image_roi); + strcpy(path_filename, szDest); // 返回新文件名 + } + else imwrite(path_filename, image_roi); // 不保留原文件,覆盖原文件 + + return RET_OK; +} + +// 查表获取指针读数 +static double dGetReadValueOf3ex5050(double du, double base, int linelen) +{ + int i = 0, min_id = -1; + double tmp_du = du, min_du = 30; + double val_inter = 0; + + if (du > base) { + tmp_du = ((int)(du * 100) % (int)(base * 100)) / 100;// +(du / base); + } + + while (g_YB_3EX5050[i].du > 0) + { + // 找du数差值最小的,也就是最接近的记录。 + if (tmp_du == g_YB_3EX5050[i].du) return g_YB_3EX5050[i].val; + if (tmp_du == g_YB_3EX5050[i + 1].du) return g_YB_3EX5050[i + 1].val; + + if (fabs(tmp_du - g_YB_3EX5050[i].du) < min_du) { + min_du = fabs(tmp_du - g_YB_3EX5050[i].du); + min_id = i; + } + i++; + } + if (min_id < 0) return 0.0f; // 没找到 + if (g_YB_3EX5050[min_id + 1].val > 0.0) + val_inter = fabs(g_YB_3EX5050[min_id + 1].val - g_YB_3EX5050[min_id].val) / 10; + else + val_inter = fabs(g_YB_3EX5050[min_id].val - g_YB_3EX5050[min_id - 1].val) / 10; + if (min_du > 10.0) + return g_YB_3EX5050[min_id].val + (val_inter * min_du); + return fabs(g_YB_3EX5050[min_id].val - (val_inter * min_du)); +} + +// 查表获取指针读数 +static double dGetReadValueOfJSY10(double du, double base, int linelen) +{ + int i = 0, min_id = -1; + double tmp_du = du, min_du = 30; + double val_inter = 0; + + if (du > base) { + tmp_du = ((int)(du * 100) % (int)(base * 100)) / 100;// +(du / base); + } + + while (g_YB_JSY10[i].du > 0) + { + // 找du数差值最小的,也就是最接近的记录。 + if (tmp_du == g_YB_JSY10[i].du) return g_YB_JSY10[i].val; + if (tmp_du == g_YB_JSY10[i + 1].du) return g_YB_JSY10[i + 1].val; + + if (fabs(tmp_du - g_YB_JSY10[i].du) < min_du) { + min_du = fabs(tmp_du - g_YB_JSY10[i].du); + min_id = i; + } + i++; + } + if (min_id < 0) return 0.0f; // 没找到 + if (g_YB_JSY10[min_id + 1].val > 0.0) + val_inter = fabs(g_YB_JSY10[min_id + 1].val - g_YB_JSY10[min_id].val) / 10; + else + val_inter = fabs(g_YB_JSY10[min_id].val - g_YB_JSY10[min_id - 1].val) / 10; + return g_YB_JSY10[min_id].val;// +val_inter; +} +// 查表获取油表指针读数 +double dGetReadValueOfOCR17NI12MO2_16(double du, double base, int linelen) +{ + int i = 0, min_id = -1; + double tmp_du = du, min_du = 3.3f; // ((360-90)/10)/2=13.5,单个区域差13.5° + double val_inter = 0; + + if (du > base) { + tmp_du = ((int)(du * 100) % (int)(base * 100)) / 100;// +(du / base); + } + while (g_YB_OCR17NI12MO2_16[i].du > 0) + { + // 找du数差值最小的,也就是最接近的记录。 + if (tmp_du == g_YB_OCR17NI12MO2_16[i].du) return g_YB_OCR17NI12MO2_16[i].val; + if (tmp_du == g_YB_OCR17NI12MO2_16[i + 1].du) return g_YB_OCR17NI12MO2_16[i + 1].val; + + if (fabs(tmp_du - g_YB_OCR17NI12MO2_16[i].du) < min_du) { + min_du = fabs(tmp_du - g_YB_OCR17NI12MO2_16[i].du); + min_id = i; + } + i++; + } + if (min_id < 0) return -1.0f; // 没找到 + //printf("Base = %.2f°-%.2f -- input:%.2f\n", g_YB_YZFTH[min_id].du, g_YB_YZFTH[min_id].val, tmp_du); + if (tmp_du > g_YB_OCR17NI12MO2_16[min_id].du) { // 当前度大于最近的度时 + val_inter = g_YB_OCR17NI12MO2_16[min_id].val + 0.02; // (min_du * 0.02 / 10); // 可能会出现负数 + //printf("(%.3f-%.3f) min_du=%.3f\n", g_YB_YZFTH[min_id].val, (min_du * 0.1 / 10), min_du); + } + else { + val_inter = g_YB_OCR17NI12MO2_16[min_id].val + (min_du * 0.02 / 10); + //printf("(%.3f+%.3f) min_du=%.3f\n", g_YB_YZFTH[min_id].val, (min_du * 0.1 / 10), min_du); + } + return val_inter; +} +// 查表获取油表指针读数 +double dGetReadValueOfOCR17NI12MO2_25(double du, double base, int linelen) +{ + int i = 0, min_id = -1; + double tmp_du = du, min_du = 3.3f; // ((360-90)/10)/2=13.5,单个区域差13.5° + double val_inter = 0; + + if (du > base) { + tmp_du = ((int)(du * 100) % (int)(base * 100)) / 100;// +(du / base); + } + while (g_YB_OCR17NI12MO2_25[i].du > 0) + { + // 找du数差值最小的,也就是最接近的记录。 + if (tmp_du == g_YB_OCR17NI12MO2_25[i].du) return g_YB_OCR17NI12MO2_25[i].val; + if (tmp_du == g_YB_OCR17NI12MO2_25[i + 1].du) return g_YB_OCR17NI12MO2_25[i + 1].val; + + if (fabs(tmp_du - g_YB_OCR17NI12MO2_25[i].du) < min_du) { + min_du = fabs(tmp_du - g_YB_OCR17NI12MO2_25[i].du); + min_id = i; + } + i++; + } + if (min_id < 0) return -1.0f; // 没找到 + //printf("Base = %.2f°-%.2f -- input:%.2f\n", g_YB_YZFTH[min_id].du, g_YB_YZFTH[min_id].val, tmp_du); + if (tmp_du > g_YB_OCR17NI12MO2_25[min_id].du) { // 当前度大于最近的度时 + val_inter = g_YB_OCR17NI12MO2_25[min_id].val + (min_du * 0.05 / 10); // 可能会出现负数 + //printf("(%.3f-%.3f) min_du=%.3f\n", g_YB_YZFTH[min_id].val, (min_du * 0.1 / 10), min_du); + } + else { + val_inter = g_YB_OCR17NI12MO2_25[min_id].val + (min_du * 0.05 / 10); + //printf("(%.3f+%.3f) min_du=%.3f\n", g_YB_YZFTH[min_id].val, (min_du * 0.1 / 10), min_du); + } + return val_inter; +} +// 100摄氏度的油温表读数 +double dReadPointValue_Wss411_100(double du, double base, int linelen) +{ + int i = 0, min_id = -1; + double tmp_du = du, min_du = 3.4f; // ((360-90)/10)/2=13.5,单个区域差13.5° + double val_inter = 0; + + if (du > base) { + tmp_du = ((int)(du * 100) % (int)(base * 100)) / 100;// +(du / base); + } + // if (tmp_du < 45) return 10.0f; + // if (tmp_du > 315) return 0.0f; // 无效范围内的角度值,默认给最大读数.系统提示告警 + if (tmp_du == 0) tmp_du = 180.0f; + while (g_YB_WSS100[i].du > 0) + { + // 找du数差值最小的,也就是最接近的记录。 + if (tmp_du == g_YB_WSS100[i].du) return g_YB_WSS100[i].val; + if (tmp_du == g_YB_WSS100[i + 1].du) return g_YB_WSS100[i + 1].val; + + if (fabs(tmp_du - g_YB_WSS100[i].du) < min_du) { + min_du = fabs(tmp_du - g_YB_WSS100[i].du); + min_id = i; + } + i++; + } + if (min_id < 0) return -1.0f; // 没找到 + //printf("Base = %.2f°-%.2f -- input:%.2f\n", g_YB_YZFTH[min_id].du, g_YB_YZFTH[min_id].val, tmp_du); + if (tmp_du > g_YB_WSS100[min_id].du) { // 当前度大于最近的度时 + val_inter = g_YB_WSS100[min_id].val - (min_du * 2 / 10); // 可能会出现负数 + } + else { + val_inter = g_YB_WSS100[min_id].val + (min_du * 2 / 10); + } + return val_inter; +} +// 150摄氏度的油温表读数 +double dGetReadValueOf_WSS150(double du, double base, int linelen) +{ + int i = 0, min_id = -1; + double tmp_du = du, min_du = 3.4f; // ((360-90)/10)/2=13.5,单个区域差13.5° + double val_inter = 0; + + if (du > base) { + tmp_du = ((int)(du * 100) % (int)(base * 100)) / 100;// +(du / base); + } + // if (tmp_du < 45) return 10.0f; + // if (tmp_du > 315) return 0.0f; // 无效范围内的角度值,默认给最大读数.系统提示告警 + + while (g_YB_WSS150[i].du > 0) + { + // 找du数差值最小的,也就是最接近的记录。 + if (tmp_du == g_YB_WSS150[i].du) return g_YB_WSS150[i].val; + if (tmp_du == g_YB_WSS150[i + 1].du) return g_YB_WSS150[i + 1].val; + + if (fabs(tmp_du - g_YB_WSS150[i].du) < min_du) { + min_du = fabs(tmp_du - g_YB_WSS150[i].du); + min_id = i; + } + i++; + } + if (min_id < 0) return -1.0f; // 没找到 + //printf("Base = %.2f°-%.2f -- input:%.2f\n", g_YB_YZFTH[min_id].du, g_YB_YZFTH[min_id].val, tmp_du); + if (tmp_du > g_YB_WSS150[min_id].du) { // 当前度大于最近的度时 + val_inter = g_YB_WSS150[min_id].val - (min_du * 3 / 10); // 可能会出现负数 + //printf("(%.3f-%.3f) min_du=%.3f\n", g_YB_YZFTH[min_id].val, (min_du * 0.1 / 10), min_du); + } + else { + //val_inter = g_YB_WSS150[min_id].val + (min_du * 3 / 10); + val_inter = g_YB_WSS150[min_id].val + min_du ; + //printf("(%.3f+%.3f) min_du=%.3f\n", g_YB_YZFTH[min_id].val, (min_du * 0.1 / 10), min_du); + } + return val_inter; +} +//double gtest(double du, double base, int linelen) +//{ +// return dGetReadValueOfYZFTH( du, base, linelen); +//} +// 遍历所有像素点1 +void colorReduce(cv::Mat &inputImage, int div) +{ + // 参数准备 + // outputImage = inputImage.clone(); + + int rowNumber = inputImage.rows; + int colNumber = inputImage.cols*inputImage.channels(); + if (inputImage.isContinuous()) { // 判断数据在内存是否连续存储的。 + colNumber = colNumber * rowNumber; + rowNumber = 1; + } + for (int i = 0; i < rowNumber; i++) + { + // 获取第i行的首地址 + uchar* data = inputImage.ptr(i); + + for (int j = 0; j < colNumber; j++) // 列循环 + { + // 开始处理每一个像素值,每一个像素值都减去div + data[j] = data[j] - div; + } + } +} +// using .ptr and * ++ and bitwise (continuous+channels) +void colorReduce7(cv::Mat &image, int div = 64) { + int nr = image.rows; // number of rows + int nc = image.cols; // number of columns + if (image.isContinuous()) { + // then no padded pixels + nc = nc*nr; + nr = 1; // it is now a 1D array + } + int n = static_cast(log(static_cast(div)) / log(2.0)); + // mask used to round the pixel value + uchar mask = 0xFF << n; // e.g. for div=16, mask= 0xF0 + for (int j = 0; j < nr; j++) { + uchar* data = image.ptr(j); + for (int i = 0; i < nc; i++) { + if (image.channels() == 1) + *data++ = *data & mask + div / 2; + else if (image.channels() == 3) { + *data++ = *data & mask + div / 2; + *data++ = *data & mask + div / 2; + *data++ = *data & mask + div / 2; + } + } // end of row + } +} +void colorReduce(cv::Mat & inputImage) +{ + // 参数准备 + int a, b, c; + int rowNumber = inputImage.rows; + int colNumber = inputImage.cols*inputImage.channels(); + if (inputImage.isContinuous()) { // 判断数据在内存是否连续存储的。 + colNumber = colNumber * rowNumber; + rowNumber = 1; + } + for (int i = 0; i < rowNumber; i++) { + for (int j = 0; j < colNumber; j++) + { + a = inputImage.at(i, j)[0]; + b = inputImage.at(i, j)[1]; + c = inputImage.at(i, j)[2]; + if (a > 180) inputImage.at(i, j)[0] = 0; + if (b < 50) inputImage.at(i, j)[1] = 255; + if (c *data++ = *data & mask + div / 2; + else if (image.channels() == 3) { + *data++ = *data & mask + div / 2; + *data++ = *data & mask + div / 2; + *data++ = *data & mask + div / 2; + } + } // end of row + } +} +void colorReduce(cv::Mat & inputImage) +{ + // 鍙傛暟鍑嗗 + int a, b, c; + int rowNumber = inputImage.rows; + int colNumber = inputImage.cols*inputImage.channels(); + if (inputImage.isContinuous()) { // 鍒ゆ柇鏁版嵁鍦ㄥ唴瀛樻槸鍚﹁繛缁瓨鍌ㄧ殑銆 \ No newline at end of file diff --git a/src/HTPublic.cpp b/src/HTPublic.cpp new file mode 100644 index 0000000..822b155 --- /dev/null +++ b/src/HTPublic.cpp @@ -0,0 +1,1012 @@ +/**************************************************************************** +** File name : HTPublic.cpp +** Description : common member function +** 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 "StdAfx.h" +#include "HTPublic.h" +#include "HTType.h" +#include "HTGlobal.h" + +void vSetPid() +{ + FILE *fp = fopen(DEF_PID_FILE, "w"); + fprintf(fp, "%d", GETPID()); + fflush(fp); + fclose(fp); +} + +int iGetPid() +{ + char szPid[20] = { 0 }; + FILE *fp = fopen(DEF_PID_FILE, "r"); + fgets(szPid, sizeof(szPid), fp); + fclose(fp); + return atoi(szPid); +} + +/**************************************************************** +** Description : 检查文件/目录是否存在 +** param in : pszName -- 要检查的文件/目录,FileName / PathName +** : +** param out : None +** return code : 0 -- exist +** : <0 -- not exist +****************************************************************/ +int iDirOrFileExist(const char *pszName) +{ +#ifdef _WIN32 + return _access(pszName, 0) ; +#else + return access(pszName, 0) ; +#endif +} +/**************************************************************** +** Description : 创建目录 +** param in : pNmae -- 要创建的目录名称 +** : +** param out : None +** return code : <0 -- failed +****************************************************************/ +int iBuildDirent(const char *pName) +{ + int iRet = -1; + char szCmd[256]; + memset(szCmd, 0x00, sizeof(szCmd)); +#ifdef _WIN32 + Unix2WindowPath((char*)pName); + sprintf(szCmd,"mkdir %s", pName); + //iRet = _mkdir(pName); +#else + sprintf(szCmd,"mkdir -p %s", pName); +#endif + iRet = system(szCmd); + return iRet; +} + +/**************************************************************** +** Description : 获取文件大小 +** param in : pNmae -- 文件名称 +** : +** param out : None +** return code : <0 -- failed +****************************************************************/ +int get_file_size(const char *path) +{ + unsigned long filesize = -1; + struct stat statbuff; + if(stat(path, &statbuff) < 0){ + return filesize; + }else{ + filesize = statbuff.st_size; + } + return filesize; +} +/**************************************************************** +** Description : 获取文件创建时间 +** param in : pNmae -- 文件名称 +** : +** param out : pCreateTime -- YYYY-MM-DD HH24:MI:SS +** return code : <=0 -- failed +** : >0 -- file size(byte) +****************************************************************/ +int getFileCreateTime(const char *path, char *pCreateTime) +{ + unsigned long filesize = -1; + char *p = (char*)path, *s = (char*)path; + struct stat statbuff; + if (stat(path, &statbuff) < 0){ + vGetHostTime(pCreateTime); + return 0; + } + //vTranHostTimeFmt(statbuff.st_ctime, pCreateTime); + while (*p != '_') { + p++; s++; + } + while (*s != '.') s++; + strncpy(pCreateTime, p + 1, s - p - 1); + return (int)statbuff.st_size ; +} +/**************************************************************** +** Description : 从文件全路径中截取文件父目录、文件名及文件扩展名称 +** param in : pFullPath -- 路径名称 +** : +** param out : pFilename -- 文件名 +** :pExt -- 扩展名 +** return code : <0 -- failed +****************************************************************/ +bool bSplitFilenameByFullPath(char *pFullPath, char *pPrantPath, char *pFilename, char *pExt) +{ + char *p, *s; + // 文件名格式:sersorID_time.jpg 或 ../img/sersorid_time.jpg + if (pFullPath && strlen(pFullPath) > 1) { + p = pFullPath + strlen((const char*)pFullPath); + + while (*p != '\\' && *p != '/' && p != pFullPath) p--; + strncpy(pPrantPath, pFullPath, p - pFullPath + 1); // 父目录名称 + s = p + 1; + while (*s != '.') s++; + if (*s != '.') strcpy(pFilename, p + 1); + else { + strncpy(pFilename, p + 1, s - p - 1); + strcpy(pExt, s + 1); + } + return true; + } + return false; +} + +/*********************************************************************** +** Description : 获取主机时间 +** param in : None +** param out : pszTime -- string time(yyyymmddhhmmss) +** return code : None +***********************************************************************/ +void vGetHostTimeOnMillsecond(char *pszTime) +{ +#ifdef _WIN32 + SYSTEMTIME t; + ::GetLocalTime(&t); + sprintf(pszTime, "%04d%02d%02d%02d%02d%02d+%04d", + t.wYear, t.wMonth, t.wDay, + t.wHour, t.wMinute, t.wSecond, t.wMilliseconds); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + + struct tm tms; + memcpy(&tms, localtime((const time_t *)&tv.tv_sec), sizeof(struct tm)); + + sprintf(pszTime, "%04d%02d%02d%02d%02d%02d+%04ld", + tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday, + tms.tm_hour, tms.tm_min, tms.tm_sec, tv.tv_usec / 1000); +#endif + return; +} +/*********************************************************************** +** Description : 获取主机时间 +** param in : None +** param out : pszTime -- string time(yyyy-mm-dd hh:mm:ss+xxxx) +** return code : None +***********************************************************************/ +time_t vGetHostTimeFmtOnMillsecond(char *pszTime) +{ +#ifdef _WIN32 + SYSTEMTIME t; + ::GetLocalTime(&t); + sprintf(pszTime, "%04d-%02d-%02d %02d:%02d:%02d+%04d", + t.wYear, t.wMonth, t.wDay, + t.wHour, t.wMinute, t.wSecond, t.wMilliseconds); +#else + struct timeval tv; + gettimeofday(&tv, NULL); + + struct tm tms; + memcpy(&tms, localtime((const time_t *)&tv.tv_sec), sizeof(struct tm)); + + sprintf(pszTime, "%04d-%02d-%02d %02d:%02d:%02d+%04ld", + tms.tm_year + 1900, tms.tm_mon + 1, tms.tm_mday, + tms.tm_hour, tms.tm_min, tms.tm_sec, tv.tv_usec / 1000); +#endif + + return time(NULL); +} + +/*********************************************************************** +** Description : 获取主机时间 +** param in : None +** param out : pszTime -- string time(yyyymmddhhmmss) +** return code : None +***********************************************************************/ +void vGetHostTime (char *pszTime) +{ + time_t t; + struct tm tm; + + t= time( NULL ); + memcpy(&tm, localtime(&t), sizeof(struct tm)); + sprintf(pszTime, "%04d%02d%02d%02d%02d%02d", + tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + return ; +} +/*********************************************************************** +** Description : 将int时间转为已经消失的时间格式串 +** param in : c -- 时间差(s) +** param out : pszTime -- string time(DD(day) hh:mm:ss) +** return code : None +***********************************************************************/ +void diffTimes(unsigned int c, char *pszTime) +{ + int day =0,hour =0 , min = 0, sec = 0; + day = c / 86400; + hour = (c%86400) / 3600; + min = (c%86400%3600) / 60 ; + sec = (c%86400%3600) % 60; + sprintf(pszTime, "%02d(day) %02d:%02d:%02d",day, hour, min, sec); +} +/*********************************************************************** +** Description : 计算与当前时间之差 +** param in : bcd_t -- BCD编码(YYMMDDHHMISS) +** param out : none +** return code : 差值 +***********************************************************************/ +int getCurrTimeDiff(unsigned char *bcd_t) +{ + unsigned char szTime[16] = {0} ; + memcpy(szTime,"20", 2) ; + bcd_to_asc(bcd_t, 6, szTime+2); + + return int(time(NULL)- strTime2int((char*)szTime)); +} +/*********************************************************************** +** Description : 获取主机时间 +** param in : None +** param out : pszTime -- string time(yyyy-mm-dd hh:mm:ss) +** return code : None +***********************************************************************/ +time_t vGetHostTimeFmt (char *pszTime) +{ + time_t t; + struct tm tm; + + t= time( NULL ); + memcpy(&tm, localtime((const time_t *)&t), sizeof(struct tm)); + sprintf(pszTime, "%04d-%02d-%02d %02d:%02d:%02d", + tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + return t; +} +/*********************************************************************** +** Description : 获取主机时间 +** param in : None +** param out : pszTime -- string time(yyyy-mm-dd hh:mm:ss) +** return code : None +***********************************************************************/ +time_t vGetHostTimeFmtBeforBay(char *pszTime, int beforbay) +{ + time_t t; + struct tm tm; + + t = time(NULL) - (beforbay * 24 * 60 * 60); + memcpy(&tm, localtime((const time_t *)&t), sizeof(struct tm)); + sprintf(pszTime, "%04d-%02d-%02d %02d:%02d:%02d", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + return t; +} + +/*********************************************************************** +** Description : 获取当天的起始和结束时间 +** param in : None +** param out : pszTime -- string time(yyyy-mm-dd hh:mm:ss) +** return code : None +***********************************************************************/ +time_t vGeOneDayTimeFmt(char *pSTime, char *pETime) +{ + time_t t; + struct tm tm; + + t = time(NULL); + memcpy(&tm, localtime((const time_t *)&t), sizeof(struct tm)); + sprintf(pSTime, "%04d-%02d-%02d 00:00:00", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + sprintf(pETime, "%04d-%02d-%02d 23:59:59", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + return t; +} + +/*********************************************************************** +** Description : 获取主机时间 +** param in : None +** param out : pszTime -- string time(yyyy-mm-dd hh:mm:ss) +** return code : None +***********************************************************************/ +unsigned int uiTime (void) +{ + time_t t; + t= time( NULL ); + return (unsigned int)(t & 0xFFFFFFFF); +} + +/*********************************************************************** +** Description : 转换time_t的时间 +** param in : t +** param out : pszTime -- string time(yyyy-mm-dd hh:mm:ss) +** return code : None +***********************************************************************/ +void vTranHostTimeFmt (time_t t, char *pszTime) +{ + struct tm tms; + memcpy(&tms, localtime((const time_t *)&t), sizeof(struct tm)); + sprintf(pszTime, "%04d-%02d-%02d %02d:%02d:%02d", + tms.tm_year+1900, tms.tm_mon+1, tms.tm_mday, + tms.tm_hour, tms.tm_min, tms.tm_sec); +} +/***************************************************************** +** Description: 时间串转整数 +** param in : pszTime -- 时间串(yyyy-mm-dd 24hh:mm:ss) +** param out : None +** return code: uintTime +*****************************************************************/ +time_t strTimeFmt2int(char *pszTime) +{ + struct tm stTm; + time_t t1 = 0; + char szTmp[20 + 1]; + + memset(szTmp, 0x00, sizeof(szTmp)); + memcpy(szTmp, pszTime, 20); + + stTm.tm_sec = atoi((char *)(szTmp + 17)); + szTmp[16] = '\0'; + stTm.tm_min = atoi((char *)(szTmp + 14)); + szTmp[13] = '\0'; + stTm.tm_hour = atoi((char *)(szTmp + 11)); /*hour since midnight[0, 23]*/ + szTmp[10] = '\0'; + stTm.tm_mday = atoi((char *)(szTmp + 8)); /* day of the month [1, 31] */ + szTmp[7] = '\0'; + stTm.tm_mon = atoi((char *)(szTmp + 5)) - 1;/*months since January[0,11]*/ + szTmp[4] = '\0'; + stTm.tm_year = atoi((char *)(szTmp)) - 1900; /* years since 1900 */ + t1 = mktime(&stTm); + return t1; +} +/*********************************************************************** +** Description : 日期时间格式转换 +** param in : t +** param out : pInTime -- string time(yyyymmddhh24mmss) +** param out : pOutTime -- string time(yyyy-mm-dd hh24:mm:ss) +** return code : None +***********************************************************************/ +void vFormatTimes(char *pszInTimeStr, char *pszOutFormatTime) +{ + sprintf(pszOutFormatTime, "%.4s-%.02s-%.02s %.02s:%.02s:%.02s", + pszInTimeStr, pszInTimeStr + 4, pszInTimeStr + 4 + 2, + pszInTimeStr + 4 + 2 + 2, pszInTimeStr + 4 + 2 + 2 + 2, pszInTimeStr + 4 + 2 + 2 + 2 + 2); +} +/*********************************************************************** +** Description : 获取当前时间点到之前360小时的时间段 +** param in : t +** param out : pSTime -- string time(yyyymmddhh24mmss) +** param out : pETime -- string time(yyyymmddhh24mmss) +** return code : None +***********************************************************************/ +void getCurrentBefor360Hour(char *pstime, char *petime) +{ + struct tm tm; + + if(pstime == NULL || petime == NULL) return ; + time_t curTime = time(NULL); + + memcpy(&tm, localtime((const time_t *)&curTime), sizeof(struct tm)); + sprintf(petime, "%04d%02d%02d%02d%02d%02d", + tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + + curTime = curTime - (360 * 60 * 60); // 360小时之前的时间 + memcpy(&tm, localtime((const time_t *)&curTime), sizeof(struct tm)); + sprintf(pstime, "%04d%02d%02d%02d%02d%02d", + tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); +} +/***************************************************************** +** Description: 时间串转整数 +** param in : pszTime -- 时间串(yyyymmddhhmmss) +** param out : None +** return code: uintTime +*****************************************************************/ +time_t strTime2int(char *pszTime) +{ + struct tm stTm ; + time_t t1 = 0; + char szTmp[14+1]; + + memset(szTmp, 0x00, sizeof(szTmp)) ; + memcpy(szTmp, pszTime, 14) ; + + stTm.tm_sec = atoi((char *)(szTmp + 12)); + szTmp[12]='\0'; + stTm.tm_min = atoi((char *)(szTmp + 10)); + szTmp[10]='\0'; + stTm.tm_hour = atoi((char *)(szTmp + 8)); /*hour since midnight[0, 23]*/ + szTmp[8]='\0'; + stTm.tm_mday = atoi((char *)(szTmp + 6)); /* day of the month [1, 31] */ + szTmp[6]='\0'; + stTm.tm_mon = atoi((char *)(szTmp + 4)) -1;/*months since January[0,11]*/ + szTmp[4]='\0'; + stTm.tm_year = atoi((char *)(szTmp)) - 1900; /* years since 1900 */ + t1 = mktime(&stTm); + return t1 ; +} +#if 0 +// 日月年(dmyy), 年的表示是先将年转换为2位十六进制数 +void setPostionDate(unsigned char *pDate, unsigned char *pTime) +{ + unsigned char szDate[5]={0}; + unsigned short usNo = 0; + + // 20130109 + memcpy(szDate, pDate+6, 2); // 日 + memcpy(szDate+2, pDate+4, 2); // 月 + asc_to_bcd(szDate, 4, pTime); + + memcpy(szDate, pDate, 4); + usNo = htons(atoi((char*)szDate)); + memcpy(pTime+2, &usNo, sizeof(short)); // 年 +} +// pDate = HH24MMSS +void setPostionTime(unsigned char *pDate, unsigned char *pTime) +{ + unsigned char szTmp[4] = {0}; + asc_to_bcd(pDate, 6, szTmp); + memcpy(pTime, szTmp, 3); +} +#else +// 日月年(dmyy), 年的表示是先将年转换为2位十六进制数 +void setPostionDate(unsigned char *pDate, unsigned char *pTime) +{ + char szDate[5]={0}; + unsigned short usNo = 0; + + // 20130109 + memcpy(szDate, pDate+6, 2); // 日 + pTime[0] = (char)atoi(szDate); + + memcpy(szDate, pDate+4, 2); // 月 + pTime[1] = (char)atoi(szDate); + + memcpy(szDate, pDate, 4); + usNo = htons(atoi((char*)szDate)); + memcpy(pTime+2, &usNo, sizeof(short)); // 年 +} + +// pDate = HH24MMSS +void setPostionTime(unsigned char *pDate, unsigned char *pTime) +{ + char szTmp[4] = {0}; + + memcpy(szTmp, pDate, 2); // 时 + pTime[0] = (char)atoi(szTmp); + + memcpy(szTmp, pDate+2, 2); // 分 + pTime[1] = (char)atoi(szTmp); + + memcpy(szTmp, pDate+4, 2); // 秒 + pTime[2] = (char)atoi(szTmp); +} +#endif + +void getGnssData(unsigned char * p_date) +{ + time_t t; + struct tm tm; + char day,month,year[2]; + short years; + + t= time( NULL ); + memcpy(&tm, localtime(&t), sizeof(struct tm)); + day = (char)tm.tm_mday; + month = (char)tm.tm_mon+1; + years = (short)tm.tm_year+1900; + memcpy(&year,(char*)&years,2); + + memcpy(p_date,&day,1); + memcpy(p_date+1,&month,1); + memcpy(p_date+2,year,2); + + return; +} + +void getGnssTime(unsigned char *p_time) +{ + time_t t; + struct tm tm; + char hour,minute,second; + + t = time(NULL); + memcpy(&tm, localtime(&t), sizeof(struct tm)); + hour = (char)tm.tm_hour; + minute = (char)tm.tm_min; + second = (char)tm.tm_sec; + + memcpy(p_time,&hour,1); + memcpy(p_time+1,&minute,1); + memcpy(p_time+2,&second,1); + + return; +} + +/*********************************************************************** +** Description : 获取主机UTC时间 +** param in : None +** param out : pszTime -- string time(yyyy-mm-dd hh:mm:ss) +** return code : None +***********************************************************************/ +void getUTCFmtTime (char *pszTime) +{ + time_t t; + struct tm tm; + + t= time( NULL ); + memcpy(&tm, gmtime(&t), sizeof(struct tm)); + sprintf(pszTime, "%04d-%02d-%02d %02d:%02d:%02d", + tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + return ; +} +/*********************************************************************** +** Description : 获取主机UTC时间 +** param in : None +** param out : pszTime -- string time(yyyy-mm-dd hh:mm:ss) +** return code : None +***********************************************************************/ +time_t getUTCLongTime (void) +{ + time_t t,t1=0; + struct tm tm={0}; + + t= time( NULL ); + memcpy(&tm, gmtime(&t), sizeof(struct tm)); + t1 = mktime(&tm); + return t1 ; +} +/*********************************************************************** +** Description : 将UTC时间转为格式串 +** param in : None +** param out : pszTime -- string time(yyyy-mm-dd hh:mm:ss) +** return code : None +***********************************************************************/ +void UTC2FmtTime (time_t utc, char *pszTime) +{ + time_t lutc= utc+(8*60*60); + struct tm tm={0}; + + memcpy(&tm, gmtime(&lutc), sizeof(struct tm)); + sprintf(pszTime, "%04d-%02d-%02d %02d:%02d:%02d", + tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + return ; +} +/*********************************************************************** +** Description : UTC时间转为本地时间 +** param in : None +** param out : pszTime -- string time(yyyy-mm-dd hh:mm:ss) +** return code : None +***********************************************************************/ +void UTC2LocalTime (time_t utc, char *pszTime) +{ + time_t lutc= utc+(8*60*60); + struct tm tm = {0}; + memcpy(&tm, localtime(&lutc), sizeof(struct tm)); + sprintf(pszTime, "%04d-%02d-%02d %02d:%02d:%02d", + tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec); + return ; +} +// 本地时间转UTC时间, pTime: YYMMDDHH24MISS +time_t local2Utc(unsigned char *pTime, int iLen) +{ + unsigned char szTime[20] = {0}; + time_t utc = 0 ,t1 = 0 ; + struct tm tm = {0}; + + bcd_to_asc(pTime, iLen, szTime+2); + memcpy(szTime, "20", 2); + utc = strTime2int((char*)szTime); + t1 = utc ; + memcpy(&tm, gmtime((const time_t*)&t1), sizeof(struct tm)); + t1 = mktime(&tm) ; + return t1 ; +} + +// 本地时间转UTC整型时间 +time_t local2UtcTime(time_t localTime) +{ + struct tm tm = {0}; + time_t t = localTime ; + memcpy(&tm, gmtime((const time_t*)&t), sizeof(struct tm)); + t = mktime(&tm); + return t; +} + +// 根据BCD编码时间转报警ID +// param_in: pTime -- YYMMDDHHMISS, \x13\x10\12\x09\x14\x11 +unsigned int getWarnID(unsigned char *pTime, int iLen, unsigned int id) +{ + unsigned char szTime[20] = {0}, szSub[20] = {0}, szTmp[8]={0}; + time_t utc = 0 ; + if(pTime == NULL || iLen <= 0) return (unsigned int)utc; + bcd_to_asc(pTime, iLen, szTime+2); // xx131012091411 + memcpy(szTime, "20", 2); // 20131012091411 + memcpy(szTmp, szTime, 4); // 2013 + sprintf((char*)szSub, "%4d0101000000", atoi((char*)szTmp)-1); + utc = strTime2int((char*)szTime) - strTime2int((char*)szSub); // 20131012091411-20121012091411 + utc = (id << 26 )| utc; + return (utc & 0xFFFFFFFF); +} +/*********************************************************************** +** Description : 获取源串中的第no个域,数字串,eg: 1923.122.3.4 +** param in : pstr -- source string end=0x00 +** : node -- split char +** : no -- index filed +** param out : None +** return code : index on filed val +***********************************************************************/ +int iSplitNumberFiled(char *pstr, char node, int no) +{ + // 192.168.3.13 + int i=0,j=0; + char *p = NULL, *s = pstr; + char szTmp[128]; + for(i =0, j=0; i<(int)strlen((const char*)pstr) && j < no; i++) { + if(pstr[i] == node) { + s = pstr+i+1; + j++; + continue; + } + } + if(s==NULL) return 0; + if(j == no ) { + while(pstr[i] != node && i<(int)strlen((const char*)pstr)) i++; + p = pstr+i; + strncpy(szTmp, s, p-s); + szTmp[p-s] = 0x00; + return atoi((const char*)szTmp); + } + return 0; +} +// 去除版本号首部字符,保留数字版本号 +// eg: Ver1.2.34 ==> 1.2.34 +int iTrimVersionHeadChar(char *strver) +{ + int i = 0 ; + if(strver == NULL) return 0 ; + if((int)strlen(strver) <= 0) return 0 ; + while(strver[i] != '.' && i < (int)strlen(strver)) { + if(!(strver[i] >= 0x30 && strver[i] <= 0x39)) + i++; + else break; + } + if(i >= (int)strlen(strver)) return 0 ; + strcpy(strver, strver+i); + return strlen(strver); +} +/*********************************************************************** +** Description : 获取源串中的第no个域, 字符串 +** param in : pstr -- source string end=0x00 +** : node -- split char +** : no -- index filed +** param out : pFiled -- index filed string +** return code : index on filed val length +** call eg: len = iSplitStringFiled("qwwa1.ddee.fwe.3.4.322.fffgsd", '.', 0, retval); +***********************************************************************/ +int iSplitStringFiled(char *pstr, char node, char no, char *pFiled) +{ + char *p = NULL, *s = pstr; + int i=0,j=0; + for(i =0, j=0; i<(int)strlen((const char*)pstr) && j < no; i++) { + if(pstr[i] == node) { + s = pstr+i+1; + j++; + continue; + } + } + if(s==NULL) return 0; + if(j == no ) { + while(pstr[i] != node && i<(int)strlen((const char*)pstr)) i++; + p = pstr+i; + strncpy(pFiled, s, p-s); + pFiled[p-s] = 0x00; + return p-s; + } + return 0; +} + +/*********************************************************************** +** Description : getDateFromTime 从时间字符串获取Date信息 +** param in : p_time -- 时间字符串 +***********************************************************************/ +void getDateFromTime(char* p_time,char* p_date) +{ + short m_year; + char m_month,m_day; + char year[5] = {0}; + char month[3] = {0}; + char day[3] = {0}; + + memcpy(year,p_time,4); + m_year = atoi(year); + m_year = htons(m_year); + + memcpy(month,p_time+5,2); + m_month = atoi(month); + memcpy(day,p_time+8,2); + m_day = atoi(day); + + memcpy(p_date,&m_day,1); + memcpy(p_date+1,&m_month,1); + memcpy(p_date+2,&m_year,2); +} + +/************************************************************** +** Description: trim string rigth space +** param in : +** : *str -- sources string +** param out : +** : *str -- trim string +** return code: +** : trim string current length +**************************************************************/ +int RigthTrim(unsigned char *str) +{ + if ( strlen((char *)str) == 0 ) return 0; + char *p = (char*)str + strlen((char*)str) - 1; + while ( p >= (char*)str && *p == ' ' ) p--; + *( ++p ) = '\0'; + return strlen( (char*)str ); +} + + /************************************************************** +** Description: trim string left space +** param in : +** : *str -- sources string(source) +** param out : +** : *str -- trim string(dest) +** return code: +** :trim string current length +**************************************************************/ +int LeftTrim(unsigned char *str) +{ + char *p = (char*)str; + while ( *p == ' ' ) p++; + strcpy( (char*)str, p ); + return strlen( (char*)str ); +} + +/************************************************************** +** Description: trim char string left and rigth space +** param in : +** : *str -- sources string +** param out : +** : *str -- dest string +** return code: None +**************************************************************/ +void LRTrim(unsigned char *str) +{ + LeftTrim(str) ; + RigthTrim(str) ; +} +/************************************************************** +** Description: trim char string middle space,仅保留一个空格 +** param in : +** : *str -- sources string +** param out : +** : *str -- dest string +** return code: None +**************************************************************/ +void MiddleTrim(unsigned char *str) +{ + char *front = (char*)str; + char *last = (char*)str; + if(str == NULL) return; + while((*front) == ' ') {++front;} + while((*front) != '\0') { + if((*front) == ' ' ) { + *last = ' '; + while((*front) == ' ') ++front; + } + else { + *last = *front; + ++front; + } + ++last; + } + *last = '\0'; +} +/************************************************************** +** Description: trim char string middle space,仅保留一个空格 +** param in : +** : *str -- sources string +** param out : +** : *str -- dest string +** return code: None +**************************************************************/ +void strMiddleTrim(unsigned char *str) +{ + char *front = (char*)str; + char *last = (char*)str; + if (str == NULL) return; + while ((*front) == '-') { ++front; } + while ((*front) != '\0') { + if ((*front) == '-') { + ++front; + continue; + } + else { + *last = *front; + ++front; + } + ++last; + } + *last = '\0'; +} +/************************************************************** +** Description: check string all char is digit(number '0'--'9') +** param in : 是否为纯数字的字符串 +** : *str -- sources string +** param out : +** : *str -- trim string +** return code: +** : true all char is digit +** : false not digit +**************************************************************/ +bool isStringDigit(char *pstr) +{ + int i = 0; + while (i < (int)strlen(pstr)) { + if(!((pstr[i] & 0xff) >= 0x30 && (pstr[i] & 0xff) <= 0x39)) return false; + else i++; + } + return true; +} + +void getTimeFromTime(char* p_time,char* p_times) +{ + char m_hour,m_minute,m_second; + char hour[3] = {0}; + char minute[3] = {0}; + char second[3] = {0}; + + memcpy(hour,p_time+11,2); + m_hour = atoi(hour); + + memcpy(minute,p_time+14,2); + m_minute = atoi(minute); + + memcpy(second,p_time+17,2); + m_second = atoi(second); + + memcpy(p_times,&m_hour,1); + memcpy(p_times+1,&m_minute,1); + memcpy(p_times+2,&m_second,1); +} + +/************************************************************************* +Function : two bytes change to one bytes +Param in : + pusFrom : source strings + uiFromLen : bytes of source strings +Param out : + pusTo : object strings. +Return Code : none +*************************************************************************/ +void asc_to_bcd(unsigned char *pusFrom, unsigned int uiFromLen, unsigned char *pusTo) +{ + unsigned char ucTmp; + unsigned int i; + + for(i=0; i> 4)]; + pusTo[2*i+1]= usHexToChar[(pusFrom[i] & 0x0F)]; + } + pusTo[2*uiFromLen] = 0x00; + return; +} +/************************************************************************* +Function : by host byte order int change to network byte order,size(int)=4 +Param in : + pusFrom : source host unsigend int +Param out : none +Return Code : network byte order +*************************************************************************/ +unsigned int htoni(unsigned int us) +{ + unsigned int i; + i=((us&0xffff)<<24)|(((us&0xffff)<<8)&0x00ff0000)| + ((us>>8)&0x0000ff00)|((us>>24)&0xffff); + return i; +} +/************************************************************************* +Function : by network byte order int change to host byte order,size(int)=4 +Param in : + pusFrom : source network unsigend int +Param out : none +Return Code : host byte order +*************************************************************************/ +unsigned int ntohi(unsigned int us) +{ + unsigned int i; + i=((us&0xffff)<<24)|(((us&0xffff)<<8)&0x00ff0000)| + ((us>>8)&0x0000ff00)|((us>>24)&0xffff); + return i; +} +/************************************************************************* +Function : by host byte order int64 change to network byte order,size(int64)=8 +Param in : + pusFrom : source host unsigend int64 +Param out : none +Return Code : network byte order +*************************************************************************/ +#ifdef htonll +utint64 htonll(utint64 u64) +{ + unsigned int hi = (unsigned int)( u64 >> 32); + unsigned int lo = (unsigned int)(u64 & 0xFFFFFFFF); + utint64 fhi = htoni(hi); + utint64 flo = htoni(lo); + flo <<= 32; + return (utint64)(flo | fhi); +} +#endif +/************************************************************************* +Function : by network byte order int64 change to host byte order,size(int64)=8 +Param in : + pusFrom : source network unsigend int64 +Param out : none +Return Code : host byte order +*************************************************************************/ +#ifdef ntohll +utint64 ntohll(utint64 u64) +{ + unsigned int hi = (unsigned int)( u64 >> 32); + unsigned int lo = (unsigned int)(u64 & 0xFFFFFFFF); + utint64 fhi = ntohi(hi); + utint64 flo = ntohi(lo); + flo <<= 32; + return (utint64)(flo | fhi); +} +#endif +/************************************************************************* +Function : one byte change to two bytes +Param in : + pusFrom : source strings + uiFromLen : bytes of source strings +Param out : + pusTo : object strings. +Return Code : none +Note : 本函数入参为网络字节序列 +*************************************************************************/ +unsigned int int64To32(utint64 u64) +{ + unsigned int hi = (unsigned int)(( u64 >> 32) & 0xFFFFFFFF \ No newline at end of file diff --git a/src/HTService.cpp b/src/HTService.cpp new file mode 100644 index 0000000..0b6a6d6 --- /dev/null +++ b/src/HTService.cpp @@ -0,0 +1,449 @@ +/****************************************************************************** +** Filename : HTService.cpp +** Description: main file +** Create Date: 2018-09-08 +** Auth By : Liuyx +** Update Date: 2018-09-08 +** Copyrigth By: xi'an huatek, Inc Co., Ltd +******************************************************************************/ +#include "HTGlobal.h" + +static const char *_FILE_ = "HTService.cpp" ; +CDBMySQL* CDBMySQL::p_dbHandle = NULL; + +static char is_down = 0 ; + +// 终止所有业务工作线程 +static void cancel_thread_work(void) +{ +#ifndef _WIN32 + int i = 0 ; + if(thread_handle_client) { + pthread_cancel(thread_handle_client); + pthread_join(thread_handle_client, NULL); + pthread_kill(thread_handle_client, SIGURG); + } + vPrtLogMsg(LOG_DEBUG, RET_OK,"thread_handle_client shutdown.") ; + + if(thread_handle_linkmgr) { + pthread_cancel(thread_handle_linkmgr); + pthread_join(thread_handle_linkmgr, NULL); + pthread_kill(thread_handle_linkmgr, SIGURG); + } + vPrtLogMsg(LOG_DEBUG, RET_OK,"thread_handle_linkmgr shutdown.") ; + + if(thread_handle_active) { + pthread_cancel(thread_handle_active); + pthread_join(thread_handle_active, NULL); + pthread_kill(thread_handle_active, SIGURG); + } + vPrtLogMsg(LOG_DEBUG, RET_OK,"thread_handle_active shutdown.") ; + + + //for(i=0; i < (int)g_TConfig.getParseThreadNumber(); i++) { + if(thread_handle_parse) { + pthread_cancel(thread_handle_parse); + pthread_join(thread_handle_parse, NULL); + pthread_kill(thread_handle_parse, SIGURG); + } + //} + vPrtLogMsg(LOG_DEBUG, RET_OK,"thread_handle_parse group shutdown.") ; + + // + //for(i=0; i < (int)g_TConfig.getOprationThreadNumber(); i++) { + // if(thread_handle_opration[i]) { + // pthread_cancel(thread_handle_opration[i]); + // pthread_join(thread_handle_opration[i], NULL); + // pthread_kill(thread_handle_opration[i], SIGURG); + // } + //} + //vPrtLogMsg(LOG_DEBUG, RET_OK,"thread_handle_opration group shutdown.") ; + + //for(i=0; i < (int)g_TConfig.getResponeThreadNumber(); i++) { + if(thread_handle_active) { + pthread_cancel(thread_handle_active); + pthread_join(thread_handle_active, NULL); + pthread_kill(thread_handle_active, SIGURG); + } + //} + vPrtLogMsg(LOG_DEBUG, RET_OK,"thread_handle_respone group shutdown.") ; +#endif +} +static void sig_exit(int signo) +{ + vPrtLogMsg(LOG_DEBUG, errno,"recv signal, service shutdown.sig:%d", signo ) ; + + cancel_thread_work(); + vPrtLogMsg(LOG_DEBUG, errno,"unloading service is done...1"); + g_Running = 0 ; // 先停止所有的业务线程 + + _SLEEP(1000*2); + + vPrtLogMsg(LOG_DEBUG, errno,"unloading service is done...2"); + unLoadServiceEvent();// 卸载运行配置 + is_down = 0 ; + vPrtLogMsg(LOG_DEBUG, errno,"unloading service is done."); +} + +void sig_chld(int signo) +{ +#ifndef _WIN32 + pid_t pid; + int stat; + while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0) + vPrtLogMsg(LOG_DEBUG, RET_OK, "child %d terminated\n", pid); +#endif + return; +} + +// 创建守护进程环境 +static int HTStartBackgroundProcess() +{ +#ifndef _WIN32 + pid_t pid; + + // 1.转变为后台进程 + if ((pid = fork() ) != 0 ) + exit( 0); + + // 2.离开原先的进程组 + setsid(); + + // 3.禁止再次打开控制终端 + if ((pid = fork() ) != 0 ) + exit( 0); + + // 4.关闭打开的文件描述符,避免浪费系统资源 + /* + rlimit rlim; + if(getrlimit(RLIMIT_NOFILE,&rlim) == 0) + { + for(int fd=3; fd<=(int)rlim.rlim_cur; fd++) + { + close(fd); + } + } + */ + + // 5.改变当前的工作目录,避免卸载不了文件系统 + //if (chdir("/") == -1) exit(1); + + // 6.重设文件掩码,防止某些属性被父进程屏蔽 + umask(0); + setpgrp(); + + // 7.重定向标准输入,输出,错误流,因为守护进程没有控制终端 + /* + if ((fd = open("/dev/null", O_RDWR)) == -1) + exit(1); + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + close(fd); + */ + signal(SIGINT, sig_exit); // Program terminated with signal 11, Segmentation fault. + signal(SIGTERM, sig_exit); + // 8.屏蔽信号 + signal( SIGHUP, SIG_IGN); + signal( SIGQUIT, SIG_IGN); + signal( SIGPIPE, SIG_IGN); + signal( SIGTTOU, SIG_IGN); + signal( SIGTTIN, SIG_IGN); + signal( SIGCHLD, SIG_IGN); + + struct sigaction sig; + + sig.sa_handler = SIG_IGN; + sig.sa_flags = 0; + sigemptyset( &sig.sa_mask); + sigaction( SIGHUP,&sig,NULL); +#endif + return 0; +} + + +void getcptime(unsigned char *data, int len) +{ + SYSTEMTIME st ; + + st.wMilliseconds = (data[0]+ 256 * data[1])%1000; + + st.wSecond = (data[0] + 256 * data[1])/1000; + + st.wMinute = data[2] & 0x3f; + + st.wHour = data[3]&0x1f; + + st.wDay = data[4]&0x1f; + + st.wMonth = data[5]&0x0f; + + st.wYear = data[6] & 0x7f; +} + +static void Usage(char *prgname) +{ + printf("==>> Usage: \n"); + printf(" %s [start | stop | version] [img_file shigh ehigh swidth ewidth[tabtype 180 | 360]]\n", prgname); + printf("Parameters:\n"); + printf(" --> img_file ... Pictures file path and name\n"); + printf(" --> shigh ... Pictures's start high pointer\n"); + printf(" --> ehigh ... Pictures's end high pointer\n"); + printf(" --> swidth ... Pictures's start width pointer\n"); + printf(" --> ewidth ... Pictures's end width pointer\n"); + // add by ramon 2019-06-27, add TYPE=xxxx + printf(" --> tabtype:[TYPE] ... Pictures's end width pointer,TYPE=3EX5050 | JSY-10 | YZF250TH\n"); + + printf("Examples:\n"); + printf(" --> %s start ... Startup Service\n", prgname); + printf(" --> %s stop ... Shutdown Service\n", prgname); + printf(" --> %s ./img.jpg 10 200 50 210 ... Clipping pictures to high(10,200) width(50,210)\n", prgname); + // add by ramon 2019-06-27, add TYPE=xxxx + printf(" --> %s ./img.jpg TYPE 180|360 ... Get pictuer point value, TYPE=3EX5050|JSY-10|YZF250TH\n", prgname); + printf(" --> %s ./img.jpg 10 200 50 210 JSY-10 360 ... Clipping pictures and get point number\n", prgname); + printf(" --> %s ./img.jpg 10 200 50 210 3EX5050 180 ... Clipping pictures and get point number\n", prgname); + printf(" --> %s ./img.jpg 10 200 50 210 YZF250TH 360 ... Clipping pictures and get point number\n", prgname); // add by ramon 2019-06-27 + printf("Version:\n"); + //printf(" %s version %s Copyright (c) 2020 the Huatek developers group.\n", prgname, HT_VERSION_BUILD_ID); + printf(" %s version %s Copyright (c) 2020 the Xydl developers group.\n", prgname, HT_VERSION_BUILD_ID); +} + +static void task_kill() +{ + char szCmd[128] = { 0 }; + int pid = iGetPid(); +#ifdef _WIN32 + sprintf(szCmd, "taskkill /PID %d /F", pid); +#else + sprintf(szCmd, "kill -9 %d >/dev/null 2>&1", pid); +#endif + system(szCmd); +} +#if 1 +int main(int argc, char* argv[]) +{ + //char szTime[] = "20191122140322"; + //char szOut[32] = { 0 }; + //double dOilTempOuter = -9999.0f, dInitValue = -9999.0f; + //vFormatTimes(szTime, szOut); + //printf("szTime=%s out=%s\n", szTime, szOut); + //for (int i = 0; i < 100; i++) + // printf("%s\n", double2str(dOilTempOuter, dInitValue, szOut)); + + //getchar(); + + if (argc != 2 && argc != 4 && argc != 6 && argc != 8) { + Usage(argv[0]); + return 0; + } + if (argc == 4) //获取图片指针读数 + { + vInitLogMutex(); // 初始化log文件锁与句柄 + g_TConfig.getIniConfig(); + ST_OPENCV_CONF stConf; + strcpy((char*)stConf.img_path, argv[1]); + stConf.is_replace = false; + strcpy((char*)stConf.table_type, argv[2]); + stConf.base_angle = atoi(argv[3]); + stConf.dInitVal = 1; + + printf("-->> Table type:[%s] Base_angle:[%d°]\n", argv[2], stConf.base_angle); + if (stringncasecmp("JSY-10", argv[2], strlen("JSY-10")) == 0) + printf("-->> ReadPoint: [%s] read num: %.2f\n", argv[1], dReadPointValue_JSY10(&stConf, argv[1])); + else if (stringncasecmp("3EX5050", argv[2], strlen("3EX5050")) == 0) + printf("-->> ReadPoint: [%s] read num: %.2f\n", argv[1], dReadPointValue_3EX5050(&stConf, argv[1])); + // add by ramon 2019-06-27 + else if (stringncasecmp("YZF250TH", argv[2], strlen("YZF250TH")) == 0) + printf("-->> ReadPoint: [%s] read num: %.2f\n", argv[1], dReadPointValue_JSY10(&stConf, argv[1])); + // add by ramon 2019-06-27 + else printf("ERROR-->> Unkonw table type:%s, TYPE: JSY-10|3EX5050|YZF250TH", argv[2]); + //getchar(); + return 0; + } + if (argc == 6) // 截图工具方式 + { + ST_OPENCV_CONF stConf; + strcpy((char*)stConf.img_path, argv[1]); + stConf.s_height = atoi(argv[2]); + stConf.e_height = atoi(argv[3]); + stConf.s_width = atoi(argv[4]); + stConf.e_width = atoi(argv[5]); + stConf.is_replace = false; + vCutImageSave(&stConf, argv[1]); + printf("-->> Clipping pictures:[%s] to :[%s] ... complete.\n", stConf.img_path, argv[1]); + return 0; + } + if (argc == 8) //获取图片指针读数 + { + vInitLogMutex(); // 初始化log文件锁与句柄 + g_TConfig.getIniConfig(); + ST_OPENCV_CONF stConf; + strcpy((char*)stConf.img_path, argv[1]); + stConf.s_height = atoi(argv[2]); + stConf.e_height = atoi(argv[3]); + stConf.s_width = atoi(argv[4]); + stConf.e_width = atoi(argv[5]); + stConf.is_replace = false; + stConf.dInitVal = 5.8f; + + strcpy((char*)stConf.table_type, argv[6]); + stConf.base_angle = atoi(argv[7]); + vCutImageSave(&stConf,argv[1]); + printf("-->> Clipping pictures:[%s] to :[%s] ... complete.\n", stConf.img_path, argv[1]); + printf("-->> Table type:[%s] Base_angle:[%d°]\n", (char*)stConf.table_type, stConf.base_angle); + if (stringncasecmp("JSY-10", argv[6], strlen("JSY-10")) == 0) + printf("-->> ReadPoint: [%s] read num: %.2f\n", argv[1], dReadPointValue_JSY10(&stConf, argv[1])); + else if (stringncasecmp("3EX5050", argv[6],strlen("3EX5050")) == 0) + printf("-->> ReadPoint: [%s] read num: %.2f\n", argv[1], dReadPointValue_3EX5050(&stConf, argv[1])); + // add by ramon 2019-06-27 + else if (stringncasecmp("YZF250TH", argv[6], strlen("YZF250TH")) == 0) + printf("-->> ReadPoint: [%s] read num: %.2f\n", argv[1], dReadPointValue_JSY10(&stConf, argv[1])); + else printf("ERROR-->> Unkonw table type:%s, TYPE: JSY-10|3EX5050|YZF250TH", argv[6]); + return 0; + } + + if (argc == 2) { + if (!stringcasecmp("start", argv[1])) { + int i = 0; + is_down = 1; + + if (RET_OK != loadServiceEvent()) return 0; // 加载运行配置 + HTStartBackgroundProcess(); + HTInitThreadHandle(); + vSetPid(); // 记录PID + + ht_pthread_create_background(&thread_handle_cache,thread_cache_proc,NULL); // 内存数据同步线程 +#ifdef _HT_IEC104_APP + ht_pthread_create_background(&thread_handle_warning, thread_warn_proc, NULL); // 告警处理线程 + ht_pthread_create_background(&thread_handle_origin, thread_origin_proc, NULL); // 原始数据入库线程 + ht_pthread_create_background(&thread_handle_pingce, thread_pingce_proc, NULL); // 评测数据入库线程 + ht_pthread_create_background(&thread_handle_gishold, thread_gis_hold_proc, NULL); // 评测数据入库线程 + + ht_pthread_create_background(&thread_handle_linkmgr, thread_client_proc, NULL); // 链路管理线程 + ht_pthread_create_background(&thread_handle_parse, thread_parser_proc, NULL); // 104报文解析线程 + ht_pthread_create_background(&thread_handle_timer, thread_Timer_proc, NULL); // 104链路超时管理线程 + ht_pthread_create_background(&thread_handle_active, thread_active_proc, NULL); // 104报文应答线程 +#endif +#ifdef _HT_OPENCV_APP + ht_pthread_create_background(&thread_handle_opecvimg, thread_opencv_proc, NULL); // 图片解析线程 +#endif + printf("Service start ...... OK\n"); + while (1) { + if (!is_down) break; + _SLEEP(2000); + } + vPrtLogMsg(LOG_DEBUG, 0, "free manager database connection pool:%s/%s@%s successed!", + g_TConfig.getdbUserName(), g_TConfig.getdbUserPass(), g_TConfig.getdbName()); + vPrtLogMsg(LOG_DEBUG, 0, "HTService shutdown completed immediately!"); + vFreeLogMutex(); // 关闭log文件锁与句柄 + return 0; + } + if (!stringcasecmp("stop", argv[1])) { + task_kill(); + printf("Service stop ...... OK\n"); + return 0; + } + if (!stringcasecmp("version", argv[1])) { + printf("--> %s version %s Copyright (c) 2020 the Xydl developers group.\n", argv[0], HT_VERSION_BUILD_ID); + return 0; + } + } + Usage(argv[0]); + return 0; +} + +#else +bool bSetPointTableValue(unsigned char *v, int len, unsigned int adr, char stype) +{ + unsigned char cval = 0; + float fval = 0; + switch (stype) + { + case 1: // 遥信量 + if (v) cval = ((unsigned char)v[0] & 0xff); + printf("cval=%d\n", cval); + break; + case 2: // 遥测量 + if (v) memcpy(&fval, &v, len); + + printf("fval=%.3f\n", fval); + break; + default: + break; + } + + return true; +} + + + +//计算得到指针指向的角度 theta,直接测量可以得到指针刻度起点所对应的角度 minangle, +//以及终止角度maxangle,以及最大刻度量 10. +//则可以得到实际的示数: +// +//value = (theta - minangle) * 10 / (maxangle - minangle) +// +//利用这个公式对上图的示数进行计算, +// +//minangle = 60 maxangle = 320 最大刻度量 10,theta = 220 +// +//value = (220 - 60) * 10 / (320 - 60) = 6.15384615.... +// +//接近真实数值,当然为了获得尽可能准确的数值,我们需要精确的 minangle maxangle 以及theta +/////////////////////////////// +//指针所在的线段是我们通过霍夫检测得到的, +//所以我们可以得到线段的两个端点 a(x1, y1) b(x2, y2) +//计算线段的 tan(theta), 然后计算反三角函数得到 theta +//前面我们得到圆的一些基本参数:圆心坐标 c(x, y), 半径 r +//假设 a 是离圆心的近点,b 是远点 +// +//x_angle = x2 - x +//y_angle = y - y2 +// +//一定要注意这里是 y - y2,不是 y2 - y, +//这是因为对图像所在的笛卡尔直角坐标系,(0,0)点在图像的左上角, +//所以越往下 y 越大。 +// +//则有 tan(theta) = y_angle / x_angle theta = arctan(tan(theat)) +///////////////////////////// +//(1)(x_angle > 0 and y_angle >0) or(x_angle > 0 and y_angle < 0) +// +// final_theta = 270 - theta +// +// 但是这包含了两种小情况,前半部分说明指针的终点在右半部分的上半部分, +// theta > 0, final_theta < 270;后半部分说明指针的终点在右半部分的 +// 下半部分,theta < 0, final_theta > 270. +//(2) (x_angle < 0 and y_angle >0) or(x_angle < 0 and y_angle < 0) +// +// final_theta = 90 - theta +// +// 依然是两种情况,前半部分说明指针指向的是左半部分的上半部分, +// theta < 0, final_theta > 90; 后半部分说明指针指向了左半部分的 +// 下半部分,theta > 0, final_theta < 90 +void genWainningTables() +{ + +} +/** @函数 main */ +int main(int argc, char** argv) +{ + // vInitPress_OCR17NI12MO2_16(); + + if (argc == 6) // 截图工具方式 + { + ST_OPENCV_CONF stConf; + strcpy((char*)stConf.img_path, argv[1]); + stConf.s_height = atoi(argv[2]); + stConf.e_height = atoi(argv[3]); + stConf.s_width = atoi(argv[4]); + stConf.e_width = atoi(argv[5]); + stConf.is_replace = false; + vCutImageSave(&stConf, argv[1]); + printf("-->> Clipping pictures:[%s] to :[%s] ... complete.\n", stConf.img_path, argv[1]); + //return 0; + } + HTImgAnalys(argv[1]); + + return 0; +} +#endif diff --git a/src/HTTcpSocket.cpp b/src/HTTcpSocket.cpp new file mode 100644 index 0000000..d17e903 --- /dev/null +++ b/src/HTTcpSocket.cpp @@ -0,0 +1,518 @@ +/**************************************************************************** +** File name : FLTTcpSocket.h +** Description : define common api for tcp socket +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +// #include "StdAfx.h" +#include +#include "HTGlobal.h" +#include "HTTcpSocket.h" + +static const char *_FILE_ ="HTTcpSocket.cpp" ; + +TTcpSocket::TTcpSocket() +{ + m_tcpPort = 0 ; + m_server_fd = -1; + m_sockid = -1; + #ifdef _WIN32 + WSADATA Data ; + WSAStartup(MAKEWORD(2, 2), &Data) ; + #endif +} + +TTcpSocket::~TTcpSocket() +{ + #ifdef _WIN32 + WSACleanup(); + #endif +} + +void TTcpSocket::tcpSetServerfd(int fd) +{ + if (fd > 0) m_server_fd = fd; +} +void TTcpSocket::tcpSetSockID(int fd) +{ + if (fd > 0) m_sockid = fd; +} + +int TTcpSocket::tcpGetServerfd() +{ + return m_server_fd; +} +int TTcpSocket::tcpGetSockID() +{ + return m_sockid; +} +//关闭socket +int TTcpSocket::tcpCloseSocket(int sockfd) +{ + if(sockfd > 0) { + #ifdef _WIN32 + //if(_close(sockfd) == -1) + if(shutdown(sockfd, 2) == -1) + #else + if(close(sockfd) == -1) + #endif +// vPrtLogMsg(LOG_WARNG, RET_FAIL, "_close sockid=%d return:%d:%s",sockfd, errno, strerror(errno)); + return 1; + } + return 0 ; +} + +void TTcpSocket::SetSocketMode(int sockid, int iMode) +{ + //将SOCKET置为非阻塞的I/O +#ifndef _WIN32 + if (fcntl(sockid, F_SETFL, (fcntl(sockid, F_GETFL) | O_NONBLOCK)) == -1) { + vPrtLogMsg(LOG_WARNG, errno,"error occured when fcntl,sockid:%d msg:%s.",sockid, strerror(errno)); + return ; + } +#else + unsigned long flag = iMode ; //0:阻塞模式 1:非阻塞方式 + if((ioctlsocket(sockid, FIONBIO, &flag)) < 0) { + vPrtLogMsg(LOG_WARNG, errno,"error occured when ioctlsocket,sockid:%d msg:%s.",sockid, strerror(errno)); + return ; + } +#endif +} + +// 根据sockid获取源地址和源端口 +int TTcpSocket::getPeerInfo(int sockid, unsigned char *sip, unsigned short *sport) +{ + if(sockid < 0) return -1; + struct sockaddr_in clientaddr; + #ifndef _WIN32 + socklen_t clilen =sizeof(struct sockaddr_in); ; + #else + int clilen = sizeof(struct sockaddr_in) ; + #endif + + if(getpeername(sockid, (struct sockaddr *)&clientaddr, &clilen) < 0) { + vPrtLogMsg(LOG_ERROR, errno, "getpeername failed, sockid=%d", sockid); + return -1; + } + strcpy((char*)sip, inet_ntoa(clientaddr.sin_addr)); + *sport = ntohs(clientaddr.sin_port); + return 0; +} +// 根据sockid获取目标地址和目标端口 +int TTcpSocket::getLocalSocketInfo(int sockid, unsigned char *sip, unsigned short *sport) +{ + if(sockid < 0) return -1; + struct sockaddr_in clientaddr; +#ifndef _WIN32 + socklen_t clilen =sizeof(struct sockaddr_in); ; +#else + int clilen = sizeof(struct sockaddr_in) ; +#endif + + if(getsockname(sockid, (struct sockaddr *)&clientaddr, &clilen) < 0) { + vPrtLogMsg(LOG_ERROR, errno, "getpeername failed, sockid=%d", sockid); + return -1; + } + strcpy((char*)sip, inet_ntoa(clientaddr.sin_addr)); + *sport = ntohs(clientaddr.sin_port); + return 0; +} +//创建socket TCP服务。 +// return val : 0 -- successed +// : <0 -- failed +int TTcpSocket::tcpOpenServer(const char *ip,unsigned short port) +{ + int m_sockfd = -1; + + if(!(port > 1024 && port < 65535) ) + { + vPrtLogMsg(LOG_ERROR, ErrSockParam, "server port:%d is invalid(1024-65535)", port); + return ErrSockParam; + } + + m_tcpPort = port; + setvbuf(stdin,NULL,_IONBF,MAX_SBUFF_TCP); + setvbuf(stdout, NULL, _IONBF, MAX_SBUFF_TCP); + + //创建SOCKET对象 + m_sockfd = socket(AF_INET, SOCK_STREAM, 0); + if(m_sockfd == -1) + { + vPrtLogMsg(LOG_ERROR, ErrOpenServer, "create socket error,msg:%s.",strerror(errno)); + return ErrOpenServer; + } + + //将SOCKET置为非阻塞的I/O + // SetSocketMode(m_sockfd) ; + + struct sockaddr_in fsock; + int iRet = -1; + #ifndef _WIN32 + bzero((char *)&fsock, sizeof(struct sockaddr_in)) ; + #else + memset(&fsock, 0x00, sizeof(struct sockaddr_in)) ; + #endif + fsock.sin_family=AF_INET; + fsock.sin_port=htons(m_tcpPort); + fsock.sin_addr.s_addr=htoni(INADDR_ANY); + if (ip) fsock.sin_addr.s_addr=inet_addr(ip); + + int iFlag = 1; + #ifndef _WIN32 + if(setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&iFlag, sizeof(iFlag)) != 0) + #else + if(setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&iFlag, sizeof(iFlag)) != 0) + #endif + { + vPrtLogMsg(LOG_ERROR, ErrSetSockOpt,"setsockopt of so_reuseaddr error." + "sockid:%d msg:%s.",m_sockfd, strerror(errno)) ; + tcpCloseSocket(m_sockfd) ; + return ErrSetSockOpt ; + } + + if((iRet = bind(m_sockfd, (struct sockaddr*)&fsock, sizeof(fsock))) == -1) + { + vPrtLogMsg(LOG_ERROR, ErrBindFail, "socket bind error,sockid:%d msg:%s.",m_sockfd, strerror(errno)) ; + tcpCloseSocket(m_sockfd) ; + return ErrBindFail; + } + if((iRet = listen(m_sockfd, LISTENQ)) == -1) + { + vPrtLogMsg(LOG_ERROR, ErrListenFail,"socket listen error,sockid:%d msg:%s.",m_sockfd, strerror(errno)) ; + tcpCloseSocket(m_sockfd) ; + return ErrListenFail; + } + + // m_tcpConnected = true ; + vPrtLogMsg(LOG_DEBUG, 0, "Acceptting on %s:%d, waitting request...",ip,m_tcpPort) ; + return m_sockfd ; +} + +//侦听是否有连接请求 +int TTcpSocket::tcpAcceptSocket(int sockid) +{ + fd_set fd_Read ; + struct timeval st_TimeOut ; + int isel = 0 ; + int iClientID = -1 ; + struct sockaddr_in cliaddr; + + #ifndef _WIN32 + socklen_t cliAddrLen = sizeof(sockaddr_in) ; + #else + int cliAddrLen = sizeof(sockaddr_in) ; + #endif + + st_TimeOut.tv_sec = 5 ; + st_TimeOut.tv_usec = 0; + FD_ZERO(&fd_Read); + FD_SET((unsigned int)sockid, &fd_Read); + isel = select(sockid + 1 , &fd_Read, NULL, NULL, &st_TimeOut); + if(isel == 0 || isel == EINTR) { + // vPrtLogMsg(LOG_DEBUG, errno, "accept...isel=%d errno=%d",isel, errno); + return -1 ; + } + else if( FD_ISSET(sockid , &fd_Read) ) + { + iClientID = accept(sockid, (struct sockaddr*)&cliaddr, &cliAddrLen); + if(iClientID > 0) + { + vPrtLogMsg(LOG_DEBUG, 0,"Have once new link from %s:%d sockid:%d.", + inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port), iClientID) ; + } + else { + vPrtLogMsg(LOG_DEBUG, errno, "accept...isel=%d errno=%d",isel, errno); + return -1; + } + } + SetSocketMode(iClientID); //设置为非阻塞 + int iFlag = 1; + #ifndef _WIN32 + if(setsockopt(iClientID, SOL_SOCKET, SO_REUSEADDR, (const void *)&iFlag, sizeof(iFlag)) != 0) + #else + if(setsockopt(iClientID, SOL_SOCKET, SO_REUSEADDR, (const char *)&iFlag, sizeof(iFlag)) != 0) + #endif + { + vPrtLogMsg(LOG_ERROR, ErrSetSockOpt,"setsockopt of so_reuseaddr error,sockid:%d msg:%s.",iClientID, strerror(errno)) ; + tcpCloseSocket(iClientID) ; + return ErrSetSockOpt ; + } + tcpSetlinger(iClientID); + return iClientID ; +} + +/************************************************************ +** Description : send data for TCP/IP +** Para in : tcpID TCP/IP socket description +** *buf send data buffer +** length send data size +** Para out : None +** Return Code : >0 send data length +** <0 error +************************************************************/ +int TTcpSocket::tcpSendBuffer(int sockid, const char *pBuffer, int length) +{ + if ((sockid <= 0) || (pBuffer == NULL) ) + return -1 ; + if(length <= 0) length = strlen(pBuffer); + + int iSendLen = 0,iLen=0,i=0,iCnt=0,len=length ; + char *p = (char *)pBuffer; + fd_set fd_Write, fd_Except ; + struct timeval st_TimeOut ; + + if(length > MAX_SBUFF_TCP) + iCnt = length/MAX_SBUFF_TCP ; + else + iCnt = 0 ; + for(;;) + { + FD_ZERO(&fd_Write) ; + FD_ZERO(&fd_Except) ; + FD_SET((unsigned int)sockid, &fd_Write) ; + FD_SET((unsigned int)sockid, &fd_Except) ; + iSendLen = -1 ; + st_TimeOut.tv_sec = 0 ; + st_TimeOut.tv_usec = 10 ; + + iSendLen = select (sockid+1 , NULL, &fd_Write, &fd_Except, &st_TimeOut) ; + if((iSendLen == 0 && errno == EPIPE) || (iSendLen < 0)) { // EPIPE =32 Broken pipe EBADF=9 Bad file number + vPrtLogMsg(LOG_ERROR,errno, "socket execption close,sockid:%d ret:%d msg:%s", sockid, iSendLen, strerror(errno)); + //add_monitor_mesg(len, 0x00, (unsigned char*)pBuffer); // 添加监控消息到监控发送队列 + return ErrException; + } + if( FD_ISSET(sockid, &fd_Except) ) + { + vPrtLogMsg(LOG_ERROR,errno, "socket execption,sockid:%d msg:%s", sockid, strerror(errno)); + //add_monitor_mesg(len, 0x00, (unsigned char*)pBuffer); // 添加监控消息到监控发送队列 + return ErrSendFail ; //socket exception + } + else if( FD_ISSET(sockid , &fd_Write) ) + { + iSendLen = 0 ; + for(i=0; i< iCnt; i++) + { + iLen = send(sockid, p+(i*MAX_SBUFF_TCP), MAX_SBUFF_TCP,0); + if( iLen < 0 ) + { + vPrtLogMsg(LOG_ERROR,errno, "send buffer fail,sockid:%d toplen:%ld sendlen:%d msg:%s", + sockid, len, iSendLen, strerror(errno)); + if(errno == 0 && iLen == -1) { + //add_monitor_mesg(len, 0x00, (unsigned char*)pBuffer); // 添加监控消息到监控发送队列 + return ErrException; + } + if(errno == EPIPE || errno == EBADF || errno == ECONNRESET || errno == EINVAL) { + //add_monitor_mesg(len, 0x00, (unsigned char*)pBuffer); // 添加监控消息到监控发送队列 + return ErrException; + } + else { + //add_monitor_mesg(len, 0x00, (unsigned char*)pBuffer); // 添加监控消息到监控发送队列 + return ErrSendFail ; // send data fail + } + } + length -= MAX_SBUFF_TCP; + iSendLen += iLen ; + } + if(length == 0 ) { + //add_monitor_mesg(len, 0x01, (unsigned char*)pBuffer); // 添加监控消息到监控发送队列 + return iSendLen ; + } + if(length >0) + { + iLen = send(sockid, p+(i*MAX_SBUFF_TCP), length,0); + if(iLen < 0) + { + vPrtLogMsg(LOG_ERROR, errno, "send buffer fail! sockid:%d toplen:%ld sendlen:%d msg:%s", + sockid, len, iSendLen, strerror(errno)); + if(errno == 0 && iLen == -1) { + //add_monitor_mesg(len, 0x00, (unsigned char*)pBuffer); // 添加监控消息到监控发送队列 + return ErrException; + } + if(errno == EPIPE || errno == EBADF || errno == ECONNRESET || errno == EINVAL) { + //add_monitor_mesg(len, 0x00, (unsigned char*)pBuffer); // 添加监控消息到监控发送队列 + return ErrException; + } + else { + //add_monitor_mesg(len, 0x00, (unsigned char*)pBuffer); // 添加监控消息到监控发送队列 + return ErrSendFail ; // send data fail + } + } + break ; + } + } + } //end for(;;) + //add_monitor_mesg(iSendLen+iLen, 0x01, (unsigned char*)pBuffer); // 添加监控消息到监控发送队列 + return (iSendLen+iLen); +} + +/************************************************************ +** Description : recv data for TCP/IP +** Para in : tcpID TCP/IP socket description +** *buf send data buffer +** length send data size +** Para out : None +** Return Code : >0 recv data length +** <0 error +************************************************************/ +int TTcpSocket::tcpRecvBuffer(int sockid, char* pBuffer,int nMaxLength, int timeout) +{ + int nLength = -2; + int iTop = 0; + fd_set fd_Read,fd_Except; + struct timeval st_TimeOut; + int isel = 0; + + if( sockid <= 0 || pBuffer == NULL) return -1; + while(iTop != nMaxLength) + { + st_TimeOut.tv_sec = timeout ; + st_TimeOut.tv_usec = 0; + FD_ZERO(&fd_Read); + FD_ZERO(&fd_Except) ; + FD_SET((unsigned int)sockid, &fd_Read) ; + FD_SET((unsigned int)sockid, &fd_Except) ; + isel= select (sockid + 1 , &fd_Read, NULL, &fd_Except, &st_TimeOut) ; + + if(isel <= 0 || isel == EINTR) + { + // vPrtLogMsg(LOG_DEBUG,errno, "select socket timeout,isel=%d",isel); + break ; + } + else if( FD_ISSET(sockid, &fd_Except) ) + { + vPrtLogMsg(LOG_ERROR,errno,"socket execption,sockid:%d errno:%d iselect:%d", sockid, errno, isel) ; + return ErrRecvFail; // recv fail + } + else if (isel > 0) //EINTR + { + if (FD_ISSET(sockid,&fd_Read)) //检测Socket读状态 + { + nLength = recv(sockid, pBuffer, MAX_SBUFF_TCP, MSG_PEEK); // MSG_PEEK + if ( nLength < 0 && (errno == EPIPE || errno == EBADF || errno == ECONNRESET || errno == EINVAL)) + return ErrException; + else if( isel == 1 && nLength == 0 && (errno == EPIPE || errno == EBADF || errno == ECONNRESET || errno == EINVAL)) { + vPrtLogMsg(LOG_DEBUG,errno, "select socket timeout,isel=%d nLength=%d",isel,nLength); + return ErrException; // iTop; //检查到客户端主动断开连接. + } + else if(nLength < 0 && errno == 0) + return ErrException ; + else if (nLength < 0) + return ErrRecvFail; // recv fail + else if (nLength == 0) + return ErrException; + else { + iTop += nLength; + } + } + break ; + } + } + return iTop; +} + +//连接是否已经建立 +bool TTcpSocket::tcpIsConnected(int sockid) +{ + char msg[5] = {0}; + int err = 0; + if(sockid <= 0 ) return false ; + err = recv(sockid, msg, sizeof(msg), MSG_PEEK); + /* client already close connection. */ + if(err < 0 && (errno == EPIPE || errno == EBADF || errno == ECONNRESET)) + return false; + return true; +} + +int TTcpSocket::tcpSetlinger(int sockid) +{ + struct linger lingerStruct={1,0}; + + if(setsockopt(sockid, SOL_SOCKET, SO_LINGER, (char *)&lingerStruct, sizeof(lingerStruct)) == -1) + return -1; + return 0; +} +int TTcpSocket::tcpSetNodelay(int sockid) +{ + int nodelay = 1; +#ifdef TCP_NODELAY + if(setsockopt(sockid, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, sizeof(nodelay)) == -1) + return -1; +#endif + return 0; +} + +// 连接TCP 服务器 +int TTcpSocket::tcpConnect(const char *pszIP, short port, int iTimeout) +{ + int iRet = -1, sockid=-1; + struct sockaddr_in addr; + int on = 1; + + if(!pszIP || !((unsigned int)port > 1024 && (unsigned int)port < 65535)) { + vPrtLogMsg(LOG_ERROR, ErrSockParam, "in parameter ip/port %s:%d(1024-65535) invalid.", pszIP, port); + return ErrSockParam; + } + // Create socket + sockid = socket(AF_INET, SOCK_STREAM, 0); + if(sockid < 0 ) + { + vPrtLogMsg (LOG_ERROR, errno, "create socket failed! errno[%d],msg:%s", errno,strerror(errno)); + sockid = -1; + return sockid; // break; + } + + memset(&addr, 0x00, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = inet_addr(pszIP); //htoni(INADDR_ANY); + + /* set socket options */ + #ifdef _WIN32 + //setsockopt(sockid, SOL_SOCKET, SO_ERROR, (const char*)&on, sizeof(int)); + if(setsockopt(sockid, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(int)) < 0) { + #else + if(setsockopt(sockid, SOL_SOCKET, SO_REUSEADDR, (const void*)&on, sizeof(int)) < 0) { + #endif + vPrtLogMsg (LOG_ERROR, errno, "setsockopt error! errno[%d],msg:%s", errno,strerror(errno)); + tcpCloseSocket(sockid); + sockid = -1; + return sockid; // break; + } + //SetSocketMode(sockid); // 将建立的新连接置为非阻塞 + iRet = connect(sockid, (struct sockaddr *)&addr, sizeof(addr)); + if (iRet == 0) { + tcpSetlinger(sockid); // 建链成功 + SetSocketMode(sockid); // 将建立的新连接置为非阻塞 + return sockid; + } + tcpCloseSocket(sockid); + sockid = -1; + + return sockid; +} + +void TTcpSocket::clear_tcp_buffer(int socket_fd, int nbytes) +{ + char buffer[MAX_TEMP_BUFFER_SIZE]={0}; + int recv_len; + int i; + if(nbytes == 0) return ; // 如果需要清除的字节数为0 则直接返回成功 + for(i = 0; i < (int)(nbytes / MAX_TEMP_BUFFER_SIZE); i++) { + recv_len = recv(socket_fd, buffer, MAX_TEMP_BUFFER_SIZE, 0); + if(recv_len >= 0 && recv_len < MAX_TEMP_BUFFER_SIZE) { // 期间如果发现缓冲区的数据已经被清空了则返回 + return ; + } + else if(recv_len < 0) { // 异常了 + return ; + } + } + recv_len = recv(socket_fd, buffer, (nbytes % MAX_TEMP_BUFFER_SIZE), 0); + if(recv_len >= 0) return ; + else return ; +} diff --git a/src/HTTestOpencv.cpp b/src/HTTestOpencv.cpp new file mode 100644 index 0000000..24f10fc --- /dev/null +++ b/src/HTTestOpencv.cpp @@ -0,0 +1 @@ +锘 \ No newline at end of file diff --git a/src/HTThread.cpp b/src/HTThread.cpp new file mode 100644 index 0000000..2392f22 --- /dev/null +++ b/src/HTThread.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** File name : HTThread.h +** Description : define server 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 "HTGlobal.h" +#include "HTThread.h" + +static const char *_FILE_ ="HTThread.cpp"; + +/******************************************************************** + * function : 创建线程句柄 + * param in : none + * param out : None + * return val: 0 -- successed + * : <0 -- failed +********************************************************************/ +static int HTNewThreadHandle(pthread_t **pThreadHandle, int thread_count) +{ + *pThreadHandle = (pthread_t*)calloc(1, sizeof(pthread_t)*thread_count); + if(*pThreadHandle == NULL) { + vPrtLogMsg(LOG_ERROR, errno, "calloc for thread handle failed."); + return -1; + } + memset(*pThreadHandle, 0xff, sizeof(pthread_t)*thread_count); + return 0; +} +// 释放系统线程句柄 +static int HTDelThreadHandle(pthread_t **pThreadHandle) +{ + if(*pThreadHandle) { + free(*pThreadHandle); + *pThreadHandle = NULL; + } + return 0; +} +// 释放句柄 +void HTFreeThreadHandle(void) +{ + //HTDelThreadHandle(&thread_handle_recv); + //HTDelThreadHandle(&thread_handle_parse); + //HTDelThreadHandle(&thread_handle_setdb); + //HTDelThreadHandle(&thread_handle_respone); +} + +/******************************************************************** + * function : 初始化线程句柄 + * param in : none + * param out : None + * return val: 0 -- successed + * : <0 -- failed +********************************************************************/ +int HTInitThreadHandle(void) +{ +// if(HTNewThreadHandle(&thread_handle_recv,g_TConfig.getRecvThreadNumber()) != RET_OK) { +// HTFreeThreadHandle(); +// return RET_FAIL; +// } +// if(HTNewThreadHandle(&thread_handle_parse,g_TConfig.getParseThreadNumber()) != RET_OK) { +// HTFreeThreadHandle(); +// return RET_FAIL; +// } + //if(HTNewThreadHandle(&thread_handle_setdb,g_TConfig.getOprationThreadNumber()) != RET_OK) { + // HTFreeThreadHandle(); + // return RET_FAIL; + //} +// if(HTNewThreadHandle(&thread_handle_respone,g_TConfig.getResponeThreadNumber()) != RET_OK) { +// HTFreeThreadHandle(); +// return RET_FAIL; +// } + + return 0; +} + +/******************************************************************** + * function : 创建链接政府监管平台主链路线程 + * param in : none + * param out : None + * return val: 0 -- successed + * : <0 -- failed +********************************************************************/ +int ht_pthread_create_background(pthread_t *thread_handle, void *(*pfunc)(void *), void *data) +{ +#ifdef _WIN32 + HANDLE handle = NULL; + handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)pfunc,(LPVOID)data, 0, thread_handle); + if (!handle) { + ::CloseHandle(handle); + return -1 ; + } +#else + if(pthread_create(thread_handle, NULL, pfunc, data) !=0 ) { + return -1 ; + } +#endif + return 0 ; +} + +void pthread_testcancels(void) +{ +#ifndef _WIN32 + pthread_testcancel(); +#endif +} + + + diff --git a/src/HTUnit.cpp b/src/HTUnit.cpp new file mode 100644 index 0000000..8a37efd --- /dev/null +++ b/src/HTUnit.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** File name : HTUnit.cpp +** Description : units changes for API +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#include "HTGlobal.h" + +static const char *_FILE_ = "HTUnit.cpp" ; + +//1:kV(千伏) 2 : V(伏) 3 : kA(千安) 4 : A(安) 5 : mA(毫安) 6 : ℃(度) 7 : Pa(帕) 8 : KPa(千帕) 9 : MPa(兆帕) 10 : pF(皮法-电容单位) +//11 : pC(皮库仑-电量单位) 12 : dB(分贝) 13 : μL(微升) 14 : mL(毫升) 15 : L(升) 16 : m / s(米 / 秒) 17 : rpm&r / min(转 / 分钟) + +// 单位转换 +double getChangeUnit(short Unit, short sysUnit, double val) +{ + double retval = val; + switch (Unit) + { + case 1: // kV + if (sysUnit == 2) { + retval = val * 1000; + } + break; + case 2: // V + if (sysUnit == 1) { + retval = val / 1000; + } + break; + case 3: // kA + if (sysUnit == 4) { //A + retval = val * 1000; + } + else if (sysUnit == 5) { // mA + retval = val * 1000 * 1000; + } + break; + case 4: // A + if (sysUnit == 3) { //kA + retval = val / 1000; + } + else if (sysUnit == 5) { // mA + retval = val * 1000 ; + } + break; + case 5: // mA + if (sysUnit == 3) { //kA + retval = val / 1000 / 1000; + } + else if (sysUnit == 4) { // A + retval = val / 1000; + } + break; + case 6: //摄氏度 + //if (sysUnit == 26) ////华氏度 + // retval = (val - 32 / 1.800f); + break; + case 7: //Pa + if (sysUnit == 8) //KPa + retval = (val / 1000 ); + else if (sysUnit == 9) //MPa + retval = (val / 1000 / 1000); + break; + case 8: //KPa + if (sysUnit == 7) //Pa + retval = (val * 1000); + else if (sysUnit == 9) //MPa + retval = (val / 1000 ); + break; + case 9: //MPa + if (sysUnit == 7) //Pa + retval = (val * 1000 * 1000); + else if (sysUnit == 8) //KPa + retval = (val * 1000); + break; + case 13: //μL + if (sysUnit == 14) // mL + retval = val / 1000; + else if (sysUnit == 15) // L + retval = val / 1000 / 1000; + break; + case 14: //mL + if (sysUnit == 13) // μL + retval = val * 1000; + else if (sysUnit == 15) // L + retval = val / 1000; + break; + case 15: //L + if (sysUnit == 13) // μL + retval = val * 1000 * 1000; + else if (sysUnit == 14) // mL + retval = val * 1000; + break; + default:; + } + return retval; +} +//(1)1法拉(F) = 1000毫法(mF) +// +//(2)1毫法(mF) = 1000微法(μF) +// +//(3)1微法(μF) = 1000纳法(nF) +// +//(4)1纳法(nF) = 1000皮法(pF) + + + +// 比较double之差是否大于rate. +// return : > true <= : false +bool bCompare(double ov, double nv, double rate) +{ + if(rate <= 0.0f) return false; + double d= ((abs(nv - ov) / ov) * 100); + return d > rate ? true : false; +} + + diff --git a/src/HXIec104.cpp b/src/HXIec104.cpp new file mode 100644 index 0000000..40d4ded --- /dev/null +++ b/src/HXIec104.cpp @@ -0,0 +1,912 @@ +/**************************************************************************** +** File name : HTConfig.cpp +** Description : config parameter +** Create date : 2018.09.01 +** Auther by : Liuyx +** Version info : V1.0.01 +** Copyright (C) 2002-2018 xi'an huatek, Inc Co., Ltd +** Update record: +** DATE AUTHER DESC +** ------------------------------------------------------------------------- +** 2018.09.01 Liuyx first build +****************************************************************************/ +#include "HTGlobal.h" +#include "HXIec104.h" + + + +void NsNetServerProcess(void); + +static void NsIec104Process(void); +static void NsIec104Init(unsigned char Card,short Port); +static void NsIec104NetInit(void); + +static void NsIec104Reset(void); +static void NsIec104ProcessFormatI(void); +static void NsIec104ProcessFormatS(void); +static void NsIec104ProcessFormatU(void); +static void NsIec104Interrogation(void); +static void NsIec104InterrogationGroup(void); +static void NsIec104InterrogationAll(void); +static void NsIec104ProcessYxGroup(unsigned char Group); +static void NsIec104ProcessYcGroup(unsigned char Group); +static void NsIec104ProcessCellGroup(unsigned char Group); +static void NsIec104ProcessTime(void); +static void NsIec104ProcessYkYt(void); +static void NsIec104ProcessPulse(void); +static void NsIec104DefaultGroup(unsigned char Group); +static void NsIec104ProcessPulseData(void); +static void NsIec104SendGroup(void); + +static void NsIec104SendYkMessage(short Who,unsigned char Action); +static void NsIec104ReceiveYkReturn(void); +static void NsIec104SendYkSelectConfirm(void); +static void NsIec104SendYkExeConfirm(void); +static void NsIec104SendYkEscConfirm(void); +static unsigned char NsIec104SendCosSoe(void); +static void NsIec104InitYk(void); +static void NsIec104CycleCount(void); +static void NsIec104SendChangeYc(void); +/* +static void Iec104testCosSoe(void); +void debug104(void); +*/ +static void NsIec104Init(unsigned char Card,short Port) +{ + unsigned short i; + int Result; +// char Buff[32]; +// char Ip0Buff[64],Ip0Route[64]; +//// char Ip1Buff[64],Ip1Route[64]; + NS_SYSTEM_DATA_MODE SysData; + + NsIec104Struct.LinkState=NS_DISCONNECTED; + NsIec104Struct.NsNewSocketId=0; +// getforsecond(&NsIec104Struct.LinkValidTime); + NsIec104Struct.ReceiveIndex=0; + NsIec104Struct.ReceiveIndexLength=0; + NsIec104Struct.SendMeNumber=0; + NsIec104Struct.HasSendNumber=0; + NsIec104Struct.NeedSendNumber=0; + NsIec104Struct.LeftSendNumber=0; + NsIec104Struct.Card=Card; + NsIec104Struct.Port=Port; + NsIec104Struct.YkStartSign=OFF; + NsIec104Struct.Table=0; + NsIec104Struct.NetRunSign=OFF; + NsIec104Struct.SetNetSign=OFF; + +// Result=ReadNsc200Ini("NsIec104","SetTimeFlag",Buff); + if(Result) + { + NsIec104Struct.SetTimeFlag=1; + } + + for(i=0;i0) + { + Card-=1; + } + } + NsIec104Init(Card,2404); + for(;;) + { + NsIec104Struct.SystemState = NsGetSysParameter(NS_NSCC_STATE); + NsIec104Struct.NetRunSign = NsNetConfigState(); + + if(NsIec104Struct.NetRunSign==ON&&NsIec104Struct.SetNetSign==OFF&&NsIec104Struct.SystemState==DUTY) + { + NsIec104NetInit(); + NsIec104Struct.SetNetSign=ON; + } + if(NsIec104Struct.NetRunSign==ON&&NsIec104Struct.SetNetSign==ON&&NsIec104Struct.SystemState==DUTY) + { + getforsecond(&Now); + Nap=DiffMsLong(Now,NsIec104Struct.LinkValidTime); + if(Nap>NS_IEC104_PERMIT_TIME) + { + NsIec104Struct.LinkState=NS_DISCONNECTED; + } + if(NsIec104Struct.YkStartSign==ON) + { + Nap=DiffMsLong(Now,NsIec104Struct.YkStartTime); + if(Nap>NS_IEC104_YK_PERMIT_TIME) + { + NsIec104InitYk(); + } + } + if(NsIec104Struct.LinkState==NS_DISCONNECTED) + { + + NsIec104Struct.NsNewSocketId=NsTcpConnect(NsIec104Struct.NsNewSocketId,NsIec104Struct.Card); + + if(NsIec104Struct.NsNewSocketId>0) + { + NsIec104Struct.LinkState=NS_CONNECTED; + NsIec104Struct.SendMeNumber=0; + getforsecond(&NsIec104Struct.LinkValidTime); + } + else + { + /*NsIec104Init(NsIec104Struct.Card,NsIec104Struct.Port);*/ + + /* NsTcpServerInit(NsIec104Struct.Card,NsIec104Struct.Port,"10.14.8.23");*/ + NsIec104Struct.LinkState=NS_DISCONNECTED; + NsIec104Reset(); + taskDelay(866); + } + } + else + { + + NsIec104Struct.ReceiveIndexLength=recv(NsIec104Struct.NsNewSocketId,&NsIec104Struct.ReceiveBuffer[NsIec104Struct.ReceiveIndex],198,0); + + if(NsIec104Struct.ReceiveIndexLength>0) + { + NsIec104Struct.ReceiveLength+=NsIec104Struct.ReceiveIndexLength; + if(NsIec104Struct.ReceiveLengthNsIec104Struct.YcNap[NsIec104Struct.YcLibIndex+i]) + { + NsIec104Struct.YcChangeCount++; + NsIec104Struct.YcLastValue[NsIec104Struct.YcLibIndex+i]=YcValue;*/ + /* Information Object Address Now Three Bytes */ + General=0x701+NsIec104Struct.YcLibIndex+i; + P=(unsigned char *)&General; + NsIec104Struct.SendBuffer[Index++]=P[0]; + NsIec104Struct.SendBuffer[Index++]=P[1]; + NsIec104Struct.SendBuffer[Index++]=0; + + /*fYc = YcValue * 1.0; + P=(unsigned char *)&fYc; + + NsIec104Struct.SendBuffer[Index++]=P[0]; + NsIec104Struct.SendBuffer[Index++]=P[1]; + NsIec104Struct.SendBuffer[Index++]=P[2]; + NsIec104Struct.SendBuffer[Index++]=P[3];*/ + NsIec104Struct.SendBuffer[Index++]=NsIec104Struct.DataBuff[2*i]; + NsIec104Struct.SendBuffer[Index++]=NsIec104Struct.DataBuff[2*i + 1]; + NsIec104Struct.SendBuffer[Index++]=0x00; /*qds*/ + /*}*/ + } + + /* Repair Length and Count*/ + NsIec104Struct.SendBuffer[1]=Index-2; + NsIec104Struct.SendBuffer[7]=NsIec104Struct.YcChangeCount; + if(NsIec104Struct.YcChangeCount>0) + {/* + printf("\n Co=%d Ind=%dGe=%d",NsIec104Struct.YcChangeCount,NsIec104Struct.YcLibIndex,General); + */ + if((NsIec104Struct.SendLength=send(NsIec104Struct.NsNewSocketId,&NsIec104Struct.SendBuffer[0],Index,0x0))<0) + { + perror ("Client FirstWrite Error"); + } + } +} + + +static void NsIec104SendGroup(void) +{ + if(NsIec104Struct.NeedSendNumber>0&&NsIec104Struct.HasSendNumber=NsIec104Struct.NeedSendNumber) + { + NsIec104Struct.HasSendNumber=0; + NsIec104Struct.NeedSendNumber=0; + NsIec104Struct.LeftSendNumber=0; + } + } + taskDelay(108); + +} + + +static void NsIec104Process(void) +{ + int i; + +/* printf("r:"); + for(i=0;i=NS_IEC_104_MIN_LENGTH && NsIec104Struct.ReceiveBuffer[0]==NS_IEC_104_HEAD) + { + NsIec104Struct.FormatType=NsIec104Struct.ReceiveBuffer[2]&0x03; + if(NsIec104Struct.FormatType==0||NsIec104Struct.FormatType==2) /* I */ + { + NsIec104ProcessFormatI(); + } + else + { + if(NsIec104Struct.FormatType==1) /* S */ + NsIec104ProcessFormatS(); + else + { + if(NsIec104Struct.FormatType==3)/* U */ + NsIec104ProcessFormatU(); + } + } + NsIec104Reset(); + } + +} + +static void NsIec104ProcessFormatI(void) +{ +int i; +unsigned char *p; +unsigned short NoWay; +/* + printf("\nFormatI"); +*/ + NsIec104Struct.ApduLength=NsIec104Struct.ReceiveBuffer[1]; + if(NsIec104Struct.ApduLength>NS_IEC_104_MIN_LENGTH) + { + NsIec104Struct.ReceiveHimNumber[0]=NsIec104Struct.ReceiveBuffer[2]; + NsIec104Struct.ReceiveHimNumber[1]=NsIec104Struct.ReceiveBuffer[3]; + NoWay=*(unsigned short *)&NsIec104Struct.ReceiveHimNumber[0]; + NoWay>>=1; + NoWay+=1; + NoWay<<=1; + p=(unsigned char *)&NoWay; + NsIec104Struct.ReceiveHimNumber[0]=p[0]; + NsIec104Struct.ReceiveHimNumber[1]=p[1]; + + NsIec104Struct.AsduType=NsIec104Struct.ReceiveBuffer[6]; + + for(i=0;i< NS_IEC_104_REASONBYTE;i++) + NsIec104Struct.TransmitReason[i]=NsIec104Struct.ReceiveBuffer[NS_STARTREASON+i]; + + for(i=0;i0) + { + if(Number>36) + Number=36; + SendCount=0; + Index=0; + NsIec104Struct.SendBuffer[Index++]=0x68; + NsIec104Struct.SendBuffer[Index++]=0x00; + + RealNumber=(NsIec104Struct.SendMeNumber<<1); + P=(unsigned char *)&RealNumber; + NsIec104Struct.SendBuffer[Index++]=P[0]; /* send number */ + NsIec104Struct.SendBuffer[Index++]=P[1]; + NsIec104Struct.SendMeNumber=(NsIec104Struct.SendMeNumber+1)%65535; + + + NsIec104Struct.SendBuffer[Index++]=NsIec104Struct.ReceiveHimNumber[0]; /* receive number */ + NsIec104Struct.SendBuffer[Index++]=NsIec104Struct.ReceiveHimNumber[1]; + + NsIec104Struct.SendBuffer[Index++]=0x01; /* 0x01--->0x02 asdu type */ + NsIec104Struct.SendBuffer[Index++]=1; /* information object count */ + + /* REASONBYTE now is two */ + NsIec104Struct.SendBuffer[Index++]=0x03; /* reason */ + NsIec104Struct.SendBuffer[Index++]=0x00; /* reason */ + + + for(i=0;i0) + { + if(Number>18) + Number=18; + SendCount=0; + Index=0; + NsIec104Struct.SendBuffer[Index++]=0x68; + NsIec104Struct.SendBuffer[Index++]=0x00; + + RealNumber=(NsIec104Struct.SendMeNumber<<1); + P=(unsigned char *)&RealNumber; + NsIec104Struct.SendBuffer[Index++]=P[0]; /* send number */ + NsIec104Struct.SendBuffer[Index++]=P[1]; + NsIec104Struct.SendMeNumber=(NsIec104Struct.SendMeNumber+1)%65535; + + + NsIec104Struct.SendBuffer[Index++]=NsIec104Struct.ReceiveHimNumber[0]; /* receive number */ + NsIec104Struct.SendBuffer[Index++]=NsIec104Struct.ReceiveHimNumber[1]; + + NsIec104Struct.SendBuffer[Index++]=30; /* asdu type */ + NsIec104Struct.SendBuffer[Index++]=1; /* information object count */ + + /* REASONBYTE now is two */ + NsIec104Struct.SendBuffer[Index++]=0x03; /* reason */ + NsIec104Struct.SendBuffer[Index++]=0x00; /* reason */ + + + for(i=0;i0) + { + NsIec104Struct.SendLength=send(NsIec104Struct.NsNewSocketId,&NsIec104Struct.SendBuffer[0],Index,0x0); + CosSendSign=0x01; + } + return CosSendSign; +} + + + +static void NsIec104ProcessYkYt(void) +{ + +unsigned char YkInformation,YkReason,YkWhat; +unsigned short YkObject; +unsigned char Media,YkAction; +NS_RELATION Dear; + +/* + Information Object Address 0xb01---0xb80 + for(i=0;i< NS_IEC_104_REASONBYTE;i++) + NsIec104Struct.TransmitReason[i]=NsIec104Struct.ReceiveBuffer[NS_STARTREASON+i]; +for(i=0;i