├── IEC103.cpp ├── business ├── IEC103Manager.cpp ├── IEC103Manager.h ├── IEC103Type.h ├── Serial485ClientService.cpp ├── Serial485ClientService.h ├── SerialService.cpp ├── SerialService.h ├── Service.cpp ├── Service.h ├── TcpService.cpp └── TcpService.h └── core ├── Config.cpp ├── Config.h ├── DBHelper.h ├── EncapMysql.cpp ├── EncapMysql.h ├── FileHelper.h ├── Inet.cpp ├── Inet.h ├── Logger.cpp ├── Logger.h ├── MemCache.cpp ├── MemCache.h ├── Mutex.h ├── SerialNet.cpp ├── SerialNet.h ├── TcpNet.cpp ├── TcpNet.h ├── UdpNet.cpp ├── UdpNet.h ├── WarningLib.cpp └── WarningLib.h /IEC103.cpp: -------------------------------------------------------------------------------- 1 | //============================================================================ 2 | // Name : IEC103.cpp 3 | // Author : 4 | // Version : 5 | // Copyright : Your copyright notice 6 | // Description : Hello World in C++, Ansi-style 7 | //============================================================================ 8 | 9 | #include 10 | #include "business/IEC103Manager.h" 11 | 12 | 13 | int main(int32_t argc, char *argv[]) 14 | { 15 | IEC103Manager manager; 16 | 17 | if(!manager.Init()) 18 | { 19 | return -1; 20 | } 21 | 22 | manager.Start(); 23 | manager.Stop(); 24 | 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /business/IEC103Manager.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * IEC103Manager.cpp 3 | * 4 | * Created on: Jun 19, 2015 5 | * Author: root 6 | */ 7 | 8 | #include "IEC103Manager.h" 9 | 10 | 11 | IEC103Manager::IEC103Manager():m_service(NULL) 12 | { 13 | 14 | } 15 | 16 | IEC103Manager::~IEC103Manager() 17 | { 18 | delete m_service; 19 | } 20 | 21 | bool IEC103Manager::Init() 22 | { 23 | //从配置文件初始化配置参数 mysql连接的ip usr pwd 24 | if(!Config::GetInstance()->Init(CONFIGPATHNAME)) 25 | { 26 | std::cout << "init config error" << std::endl; 27 | return false; 28 | } 29 | 30 | //初始化日志文件 31 | InitLogging("",(LogLevel)Config::GetInstance()->GetLogLv(),LOGPATH); 32 | 33 | signal(SIGTERM, SignalHandle); 34 | 35 | //初始化mysql 36 | std::string strMysqlIp = Config::GetInstance()->GetMysqlIp(); 37 | std::string strMysqlUser = Config::GetInstance()->GetMysqlUser(); 38 | std::string strMysqlPwd = Config::GetInstance()->GetMysqlPwd(); 39 | std::string strMysqlDbname = Config::GetInstance()->GetMysqlDbname(); 40 | uint16_t mysqlPort = Config::GetInstance()->GetMysqlPort(); 41 | if(0 != EncapMysql::GetInstance()->Connect(strMysqlIp.c_str(), strMysqlUser.c_str(), strMysqlPwd.c_str(), strMysqlDbname.c_str(), mysqlPort)) 42 | { 43 | std::cout << "EncapMysql error" << std::endl; 44 | return false; 45 | } 46 | 47 | //初始化告警库 48 | // if(!WarningLib::GetInstance()->Init(strMysqlIp.c_str(), strMysqlUser.c_str(), strMysqlPwd.c_str(), strMysqlDbname.c_str(), mysqlPort)) 49 | // { 50 | // return false; 51 | // } 52 | // if(!WarningLib::GetInstance()->Start()) 53 | // { 54 | // return false; 55 | // } 56 | 57 | //从mysql中读取配置参数初始化本地配置参数 58 | // if(!Config::GetInstance()->InitMysqlParams()) 59 | // { 60 | // std::cout << "Config read d eata rror" << std::endl; 61 | // return false; 62 | // } 63 | 64 | //初始化内存数据库 65 | // std::string redisAddr = Config::GetInstance()->GetRedisIp(); 66 | // uint16_t redisPort = Config::GetInstance()->GetRedisPort(); 67 | // if(!MemCache::GetInstance()->Init(redisAddr, redisPort)) 68 | // { 69 | // std::cout << "memcache error" << std::endl; 70 | // return false; 71 | // } 72 | 73 | //初始化服务 74 | uint16_t netType = Config::GetInstance()->GetNetType(); 75 | std::string strNetType(""); 76 | if(1 == netType) 77 | { 78 | if(Config::RS485_CLIENT_RUN == Config::GetInstance()->GetIec103RunType()) 79 | { 80 | m_service = new Serial485ClientService(); 81 | } 82 | else 83 | { 84 | m_service = new SerialService(); 85 | } 86 | 87 | strNetType = "serial"; 88 | } 89 | else if(2 == netType) 90 | { 91 | //网络通信 92 | strNetType = "Internet"; 93 | //m_service = new TcpService(); 94 | m_service = new Service(); 95 | //return false; 96 | } 97 | else 98 | { 99 | ERROR("invalid netType \n"); 100 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "invalid netType"); 101 | return false; 102 | } 103 | 104 | INFO("IEC103 Start with %s \n",strNetType.c_str()); 105 | 106 | if(!m_service->Init()) 107 | { 108 | ERROR("IEC103 init failed \n"); 109 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "IEC103 init failed"); 110 | return false; 111 | } 112 | 113 | //更新pid到采集进程表 114 | // char cmd[512] = {0}; 115 | // sprintf(cmd, "update collect_process set PROCESS_ID=%d WHERE id=%d;", getpid(), Config::GetInstance()->GetId()); 116 | // if(0 != EncapMysql::GetInstance()->ModifyQuery(cmd)) 117 | // { 118 | // std::cout << "update Process Error "<< getpid()<< " "<< Config::GetInstance()->GetId()<Start(); //启动服务 128 | } 129 | 130 | void IEC103Manager::Stop() 131 | { 132 | WarningLib::GetInstance()->Stop(); 133 | } 134 | 135 | void IEC103Manager::SignalHandle(int sigNo) 136 | { 137 | INFO("received SIGTERM IEC103 pid[%d] exit\n", getpid() ); 138 | WarningLib::GetInstance()->Stop(); 139 | exit(0); 140 | } 141 | -------------------------------------------------------------------------------- /business/IEC103Manager.h: -------------------------------------------------------------------------------- 1 | /* 2 | * IEC103Manager.h 3 | * 4 | * Created on: Jun 19, 2015 5 | * Author: root 6 | */ 7 | 8 | #ifndef IEC103MANAGER_H_ 9 | #define IEC103MANAGER_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include "../core/Logger.h" 15 | #include "../core/Config.h" 16 | #include "SerialService.h" 17 | #include "TcpService.h" 18 | #include "Serial485ClientService.h" 19 | #include "../core/EncapMysql.h" 20 | #include "../core/MemCache.h" 21 | #include "../core/WarningLib.h" 22 | using namespace std; 23 | 24 | #define LOGPATH "./log/" 25 | #define CONFIGPATHNAME "./config.ini" 26 | 27 | class IEC103Manager { 28 | public: 29 | IEC103Manager(); 30 | virtual ~IEC103Manager(); 31 | bool Init(); 32 | void Start(); 33 | void Stop(); 34 | static void SignalHandle(int sigNo); 35 | private: 36 | Service * m_service; 37 | }; 38 | 39 | #endif /* IEC103MANAGER_H_ */ 40 | -------------------------------------------------------------------------------- /business/IEC103Type.h: -------------------------------------------------------------------------------- 1 | /* 2 | * IEC103Type.h 3 | * 4 | * Created on: Jun 15, 2015 5 | * Author: root 6 | */ 7 | 8 | #ifndef IEC103TYPE_H_ 9 | #define IEC103TYPE_H_ 10 | 11 | #include 12 | #include 13 | 14 | 15 | enum ASDU_TYPE 16 | { 17 | ASDU_1 = 0x01, 18 | ASDU_2 = 0x02, 19 | ASDU_10 = 0x0A, 20 | ASDU_40 = 0x28, 21 | ASDU_41 = 0x29, 22 | ASDU_42 = 0x2A, 23 | ASDU_43 = 0x2B, 24 | ASDU_44 = 0x2C, 25 | ASDU_45 = 0x2D, 26 | ASDU_46 = 0x2E, 27 | ASDU_50 = 0x32, 28 | }; 29 | 30 | enum CMD_SEND 31 | { 32 | CMD_RESET_CON, 33 | CMD_RESET_NUM, 34 | CMD_RESET_TIMESTAMP, //对时 35 | CMD_RESET_EVENT, //复归命令 36 | CMD_SETTING_DOWNLOAD, //定值下载 37 | CMD_SETTING_MODIFY, //定值修改 38 | CMD_GET_ALL, 39 | CMD_GET_DATA_LV1, //获取一级数据 40 | CMD_GET_DATA_LV2, //获取二级数据 41 | CMD_GET_SINGLE_SETTING_VALUE, //获取单个条目值 42 | CMD_GENERAL_READ_YX_GROUP_VALUE, 43 | CMD_GENERAL_READ_YC_GROUP_VALUE, 44 | }; 45 | 46 | //标志位在报文中的位置 47 | #define CODE_POSI 4 //控制域 48 | #define TYP_POSI 6 //类型标识 49 | #define VSQ_POSI 7 //可变结构限定词 50 | #define COT_POSI 8 //传送原因 51 | #define ADDR_POSI 9 //设备地址 52 | #define FUN_POSI 10 //功能类型 53 | #define INF_POSI 11 //信息序号 54 | #define RII_POSI 12 //返回信息标识符 55 | #define DPI_POSI 12 //双点信息 56 | #define RET_POSI 13 //相对时间 表示装置启动到该元件动作的相对时间,毫秒 57 | #define FAN_POSI 15 //故障序号 58 | #define ASDU_1_TIMESTAMP 13 //ASDU1中四字节时间起始位置 59 | #define ASDU_2_TIMESTAMP 17 //ASDU2中四字节时间起始位置 60 | #define GROUP_POSI 14 //组号 61 | #define TNTRY_POSI 15 //条目号 62 | #define KOD_POSI 16 //描述的类别 63 | #define GDD_POSI 17 //通用分类数据描述 64 | #define GID_POSI 20 //通用分类标识数据 65 | #define NGD_POSI 13 //通用分类数据集数目 66 | 67 | 68 | 69 | #define START_10H 0x10 //固定长度报文启动字符 70 | #define START_68H 0x68 //可变长度报文启动字符 71 | #define END_16H 0x16 //结束字符 72 | #define FCB_1 0x20 //帧计数位 73 | #define FCV_1 0x10 //帧计数有效位 74 | #define ACD_1 0x20 //有一级数据上送 75 | #define PRA_1 0x40 //启动报文位 主到从 76 | #define KOD_1 0x01 //描述类别 1为实际值 77 | 78 | //功能码定义 79 | #define FNA_S2C_RESET_CON 0 //复位通信功能码 80 | #define FNA_S2C_RESET_NUM 7 //复位帧计数位功能码 81 | #define FNA_S2C_POSTDATA_3 3 //传送数据(发送/确认帧) 82 | #define FNA_S2C_POSTDATA_4 4 //传送数据(发送/无回答帧) 83 | #define FNA_S2C_GETDATA_LV1 10 //召唤一级数据功能码 84 | #define FNA_S2C_GETDATA_LV2 11 //召唤二级数据功能码 85 | 86 | //ASDU号定义 87 | #define ASDU6_TIMESTAMP 6 // 对时 88 | #define ASDU7_GETALL 7 // 总召唤,遥信 89 | #define ASDU20_RESET 20 // 复归 90 | #define ASDU21_GETGROUP 21 // 总召唤,要测 91 | #define ASDU10_SETTING 10 // 定值 92 | #define ASDU20_RESET 20 // 复归 93 | #define ASDU21_GETGROUP 21 // 总召唤,遥测 94 | 95 | //COT传送原因定义 96 | //控制方向 97 | #define COT_S2C_TIMESTAMP 8 //时间同步 98 | #define COT_S2C_GETALL_START 9 //总查询(总召唤)的启动 99 | #define COT_S2C_COMMON_ORDER 0x14 //一般命令 100 | #define COT_S2C_GENERAL_WRITE 0x28 //通用分类写命令 101 | #define COT_S2C_GENERAL_READ 0x2A //通用分类读命令 102 | 103 | //FUN定义 104 | #define FUN_GLB 0xFF //全局功能类型 105 | #define FUN_GEN 0xFE //通用分类服务功能类型 106 | 107 | 108 | //INF定义 109 | #define INF_RESET_ORDER 0x13 //复归命令,所有装置相同 110 | #define INF_READ_GROUP 0xF1 //读一个组的全部条目的值或者属性 111 | #define INF_READ_EBTRY 0xF4 //读一个条目的值或者属性 112 | #define INF_CONFIRM_WRITE 0xF9 //带确认的写条目 113 | #define INF_EXEC_WRITE 0xFA //带执行的写条目 114 | 115 | #define MAX_SIZE 1024 116 | 117 | 118 | typedef struct { 119 | uint8_t fcb; // 桢记数位 120 | uint8_t fcv; // 桢记数有效位 121 | } IEC103CodeS2C; 122 | 123 | 124 | 125 | union UnionConvert4Byte 126 | { 127 | unsigned int uValue; 128 | float fValue; 129 | char buf[4]; 130 | }; 131 | 132 | union UnionConvert2Byte 133 | { 134 | short value; 135 | ushort uValue; 136 | char buf[2]; 137 | }; 138 | 139 | typedef struct 140 | { 141 | //通用分类标识序号GIN 142 | uint8_t groupNo; //组号 143 | uint8_t entryNo; //条目号 144 | 145 | //描述的类别KOD 146 | uint8_t kod; //1为实际值 147 | 148 | //通用分类数据描述GDD 149 | uint8_t datatype; //数据类型 150 | uint8_t datasize; //数据宽度 151 | uint8_t number:7, //数目 152 | cont:1; //后续状态位 153 | }stDataUnit; //通用分类数据单元 154 | 155 | 156 | typedef struct 157 | { 158 | uint16_t msec; //毫秒 159 | uint8_t min:6, //分钟 160 | res1:1, //备用 161 | iv:1; //IV=0为有效 =1为无效 162 | uint8_t hour:7, //小时 163 | su:1; //su夏时制标志 164 | uint8_t day:5, //日 165 | dayofweek:3; //未采用 166 | uint8_t month:4, //月 167 | res2:4; //备用 168 | uint8_t year:7, //年 169 | res3:1; //备用 170 | }stTime7Byte; 171 | 172 | 173 | 174 | // 带品质描述词的被测量(MEA) 175 | typedef struct { 176 | union { 177 | short mval:13, // 带符号规一化定点数,最高位符合位,数据位占12位 178 | res:1, // 备用位:未用(常为0) 179 | er:1, // 差错位:0-有效,1-无效 180 | ov:1; // 溢出位:0-无溢出,1-溢出 181 | 182 | short wVal; 183 | }mea; 184 | }MEA; 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | #endif /* IEC103TYPE_H_ */ 193 | -------------------------------------------------------------------------------- /business/Serial485ClientService.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Serial485ClientService.cpp 3 | * 4 | * Created on: Jul 14, 2015 5 | * Author: root 6 | */ 7 | 8 | #include "Serial485ClientService.h" 9 | #include 10 | #include 11 | #include 12 | 13 | #include "../core/SerialNet.h" 14 | #include "../core/Logger.h" 15 | #include "../core/WarningLib.h" 16 | 17 | Serial485ClientService::Serial485ClientService():SerialService() 18 | { 19 | 20 | } 21 | 22 | Serial485ClientService::~Serial485ClientService() 23 | { 24 | } 25 | 26 | void Serial485ClientService::Start() 27 | { 28 | m_net = new SerialNet(m_portPath, m_speed, m_databits, m_stopbits, m_parity, m_outTime); 29 | 30 | //连接 31 | if(!m_net->Connect()) 32 | { 33 | ERROR( "serial port connect failed \n"); 34 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "serial port connect failed"); 35 | return; 36 | } 37 | 38 | while(true) 39 | { 40 | usleep(50*1000); 41 | if(!Read()) 42 | { 43 | break; 44 | } 45 | } 46 | 47 | } 48 | 49 | 50 | bool Serial485ClientService::Read() 51 | { 52 | memset(m_datapacket, 0, sizeof(m_datapacket)); 53 | static uint16_t reSendTimes = 0; //同一指令从发次数(不包括复位通信) 54 | int readSize = m_net->Read(m_datapacket, sizeof(m_datapacket)); 55 | if(-1 == readSize) 56 | { 57 | return false; 58 | } 59 | else if(-2 == readSize) //读到无效的数据重发 60 | { 61 | } 62 | else if(0 == readSize)//未读到数据 63 | { 64 | } 65 | else 66 | { 67 | reSendTimes = 0; 68 | DEBUG("read[%s]:%s \n", g_cmdName[m_nextCmd], ToHexString(m_datapacket, readSize).c_str()); 69 | if(START_68H == m_datapacket[0]) 70 | DEBUG("{code=%d, ASDU=%d, FUN=%d, INF=%d} \n", (uint8_t)m_datapacket[4], (uint8_t)m_datapacket[6], (uint8_t)m_datapacket[10], (uint8_t)m_datapacket[11]); 71 | //TODO:测试时使用 72 | printf("read[%s]: ",g_cmdName[m_nextCmd]); 73 | printf("%s \n", ToHexString(m_datapacket, readSize).c_str()); 74 | if(START_68H == m_datapacket[0]) 75 | printf("{code=%d, ASDU=%d, FUN=%d, INF=%d} \n", (uint8_t)m_datapacket[4], (uint8_t)m_datapacket[6], (uint8_t)m_datapacket[10], (uint8_t)m_datapacket[11]); 76 | if(!ParseRecvData(m_datapacket, readSize)) 77 | { 78 | WARN("recv invalied data: %s\n", ToHexString(m_datapacket, readSize).c_str()); 79 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV0, "recv invalied data"); 80 | } 81 | return true; 82 | 83 | } 84 | 85 | return true; 86 | } 87 | 88 | -------------------------------------------------------------------------------- /business/Serial485ClientService.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Serial485ClientService.h 3 | * 4 | * Created on: Jul 14, 2015 5 | * Author: root 6 | */ 7 | 8 | #ifndef SERIAL485CLIENTSERVICE_H_ 9 | #define SERIAL485CLIENTSERVICE_H_ 10 | 11 | #include "SerialService.h" 12 | 13 | class Serial485ClientService :public SerialService 14 | { 15 | public: 16 | Serial485ClientService(); 17 | virtual ~Serial485ClientService(); 18 | virtual void Start(); 19 | protected: 20 | /* 21 | * @Desc: 读取从站上送的数据 22 | * @Return: 成功或失败 23 | */ 24 | virtual bool Read(); 25 | }; 26 | 27 | #endif /* SERIAL485CLIENTSERVICE_H_ */ 28 | -------------------------------------------------------------------------------- /business/SerialService.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SerialService.cpp 3 | * 4 | * Created on: Jun 15, 2015 5 | * Author: root 6 | */ 7 | 8 | #include "SerialService.h" 9 | #include 10 | #include 11 | #include 12 | 13 | #include "../core/TcpNet.h" 14 | #include "../core/SerialNet.h" 15 | #include "../core/Logger.h" 16 | #include "../core/WarningLib.h" 17 | 18 | SerialService::SerialService():Service() 19 | { 20 | memset(m_datapacket, 0, sizeof(m_datapacket)); 21 | 22 | m_iec103CodeS2C.fcv = 0; 23 | m_iec103CodeS2C.fcb = 0; 24 | 25 | m_nextCmd = CMD_RESET_NUM; 26 | } 27 | 28 | SerialService::~SerialService() 29 | { 30 | 31 | } 32 | 33 | void SerialService::Start() 34 | { 35 | uint16_t netType = Config::GetInstance()->GetNetType(); 36 | switch(netType) 37 | { 38 | case 1: 39 | m_net = new SerialNet(m_portPath, m_speed, m_databits, m_stopbits, m_parity, m_outTime); 40 | break; 41 | case 2: 42 | m_net = new TcpNet(m_tcpip,m_tcpport); 43 | break; 44 | default: 45 | std::cout<<"Start Error :Unknown Type ="<Connect()) 53 | { 54 | ERROR( "serial port connect failed \n"); 55 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "serial port connect failed"); 56 | return; 57 | } 58 | 59 | while(true) 60 | { 61 | //usleep(50*1000); 62 | if(!Write()) 63 | { 64 | 65 | break; 66 | } 67 | //usleep(50*1000); 68 | if(!Read()) 69 | { 70 | break; 71 | } 72 | } 73 | 74 | } 75 | //com send data 76 | bool SerialService::Write() 77 | { 78 | std::vector strCmd; 79 | m_iec103CodeS2C.fcv = FCV_1; 80 | std::string cmdName(""); 81 | switch(m_nextCmd) 82 | { 83 | case CMD_RESET_CON: 84 | strCmd = CmdResetCon(); 85 | break; 86 | case CMD_RESET_NUM: 87 | strCmd = CmdResetNum(); 88 | break; 89 | case CMD_GET_ALL: 90 | strCmd = CmdGetAll(); 91 | break; 92 | case CMD_GET_DATA_LV1: 93 | strCmd = CmdGetDataLv1(); 94 | break; 95 | case CMD_GET_DATA_LV2: 96 | strCmd = CmdGetDataLv2(); 97 | break; 98 | case CMD_GENERAL_READ_YX_GROUP_VALUE: 99 | strCmd = CmdGetGroupValue(2); //TODO 遥信组号为2,需要确认不同厂家是否一致 100 | break; 101 | case CMD_GENERAL_READ_YC_GROUP_VALUE: 102 | strCmd = CmdGetGroupValue(0);//TODO 遥测组号为0,需要确认不同厂家是否一致 103 | break; 104 | default: 105 | ERROR("cmd not defined \n" ); 106 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "cmd not defined"); 107 | return false; 108 | } 109 | DEBUG("Write[%s]:%s \n", g_cmdName[m_nextCmd], ToHexString(strCmd.data(), strCmd.size()).c_str()); 110 | //TODO:测试时使用 111 | printf("write[%s]: ", g_cmdName[m_nextCmd]); 112 | printf("%s \n", ToHexString(strCmd.data(), strCmd.size()).c_str()); 113 | 114 | if(-1 == m_net->Write(strCmd.data(), strCmd.size())) 115 | { 116 | ERROR("send cmd %d error\n", m_nextCmd); 117 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "send data error"); 118 | return false; 119 | } 120 | return true; 121 | } 122 | 123 | bool SerialService::Read() 124 | { 125 | memset(m_datapacket, 0, sizeof(m_datapacket)); 126 | static uint16_t reSendTimes = 0; //同一指令从发次数(不包括复位通信) 127 | int readSize = m_net->Read(m_datapacket, sizeof(m_datapacket)); 128 | if(-1 == readSize) 129 | { 130 | return false; 131 | } 132 | else if(-2 == readSize) //读到无效的数据重发 133 | { 134 | //TODO:测试时使用 135 | printf("read[%s]: ",g_cmdName[m_nextCmd]); 136 | printf("%s \n", ToHexString(m_datapacket, strlen(m_datapacket)).c_str()); 137 | } 138 | else if(0 == readSize)//未读到数据 139 | { 140 | printf("read[%s]: no data\n",g_cmdName[m_nextCmd]); 141 | WARN("read[%s]: no data\n",g_cmdName[m_nextCmd]); 142 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV0, "receive no data"); 143 | 144 | if(CMD_RESET_CON == m_nextCmd) //如果上一次指令是通信复位不做重发计数 145 | { 146 | //sleep(1); 147 | return true; 148 | } 149 | } 150 | else 151 | { 152 | reSendTimes = 0; 153 | DEBUG("read[%s]:%s \n", g_cmdName[m_nextCmd], ToHexString(m_datapacket, readSize).c_str()); 154 | if(START_68H == m_datapacket[0]) 155 | DEBUG("{code=%d, ASDU=%d, FUN=%d, INF=%d} \n", (uint8_t)m_datapacket[4], (uint8_t)m_datapacket[6], (uint8_t)m_datapacket[10], (uint8_t)m_datapacket[11]); 156 | //TODO:测试时使用 157 | printf("read[%s]: ",g_cmdName[m_nextCmd]); 158 | printf("%s \n", ToHexString(m_datapacket, readSize).c_str()); 159 | if(START_68H == m_datapacket[0]) 160 | printf("{code=%d, ASDU=%d, FUN=%d, INF=%d} \n", (uint8_t)m_datapacket[4], (uint8_t)m_datapacket[6], (uint8_t)m_datapacket[10], (uint8_t)m_datapacket[11]); 161 | if(!ParseRecvData(m_datapacket, readSize)) 162 | { 163 | WARN("recv invalied data: %s\n", ToHexString(m_datapacket, readSize).c_str()); 164 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV0, "recv invalied data"); 165 | } 166 | return true; 167 | 168 | } 169 | 170 | //重发计数超过最大重发次数则进行复位通信 171 | if(++reSendTimes >= m_maxReSendTimes) 172 | { 173 | reSendTimes = 0; 174 | m_nextCmd = CMD_RESET_CON; 175 | m_isResetConEnd = false; 176 | m_isResetNumEnd = false; 177 | WARN("cmd send thress times , cmd resetcon send \n"); 178 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV1, "Link disconnect , cmd resetcon send"); 179 | } 180 | //sleep(m_sendInterval); 181 | 182 | return true; 183 | } 184 | 185 | /* 186 | * @Desc: 解析接收到的数据 187 | * @Param: pData 解析数据开始地址 188 | * @Param: dataLen 解析数据长度 189 | * @Return: 无 190 | */ 191 | bool SerialService::ParseRecvData(const char* pData, int32_t dataLen) 192 | { 193 | if(dataLen < 5) 194 | { 195 | return false; 196 | } 197 | if(START_10H == pData[0]) //固定长度报文(固定五个字节) 198 | { 199 | ParseFixedData(pData, dataLen); // 处理定长数据 200 | } 201 | else if(START_68H == pData[0]) //可变长报文(最少14个字节) 202 | { 203 | if(!ParseVariableData(pData, dataLen)) // 处理可变长数据 204 | { 205 | return false; 206 | } 207 | } 208 | else 209 | { 210 | return false; 211 | } 212 | return true; 213 | } 214 | 215 | /* 216 | * @Desc: 处理接收到的固定长度报文 217 | * @Param: pData 解析数据开始地址 218 | * @Param: dataLen 解析数据长度 219 | * @Return: 解析成功或失败 220 | */ 221 | bool SerialService::ParseFixedData(const char* pData, int32_t dataLen) 222 | { 223 | m_iec103CodeS2C.fcb ^= FCB_1; 224 | 225 | //通信复位的确认处理 226 | if(CMD_RESET_CON == m_nextCmd 227 | || CMD_RESET_NUM == m_nextCmd) 228 | { 229 | m_nextCmd = CMD_GET_DATA_LV1; 230 | return true; 231 | } 232 | 233 | //判断是否有一级数据上送,有则继续召唤一级数据,没有则召唤二级数据 234 | if ( (pData[1]&ACD_1) == ACD_1) 235 | { 236 | m_nextCmd = CMD_GET_DATA_LV1; 237 | } 238 | else 239 | { 240 | m_nextCmd = CMD_GET_DATA_LV2; 241 | } 242 | 243 | if(CMD_GET_DATA_LV2 == m_nextCmd 244 | && (pData[1] & 0x0F) == 9) //从站没有所召唤的数据 245 | { 246 | sleep(1); 247 | } 248 | return true; 249 | } 250 | 251 | /* 252 | * @Desc: 处理接收到的可变长度报文 253 | * @Param: pData 解析数据开始地址 254 | * @Param: dataLen 解析数据长度 255 | * @Return: 解析成功或失败 256 | */ 257 | bool SerialService::ParseVariableData(const char* pData, int32_t dataLen) 258 | { 259 | m_iec103CodeS2C.fcb ^= FCB_1; 260 | uint8_t asduType = pData[6]; // asdu类型 261 | 262 | if((CMD_GET_DATA_LV1 == m_nextCmd) 263 | && (5 == asduType)) //复位通信或复位帧计数位一级数据召唤 264 | { 265 | if((pData[4]&ACD_1) != ACD_1 ) 266 | { 267 | if(!m_isResetConEnd) 268 | { 269 | m_isResetConEnd = true; //复位通信单元完成 270 | m_nextCmd = CMD_RESET_NUM; //复位帧计数位 271 | return true; 272 | } 273 | 274 | if(!m_isResetNumEnd) 275 | { 276 | m_isResetNumEnd = true; //复位帧计数位完成 277 | m_nextCmd = CMD_GET_ALL; //复位帧计数位 278 | return true; 279 | } 280 | } 281 | return true; 282 | } 283 | 284 | //判断是否有一级数据上送,有则继续召唤一级数据,没有则召唤二级数据 285 | if ( (pData[4]&ACD_1) == ACD_1 ) 286 | { 287 | m_nextCmd = CMD_GET_DATA_LV1; 288 | } 289 | else 290 | { 291 | m_nextCmd = CMD_GET_DATA_LV2; 292 | } 293 | 294 | switch(asduType) 295 | { 296 | case 1: 297 | ParseASDU1(pData, dataLen); 298 | break; 299 | case 10: 300 | ParseASDU10(pData, dataLen); 301 | break; 302 | case 40: 303 | ParseASDU40(pData, dataLen); 304 | break; 305 | case 41: 306 | ParseASDU41(pData, dataLen); 307 | break; 308 | case 44: 309 | ParseASDU44(pData, dataLen); 310 | break; 311 | case 50: 312 | ParseASDU50(pData, dataLen); 313 | break; 314 | default: 315 | break; 316 | } 317 | return true; 318 | } 319 | 320 | /* 321 | * @Desc: 从配置文件初始化具体类型网络需要的配置 322 | * @Return: 无 323 | */ 324 | void SerialService::InitConfig() 325 | { 326 | 327 | m_portPath = Config::GetInstance()->GetSerialPortPath(); 328 | m_speed = Config::GetInstance()->GetSpeed(); 329 | m_databits = Config::GetInstance()->GetDatabits(); 330 | m_stopbits = Config::GetInstance()->GetStopbits(); 331 | m_parity = Config::GetInstance()->GetParity(); 332 | 333 | m_outTime = Config::GetInstance()->GetOutTime(); 334 | 335 | m_clientAddr = static_cast(Config::GetInstance()->GetClientAddr()[0]); 336 | 337 | m_tcpip = Config::GetInstance()->GetIp(); 338 | m_tcpport = Config::GetInstance()->GetTcpPort(); 339 | } 340 | 341 | -------------------------------------------------------------------------------- /business/SerialService.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SerialService.h 3 | * 4 | * Created on: Jun 15, 2015 5 | * Author: root 6 | */ 7 | 8 | #ifndef SERIALSERVICE_H_ 9 | #define SERIALSERVICE_H_ 10 | 11 | #include 12 | 13 | #include "IEC103Type.h" 14 | #include "Service.h" 15 | 16 | #define MAX_SIZE 1024 17 | 18 | class SerialNet; 19 | class SerialService : public Service 20 | { 21 | public: 22 | SerialService(); 23 | virtual ~SerialService(); 24 | virtual void Start(); 25 | 26 | protected: 27 | /* 28 | * @Desc: 读取从站上送的数据 29 | * @Return: 成功或失败 30 | */ 31 | virtual bool Read(); 32 | 33 | /* 34 | * @Desc: 主站发送指令 35 | * @Return: 成功或失败 36 | */ 37 | virtual bool Write(); 38 | 39 | /* 40 | * @Desc: 解析接收到的数据 41 | * @Param: pData 解析数据开始地址 42 | * @Param: dataLen 解析数据长度 43 | * @Return: 解析成功或失败 44 | */ 45 | virtual bool ParseRecvData(const char* pData, int32_t dataLen); 46 | 47 | /* 48 | * @Desc: 处理接收到的固定长度报文 49 | * @Param: pData 解析数据开始地址 50 | * @Param: dataLen 解析数据长度 51 | * @Return: 解析成功或失败 52 | */ 53 | virtual bool ParseFixedData(const char* pData, int32_t dataLen); 54 | 55 | /* 56 | * @Desc: 处理接收到的可变长度报文 57 | * @Param: pData 解析数据开始地址 58 | * @Param: dataLen 解析数据长度 59 | * @Return: 解析成功或失败 60 | */ 61 | virtual bool ParseVariableData(const char* pData, int32_t dataLen); 62 | 63 | /* 64 | * @Desc: 从配置文件初始化具体类型网络需要的配置 65 | * @Return: 无 66 | */ 67 | virtual void InitConfig(); 68 | protected: 69 | //串口参数从配置文件读取 70 | std::string m_portPath; 71 | int32_t m_speed; 72 | int32_t m_databits; 73 | int32_t m_stopbits; 74 | uint16_t m_parity; 75 | int32_t m_outTime; 76 | 77 | //com param 78 | std::string m_tcpip; 79 | uint16_t m_tcpport; 80 | 81 | }; 82 | 83 | #endif /* SERIALSERVICE_H_ */ 84 | -------------------------------------------------------------------------------- /business/Service.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Service.cpp 3 | * 4 | * Created on: Jun 15, 2015 5 | * Author: root 6 | */ 7 | 8 | #include "Service.h" 9 | #include 10 | #include 11 | #include 12 | 13 | #include "../core/Logger.h" 14 | #include "../core/MemCache.h" 15 | #include "../core/EncapMysql.h" 16 | #include "../core/WarningLib.h" 17 | 18 | 19 | const char * g_cmdName[]= { 20 | "CMD_RESET_CON", 21 | "CMD_RESET_NUM", 22 | "CMD_GET_ALL", 23 | "CMD_GET_DATA_LV1", 24 | "CMD_GET_DATA_LV2", 25 | "CMD_GENERAL_READ_YX_GROUP_VALUE", 26 | "CMD_GENERAL_READ_YC_GROUP_VALUE"}; 27 | 28 | const char * g_TcpCmdName[]= { 29 | "CMD_CONNECTION_CON", 30 | "CMD_CALL_DATA", 31 | "CMD_TEST1_DATA", 32 | "CMD_TEST2_DATA", 33 | "CMD_GET_GROUPDATA", 34 | 35 | "CMD_GET_DATA_LV1", 36 | "CMD_GET_GROUPDATA", 37 | "CMD_GENERAL_READ_YX_GROUP_VALUE", 38 | "CMD_GENERAL_READ_YC_GROUP_VALUE"}; 39 | uint16_t Service::m_heartInterval=60; 40 | 41 | Service::Service():m_net(NULL) 42 | { 43 | memset(m_datapacket, 0, sizeof(m_datapacket)); 44 | m_maxReSendTimes = 3; 45 | m_sendInterval = 3; 46 | 47 | m_iec103CodeS2C.fcv = FCV_1; 48 | m_iec103CodeS2C.fcb = 0; 49 | 50 | m_isResetConEnd = false; //复位通信 51 | m_isResetNumEnd = false; //复位帧计数位 52 | m_isGetAllEnd = false; //总召唤 53 | 54 | m_ycGroupNum = 0x09; 55 | m_yxGroupNum = 0x60; 56 | m_timeStampAddr = 0xff; 57 | m_clientAddr = 0x32; 58 | 59 | m_nextCmd = CMD_RESET_EVENT; 60 | } 61 | 62 | Service::~Service() 63 | { 64 | if(NULL != m_net) 65 | { 66 | delete m_net; 67 | } 68 | } 69 | 70 | void Service::InitConfig() 71 | { 72 | 73 | } 74 | 75 | bool Service::Init() 76 | { 77 | //初始化配置参数 78 | InitConfig(); 79 | 80 | // m_heartInterval = Config::GetInstance()->GetHeartInterval(); 81 | // 82 | // //初始化103点表 83 | // if(!InitPointAddrMap()) 84 | // { 85 | // return false; 86 | // } 87 | // 88 | // //定时更新心跳 89 | // if(!StartBreakHeart()) 90 | // { 91 | // return false; 92 | // } 93 | 94 | return true; 95 | } 96 | 97 | void Service::Start() 98 | { 99 | m_net = new TcpNet(Config::GetInstance()->GetIp(),Config::GetInstance()->GetTcpPort()); 100 | 101 | std::cout<<"Connection TYPE:103 TcpNet,ipAddr="<< Config::GetInstance()->GetIp()<<" Port = "<GetTcpPort()<Connect()) 104 | { 105 | ERROR( "tcp connection error \n"); 106 | return; 107 | } 108 | 109 | while(true) 110 | { 111 | if(!Write()) 112 | { 113 | break; 114 | } 115 | if(!Read()) 116 | { 117 | break; 118 | } 119 | } 120 | } 121 | 122 | bool Service::Write() 123 | { 124 | std::vector strCmd; 125 | std::string cmdName(""); 126 | //首先连接,再启动总召换 127 | switch(m_nextCmd) 128 | { 129 | case CMD_RESET_CON: 130 | strCmd = CmdResetCon(); 131 | break; 132 | case CMD_RESET_TIMESTAMP: 133 | strCmd = CmdSetTimeStamp(); 134 | break; 135 | case CMD_RESET_EVENT: 136 | strCmd = CmdResetEventAlarm(); 137 | break; 138 | case CMD_SETTING_DOWNLOAD: 139 | strCmd = CmdSettingDownload(); 140 | break; 141 | case CMD_SETTING_MODIFY: 142 | strCmd = CmdSettingModify(); 143 | break; 144 | case CMD_GET_ALL: 145 | strCmd = CmdGetAll(); 146 | break; 147 | case CMD_GET_DATA_LV1: 148 | strCmd = CmdGetDataLv1(); 149 | break; 150 | case CMD_GET_DATA_LV2: 151 | strCmd = CmdGetDataLv2(); 152 | break; 153 | case CMD_GET_SINGLE_SETTING_VALUE: 154 | strCmd = CmdGetEntryValue(m_GroupNo,m_EntryNo); 155 | break; 156 | case CMD_GENERAL_READ_YX_GROUP_VALUE: 157 | strCmd = CmdGetGroupValue(m_yxGroupNum); 158 | break; 159 | case CMD_GENERAL_READ_YC_GROUP_VALUE: 160 | strCmd = CmdGetGroupValue(m_ycGroupNum); 161 | break; 162 | default: 163 | ERROR("cmd not defined \n" ); 164 | return false; 165 | } 166 | DEBUG("Write[%s]:%s \n" ,g_cmdName[m_nextCmd], ToHexString(strCmd.data(), strCmd.size()).c_str()); 167 | //TODO:测试时使用 168 | printf("write[%s]: ", g_cmdName[m_nextCmd]); 169 | printf("%s \n", ToHexString(strCmd.data(), strCmd.size()).c_str()); 170 | 171 | //如果发送失败,就认为是已经断开连接了 172 | if(-1 == m_net->Write(strCmd.data(), strCmd.size())) 173 | { 174 | ERROR("send cmd %d error\n", m_nextCmd); 175 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "send data error"); 176 | m_nextCmd = CMD_RESET_CON; 177 | //return false; 178 | } 179 | return true; 180 | } 181 | 182 | bool Service::Read() 183 | { 184 | memset(m_datapacket, 0, sizeof(m_datapacket)); 185 | static uint16_t reSendTimes = 0; //同一指令从发次数(不包括复位通信) 186 | int readSize = m_net->Read(m_datapacket, sizeof(m_datapacket)); 187 | if(-1 == readSize) 188 | { 189 | return false; 190 | } 191 | else if(-2 == readSize) //读到无效的数据重发 192 | { 193 | //TODO:测试时使用 194 | printf("read[%s]: ",g_cmdName[m_nextCmd]); 195 | printf("%s \n", ToHexString(m_datapacket, strlen(m_datapacket)).c_str()); 196 | } 197 | else if(0 == readSize)//未读到数据 198 | { 199 | printf("read[%s]: no data\n",g_cmdName[m_nextCmd]); 200 | WARN("read[%s]: no data\n",g_cmdName[m_nextCmd]); 201 | if(CMD_RESET_CON == m_nextCmd) //如果上一次指令是通信复位不做重发计数 202 | { 203 | return true; 204 | } 205 | reSendTimes++; 206 | } 207 | else 208 | { 209 | reSendTimes = 0; 210 | DEBUG("read[%s] size %d :%s \n", g_cmdName[m_nextCmd], readSize,ToHexString(m_datapacket, readSize).c_str()); 211 | 212 | //TODO:测试时使用 213 | printf("size: %d read[%s] : ",readSize,g_cmdName[m_nextCmd]); 214 | printf("%s \n", ToHexString(m_datapacket, readSize).c_str()); 215 | 216 | if(!ParseRecvData(m_datapacket, readSize)) 217 | { 218 | WARN("recv invalied data: %s\n", ToHexString(m_datapacket, readSize).c_str()); 219 | } 220 | return true; 221 | } 222 | 223 | //重发计数超过最大重发次数则进行复位通信 224 | if(++reSendTimes >= m_maxReSendTimes) 225 | { 226 | reSendTimes = 0; 227 | // m_tcpSendCmd = CMD_CALL_DATA; 228 | m_isResetConEnd = false; 229 | m_isResetNumEnd = false; 230 | WARN("cmd send thress times , cmd resetcon send \n"); 231 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV1, "Link disconnect , cmd resetcon send"); 232 | } 233 | 234 | return true; 235 | } 236 | 237 | /* 238 | * @Desc: 解析接收到的数据 239 | * @Param: pData 解析数据开始地址 240 | * @Param: dataLen 解析数据长度 241 | * @Return: 无 242 | */ 243 | bool Service::ParseRecvData(const char* pData, int32_t dataLen) 244 | { 245 | uint8_t sumcheck = 0; 246 | if(START_10H == pData[0] && 5 == dataLen) //固定长度报文(固定五个字节) 247 | { 248 | sumcheck = SumCheck( pData+1, 2); //较验数据 249 | if (sumcheck == (uint8_t)pData[3]) 250 | { 251 | ParseFixedData(pData, dataLen); // 处理定长数据 252 | } 253 | else //数据错误 254 | { 255 | return false; 256 | } 257 | } 258 | else if(START_68H == pData[0] && dataLen >= 14) //可变长报文(最少14个字节) 259 | { 260 | sumcheck = SumCheck( pData+4, (uint8_t)pData[1] ); //较验数据 261 | if (sumcheck == (uint8_t)pData[(uint8_t)pData[1]+4]) 262 | { 263 | if(!ParseVariableData(pData, dataLen)) // 处理可变长数据 264 | { 265 | return false; 266 | } 267 | } 268 | else 269 | { 270 | return false; 271 | } 272 | } 273 | else 274 | { 275 | // 不应该出现此种情况 276 | ERROR("received invalid data \n"); 277 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV0, "received invalid data"); 278 | return false; 279 | } 280 | return true; 281 | } 282 | 283 | /* 284 | * @Desc: 处理接收到的固定长度报文 285 | * @Param: pData 解析数据开始地址 286 | * @Param: dataLen 解析数据长度 287 | * @Return: 解析成功或失败 288 | */ 289 | bool Service::ParseFixedData(const char* pData, int32_t dataLen) 290 | { 291 | int acd = pData[2] & ACD_1; 292 | if(acd) 293 | { 294 | m_iec103CodeS2C.fcb = m_iec103CodeS2C.fcb ^ FCB_1; //把FCB位取反 295 | m_iec103CodeS2C.fcv = FCV_1; 296 | m_nextCmd = CMD_GET_DATA_LV1; 297 | } 298 | else 299 | { 300 | m_iec103CodeS2C.fcv = (m_iec103CodeS2C.fcv | FCV_1) ^ FCV_1; //把FCV位置0 301 | } 302 | 303 | return true; 304 | } 305 | 306 | /* 307 | * @Desc: 处理接收到的可变长度报文 308 | * @Param: pData 解析数据开始地址 309 | * @Param: dataLen 解析数据长度 310 | * @Return: 解析成功或失败 311 | */ 312 | bool Service::ParseVariableData(const char* pData, int32_t dataLen) 313 | { 314 | uint8_t asduType = pData[TYP_POSI]; // asdu类型 315 | 316 | switch(asduType) 317 | { 318 | case ASDU_1: 319 | ParseASDU1(pData, dataLen); 320 | break; 321 | case ASDU_2: 322 | ParseASDU2(pData, dataLen); 323 | break; 324 | case ASDU_10: 325 | ParseASDU10(pData, dataLen); 326 | break; 327 | case ASDU_40: 328 | ParseASDU40(pData, dataLen); 329 | break; 330 | case ASDU_41: 331 | ParseASDU41(pData, dataLen); 332 | break; 333 | case ASDU_42: 334 | ParseASDU42(pData, dataLen); 335 | break; 336 | case ASDU_44: 337 | ParseASDU44(pData, dataLen); 338 | break; 339 | case ASDU_50: 340 | ParseASDU50(pData, dataLen); 341 | break; 342 | default: 343 | break; 344 | } 345 | return true; 346 | } 347 | 348 | // 复位通信单元 349 | std::vector Service::CmdResetCon() 350 | { 351 | m_iec103CodeS2C.fcb = 0; //复位时将桢记数位置0 352 | m_iec103CodeS2C.fcv = 0; 353 | uint8_t code = PRA_1|0|0|FNA_S2C_RESET_CON; 354 | return CmdFixedData(code); 355 | } 356 | 357 | /* 358 | * @Desc: 构造复位帧计数位字符串 359 | * @Return: 复位通信指令字符串 360 | */ 361 | std::vector Service::CmdResetNum() 362 | { 363 | m_iec103CodeS2C.fcb = 0; //复位时将桢记数位置0 364 | m_iec103CodeS2C.fcv = 0; 365 | uint8_t code = PRA_1|0|0|FNA_S2C_RESET_NUM; 366 | return CmdFixedData(code); 367 | } 368 | 369 | // 召唤一级数据 370 | std::vector Service::CmdGetDataLv1() 371 | { 372 | uint8_t code = PRA_1|m_iec103CodeS2C.fcb|m_iec103CodeS2C.fcv|FNA_S2C_GETDATA_LV1; 373 | return CmdFixedData(code); 374 | } 375 | 376 | // 召唤二级数据 377 | std::vector Service::CmdGetDataLv2() 378 | { 379 | uint8_t code = PRA_1|m_iec103CodeS2C.fcb|m_iec103CodeS2C.fcv|FNA_S2C_GETDATA_LV2; 380 | return CmdFixedData(code); 381 | } 382 | 383 | // 固定长度报文 384 | std::vector Service::CmdFixedData(uint8_t code) 385 | { 386 | std::vector packet(5); 387 | packet[0] = START_10H; 388 | packet[1] = code; 389 | packet[2] = m_clientAddr; 390 | packet[3] = packet[1]+packet[2]; 391 | packet[4] = END_16H; 392 | return packet; 393 | } 394 | 395 | 396 | // 对时 397 | std::vector Service::CmdSetTimeStamp() 398 | { 399 | std::vector packet(21); 400 | 401 | struct timeval cur_t; 402 | gettimeofday(&cur_t,NULL); 403 | struct tm *p; 404 | p = localtime(&cur_t.tv_sec); 405 | stTime7Byte timeByte; 406 | timeByte.year = p->tm_year + 1900; 407 | timeByte.month = p->tm_mon + 1; 408 | timeByte.day = p->tm_mday; 409 | timeByte.hour = p->tm_hour; 410 | timeByte.min = p->tm_min; 411 | timeByte.msec = cur_t.tv_usec/1000; 412 | //printf("time_now:%d%d%d%d%d%d.%ld\n", 1900+p->tm_year, 1+p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec, cur_t.tv_usec/1000); 413 | 414 | packet[0] = START_68H; 415 | packet[1] = 0x0f; 416 | packet[2] = 0x0f; 417 | packet[3] = START_68H; 418 | packet[4] = PRA_1|m_iec103CodeS2C.fcb|m_iec103CodeS2C.fcv|FNA_S2C_POSTDATA_4; 419 | packet[5] = m_timeStampAddr; 420 | packet[6] = ASDU6_TIMESTAMP; 421 | packet[7] = 0x81; //vsq 422 | packet[8] = COT_S2C_TIMESTAMP; 423 | packet[9] = m_timeStampAddr; //ASDU_ADDR 0xFF=广播方式 装置地址=点对点方式 424 | packet[10] = FUN_GLB; 425 | packet[11] = 0x00; 426 | packet[12] = ((char*)(&timeByte))[0]; 427 | packet[13] = ((char*)(&timeByte))[1]; 428 | packet[14] = ((char*)(&timeByte))[2]; 429 | packet[15] = ((char*)(&timeByte))[3]; 430 | packet[16] = ((char*)(&timeByte))[4]; 431 | packet[17] = ((char*)(&timeByte))[5]; 432 | packet[18] = ((char*)(&timeByte))[6]; 433 | packet[19] = SumCheck( &(packet[4]), (uint8_t)packet[1] ); 434 | packet[20] = END_16H; 435 | return packet; 436 | } 437 | 438 | 439 | // 事件告警复归 440 | std::vector Service::CmdResetEventAlarm() 441 | { 442 | std::vector packet(16); 443 | 444 | packet[0] = START_68H; 445 | packet[1] = 0x0a; 446 | packet[2] = 0x0a; 447 | packet[3] = START_68H; 448 | packet[4] = PRA_1|m_iec103CodeS2C.fcb|m_iec103CodeS2C.fcv|FNA_S2C_POSTDATA_3; 449 | packet[5] = m_clientAddr; 450 | packet[6] = ASDU20_RESET; 451 | packet[7] = 0x81; //vsq 452 | packet[8] = COT_S2C_COMMON_ORDER; //一般命令 453 | packet[9] = m_clientAddr; 454 | packet[10] = FUN_GLB; //FUN 455 | packet[11] = INF_RESET_ORDER; //复归命令 456 | packet[12] = 0x02; //DCO=1 跳 =2合 0,3未用 457 | packet[13] = 0x00; //如果时点对点发送,从站响应报文附加信息SIN和此值相同 458 | packet[14] = SumCheck( &(packet[4]), (uint8_t)packet[1] ); 459 | packet[15] = END_16H; 460 | return packet; 461 | } 462 | 463 | 464 | // 定值下载 465 | std::vector Service::CmdSettingDownload() 466 | { 467 | std::vector packet(26); 468 | 469 | stDataUnit dataUnit; 470 | dataUnit.groupNo = 1; 471 | dataUnit.entryNo = 3; 472 | dataUnit.datatype = 1; 473 | dataUnit.kod = 1; 474 | dataUnit.datatype = 7; 475 | dataUnit.datasize = 4; 476 | dataUnit.number = 1; 477 | 478 | packet[0] = START_68H; 479 | packet[1] = 0x14; 480 | packet[2] = 0x14; 481 | packet[3] = START_68H; 482 | packet[4] = PRA_1|m_iec103CodeS2C.fcb|m_iec103CodeS2C.fcv|FNA_S2C_POSTDATA_3; 483 | packet[5] = m_clientAddr; 484 | packet[6] = ASDU10_SETTING; 485 | packet[7] = 0x81; //vsq 486 | packet[8] = COT_S2C_GENERAL_WRITE; //通用分类写命令 487 | packet[9] = m_clientAddr; 488 | packet[10] = FUN_GEN; //FUN 489 | packet[11] = INF_CONFIRM_WRITE; //INF 490 | packet[12] = 0x03; //RII 491 | packet[13] = 0x01; //通用分类标识符数目 492 | 493 | packet[14] = ((char*)&dataUnit)[0]; 494 | packet[15] = ((char*)&dataUnit)[1]; 495 | packet[16] = ((char*)&dataUnit)[2]; 496 | packet[17] = ((char*)&dataUnit)[3]; 497 | packet[18] = ((char*)&dataUnit)[4]; 498 | packet[19] = ((char*)&dataUnit)[5]; 499 | 500 | packet[20] = 0x00; 501 | packet[21] = 0x00; 502 | packet[22] = 0xa0; 503 | packet[23] = 0x41; 504 | 505 | packet[24] = SumCheck( &(packet[4]), (uint8_t)packet[1] ); 506 | packet[25] = END_16H; 507 | return packet; 508 | } 509 | 510 | 511 | // 定值修改 512 | std::vector Service::CmdSettingModify() 513 | { 514 | std::vector packet(26); 515 | 516 | stDataUnit dataUnit; 517 | dataUnit.groupNo = 1; 518 | dataUnit.entryNo = 3; 519 | dataUnit.datatype = 1; 520 | dataUnit.kod = 1; 521 | dataUnit.datatype = 7; 522 | dataUnit.datasize = 4; 523 | dataUnit.number = 1; 524 | 525 | packet[0] = START_68H; 526 | packet[1] = 0x14; 527 | packet[2] = 0x14; 528 | packet[3] = START_68H; 529 | packet[4] = PRA_1|m_iec103CodeS2C.fcb|m_iec103CodeS2C.fcv|FNA_S2C_POSTDATA_3; 530 | packet[5] = m_clientAddr; 531 | packet[6] = ASDU10_SETTING; 532 | packet[7] = 0x81; //vsq 533 | packet[8] = COT_S2C_GENERAL_WRITE; //通用分类写命令 534 | packet[9] = m_clientAddr; 535 | packet[10] = FUN_GEN; //FUN 536 | packet[11] = INF_EXEC_WRITE; //INF 537 | packet[12] = 0x04; //RII 538 | packet[13] = 0x01; //通用分类标识符数目 539 | 540 | packet[14] = ((char*)&dataUnit)[0]; 541 | packet[15] = ((char*)&dataUnit)[1]; 542 | packet[16] = ((char*)&dataUnit)[2]; 543 | packet[17] = ((char*)&dataUnit)[3]; 544 | packet[18] = ((char*)&dataUnit)[4]; 545 | packet[19] = ((char*)&dataUnit)[5]; 546 | 547 | packet[20] = 0x00; 548 | packet[21] = 0x00; 549 | packet[22] = 0xa0; 550 | packet[23] = 0x41; 551 | 552 | packet[24] = SumCheck( &(packet[4]), (uint8_t)packet[1] ); 553 | packet[25] = END_16H; 554 | return packet; 555 | } 556 | 557 | // 总召唤 558 | std::vector Service::CmdGetAll() 559 | { 560 | std::vector packet(15); 561 | static uint8_t scn = 1; 562 | if(255 == scn) 563 | { 564 | scn = 1; 565 | } 566 | packet[0] = START_68H; 567 | packet[1] = 0x09; 568 | packet[2] = 0x09; 569 | packet[3] = START_68H; 570 | packet[4] = PRA_1|m_iec103CodeS2C.fcb|m_iec103CodeS2C.fcv|FNA_S2C_POSTDATA_3; 571 | packet[5] = m_clientAddr; 572 | packet[6] = ASDU7_GETALL; 573 | packet[7] = 0x81; //vsq 574 | packet[8] = COT_S2C_GETALL_START; //总召唤 575 | packet[9] = m_clientAddr; 576 | packet[10] = FUN_GLB; // FUN 577 | packet[11] = 0x00; 578 | packet[12] = scn++; 579 | packet[13] = SumCheck( &(packet[4]), (uint8_t)packet[1] ); 580 | packet[14] = END_16H; 581 | return packet; 582 | } 583 | 584 | /* 585 | * @Desc: 构造通用分类读命令(读一个组所有条目的值) 586 | * @Param: groupNum要读的组号 587 | * @Return: 通用分类读命令字符串 588 | */ 589 | std::vector Service::CmdGetGroupValue(uint8_t groupNo) 590 | { 591 | std::vector packet(19); 592 | packet[0] = START_68H; 593 | packet[1] = 0x0D; 594 | packet[2] = 0x0D; 595 | packet[3] = START_68H; 596 | packet[4] = PRA_1|m_iec103CodeS2C.fcb|m_iec103CodeS2C.fcv|FNA_S2C_POSTDATA_3; 597 | packet[5] = m_clientAddr; 598 | packet[6] = ASDU21_GETGROUP; 599 | packet[7] = 0x81; //vsq 600 | packet[8] = COT_S2C_GENERAL_READ; 601 | packet[9] = m_clientAddr; 602 | packet[10] = FUN_GEN; //通用分类服务功能类型 603 | packet[11] = INF_READ_GROUP; //读一个组的全部条目的值或者属性 604 | packet[12] = 0x15; //返回信息标识符RII 605 | packet[13] = 0x01; //通用分类标识数目 606 | packet[14] = groupNo; 607 | packet[15] = 0; 608 | packet[16] = KOD_1; 609 | packet[17] = SumCheck( &(packet[4]), (uint8_t)packet[1] ); 610 | packet[18] = END_16H; 611 | return packet; 612 | } 613 | 614 | std::vector Service::CmdGetEntryValue(uint8_t groupNo, uint8_t entryNo) 615 | { 616 | std::vector packet(19); 617 | packet[0] = START_68H; 618 | packet[1] = 0x0D; 619 | packet[2] = 0x0D; 620 | packet[3] = START_68H; 621 | packet[4] = PRA_1|m_iec103CodeS2C.fcb|m_iec103CodeS2C.fcv|FNA_S2C_POSTDATA_3; 622 | packet[5] = m_clientAddr; 623 | packet[6] = ASDU21_GETGROUP; 624 | packet[7] = 0x81; //vsq 625 | packet[8] = COT_S2C_GENERAL_READ; 626 | packet[9] = m_clientAddr; 627 | packet[10] = FUN_GEN; //通用分类服务功能类型 628 | packet[11] = INF_READ_EBTRY; //读一个组的全部条目的值或者属性 629 | packet[12] = 0x15; //返回信息标识符RII 630 | packet[13] = 0x01; //通用分类标识数目 631 | packet[14] = groupNo; 632 | packet[15] = entryNo; 633 | packet[16] = KOD_1; 634 | packet[17] = SumCheck( &(packet[4]), (uint8_t)packet[1] ); 635 | packet[18] = END_16H; 636 | return packet; 637 | } 638 | uint8_t Service::SumCheck( const char* packet, int32_t length ) 639 | { 640 | uint8_t result = 0; 641 | for( int32_t i = 0; i < length; i++ ) 642 | { 643 | result += packet[i]; 644 | } 645 | return result; 646 | } 647 | 648 | /* 649 | * @Desc: 解析ASDU44上送全遥信 650 | * @Param: packet 开始地址 651 | * @Param: length 开始地址 652 | */ 653 | void Service::ParseASDU44(const char* packet, int32_t length) 654 | { 655 | uint8_t clientAddr = packet[5]; 656 | uint8_t vsq = packet[7]; 657 | uint8_t fun = packet[10]; 658 | uint8_t inf = packet[11]; 659 | uint8_t scdNum = vsq & 0x7F; // 信息元个数 660 | bool bValue = false; 661 | char addr[100] = {0}; //103地址 662 | std::vector vecTag; 663 | for(int i = 0; i < scdNum; ++i) 664 | { 665 | memset(addr, 0, sizeof(addr)); 666 | //信息元 667 | uint8_t pScd = packet[12 + i*5]; 668 | uint8_t qds = packet[16 + i*5]; //品质描述字节 669 | if(qds & 0x80) //当前值无效 670 | { 671 | ++inf; 672 | continue; 673 | } 674 | if(0x01 & pScd) 675 | { 676 | bValue = true; //true为合,false为分 677 | } 678 | sprintf(addr, "%d_%d%03d", clientAddr, fun, inf); //构造103地址 679 | Tag tagTemp; 680 | tagTemp.ZeroTag(); 681 | tagTemp.dataType = TYPE_BOOL; 682 | std::string strGlgAddr = GetGlobalAddrByPrivateAddr(addr);//公共点地址 683 | if(!strGlgAddr.empty()) 684 | { 685 | uint16_t addrLen = (strGlgAddr.length() > sizeof(tagTemp.pName))? sizeof(tagTemp.pName): strGlgAddr.length(); 686 | memcpy(tagTemp.pName, strGlgAddr.c_str(), addrLen); 687 | sprintf(tagTemp.pdata, "%d", bValue); 688 | vecTag.push_back(tagTemp); 689 | } 690 | ++inf; 691 | 692 | } 693 | if(!vecTag.empty()) 694 | { 695 | MemCache::GetInstance()->WritePointsValue_V(vecTag); //更新点到内存数据库 696 | } 697 | 698 | } 699 | 700 | /* 701 | * @Desc: 解析ASDU40上送变位遥信 702 | * @Param: packet 开始地址 703 | * @Param: length 开始地址 704 | */ 705 | void Service::ParseASDU40(const char* packet, int32_t length) 706 | { 707 | uint8_t clientAddr = packet[5]; 708 | uint8_t fun = packet[10]; 709 | uint8_t inf = packet[11]; 710 | uint8_t siq = packet[12]; //带品质描述的单点信息字节 711 | bool bValue = false; 712 | char addr[100] = {0}; //103地址 713 | std::vector vecTag; 714 | if(siq & 0x80) //无效 715 | { 716 | return; 717 | } 718 | if(0x01 & siq) 719 | { 720 | bValue = true; //true为合,false为分 721 | } 722 | 723 | sprintf(addr, "%d_%d%03d", clientAddr, fun, inf); //构造103地址 724 | Tag tagTemp; 725 | tagTemp.ZeroTag(); 726 | tagTemp.dataType = TYPE_BOOL; 727 | std::string strGlgAddr = GetGlobalAddrByPrivateAddr(addr);//公共点地址 728 | if(!strGlgAddr.empty()) 729 | { 730 | uint16_t addrLen = (strGlgAddr.length() > sizeof(tagTemp.pName))? sizeof(tagTemp.pName): strGlgAddr.length(); 731 | memcpy(tagTemp.pName, strGlgAddr.c_str(), addrLen); 732 | sprintf(tagTemp.pdata, "%d", bValue); 733 | vecTag.push_back(tagTemp); 734 | } 735 | if(!vecTag.empty()) 736 | { 737 | MemCache::GetInstance()->WritePointsValue_V(vecTag); //更新点到内存数据库 738 | } 739 | } 740 | 741 | /* 742 | * @Desc: 解析ASDU44上送SOE 743 | * @Param: packet 开始地址 744 | * @Param: length 开始地址 745 | * @Return: 较验码 746 | */ 747 | void Service::ParseASDU41(const char* packet, int32_t length) 748 | { 749 | ParseASDU40(packet, length); 750 | } 751 | 752 | void Service::ParseASDU42(const char* packet, int32_t length) 753 | { 754 | uint8_t vsq = packet[VSQ_POSI]; 755 | uint8_t clientAddr = packet[ADDR_POSI]; 756 | uint8_t fun = packet[FUN_POSI];; 757 | uint8_t inf = packet[INF_POSI]; 758 | uint8_t dpiNum = vsq & 0x7F; // 信息元个数 759 | 760 | std::vector vecTag; 761 | for(int i = 0; i < dpiNum; ++i) 762 | { 763 | uint8_t dpi = packet[DPI_POSI + i]; //品质描述的双点信息 764 | 765 | if(!((dpi == 0x01) || (dpi == 0x02))) //当前值无效 dpi为2位数组,值=0/3为无意义,值=1为分,值=2为合 766 | { 767 | continue; 768 | } 769 | 770 | char addr[100] = {0}; //103地址 771 | sprintf(addr, "%d_%d%03d", clientAddr, fun, inf); //构造103地址 772 | 773 | Tag tagTemp; 774 | tagTemp.ZeroTag(); 775 | tagTemp.dataType = TYPE_BOOL; 776 | std::string strGlgAddr = GetGlobalAddrByPrivateAddr(addr);//公共点地址 777 | if(!strGlgAddr.empty()) 778 | { 779 | uint16_t addrLen = (strGlgAddr.length() > sizeof(tagTemp.pName))? sizeof(tagTemp.pName): strGlgAddr.length(); 780 | memcpy(tagTemp.pName, strGlgAddr.c_str(), addrLen); 781 | sprintf(tagTemp.pdata, "%d", (dpi - 1) & 0x01); 782 | vecTag.push_back(tagTemp); 783 | } 784 | } 785 | if(!vecTag.empty()) 786 | { 787 | MemCache::GetInstance()->WritePointsValue_V(vecTag); //更新点到内存数据库 788 | } 789 | } 790 | 791 | /* 792 | * @Desc: 解析ASDU50遥测上送 793 | * @Param: packet 开始地址 794 | * @Param: length 开始地址 795 | */ 796 | void Service::ParseASDU50(const char* packet, int32_t length) 797 | { 798 | uint8_t vsq = packet[VSQ_POSI]; 799 | uint8_t clientAddr = packet[ADDR_POSI]; 800 | uint8_t fun = packet[FUN_POSI]; 801 | uint8_t inf = packet[INF_POSI]; 802 | uint8_t scdNum = vsq & 0x7F; // 信息元个数 803 | float value = 0.0f; 804 | char addr[100] = {0}; //103地址 805 | std::vector vecTag; 806 | for(int i = 0; i < scdNum; ++i) 807 | { 808 | memset(addr, 0, sizeof(addr)); 809 | //信息元 810 | uint8_t qds = packet[12 + i*2]; 811 | uint16_t tmpValue = packet[12 + i*2]; 812 | if(qds & 0x02) //当前值无效 813 | { 814 | ++inf; 815 | continue; 816 | } 817 | sprintf(addr, "%d_%d%03d", clientAddr, fun, inf); //构造103地址 818 | 819 | bool flag = (tmpValue & 0x8000) ? true: false; //是否为负数 820 | tmpValue = ~tmpValue; 821 | tmpValue &= 0xfff8; //品质位置0 822 | tmpValue &= 0x7ff8; //符号位置0 823 | tmpValue >>= 3; 824 | tmpValue += 1; 825 | value = (flag?(-tmpValue):tmpValue)*GetRateByPrivateAddr(addr); 826 | 827 | Tag tagTemp; 828 | tagTemp.ZeroTag(); 829 | tagTemp.dataType = TYPE_FLOAT; 830 | std::string strGlgAddr = GetGlobalAddrByPrivateAddr(addr);//公共点地址 831 | if(!strGlgAddr.empty()) 832 | { 833 | uint16_t addrLen = (strGlgAddr.length() > sizeof(tagTemp.pName))? sizeof(tagTemp.pName): strGlgAddr.length(); 834 | memcpy(tagTemp.pName, strGlgAddr.c_str(), addrLen); 835 | sprintf(tagTemp.pdata, "%.4f", value); 836 | vecTag.push_back(tagTemp); 837 | } 838 | ++inf; 839 | 840 | } 841 | if(!vecTag.empty()) 842 | { 843 | MemCache::GetInstance()->WritePointsValue_V(vecTag); //更新点到内存数据库 844 | } 845 | } 846 | 847 | /* 848 | * @Desc: 解析ASDU1遥信变位上送 849 | * @Param: packet 开始地址 850 | * @Param: length 开始地址 851 | */ 852 | void Service::ParseASDU1(const char* packet, int32_t length) 853 | { 854 | uint8_t code = packet[CODE_POSI]; 855 | uint8_t clientAddr = packet[ADDR_POSI]; 856 | uint8_t fun = packet[FUN_POSI]; 857 | uint8_t inf = packet[INF_POSI]; 858 | 859 | 860 | char addr[100] = {0}; //103地址 861 | std::vector vecTag; 862 | stTime7Byte Time4Byte; 863 | memcpy(&Time4Byte, packet + ASDU_1_TIMESTAMP, 4); //取四字节时间 864 | printf("%d:%d:%d\n",Time4Byte.hour,Time4Byte.min,Time4Byte.msec); 865 | 866 | if(code & ACD_1) 867 | { 868 | m_iec103CodeS2C.fcb = m_iec103CodeS2C.fcb ^ FCB_1; 869 | m_iec103CodeS2C.fcv = FCV_1; 870 | } 871 | 872 | sprintf(addr, "%d_%d%03d", clientAddr, fun, inf); //构造103地址 873 | Tag tagTemp; 874 | tagTemp.ZeroTag(); 875 | tagTemp.dataType = TYPE_BOOL; 876 | std::string strGlgAddr = GetGlobalAddrByPrivateAddr(addr);//公共点地址 877 | if(!strGlgAddr.empty()) 878 | { 879 | uint16_t addrLen = (strGlgAddr.length() > sizeof(tagTemp.pName))? sizeof(tagTemp.pName): strGlgAddr.length(); 880 | memcpy(tagTemp.pName, strGlgAddr.c_str(), addrLen); 881 | sprintf(tagTemp.pdata, "%d", (packet[DPI_POSI] - 1) & 0x01); //双点描述 dpi=1为分,=2为和 0和3无意义 882 | vecTag.push_back(tagTemp); 883 | std::cout<<"save Mem database tagName ="< vecTag; 921 | if(2 == dpi) 922 | { 923 | bValue = true; //true为合,false为分 924 | } 925 | 926 | sprintf(addr, "%d_%d%03d", clientAddr, fun, inf); //构造103地址 927 | Tag tagTemp; 928 | tagTemp.ZeroTag(); 929 | tagTemp.dataType = TYPE_BOOL; 930 | std::string strGlgAddr = GetGlobalAddrByPrivateAddr(addr);//公共点地址 931 | if(!strGlgAddr.empty()) 932 | { 933 | uint16_t addrLen = (strGlgAddr.length() > sizeof(tagTemp.pName))? sizeof(tagTemp.pName): strGlgAddr.length(); 934 | memcpy(tagTemp.pName, strGlgAddr.c_str(), addrLen); 935 | sprintf(tagTemp.pdata, "%d", bValue); 936 | vecTag.push_back(tagTemp); 937 | std::cout<<"save Mem database tagName ="<::const_iterator cit = m_pointAddrMap.find(privateAddr); 952 | if(cit != m_pointAddrMap.end()) 953 | { 954 | globalKey = cit->second.pubAddr; 955 | } 956 | return globalKey; 957 | } 958 | 959 | float Service::GetRateByPrivateAddr(std::string privateAddr) 960 | { 961 | float rate = 1.0f; 962 | std::map::const_iterator cit = m_pointAddrMap.find(privateAddr); 963 | if(cit != m_pointAddrMap.end()) 964 | { 965 | rate = cit->second.rate; 966 | } 967 | return rate; 968 | } 969 | 970 | std::string Service::ToHexString(const char* data, int32_t dataLen) 971 | { 972 | uint16_t len =(dataLen+1)*3; 973 | char * hexStr = new char[len]; 974 | memset(hexStr, 0, len); 975 | for(int i = 0; i < dataLen; ++i) 976 | { 977 | sprintf(hexStr + 3*i, "%02x ", 0xff & (uint8_t)data[i]); 978 | } 979 | std::string retStr = hexStr; 980 | delete [] hexStr; 981 | return retStr; 982 | } 983 | 984 | bool Service::InitPointAddrMap() 985 | { 986 | m_pointAddrMap.clear(); 987 | 988 | //从mysql数据库读取点表 989 | std::string strCmdTemp = "select NODE_INDEX,PUB_ADDR,RATE,TERMINAL from 103_node where IED_NAME in("; 990 | std::vector::const_iterator cit = Config::GetInstance()->GetIedName().begin(); 991 | for(; cit != Config::GetInstance()->GetIedName().end(); ++cit) 992 | { 993 | strCmdTemp+="\'"; 994 | strCmdTemp+=*cit; 995 | strCmdTemp+="\'"; 996 | } 997 | strCmdTemp += ")"; 998 | char keyTemp[50] = {0}; 999 | if(0 != EncapMysql::GetInstance()->SelectQuery(strCmdTemp.c_str())) 1000 | { 1001 | return false; 1002 | } 1003 | while (char** addr = EncapMysql::GetInstance()->FetchRow()) 1004 | { 1005 | if((NULL == addr[0]) || (NULL == addr[1]) 1006 | ||(NULL == addr[2]) || (NULL == addr[3])) 1007 | { 1008 | ERROR("cdt node table error \n"); 1009 | return false; 1010 | } 1011 | memset(keyTemp, 0, sizeof(keyTemp)); 1012 | sprintf(keyTemp, "%d_%s",atoi(addr[3]), addr[0] ); 1013 | Point103 point103; 1014 | point103.pubAddr = addr[1]; 1015 | point103.rate = atof(addr[2]); 1016 | m_pointAddrMap.insert(make_pair(keyTemp, point103)); 1017 | } 1018 | 1019 | if(0 == m_pointAddrMap.size()) 1020 | { 1021 | ERROR("cmd[%s] get nothing \n", strCmdTemp.c_str()); 1022 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV1, "point table get noting"); 1023 | return false; 1024 | } 1025 | 1026 | return true; 1027 | } 1028 | 1029 | bool Service::StartBreakHeart() 1030 | { 1031 | pthread_t tid = -1; 1032 | if(0 != pthread_create(&tid, NULL, ThreadFunc, NULL)) 1033 | { 1034 | ERROR("pthread_create error \n"); 1035 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "pthread_create error"); 1036 | return false; 1037 | } 1038 | pthread_detach(tid); 1039 | return true; 1040 | } 1041 | 1042 | void * Service::ThreadFunc(void *arg) 1043 | { 1044 | while(true) 1045 | { 1046 | //更新心跳时间到采集进程表 1047 | char cmd[512] = {0}; 1048 | sprintf(cmd, "update collect_process set HEART_BEAT_TIME=%ld WHERE id=%d;", time(NULL), Config::GetInstance()->GetId()); 1049 | if(0 != EncapMysql::GetInstance()->ModifyQuery(cmd)) 1050 | { 1051 | WARN("cmd[%s] run error \n",cmd); 1052 | } 1053 | sleep(m_heartInterval); // 1054 | } 1055 | 1056 | return (void*)0; 1057 | } 1058 | 1059 | /* 1060 | * @Desc: 解析通用分类数据响应(读目录,读一个组的描述,读一个组的值) 1061 | * @Param: packet 开始地址 1062 | * @Param: length 开始地址 1063 | */ 1064 | void Service::ParseASDU10(const char* packet, int32_t length) 1065 | { 1066 | uint8_t fun = packet[FUN_POSI]; 1067 | uint8_t inf = packet[INF_POSI]; 1068 | 1069 | if((FUN_GEN == fun) && (0xF0 == inf)) //通用分类数据响应命令(装置响应的读目录) 1070 | { 1071 | 1072 | } 1073 | else if((FUN_GEN == fun) && (INF_READ_GROUP == inf)) //通用分类数据响应命令(读一个组的描述或值) 1074 | { 1075 | ParseASDU10AllValue(packet, length); 1076 | } 1077 | else if((FUN_GEN == fun) && (INF_READ_EBTRY == inf)) //通用分类数据响应命令(读一个条目的描述或值) 1078 | { 1079 | ParseASDU10AllValue(packet, length); 1080 | } 1081 | else if((FUN_GEN == fun) && (INF_CONFIRM_WRITE == inf)) //带确认的写条目响应 1082 | { 1083 | ParseASDU10AllValue(packet, length); 1084 | } 1085 | else if((FUN_GEN == fun) && (INF_EXEC_WRITE == inf)) //带执行的写条目响应 1086 | { 1087 | uint8_t rii = packet[RII_POSI]; 1088 | } 1089 | else 1090 | { 1091 | WARN("unknown asdu10:%s", ToHexString(packet, length).c_str()); 1092 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV1, "received unknown asdu10"); 1093 | return; 1094 | } 1095 | } 1096 | 1097 | void Service::ParseASDU10AllValue(const char* packet, int32_t length) 1098 | { 1099 | uint8_t code = packet[CODE_POSI]; 1100 | uint8_t clientAddr = packet[ADDR_POSI]; 1101 | uint8_t ngdNum = packet[NGD_POSI] & 0x3F; // 返回的数据个数 1102 | uint16_t offset = 0; //数据的偏移量 1103 | std::vector vecTag; 1104 | 1105 | if(code & ACD_1) 1106 | { 1107 | m_iec103CodeS2C.fcb = m_iec103CodeS2C.fcb ^ FCB_1; 1108 | m_iec103CodeS2C.fcv = FCV_1; 1109 | } 1110 | 1111 | for(int i = 0; i < ngdNum; ++i) 1112 | { 1113 | stDataUnit dataUnit; 1114 | memcpy(&dataUnit, packet + GROUP_POSI + offset, sizeof(stDataUnit)); 1115 | 1116 | char addr[100] = {0}; 1117 | memset(addr, 0, sizeof(addr)); 1118 | sprintf(addr, "%d_%d%03d", clientAddr, dataUnit.groupNo, dataUnit.entryNo); //构造103地址 1119 | 1120 | //不是遥信或者遥测数据 1121 | if(m_ycGroupNum != dataUnit.groupNo && m_yxGroupNum != dataUnit.groupNo) 1122 | { 1123 | break; 1124 | } 1125 | // 未定义的点不进行解析 1126 | std::string strGlgAddr = GetGlobalAddrByPrivateAddr(addr);//公共点地址 1127 | // if(strGlgAddr.empty()) 1128 | // { 1129 | // continue; 1130 | // } 1131 | // if(0x01 != kod) //只处理数值不处理描述 1132 | // { 1133 | // continue; 1134 | // } 1135 | Tag tagTemp; 1136 | tagTemp.ZeroTag(); 1137 | 1138 | UnionConvert4Byte convertUnion4Byte; 1139 | UnionConvert2Byte convertUnion2Byte; 1140 | switch(dataUnit.datatype) 1141 | { 1142 | case 3: //2字节无符号整形 1143 | tagTemp.dataType = TYPE_LONG; 1144 | memcpy(convertUnion2Byte.buf, packet + GID_POSI + offset, dataUnit.datasize); 1145 | sprintf(tagTemp.pdata, "%u", convertUnion2Byte.uValue); 1146 | break; 1147 | 1148 | case 7: //短实数 1149 | tagTemp.dataType = TYPE_FLOAT; 1150 | memcpy(convertUnion4Byte.buf, packet + GID_POSI + offset, dataUnit.datasize); 1151 | sprintf(tagTemp.pdata, "%.4f", convertUnion4Byte.fValue); 1152 | break; 1153 | 1154 | case 9: //双点描述 dpi=1为分,=2为和 0和3无意义 1155 | tagTemp.dataType = TYPE_BOOL; 1156 | if(!(((packet + GID_POSI + offset)[0] == 0x01) || ((packet + GID_POSI + offset)[0] == 0x02))) 1157 | { 1158 | break; 1159 | } 1160 | sprintf(tagTemp.pdata, "%d", ((packet + GID_POSI + offset)[0] - 1) & 0x01); 1161 | break; 1162 | 1163 | case 10: //单点描述 siq=0为分,=1为和 1164 | tagTemp.dataType = TYPE_BOOL; 1165 | if(!(((packet + GID_POSI + offset)[0] == 0x00) || ((packet + GID_POSI + offset)[0] == 0x01))) 1166 | { 1167 | break; 1168 | } 1169 | sprintf(tagTemp.pdata, "%d", (packet + GID_POSI + offset)[0] & 0x01); 1170 | break; 1171 | 1172 | case 12: //带品质描述词的被测值 1173 | tagTemp.dataType = TYPE_FLOAT; 1174 | //信息元 1175 | // uint8_t qds = valueStr[0]; 1176 | // uint16_t tmpValue = valueStr[0]; 1177 | // float value = 0.0f; 1178 | // if(qds & 0x02) //当前值无效 1179 | // { 1180 | // continue; 1181 | // } 1182 | // 1183 | // bool flag = (tmpValue & 0x8000) ? true: false; //是否为负数 1184 | // tmpValue = ~tmpValue; 1185 | // tmpValue &= 0xfff8; //品质位置0 1186 | // tmpValue &= 0x7ff8; //符号位置0 1187 | // tmpValue >>= 3; 1188 | // tmpValue += 1; 1189 | // value = (flag?(-tmpValue):tmpValue)*GetRateByPrivateAddr(addr); 1190 | // sprintf(tagTemp.pdata, "%.4f", value); 1191 | break; 1192 | default: 1193 | break; 1194 | } 1195 | 1196 | // uint16_t addrLen = (strGlgAddr.length() > sizeof(tagTemp.pName))? sizeof(tagTemp.pName): strGlgAddr.length(); 1197 | // memcpy(tagTemp.pName, strGlgAddr.c_str(), addrLen); 1198 | // vecTag.push_back(tagTemp); 1199 | // MemCache::GetInstance()->WritePointsValue_V(vecTag); //更新点到内存数据库 1200 | 1201 | offset = offset + dataUnit.datasize + 6; //通用分类数据单元占6个字节 1202 | } 1203 | } 1204 | 1205 | 1206 | 1207 | -------------------------------------------------------------------------------- /business/Service.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Service.h 3 | * 4 | * Created on: Jun 15, 2015 5 | * Author: root 6 | */ 7 | 8 | #ifndef SERVICE_H_ 9 | #define SERVICE_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "IEC103Type.h" 17 | #include "../core/Inet.h" 18 | #include "../core/Config.h" 19 | #include "../core/TcpNet.h" 20 | 21 | extern const char * g_cmdName[]; 22 | extern const char * g_TcpCmdName[]; 23 | class Service { 24 | public: 25 | Service(); 26 | virtual ~Service(); 27 | 28 | bool Init(); 29 | 30 | virtual void Start(); 31 | 32 | protected: 33 | /* 34 | * @Desc: 读取从站上送的数据 35 | * @Return: 成功或失败 36 | */ 37 | virtual bool Read(); 38 | 39 | /* 40 | * @Desc: 主站发送指令 41 | * @Return: 成功或失败 42 | */ 43 | virtual bool Write(); 44 | 45 | /* 46 | * @Desc: 从配置文件初始化具体类型网络需要的配置 47 | * @Return: 无 48 | */ 49 | virtual void InitConfig(); 50 | /* 51 | * @Desc: 解析接收到的数据 52 | * @Param: pData 解析数据开始地址 53 | * @Param: dataLen 解析数据长度 54 | * @Return: 解析成功或失败 55 | */ 56 | virtual bool ParseRecvData(const char* pData, int32_t dataLen); 57 | 58 | /* 59 | * @Desc: 处理接收到的固定长度报文 60 | * @Param: pData 解析数据开始地址 61 | * @Param: dataLen 解析数据长度 62 | * @Return: 解析成功或失败 63 | */ 64 | virtual bool ParseFixedData(const char* pData, int32_t dataLen); 65 | 66 | /* 67 | * @Desc: 处理接收到的可变长度报文 68 | * @Param: pData 解析数据开始地址 69 | * @Param: dataLen 解析数据长度 70 | * @Return: 解析成功或失败 71 | */ 72 | virtual bool ParseVariableData(const char* pData, int32_t dataLen); 73 | 74 | //主动发往客户端指令 75 | protected: 76 | /* 77 | * @Desc: 构造复位通信指令字符串 78 | * @Return: 复位通信指令字符串 79 | */ 80 | std::vector CmdResetCon(); 81 | 82 | /* 83 | * @Desc: 构造复位帧计数位字符串 84 | * @Return: 复位通信指令字符串 85 | */ 86 | std::vector CmdResetNum(); 87 | 88 | /* 89 | * @Desc: 指定控制域生成固定长度报文数据字符串 90 | * @Param: code 91 | * @Return: 固定长度报文数据字符串 92 | */ 93 | std::vector CmdFixedData(uint8_t code); 94 | 95 | 96 | /* 97 | * @Desc: 构造召唤一级数据指令字符串 98 | * @Return: 召唤一级数据指令字符串 99 | */ 100 | std::vector CmdGetDataLv1(); 101 | 102 | /* 103 | * @Desc: 构造召唤二级数据指令字符串 104 | * @Return: 召唤二级数据指令字符串 105 | */ 106 | std::vector CmdGetDataLv2(); 107 | 108 | /* 109 | * @Desc: 对时 110 | * @Return: 111 | */ 112 | std::vector CmdSetTimeStamp(); 113 | 114 | 115 | /* 116 | * @Desc: 事件告警复归 117 | * @Return: 118 | */ 119 | std::vector CmdResetEventAlarm(); 120 | 121 | /* 122 | * @Desc: 定值下传 123 | * @Return: 124 | */ 125 | std::vector CmdSettingDownload(); 126 | 127 | /* 128 | * @Desc: 定值修改 129 | * @Return: 130 | */ 131 | std::vector CmdSettingModify(); 132 | 133 | /* 134 | * @Desc: 构造总召唤指令字符串 135 | * @Return: 总召唤指令字符串 136 | */ 137 | std::vector CmdGetAll(); 138 | 139 | //通用分类服务使用部分 140 | /* 141 | * @Desc: 构造通用分类读命令(读一个组所有条目的值) 142 | * @Param: groupNum要读的组号 143 | * @Return: 通用分类读命令字符串 144 | */ 145 | std::vector CmdGetGroupValue(uint8_t groupNo); 146 | 147 | /* 148 | * @Desc: 构造通用分类读命令(读一个组所有条目的值) 149 | * @Param: groupNum要读的组号 150 | * @Return: 通用分类读命令字符串 151 | */ 152 | std::vector CmdGetEntryValue(uint8_t groupNo, uint8_t entryNo); 153 | 154 | /* 155 | * @Desc: 生成较验码 156 | * @Param: packet 开始地址 157 | * @Param: length 开始地址 158 | * @Return: 较验码 159 | */ 160 | uint8_t SumCheck( const char* packet, int32_t length ); 161 | 162 | //解析客户端上送的ASDU数据 163 | protected: 164 | /* 165 | * @Desc: 解析ASDU44上送全遥信 166 | * @Param: packet 开始地址 167 | * @Param: length 开始地址 168 | */ 169 | virtual void ParseASDU44(const char* packet, int32_t length); 170 | 171 | /* 172 | * @Desc: 解析ASDU40上送变位遥信 173 | * @Param: packet 开始地址 174 | * @Param: length 开始地址 175 | */ 176 | virtual void ParseASDU40(const char* packet, int32_t length); 177 | 178 | /* 179 | * @Desc: 解析ASDU44上送SOE 180 | * @Param: packet 开始地址 181 | * @Param: length 开始地址 182 | */ 183 | virtual void ParseASDU41(const char* packet, int32_t length); 184 | 185 | 186 | /* 187 | * @Desc: 解析ASDU50遥测上送 188 | * @Param: packet 开始地址 189 | * @Param: length 开始地址 190 | */ 191 | virtual void ParseASDU50(const char* packet, int32_t length); 192 | 193 | 194 | 195 | //遥信传输过程:主站以ASDU7发总查询命令 196 | // 从站以ASDU42上送全遥信,以ASDU1上送变位遥信,以ASDU2上送事故报文 197 | /* 198 | * @Desc: 解析ASDU42上送全遥信 199 | * @Param: packet 开始地址 200 | * @Param: length 开始地址 201 | */ 202 | virtual void ParseASDU42(const char* packet, int32_t length); 203 | 204 | /* 205 | * @Desc: 解析ASDU1遥信变位上送 206 | * @Param: packet 开始地址 207 | * @Param: length 开始地址 208 | */ 209 | virtual void ParseASDU1(const char* packet, int32_t length); 210 | 211 | /* 212 | * @Desc: 解析ASDU2事故报文上送 213 | * @Param: packet 开始地址 214 | * @Param: length 开始地址 215 | */ 216 | virtual void ParseASDU2(const char* packet, int32_t length); 217 | 218 | 219 | //遥测传输过程:主站以ASDU21发总召唤命令 220 | // 从站以ASDU10上送全遥测 221 | /* 222 | * @Desc: 解析通用分类数据响应(读目录,读一个组的描述,读一个组的值) 223 | * @Param: packet 开始地址 224 | * @Param: length 开始地址 225 | */ 226 | virtual void ParseASDU10(const char* packet, int32_t length); 227 | private: 228 | virtual void ParseASDU10AllValue(const char* packet, int32_t length); 229 | 230 | protected: 231 | /* 232 | * @Desc: 通过I03点地址获取对应的合局地址 233 | * @Param: privateAddr 103点地址 234 | * @Return: 全局地址 235 | */ 236 | std::string GetGlobalAddrByPrivateAddr(std::string privateAddr); 237 | 238 | float GetRateByPrivateAddr(std::string privateAddr); 239 | 240 | std::string ToHexString(const char* data, int32_t dataLen); 241 | private: 242 | /* 243 | * @Desc: 初始化103点表 244 | * @Return: 成功或失败 245 | */ 246 | bool InitPointAddrMap(); 247 | /* 248 | * @Desc: 开始监听心跳,每一段时间往数据库更新一次 249 | * @Return: 成功或失败 250 | */ 251 | bool StartBreakHeart(); 252 | static void * ThreadFunc(void *arg); 253 | 254 | 255 | protected: 256 | struct Point103 257 | { 258 | float rate; 259 | std::string pubAddr; 260 | }; 261 | 262 | protected: 263 | Inet * m_net; 264 | IEC103CodeS2C m_iec103CodeS2C; //103控制域主到从 265 | CMD_SEND m_nextCmd; //下一条主站应该发送的指令 266 | 267 | uint8_t m_clientAddr; //从站地址 268 | static uint16_t m_heartInterval; //秒 269 | 270 | std::map m_pointAddrMap; //<103点地址, 61850地址> 103地址和全局地址映射 271 | uint16_t m_maxReSendTimes; //重发次数 272 | uint16_t m_sendInterval; //重新发送间隔 273 | char m_datapacket[MAX_SIZE]; //读到的数据 274 | 275 | bool m_isResetConEnd; //复位通信 276 | bool m_isResetNumEnd; //复位帧计数位 277 | bool m_isGetAllEnd; //总召唤 278 | 279 | uint8_t m_ycGroupNum; 280 | uint8_t m_yxGroupNum; 281 | 282 | uint8_t m_GroupNo; 283 | uint8_t m_EntryNo; 284 | uint8_t m_timeStampAddr; 285 | }; 286 | 287 | #endif /* SERVICE_H_ */ 288 | -------------------------------------------------------------------------------- /business/TcpService.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TcpService.cpp 3 | * 4 | * Created on: Apr 18, 2016 5 | * Author: root 6 | */ 7 | 8 | #include "TcpService.h" 9 | #include "../core/TcpNet.h" 10 | #include "../core/SerialNet.h" 11 | #include "../core/Logger.h" 12 | #include "../core/WarningLib.h" 13 | #include "../core/MemCache.h" 14 | #include "../core/EncapMysql.h" 15 | 16 | 17 | TcpService::TcpService() { 18 | // TODO Auto-generated constructor stub 19 | //m_tcpSendCmd = CMD_CONNECTION_CON; 20 | m_tcpSendCmd = CMD_CALL_DATA; 21 | m_TcpSendID = 0; 22 | m_TcpRecvID = 0; 23 | } 24 | 25 | TcpService::~TcpService() { 26 | // TODO Auto-generated destructor stub 27 | } 28 | 29 | void TcpService::Start() 30 | { 31 | m_net = new TcpNet(m_tcpip,m_tcpport); 32 | 33 | //连接 34 | std::cout<<"Connection TYPE:103 TcpNet,ipAddr="<< m_tcpip<<" Port = "<Connect()) 37 | { 38 | ERROR( "tcp connection error \n"); 39 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "tcp connection error"); 40 | //return; 41 | } 42 | 43 | while(true) 44 | { 45 | //usleep(50*1000); 46 | if(!Write()) 47 | { 48 | break; 49 | } 50 | //usleep(50*1000); 51 | if(!Read()) 52 | { 53 | break; 54 | } 55 | } 56 | 57 | } 58 | 59 | // send data 60 | bool TcpService::Write() 61 | { 62 | std::vector strCmd; 63 | std::string cmdName(""); 64 | //首先连接,再启动总召换 65 | switch(m_tcpSendCmd) 66 | { 67 | case CMD_CONNECTION_CON: 68 | strCmd = CmdConnection(); 69 | break; 70 | case CMD_CALL_DATA: 71 | strCmd = Service::CmdGetAll(); 72 | break; 73 | case CMD_GET_GROUPDATA: 74 | strCmd = CmdGetGroupData(1); 75 | break; 76 | case CMD_TEST1_DATA: 77 | strCmd = CmdGetTest1(); 78 | break; 79 | case CMD_TEST2_DATA: 80 | strCmd = CmdGetTest2(); 81 | break; 82 | case CMD_GENERAL_READ_YC_GROUP_VALUE: 83 | strCmd = CmdGetGroupValue(0);//TODO 遥测组号为0,需要确认不同厂家是否一致 84 | break; 85 | default: 86 | ERROR("cmd not defined \n" ); 87 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "cmd not defined"); 88 | return false; 89 | } 90 | DEBUG("Write[%s]:%s \n" ,g_TcpCmdName[m_tcpSendCmd], ToHexString(strCmd.data(), strCmd.size()).c_str()); 91 | //TODO:测试时使用 92 | printf("write[%s]: ", g_TcpCmdName[m_tcpSendCmd]); 93 | printf("%s \n", ToHexString(strCmd.data(), strCmd.size()).c_str()); 94 | 95 | //如果发送失败,就认为是已经断开连接了 96 | if(-1 == m_net->Write(strCmd.data(), strCmd.size())) 97 | { 98 | ERROR("send cmd %d error\n", m_tcpSendCmd); 99 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "send data error"); 100 | m_tcpSendCmd = CMD_CONNECTION_CON; 101 | //return false; 102 | } 103 | return true; 104 | } 105 | 106 | bool TcpService::Read() 107 | { 108 | memset(m_datapacket, 0, sizeof(m_datapacket)); 109 | static uint16_t reSendTimes = 0; //同一指令从发次数(不包括复位通信) 110 | int readSize = m_net->Read(m_datapacket, sizeof(m_datapacket)); 111 | if(-1 == readSize) 112 | { 113 | return false; 114 | } 115 | else if(-2 == readSize) //读到无效的数据重发 116 | { 117 | //TODO:测试时使用 118 | printf("read[%s]: ",g_TcpCmdName[m_tcpSendCmd]); 119 | printf("%s \n", ToHexString(m_datapacket, strlen(m_datapacket)).c_str()); 120 | } 121 | else if(0 == readSize)//未读到数据 122 | { 123 | printf("read[%s]: no data\n",g_TcpCmdName[m_tcpSendCmd]); 124 | WARN("read[%s]: no data\n",g_TcpCmdName[m_tcpSendCmd]); 125 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV0, "receive no data"); 126 | 127 | if(CMD_RESET_CON == m_nextCmd) //如果上一次指令是通信复位不做重发计数 128 | { 129 | //sleep(1); 130 | return true; 131 | } 132 | } 133 | else 134 | { 135 | reSendTimes = 0; 136 | DEBUG("read[%s]:%s \n", g_TcpCmdName[m_tcpSendCmd], ToHexString(m_datapacket, readSize).c_str()); 137 | if(START_68H == m_datapacket[0]) 138 | DEBUG("{code=%d, ASDU=%d, FUN=%d, INF=%d} \n", (uint8_t)m_datapacket[4], (uint8_t)m_datapacket[6], (uint8_t)m_datapacket[10], (uint8_t)m_datapacket[11]); 139 | //TODO:测试时使用 140 | printf("read[%s]: ",g_TcpCmdName[m_tcpSendCmd]); 141 | printf("%s \n", ToHexString(m_datapacket, readSize).c_str()); 142 | 143 | if(START_68H == m_datapacket[0]) 144 | printf("{code=%d, ASDU=%d, FUN=%d, INF=%d} \n", 145 | (uint8_t)m_datapacket[4], 146 | (uint8_t)m_datapacket[TYP_POSI], 147 | (uint8_t)m_datapacket[FUN_POSI], 148 | (uint8_t)m_datapacket[INF_POSI]); 149 | if(!ParseRecvData(m_datapacket, readSize)) 150 | { 151 | WARN("recv invalied data: %s\n", ToHexString(m_datapacket, readSize).c_str()); 152 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV0, "recv invalied data"); 153 | } 154 | return true; 155 | } 156 | 157 | //重发计数超过最大重发次数则进行复位通信 158 | if(++reSendTimes >= m_maxReSendTimes) 159 | { 160 | reSendTimes = 0; 161 | // m_tcpSendCmd = CMD_CALL_DATA; 162 | m_isResetConEnd = false; 163 | m_isResetNumEnd = false; 164 | WARN("cmd send thress times , cmd resetcon send \n"); 165 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV1, "Link disconnect , cmd resetcon send"); 166 | } 167 | //sleep(m_sendInterval); 168 | 169 | return true; 170 | } 171 | bool TcpService::ParseRecvData(const char* pData, int32_t dataLen) 172 | { 173 | if(dataLen < 5) 174 | { 175 | return false; 176 | } 177 | if(START_68H == pData[0] && 7==dataLen ) //确认是否生效报文,固定报文 178 | { 179 | //连接 180 | if(CONFIRM_0BH == pData[3]) 181 | { 182 | m_tcpSendCmd = CMD_CALL_DATA; 183 | return true; 184 | } 185 | //测试 186 | if(0x43 == pData[3] || 0x83 == pData[3]) 187 | { 188 | if(0x43 == pData[3]) 189 | m_tcpSendCmd = CMD_TEST1_DATA; 190 | else 191 | m_tcpSendCmd = CMD_TEST2_DATA; 192 | return true; 193 | } 194 | 195 | } 196 | //接收的序号(可变长度中与S帧,取接收的序号) 197 | m_TcpRecvID = pData[5]>>1 + pData[6]*127; 198 | if(7 == dataLen) 199 | return true; 200 | //长度大于7的时候,计算发送序号 201 | m_TcpSendID = pData[3] / 2 + pData[4]*127 +1; 202 | std::cout< TcpService::CmdConnection() 221 | { 222 | std::vector buffer(7); 223 | buffer[0] = START_68H; 224 | buffer[1] = 0x00; 225 | buffer[2] = 0x04; 226 | buffer[3] = CONFIRM_07H; 227 | buffer[4] = 0x00; 228 | buffer[5] = 0x00; 229 | buffer[6] = 0x00; 230 | return buffer; 231 | } 232 | //测试指令1 233 | std::vector TcpService::CmdGetTest1() 234 | { 235 | std::vector buffer(7); 236 | 237 | buffer[0] = START_68H; 238 | buffer[1] = 0x00; 239 | buffer[2] = 0x04; 240 | buffer[3] = 0x83; 241 | buffer[4] = 0x00; 242 | buffer[5] = 0x00; 243 | buffer[6] = 0x00; 244 | 245 | return buffer; 246 | } 247 | //测试指令2 248 | std::vector TcpService::CmdGetTest2() 249 | { 250 | std::vector buffer(7); 251 | 252 | buffer[0] = START_68H; 253 | buffer[1] = 0x00; 254 | buffer[2] = 0x04; 255 | buffer[3] = 0x43; 256 | buffer[4] = 0x00; 257 | buffer[5] = 0x00; 258 | buffer[6] = 0x00; 259 | 260 | return buffer; 261 | } 262 | //总召唤指令 263 | std::vector TcpService::CmdGetAll() 264 | { 265 | std::vector buffer(15); 266 | static uint8_t scn = 1; 267 | if(255 == scn) 268 | { 269 | scn = 1; 270 | } 271 | 272 | buffer[0] = START_68H; 273 | buffer[1] = 0x00; 274 | buffer[2] = 12; 275 | buffer[3] = (GetSendID() % 127)<<1; 276 | buffer[4] = GetSendID() /127; 277 | buffer[5] = (GetRecvID() % 127)<<1; 278 | buffer[6] = GetRecvID() /127; 279 | buffer[7] = ASDU7_GETALL; //类型,总召换 280 | buffer[8] = 0x81; //vsq 281 | buffer[9] = 0x09; //COT传送 原因 282 | buffer[10] = m_clientAddr; //ASDU ADDR 283 | buffer[11] = m_clientAddr; //ASDU ADDR 284 | buffer[12] = FUN_GLB; 285 | buffer[13] = 0x00 ; 286 | buffer[14] = scn++; //scn 287 | 288 | return buffer; 289 | } 290 | std::vector TcpService::CmdGetGroupData(uint8_t groupNum) 291 | { 292 | std::vector buffer(20); 293 | buffer[0] = START_68H; 294 | buffer[1] = 0x00; //h len 295 | buffer[2] = 0x00; //l len 296 | 297 | buffer[3] = (GetSendID() % 127)<<1;; 298 | buffer[4] = GetSendID() /127; 299 | buffer[5] = (GetRecvID() % 127)<<1; 300 | buffer[6] = GetRecvID() / 127; 301 | 302 | buffer[7] = ASDU21_GETGROUP; 303 | buffer[8] = 0x81; //vsq 304 | buffer[9] = COT_S2C_GENERAL_READ; 305 | buffer[10] = 0x00; 306 | buffer[11] = m_clientAddr; 307 | buffer[12] = 0xFE; // FUN 308 | buffer[13] = 0xF1; 309 | buffer[14] = 0x15; 310 | buffer[15] = 0x01; 311 | buffer[16] = groupNum; 312 | buffer[17] = 0; 313 | buffer[18] = 1; 314 | buffer[19] = 0x01; 315 | 316 | return buffer; 317 | } 318 | 319 | 320 | // 处理可变长数据 321 | bool TcpService::ParseVariableData(const char* pData, int32_t dataLen) 322 | { 323 | uint8_t asduType = pData[TYP_POSI]; // asdu类型 324 | 325 | switch(asduType) 326 | { 327 | case 1: 328 | ParseASDU1(pData, dataLen); 329 | break; 330 | case 10: 331 | ParseASDU10(pData, dataLen); 332 | break; 333 | case 40: 334 | ParseASDU40(pData, dataLen); 335 | break; 336 | case 41: 337 | ParseASDU41(pData, dataLen); 338 | break; 339 | case 42: 340 | ParseASDU42(pData, dataLen); 341 | break; 342 | case 44: 343 | ParseASDU44(pData, dataLen); 344 | break; 345 | case 50: 346 | ParseASDU50(pData, dataLen); 347 | break; 348 | default: 349 | break; 350 | } 351 | return true; 352 | } 353 | //tcp ASDU1修改完 354 | void TcpService::ParseASDU1(const char* buffer, int32_t count) 355 | { 356 | uint8_t clientAddr = buffer[ADDR_POSI]; 357 | uint8_t fun = buffer[FUN_POSI]; 358 | uint8_t inf = buffer[INF_POSI]; 359 | uint8_t dpi = buffer[DPI_POSI] & 0x03; 360 | 361 | bool bValue = false; 362 | char addr[100] = {0}; //103地址 363 | std::vector vecTag; 364 | 365 | if(2 == dpi) 366 | { 367 | bValue = true; //true为合,false为分 368 | } 369 | 370 | sprintf(addr, "%d_%d%03d", clientAddr, fun, inf); //构造103地址 371 | Tag tagTemp; 372 | tagTemp.ZeroTag(); 373 | tagTemp.dataType = TYPE_BOOL; 374 | std::string strGlgAddr = GetGlobalAddrByPrivateAddr(addr);//公共点地址 375 | if(!strGlgAddr.empty()) 376 | { 377 | uint16_t addrLen = (strGlgAddr.length() > sizeof(tagTemp.pName))? sizeof(tagTemp.pName): strGlgAddr.length(); 378 | memcpy(tagTemp.pName, strGlgAddr.c_str(), addrLen); 379 | sprintf(tagTemp.pdata, "%d", bValue); 380 | vecTag.push_back(tagTemp); 381 | std::cout<<"save Mem database tagName ="<WriteWarn2(WARNING_LV1, "received unknown asdu10"); 404 | return; 405 | } 406 | } 407 | //tcp ASDU10修改完 408 | void TcpService::ParseASDU10AllValue(const char* buffer, int32_t count) 409 | { 410 | uint8_t clientAddr = buffer[ADDR_POSI]; 411 | uint8_t ngdNum = buffer[15] & 0x3F; // 返回的数据个数 412 | uint16_t index = 0;//数据的偏移量 413 | std::vector vecTag; 414 | char addr[100] = {0}; 415 | for(int i = 0; i < ngdNum; ++i) 416 | { 417 | memset(addr, 0, sizeof(addr)); 418 | uint8_t gin_0 = buffer[16 + index]; // 组号 419 | uint8_t gin_1 = buffer[17 + index]; // 条目号 420 | //uint8_t kod = buffer[16 + index]; 421 | uint8_t type = buffer[19 + index]; //数据类型 422 | uint8_t wideLen = buffer[20 + index]; //数据每个元素宽度 423 | uint8_t valueNum = buffer[21 + index] &0x7F; //数据元素数目 424 | uint8_t valueLen = wideLen * valueNum; //数据占用多少字节 425 | char valueStr[20] = {0}; 426 | memcpy(valueStr, &buffer[22 + index], valueLen); 427 | index += (6 + valueLen); 428 | sprintf(addr, "%d_%d%03d", clientAddr, gin_0, gin_1); //构造103地址 429 | //不是遥信或者遥测数据 430 | if(m_ycGroupNum != gin_0 || m_yxGroupNum != gin_0) 431 | { 432 | break; 433 | } 434 | // 未定义的点不进行解析 435 | std::string strGlgAddr = GetGlobalAddrByPrivateAddr(addr);//公共点地址 436 | if(strGlgAddr.empty()) 437 | { 438 | continue; 439 | } 440 | 441 | Tag tagTemp; 442 | tagTemp.ZeroTag(); 443 | 444 | if(12 == type) //带品质描述值 445 | { 446 | tagTemp.dataType = TYPE_FLOAT; 447 | //信息元 448 | uint8_t qds = valueStr[0]; 449 | uint16_t tmpValue = valueStr[0]; 450 | float value = 0.0f; 451 | if(qds & 0x02) //当前值无效 452 | { 453 | continue; 454 | } 455 | 456 | bool flag = (tmpValue & 0x8000) ? true: false; //是否为负数 457 | tmpValue = ~tmpValue; 458 | tmpValue &= 0xfff8; //品质位置0 459 | tmpValue &= 0x7ff8; //符号位置0 460 | tmpValue >>= 3; 461 | tmpValue += 1; 462 | value = (flag?(-tmpValue):tmpValue)*GetRateByPrivateAddr(addr); 463 | sprintf(tagTemp.pdata, "%.4f", value); 464 | } 465 | else if(9 == type)//双点信息 466 | { 467 | tagTemp.dataType = TYPE_BOOL; 468 | uint8_t dpi = valueStr[0] & 0x03; 469 | bool bValue = false; 470 | if(2 == dpi) 471 | { 472 | bValue = true; //true为合,false为分 473 | } 474 | sprintf(tagTemp.pdata, "%d", bValue); 475 | } 476 | else if(7 == type) //R32.23,IEEE标准754短实数 477 | { 478 | tagTemp.dataType = TYPE_FLOAT; 479 | float ftempValue = 0.0f; 480 | ftempValue = *((float*)valueStr[0]) * GetRateByPrivateAddr(addr); 481 | sprintf(tagTemp.pdata, "%.4f", ftempValue); 482 | } 483 | else if(3 == type)// 无符号整数 484 | { 485 | tagTemp.dataType = TYPE_LONG; 486 | uint64_t tempValue = *((uint64_t*)valueStr[0]); 487 | sprintf(tagTemp.pdata, "%ld", tempValue); 488 | } 489 | else if(10 == type)//单点信息 490 | { 491 | tagTemp.dataType = TYPE_BOOL; 492 | uint8_t siq = valueStr[0]; 493 | bool bValue = false; 494 | if(0x01 & siq) 495 | { 496 | bValue = true; //true为合,false为分 497 | } 498 | sprintf(tagTemp.pdata, "%d", bValue); 499 | } 500 | else 501 | { 502 | break; 503 | } 504 | 505 | uint16_t addrLen = (strGlgAddr.length() > sizeof(tagTemp.pName))? sizeof(tagTemp.pName): strGlgAddr.length(); 506 | memcpy(tagTemp.pName, strGlgAddr.c_str(), addrLen); 507 | vecTag.push_back(tagTemp); 508 | MemCache::GetInstance()->WritePointsValue_V(vecTag); //更新点到内存数据库 509 | 510 | if(index > count - 14 - 2) //不应该发生这种情况 511 | { 512 | WARN("data parse error:%s", ToHexString(buffer, count).c_str()); 513 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV1, "data parse error"); 514 | return; 515 | } 516 | } 517 | } 518 | void TcpService::ParseASDU40(const char* buffer, int32_t count) 519 | { 520 | uint8_t clientAddr = buffer[ADDR_POSI]; 521 | uint8_t fun = buffer[FUN_POSI]; 522 | uint8_t inf = buffer[INF_POSI]; 523 | uint8_t siq = buffer[14]; //带品质描述的单点信息字节 524 | bool bValue = false; 525 | char addr[100] = {0}; //103地址 526 | std::vector vecTag; 527 | if(siq & 0x80) //无效 528 | { 529 | return; 530 | } 531 | if(0x01 & siq) 532 | { 533 | bValue = true; //true为合,false为分 534 | } 535 | 536 | sprintf(addr, "%d_%d%03d", clientAddr, fun, inf); //构造103地址 537 | Tag tagTemp; 538 | tagTemp.ZeroTag(); 539 | tagTemp.dataType = TYPE_BOOL; 540 | std::string strGlgAddr = GetGlobalAddrByPrivateAddr(addr);//公共点地址 541 | if(!strGlgAddr.empty()) 542 | { 543 | uint16_t addrLen = (strGlgAddr.length() > sizeof(tagTemp.pName))? sizeof(tagTemp.pName): strGlgAddr.length(); 544 | memcpy(tagTemp.pName, strGlgAddr.c_str(), addrLen); 545 | sprintf(tagTemp.pdata, "%d", bValue); 546 | vecTag.push_back(tagTemp); 547 | } 548 | if(!vecTag.empty()) 549 | { 550 | MemCache::GetInstance()->WritePointsValue_V(vecTag); //更新点到内存数据库 551 | } 552 | } 553 | 554 | /* 555 | * @Desc: 解析ASDU44上送SOE 556 | * @Param: buffer 开始地址 557 | * @Param: count 开始地址 558 | * @Return: 较验码 559 | */ 560 | void TcpService::ParseASDU41(const char* buffer, int32_t count) 561 | { 562 | ParseASDU40(buffer, count); 563 | } 564 | void TcpService::ParseASDU42(const char* buffer, int32_t count) 565 | { 566 | uint8_t clientAddr = buffer[11]; 567 | uint8_t vsq = buffer[8]; 568 | uint8_t fun = 0 ; 569 | uint8_t inf = buffer[11]; 570 | uint8_t scdNum = vsq & 0x7F; // 信息元个数 571 | bool bValue = false; 572 | char addr[100] = {0}; //103地址 573 | std::vector vecTag; 574 | for(int i = 0; i < scdNum; ++i) 575 | { 576 | memset(addr, 0, sizeof(addr)); 577 | //信息元,占三个字节,fun inf diq 578 | fun = buffer[12 + i*3]; 579 | inf = buffer[13 + i*3]; 580 | uint8_t pScd = buffer[14 + i*3]; //品质描述的双点信息 581 | 582 | if(pScd & 0x80) //当前值无效 583 | { 584 | continue; 585 | } 586 | if(0x2==(0x02 & pScd)) 587 | { 588 | bValue = true; //true为合,false为分 589 | } 590 | sprintf(addr, "%d_%d%03d", clientAddr, fun, inf); //构造103地址 591 | Tag tagTemp; 592 | tagTemp.ZeroTag(); 593 | tagTemp.dataType = TYPE_BOOL; 594 | std::string strGlgAddr = GetGlobalAddrByPrivateAddr(addr);//公共点地址 595 | if(!strGlgAddr.empty()) 596 | { 597 | uint16_t addrLen = (strGlgAddr.length() > sizeof(tagTemp.pName))? sizeof(tagTemp.pName): strGlgAddr.length(); 598 | memcpy(tagTemp.pName, strGlgAddr.c_str(), addrLen); 599 | sprintf(tagTemp.pdata, "%d", bValue); 600 | vecTag.push_back(tagTemp); 601 | } 602 | } 603 | if(!vecTag.empty()) 604 | { 605 | MemCache::GetInstance()->WritePointsValue_V(vecTag); //更新点到内存数据库 606 | } 607 | 608 | } 609 | void TcpService::ParseASDU44(const char* buffer, int32_t count) 610 | { 611 | uint8_t clientAddr = buffer[ADDR_POSI]; 612 | uint8_t fun = buffer[FUN_POSI]; 613 | uint8_t inf = buffer[INF_POSI]; 614 | uint8_t vsq = buffer[VSQ_POSI]; 615 | uint8_t scdNum = vsq & 0x7F; // 信息元个数 616 | 617 | bool bValue = false; 618 | char addr[100] = {0}; //103地址 619 | std::vector vecTag; 620 | 621 | for(int i = 0; i < scdNum; ++i) 622 | { 623 | memset(addr, 0, sizeof(addr)); 624 | //信息元 625 | uint8_t pScd = buffer[14 + i*5]; 626 | uint8_t qds = buffer[18 + i*5]; //品质描述字节 627 | if(qds & 0x80) //当前值无效 628 | { 629 | ++inf; 630 | continue; 631 | } 632 | if(0x01 & pScd) 633 | { 634 | bValue = true; //true为合,false为分 635 | } 636 | sprintf(addr, "%d_%d%03d", clientAddr, fun, inf); //构造103地址 637 | Tag tagTemp; 638 | tagTemp.ZeroTag(); 639 | tagTemp.dataType = TYPE_BOOL; 640 | std::string strGlgAddr = GetGlobalAddrByPrivateAddr(addr);//公共点地址 641 | if(!strGlgAddr.empty()) 642 | { 643 | uint16_t addrLen = (strGlgAddr.length() > sizeof(tagTemp.pName))? sizeof(tagTemp.pName): strGlgAddr.length(); 644 | memcpy(tagTemp.pName, strGlgAddr.c_str(), addrLen); 645 | sprintf(tagTemp.pdata, "%d", bValue); 646 | vecTag.push_back(tagTemp); 647 | } 648 | ++inf; 649 | 650 | } 651 | if(!vecTag.empty()) 652 | { 653 | MemCache::GetInstance()->WritePointsValue_V(vecTag); //更新点到内存数据库 654 | } 655 | 656 | } 657 | 658 | void TcpService::ParseASDU50(const char* buffer, int32_t count) 659 | { 660 | uint8_t clientAddr = buffer[5]; 661 | uint8_t vsq = buffer[7]; 662 | uint8_t fun = buffer[10]; 663 | uint8_t inf = buffer[11]; 664 | uint8_t scdNum = vsq & 0x7F; // 信息元个数 665 | float value = 0.0f; 666 | char addr[100] = {0}; //103地址 667 | std::vector vecTag; 668 | for(int i = 0; i < scdNum; ++i) 669 | { 670 | memset(addr, 0, sizeof(addr)); 671 | //信息元 672 | uint8_t qds = buffer[12 + i*2]; 673 | uint16_t tmpValue = buffer[12 + i*2]; 674 | if(qds & 0x02) //当前值无效 675 | { 676 | ++inf; 677 | continue; 678 | } 679 | sprintf(addr, "%d_%d%03d", clientAddr, fun, inf); //构造103地址 680 | 681 | bool flag = (tmpValue & 0x8000) ? true: false; //是否为负数 682 | tmpValue = ~tmpValue; 683 | tmpValue &= 0xfff8; //品质位置0 684 | tmpValue &= 0x7ff8; //符号位置0 685 | tmpValue >>= 3; 686 | tmpValue += 1; 687 | value = (flag?(-tmpValue):tmpValue)*GetRateByPrivateAddr(addr); 688 | 689 | Tag tagTemp; 690 | tagTemp.ZeroTag(); 691 | tagTemp.dataType = TYPE_FLOAT; 692 | std::string strGlgAddr = GetGlobalAddrByPrivateAddr(addr);//公共点地址 693 | if(!strGlgAddr.empty()) 694 | { 695 | uint16_t addrLen = (strGlgAddr.length() > sizeof(tagTemp.pName))? sizeof(tagTemp.pName): strGlgAddr.length(); 696 | memcpy(tagTemp.pName, strGlgAddr.c_str(), addrLen); 697 | sprintf(tagTemp.pdata, "%.4f", value); 698 | vecTag.push_back(tagTemp); 699 | } 700 | ++inf; 701 | 702 | } 703 | if(!vecTag.empty()) 704 | { 705 | MemCache::GetInstance()->WritePointsValue_V(vecTag); //更新点到内存数据库 706 | } 707 | } 708 | 709 | void TcpService::InitConfig() 710 | { 711 | m_tcpip = Config::GetInstance()->GetIp(); 712 | m_tcpport = Config::GetInstance()->GetTcpPort(); 713 | } 714 | uint32_t TcpService::GetSendID() 715 | { 716 | return m_TcpSendID; 717 | } 718 | uint32_t TcpService::GetRecvID() 719 | { 720 | return m_TcpRecvID; 721 | } 722 | -------------------------------------------------------------------------------- /business/TcpService.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TcpService.h 3 | * 4 | * Created on: Apr 18, 2016 5 | * Author: root 6 | */ 7 | 8 | #ifndef TCPSERVICE_H_ 9 | #define TCPSERVICE_H_ 10 | 11 | #include "Service.h" 12 | #include "IEC103Type.h" 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | 19 | 20 | 21 | #define CONFIRM_07H 0x07 22 | #define CONFIRM_0BH 0x0B 23 | 24 | 25 | class TcpService: public Service { 26 | public: 27 | uint32_t GetSendID(); 28 | uint32_t GetRecvID(); 29 | TcpService(); 30 | virtual ~TcpService(); 31 | protected: 32 | uint32_t m_TcpSendID ; 33 | uint32_t m_TcpRecvID; 34 | protected: 35 | //com param 36 | enum TCP_CMD_SEND 37 | { 38 | CMD_CONNECTION_CON, 39 | CMD_CALL_DATA, 40 | CMD_TEST1_DATA, 41 | CMD_TEST2_DATA, 42 | CMD_GET_GROUPDATA, 43 | 44 | CMD_GET_DATA_LV2, 45 | CMD_GENERAL_READ_YX_GROUP_VALUE, 46 | CMD_GENERAL_READ_YC_GROUP_VALUE, 47 | }; 48 | std::string m_tcpip; 49 | uint16_t m_tcpport; 50 | TCP_CMD_SEND m_tcpSendCmd; 51 | 52 | 53 | virtual void Start(); 54 | /* 55 | * @Desc: 读取从站上送的数据 56 | * @Return: 成功或失败 57 | */ 58 | virtual bool Read(); 59 | 60 | /* 61 | * @Desc: 主站发送指令 62 | * @Return: 成功或失败 63 | */ 64 | virtual bool Write(); 65 | 66 | /* 67 | * @Desc: 从配置文件初始化具体类型网络需要的配置 68 | * @Return: 无 69 | */ 70 | virtual void InitConfig(); 71 | /* 72 | * @Desc: 解析接收到的数据 73 | * @Param: pData 解析数据开始地址 74 | * @Param: dataLen 解析数据长度 75 | * @Return: 解析成功或失败 76 | */ 77 | virtual bool ParseRecvData(const char* pData, int32_t dataLen); 78 | 79 | /* 80 | * @Desc: 处理接收到的固定长度报文 81 | * @Param: pData 解析数据开始地址 82 | * @Param: dataLen 解析数据长度 83 | * @Return: 解析成功或失败 84 | */ 85 | //virtual bool ParseFixedData(const char* pData, int32_t dataLen); 86 | 87 | /* 88 | * @Desc: 处理接收到的可变长度报文 89 | * @Param: pData 解析数据开始地址 90 | * @Param: dataLen 解析数据长度 91 | * @Return: 解析成功或失败 92 | */ 93 | virtual bool ParseVariableData(const char* pData, int32_t dataLen); 94 | 95 | //主动发往客户端指令 96 | protected: 97 | /* 98 | * @Desc: 构造复位通信指令字符串 99 | * @Return: 复位通信指令字符串 100 | */ 101 | std::vector CmdConnection(); 102 | /* 103 | * @Desc: 测试指令 104 | * @Return: 测试指令字符串 105 | */ 106 | std::vector CmdGetTest1(); 107 | std::vector CmdGetTest2(); 108 | /* 109 | * @Desc: 构造总召唤指令字符串 110 | * @Return: 总召唤指令字符串 111 | */ 112 | std::vector CmdGetAll(); 113 | /* 114 | * @Desc:获取发送序号 115 | * @Return: 获取发送序号 116 | */ 117 | 118 | 119 | // std::vector CmdResetNum(); 120 | 121 | /* 122 | * @Desc: 指定控制域生成固定长度报文数据字符串 123 | * @Param: code 124 | * @Return: 固定长度报文数据字符串 125 | */ 126 | //virtual std::vector CmdFixedData(uint8_t code); 127 | 128 | /* 129 | * @Desc: 构造召唤一级数据指令字符串 130 | * @Return: 召唤一级数据指令字符串 131 | */ 132 | //virtual std::vector CmdGetDataLv1(); 133 | 134 | /* 135 | * @Desc: 构造召唤二级数据指令字符串 136 | * @Return: 召唤二级数据指令字符串 137 | */ 138 | //virtual std::vector CmdGetDataLv2(); 139 | 140 | /* 141 | * @Desc: 构造总召唤指令字符串 142 | * @Return: 总召唤指令字符串 143 | */ 144 | //virtual std::vector CmdGetAll(); 145 | 146 | //通用分类服务使用部分 147 | /* 148 | * @Desc: 构造通用分类读命令(读一个组所有条目的值) 149 | * @Param: groupNum要读的组号 150 | * @Return: 通用分类读命令字符串 151 | */ 152 | std::vector CmdGetGroupData(uint8_t groupNum); 153 | 154 | /* 155 | * @Desc: 生成较验码 156 | * @Param: buffer 开始地址 157 | * @Param: count 开始地址 158 | * @Return: 较验码 159 | */ 160 | //virtual uint8_t SumCheck( const char* buffer, int32_t count ); 161 | 162 | //解析客户端上送的ASDU数据 163 | protected: 164 | /* 165 | * @Desc: 解析ASDU1遥信变位上送 166 | * @Param: buffer 开始地址 167 | * @Param: count 开始地址 168 | */ 169 | virtual void ParseASDU1(const char* buffer, int32_t count); 170 | /* 171 | * @Desc: 解析通用分类数据响应(读目录,读一个组的描述,读一个组的值) 172 | * @Param: buffer 开始地址 173 | * @Param: count 开始地址 174 | */ 175 | virtual void ParseASDU10(const char* buffer, int32_t count); 176 | /* 177 | * @Desc: 解析ASDU42上送全遥信 178 | * @Param: buffer 开始地址 179 | * @Param: count 开始地址 180 | */ 181 | void ParseASDU42(const char* buffer, int32_t count); 182 | /* 183 | * @Desc: 解析ASDU40上送变位遥信 184 | * @Param: buffer 开始地址 185 | * @Param: count 开始地址 186 | */ 187 | void ParseASDU40(const char* buffer, int32_t count); 188 | /* 189 | * @Desc: 解析ASDU44上送SOE 190 | * @Param: buffer 开始地址 191 | * @Param: count 开始地址 192 | */ 193 | virtual void ParseASDU44(const char* buffer, int32_t count); 194 | virtual void ParseASDU41(const char* buffer, int32_t count); 195 | /* 196 | * @Desc: 解析ASDU50遥测上送 197 | * @Param: buffer 开始地址 198 | * @Param: count 开始地址 199 | */ 200 | virtual void ParseASDU50(const char* buffer, int32_t count); 201 | 202 | 203 | virtual void ParseASDU10AllValue(const char* buffer, int32_t count); 204 | private: 205 | //virtual void ParseASDU10AllValue(const char* buffer, int32_t count); 206 | 207 | }; 208 | 209 | #endif /* TCPSERVICE_H_ */ 210 | -------------------------------------------------------------------------------- /core/Config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Config.cpp 3 | * 4 | * Created on: Jun 17, 2015 5 | * Author: root 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include "Config.h" 12 | #include "Logger.h" 13 | #include "EncapMysql.h" 14 | #include "WarningLib.h" 15 | 16 | Config * Config::m_instance = NULL; 17 | 18 | Config::Config():m_serialPortPath(""), 19 | m_speed(0), 20 | m_databits(0), 21 | m_stopbits(0), 22 | m_parity(2), 23 | m_netType(2), 24 | m_ip(""), 25 | m_tcpPort(6000), 26 | m_udpPort(6001), 27 | m_outTime(3), 28 | m_mysqlIp(""), 29 | m_mysqlUser(""), 30 | m_mysqlPwd(""), 31 | m_mysqlPort(0), 32 | m_mysqlDbname(""), 33 | m_redisIp(""), 34 | m_redisPort(0), 35 | m_id(1), 36 | m_logLv(1), 37 | m_heartInterval(60), 38 | m_redisPostSize(0), 39 | m_iec103RunType(RS232_RUN) 40 | { 41 | memset(m_redisPostName, 0, sizeof(m_redisPostName)); 42 | m_clientAddr.clear(); 43 | m_iedId.clear(); 44 | m_iedName.clear(); 45 | } 46 | 47 | Config * Config::GetInstance() 48 | { 49 | if(NULL == m_instance) 50 | { 51 | m_instance = new Config(); 52 | } 53 | return m_instance; 54 | } 55 | 56 | Config::~Config() 57 | { 58 | 59 | } 60 | 61 | bool Config::Init(const std::string & configName) 62 | { 63 | std::string strTempValue(""); 64 | std::vector tempValueVec; 65 | if(!ReadConfig(configName)) 66 | { 67 | return false; 68 | } 69 | 70 | if(!GetStrValueByKey("serialPath", m_serialPortPath)) 71 | { 72 | } 73 | 74 | if(!GetValueByKey("speed", m_speed)) 75 | { 76 | } 77 | 78 | if(!GetValueByKey("databits", m_databits)) 79 | { 80 | } 81 | 82 | if(!GetValueByKey("stopbits", m_stopbits)) 83 | { 84 | } 85 | 86 | if(!GetValueByKey("parity", m_parity)) 87 | { 88 | } 89 | 90 | if(!GetValueByKey("netType", m_netType)) 91 | { 92 | } 93 | 94 | if(!GetStrValueByKey("ip", m_ip)) 95 | { 96 | } 97 | 98 | if(!GetValueByKey("tcpPort", m_tcpPort)) 99 | { 100 | } 101 | 102 | if(!GetValueByKey("udpPort", m_udpPort)) 103 | { 104 | } 105 | 106 | if(!GetValueByKey("outTime", m_outTime)) 107 | { 108 | } 109 | 110 | if(!GetStrValueByKey("mysql_ip", m_mysqlIp)) 111 | { 112 | } 113 | 114 | if(!GetValueByKey("mysql_port", m_mysqlPort)) 115 | { 116 | } 117 | 118 | if(!GetStrValueByKey("mysql_user", m_mysqlUser)) 119 | { 120 | } 121 | 122 | if(!GetStrValueByKey("mysql_pwd", m_mysqlPwd)) 123 | { 124 | } 125 | 126 | if(!GetStrValueByKey("mysql_dbname", m_mysqlDbname)) 127 | { 128 | } 129 | 130 | if(!GetStrValueByKey("redis_ip", m_redisIp)) 131 | { 132 | } 133 | 134 | if(!GetValueByKey("redis_port", m_redisPort)) 135 | { 136 | } 137 | 138 | if(!GetValueByKey("logLv", m_logLv)) 139 | { 140 | } 141 | 142 | if(!GetValueByKey("heart_beat_time", m_heartInterval)) 143 | { 144 | 145 | } 146 | 147 | if(!GetValueByKey("ied_id", strTempValue)) 148 | { 149 | ERROR("no ied_id \n"); 150 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "no ied_id"); 151 | return false; 152 | } 153 | else 154 | { 155 | tempValueVec=Split(strTempValue, ","); 156 | std::vector::const_iterator cit = tempValueVec.begin(); 157 | uint16_t iedId= 0 ; 158 | for(; cit != tempValueVec.end(); ++cit) 159 | { 160 | iedId = 0; 161 | if(String2Int((*cit).c_str(), iedId)) 162 | { 163 | m_iedId.push_back(iedId); 164 | } 165 | } 166 | } 167 | strTempValue = ""; 168 | tempValueVec.clear(); 169 | if(!GetValueByKey("ied_name", strTempValue)) 170 | { 171 | ERROR("no ied_name \n"); 172 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "no ied_name"); 173 | return false; 174 | } 175 | else 176 | { 177 | tempValueVec=Split(strTempValue, ","); 178 | std::vector::const_iterator cit = tempValueVec.begin(); 179 | for(; cit != tempValueVec.end(); ++cit) 180 | { 181 | m_iedName.push_back(*cit); 182 | } 183 | } 184 | 185 | if((m_iedName.size() != m_iedId.size()) 186 | || m_iedName.empty() 187 | || m_iedId.empty()) 188 | { 189 | ERROR("ied_name or ied_id error \n"); 190 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "ied_name or ied_id error"); 191 | return false; 192 | } 193 | 194 | return true; 195 | } 196 | 197 | 198 | bool Config::IsSpace(char c) 199 | { 200 | if (' ' == c || '\t' == c) 201 | return true; 202 | return false; 203 | } 204 | 205 | bool Config::IsCommentChar(char c) 206 | { 207 | switch(c) { 208 | case COMMENT_CHAR: 209 | return true; 210 | default: 211 | return false; 212 | } 213 | } 214 | 215 | void Config::Trim(string & str) 216 | { 217 | if (str.empty()) { 218 | return; 219 | } 220 | uint32_t i, start_pos, end_pos; 221 | for (i = 0; i < str.size(); ++i) { 222 | if (!IsSpace(str[i])) { 223 | break; 224 | } 225 | } 226 | if (i == str.size()) { // 全部是空白字符串 227 | str = ""; 228 | return; 229 | } 230 | 231 | start_pos = i; 232 | 233 | for (i = str.size() - 1; i >= 0; --i) { 234 | if (!IsSpace(str[i])) { 235 | break; 236 | } 237 | } 238 | end_pos = i; 239 | 240 | str = str.substr(start_pos, end_pos - start_pos + 1); 241 | } 242 | 243 | bool Config::AnalyseLine(const string & line, string & key, string & value) 244 | { 245 | if (line.empty()) 246 | return false; 247 | int start_pos = 0, end_pos = line.size() - 1, pos; 248 | if ((pos = line.find(COMMENT_CHAR)) != -1) { 249 | if (0 == pos) { // 行的第一个字符就是注释字符 250 | return false; 251 | } 252 | end_pos = pos - 1; 253 | } 254 | string new_line = line.substr(start_pos, start_pos + 1 - end_pos); // 预处理,删除注释部分 255 | 256 | if ((pos = new_line.find('=')) == -1) 257 | return true; // 没有=号 258 | 259 | key = new_line.substr(0, pos); 260 | value = new_line.substr(pos + 1, end_pos + 1- (pos + 1)); 261 | 262 | Trim(key); 263 | if (key.empty()) { 264 | return false; 265 | } 266 | Trim(value); 267 | return true; 268 | } 269 | // 270 | bool Config::ReadConfig(const string & filename) 271 | { 272 | m_params.clear(); 273 | ifstream infile(filename.c_str()); 274 | if (!infile) { 275 | ERROR("file %s open error \n", filename.c_str()); 276 | //WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "config file open error"); 277 | return false; 278 | } 279 | string line, key, value; 280 | while (getline(infile, line)) { 281 | if (AnalyseLine(line, key, value)) { 282 | m_params[key] = value; 283 | //m_params.insert(key,value); 284 | } 285 | } 286 | infile.close(); 287 | return true; 288 | } 289 | 290 | 291 | //find m_params key 292 | bool Config::GetStrValueByKey(const std::string & key, std::string &value) 293 | { 294 | std::map::const_iterator cit = m_params.find(key); 295 | if(cit != m_params.end()) 296 | { 297 | value = cit->second; 298 | return true; 299 | } 300 | return false; 301 | } 302 | 303 | bool Config::InitMysqlParams() 304 | { 305 | char cmd[512] = {0}; 306 | sprintf(cmd, "select ID FROM ied_process where IED_NAME=\'%s\'",m_iedName[0].c_str()); 307 | //获取通过iedname获取进程编号 308 | if(0 != EncapMysql::GetInstance()->SelectQuery(cmd)) 309 | { 310 | ERROR("iedname [%s]no find \n",m_iedName[0].c_str()); 311 | return false; 312 | } 313 | if(char** value = EncapMysql::GetInstance()->FetchRow()) 314 | { 315 | if(!String2Int(value[0], m_id)) 316 | { 317 | ERROR("convert heartInterval error \n"); 318 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV1, "convert heartInterval error"); 319 | return false; 320 | } 321 | } 322 | else 323 | { 324 | WARN("heartInterval get null set to 1 min \n"); 325 | } 326 | 327 | //从点表中获取从站地址 328 | memset(cmd, 0, sizeof(cmd)); 329 | std::string strCmdTemp = "select DISTINCT TERMINAL from 103_node where IED_NAME in ("; 330 | std::vector::const_iterator cit = m_iedName.begin(); 331 | for(; cit != m_iedName.end(); ++cit) 332 | { 333 | strCmdTemp+="\'"; 334 | strCmdTemp+=*cit; 335 | strCmdTemp+="\'"; 336 | } 337 | strCmdTemp += ")"; 338 | if(0 != EncapMysql::GetInstance()->SelectQuery(strCmdTemp.c_str())) 339 | { 340 | return false; 341 | } 342 | uint16_t clientAddr = 0; 343 | while (char** addr = EncapMysql::GetInstance()->FetchRow()) 344 | { 345 | clientAddr = 0; 346 | if(!String2Int(addr[0], clientAddr)) 347 | { 348 | ERROR("convert clientAddr error \n"); 349 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "convert clientAddr error"); 350 | return false; 351 | } 352 | m_clientAddr.push_back(clientAddr); 353 | } 354 | if(m_clientAddr.empty()) 355 | { 356 | ERROR("cmd[%s] return nothing \n ", strCmdTemp.c_str()); 357 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "clientAddr is null "); 358 | return false; 359 | } 360 | 361 | //从通信表中获取配置数据 362 | memset(cmd, 0, sizeof(cmd)); 363 | sprintf(cmd, "select BAUD_RATE, DATA_BIT, STOP_BIT, CHECK_BIT, SERIAL_PORT_NAME, IP, PORT, REMARK, COMM_MODE "\ 364 | "FROM communication where IED_ID=%d", m_iedId[0]); 365 | if(0 != EncapMysql::GetInstance()->SelectQuery(cmd)) 366 | { 367 | return false; 368 | } 369 | 370 | if(char** value = EncapMysql::GetInstance()->FetchRow()) 371 | { 372 | if(!String2Int(value[0], m_speed)) 373 | { 374 | ERROR("convert speed error \n"); 375 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "convert speed error"); 376 | return false; 377 | } 378 | if(!String2Int(value[1], m_databits)) 379 | { 380 | ERROR("convert databits error \n"); 381 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "convert databits error"); 382 | return false; 383 | } 384 | if(!String2Int(value[2], m_stopbits)) 385 | { 386 | ERROR("convert stopbits error \n"); 387 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "convert stopbits error"); 388 | return false; 389 | } 390 | //uint16_t parity; 391 | if(!String2Int(value[3], m_parity)) 392 | { 393 | ERROR("convert parity error \n"); 394 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "convert parity error"); 395 | return false; 396 | } 397 | 398 | if(NULL == value[4]) 399 | { 400 | ERROR("convert serialPortPath error \n"); 401 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "convert serialPortPath error"); 402 | return false; 403 | } 404 | m_serialPortPath = value[4]; 405 | if(NULL == value[5]) 406 | { 407 | ERROR("convert ip error \n"); 408 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "convert ip error"); 409 | return false; 410 | } 411 | m_ip=value[5]; 412 | if(!String2Int(value[6], m_tcpPort)) 413 | { 414 | ERROR("convert tcpPort error \n"); 415 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "convert tcpPort error"); 416 | return false; 417 | } 418 | std::string strRedisPostName(value[7]); 419 | vector vecName; 420 | char strNameTemp[1000] = {0}; 421 | vecName = Split(strRedisPostName, ","); 422 | 423 | for(uint32_t i = 0; i < vecName.size(); ++i) 424 | { 425 | uint16_t len = 0; 426 | len = ((vecName[i].length() > 10)?10:vecName[i].length()); 427 | memcpy(strNameTemp + 10*i, vecName[i].c_str(), len); 428 | } 429 | memcpy(m_redisPostName, strNameTemp, sizeof(m_redisPostName)); 430 | m_redisPostSize = vecName.size(); 431 | 432 | if(!String2Int(value[8], m_netType)) 433 | { 434 | ERROR("convert netType error \n"); 435 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "convert netType error"); 436 | return false; 437 | } 438 | } 439 | else 440 | { 441 | ERROR("select communication error \n"); 442 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "select communication error"); 443 | return false; 444 | } 445 | return true; 446 | } 447 | 448 | //字符串分割函数 449 | std::vector Config::Split(std::string str,std::string pattern) 450 | { 451 | std::string::size_type pos; 452 | std::vector result; 453 | str+=pattern;//扩展字符串以方便操作 454 | uint32_t size=str.size(); 455 | for(uint32_t i=0; i 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #define COMMENT_CHAR '#' 18 | 19 | using namespace std; 20 | 21 | class Config 22 | { 23 | public: 24 | static Config * GetInstance(); 25 | bool Init(const std::string & configName); 26 | bool InitMysqlParams(); 27 | public: 28 | enum IEC103_RUN_TYPE 29 | { 30 | RS232_RUN = 1, 31 | RS485_CLIENT_RUN, 32 | RS485_SERVER_RUN 33 | }; 34 | public: 35 | std::string GetSerialPortPath() 36 | { 37 | return m_serialPortPath; 38 | } 39 | int32_t GetSpeed() 40 | { 41 | return m_speed; 42 | } 43 | int32_t GetDatabits() 44 | { 45 | return m_databits; 46 | } 47 | int32_t GetStopbits() 48 | { 49 | return m_stopbits; 50 | } 51 | uint16_t GetParity() 52 | { 53 | return m_parity; 54 | } 55 | const std::vector & GetClientAddr() 56 | { 57 | return m_clientAddr; 58 | } 59 | uint16_t GetNetType() 60 | { 61 | return m_netType; 62 | } 63 | std::string GetIp() 64 | { 65 | return m_ip; 66 | } 67 | uint16_t GetTcpPort() 68 | { 69 | return m_tcpPort; 70 | } 71 | uint16_t GetUdpPort() 72 | { 73 | return m_udpPort; 74 | } 75 | uint16_t GetOutTime() 76 | { 77 | return m_outTime; 78 | } 79 | std::string GetMysqlIp() 80 | { 81 | return m_mysqlIp; 82 | } 83 | uint16_t GetMysqlPort() 84 | { 85 | return m_mysqlPort; 86 | } 87 | std::string GetMysqlUser() 88 | { 89 | return m_mysqlUser; 90 | } 91 | std::string GetMysqlPwd() 92 | { 93 | return m_mysqlPwd; 94 | } 95 | std::string GetMysqlDbname() 96 | { 97 | return m_mysqlDbname; 98 | } 99 | std::string GetRedisIp() 100 | { 101 | return m_redisIp; 102 | } 103 | uint16_t GetRedisPort() 104 | { 105 | return m_redisPort; 106 | } 107 | uint16_t GetId() 108 | { 109 | return m_id; 110 | } 111 | int32_t GetLogLv() 112 | { 113 | return m_logLv; 114 | } 115 | uint16_t GetHeartInterval() 116 | { 117 | return m_heartInterval; 118 | } 119 | const std::vector & GetIedId() 120 | { 121 | return m_iedId;; 122 | } 123 | const std::vector & GetIedName() 124 | { 125 | return m_iedName; 126 | } 127 | char* GetRedisPostName() 128 | { 129 | return m_redisPostName; 130 | } 131 | uint16_t GetRedisPostSize() 132 | { 133 | return m_redisPostSize; 134 | } 135 | IEC103_RUN_TYPE GetIec103RunType() 136 | { 137 | return m_iec103RunType; 138 | } 139 | 140 | private: 141 | bool ReadConfig(const std::string & configName); 142 | bool IsSpace(char c); 143 | bool IsCommentChar(char c); 144 | void Trim(string & str); 145 | bool AnalyseLine(const string & line, string & key, string & value); 146 | template 147 | bool GetValueByKey(const std::string & key, T &value); 148 | bool GetStrValueByKey(const std::string & key, std::string &value); 149 | std::vector Split(std::string str,std::string pattern); 150 | private: 151 | Config(); 152 | virtual ~Config(); 153 | template 154 | bool String2Int(const char * strValue, T & value) 155 | { 156 | if(NULL == strValue) 157 | { 158 | return false; 159 | } 160 | stringstream ss; 161 | ss << strValue; 162 | ss >> value; 163 | if(ss.fail()) 164 | { 165 | return false; 166 | } 167 | return true; 168 | } 169 | private: 170 | std::string m_configName; 171 | std::map m_params; //配置参数键值对 172 | static Config * m_instance; 173 | 174 | std::string m_serialPortPath; 175 | int32_t m_speed; 176 | int32_t m_databits; 177 | int32_t m_stopbits; 178 | uint16_t m_parity; 179 | uint16_t m_netType; 180 | std::string m_ip; 181 | uint16_t m_tcpPort; 182 | uint16_t m_udpPort; 183 | std::vector m_clientAddr; 184 | 185 | uint16_t m_outTime; 186 | std::string m_mysqlIp; 187 | std::string m_mysqlUser; 188 | std::string m_mysqlPwd; 189 | uint16_t m_mysqlPort; 190 | std::string m_mysqlDbname; 191 | std::string m_redisIp; 192 | uint16_t m_redisPort; 193 | uint16_t m_id; // 进程表主键ID,进程编号 194 | int32_t m_logLv; 195 | uint16_t m_heartInterval; 196 | std::vector m_iedId; 197 | std::vector m_iedName; 198 | char m_redisPostName[1000]; 199 | uint16_t m_redisPostSize; 200 | IEC103_RUN_TYPE m_iec103RunType; 201 | }; 202 | 203 | template 204 | bool Config::GetValueByKey(const std::string & key, T &value) 205 | { 206 | std::map::const_iterator cit = m_params.find(key); 207 | if(cit != m_params.end()) 208 | { 209 | std::string strValue = cit->second; 210 | stringstream ss(strValue); 211 | ss >> value; 212 | return true; 213 | } 214 | return false; 215 | } 216 | 217 | 218 | 219 | #endif /* CONFIG_H_ */ 220 | -------------------------------------------------------------------------------- /core/DBHelper.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xibeilang524/IEC103_SF/4118d8ef64ff9dd3451b6d44a51835a21694f98b/core/DBHelper.h -------------------------------------------------------------------------------- /core/EncapMysql.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * EncapMysql.cpp 3 | * 4 | * Created on: Jun 16, 2015 5 | * Author: root 6 | */ 7 | /* 8 | * encapsulation_mysql.cpp 9 | * 10 | * Created on: 2013-3-28 11 | * Author: holy 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "EncapMysql.h" 27 | #include "Logger.h" 28 | 29 | using namespace std; 30 | 31 | EncapMysql * EncapMysql::m_instance = NULL; 32 | 33 | Mutex EncapMysql::m_mutex; 34 | 35 | EncapMysql::EncapMysql() { 36 | SetConnected(false); 37 | //把结果集置为空 38 | m_result = NULL; 39 | //初始化连接 40 | mysql_init(&m_connection); 41 | } 42 | EncapMysql::~EncapMysql() { 43 | //释放上一次的结果集 44 | FreePreResult(); 45 | //关闭数据库连接 46 | CloseConnect(); 47 | } 48 | 49 | EncapMysql * EncapMysql::GetInstance() 50 | { 51 | if(NULL == m_instance) 52 | { 53 | m_instance = new EncapMysql(); 54 | } 55 | return m_instance; 56 | } 57 | 58 | int EncapMysql::Connect(const char* szDbIp, const char* szUser, 59 | const char* szPassword,const char* szDb, uint32_t port) { 60 | SaveParam(szDbIp, szUser, szPassword); 61 | //先判断是否已经连接了, 防止重复连接 62 | if (IsConnected()) 63 | return 0; 64 | //连接数据库 65 | if (mysql_real_connect(&m_connection, szDbIp, szUser, szPassword, szDb, port, 66 | NULL, 0) == NULL) 67 | { 68 | ERROR("mysql connect error:%s \n", mysql_error(&m_connection)); 69 | return -1; 70 | } 71 | 72 | //设置连接标志为 true 73 | SetConnected(true); 74 | return 0; 75 | } 76 | 77 | void EncapMysql::CloseConnect() { 78 | //不论m_connection曾经是否连接过, 这样关闭都不会有问题 79 | mysql_close(&m_connection); 80 | SetConnected(false); 81 | } 82 | 83 | int EncapMysql::SelectQuery(const char* szSQL) { 84 | WriterMutexLock lock(&m_mutex); 85 | //如果查询串是空指针,则返回 86 | if (szSQL == NULL) { 87 | WARN("selectQuery is null \n"); 88 | return -1; 89 | } 90 | //如果还没有连接,则返回 91 | if (!IsConnected()) { 92 | ERROR("mysql is not connect \n"); 93 | return -2; 94 | } 95 | try //这些语句与连接有关,出异常时就重连 96 | { 97 | //查询 98 | if (mysql_real_query(&m_connection, szSQL, strlen(szSQL)) != 0) { 99 | WARN("mysql error:%s \n", mysql_error(&m_connection)); 100 | WARN("ReConnect() is called !!! \n"); 101 | int nRet = ReConnect(); 102 | if (nRet != 0) 103 | return -3; 104 | // 105 | if (mysql_real_query(&m_connection, szSQL, strlen(szSQL)) != 0) 106 | return -33; 107 | // 108 | } 109 | //释放上一次的结果集 110 | FreePreResult(); 111 | //取结果集 112 | m_result = mysql_store_result(&m_connection); 113 | if (m_result == NULL) 114 | { 115 | ERROR("mysql error:%s \n", mysql_error(&m_connection)); 116 | return -4; 117 | } 118 | } catch (...) { 119 | WARN("ReConnect() is called \n"); 120 | ReConnect(); 121 | return -5; 122 | } 123 | //取字段的个数 124 | m_iFields = mysql_num_fields(m_result); 125 | m_mapFieldNameIndex.clear(); 126 | //取各个字段的属性信息 127 | MYSQL_FIELD *fields; 128 | fields = mysql_fetch_fields(m_result); 129 | //把字段名字和索引保存到一个map中 130 | for (unsigned int i = 0; i < m_iFields; i++) { 131 | m_mapFieldNameIndex[fields[i].name] = i; 132 | } 133 | return 0; 134 | } 135 | 136 | int EncapMysql::ModifyQuery(const char* szSQL) { 137 | WriterMutexLock lock(&m_mutex); 138 | //如果查询串是空指针,则返回 139 | if (szSQL == NULL) { 140 | WARN("ModifyQuery is null \n"); 141 | return -1; 142 | } 143 | //如果还没有连接,则返回 144 | if (!IsConnected()) { 145 | ERROR("mysql is not connect \n"); 146 | return -2; 147 | } 148 | try //这些语句与连接有关,出异常时就重连 149 | { 150 | //查询, 实际上开始真正地修改数据库 151 | if (mysql_real_query(&m_connection, szSQL, strlen(szSQL)) != 0) { 152 | ERROR("mysql error:%s \n", mysql_error(&m_connection)); 153 | return -3; 154 | } 155 | } catch (...) { 156 | WARN("ReConnect() is called \n"); 157 | ReConnect(); 158 | return -5; 159 | } 160 | return 0; 161 | } 162 | 163 | char** EncapMysql::FetchRow() { 164 | //如果结果集为空,则直接返回空; 调用FetchRow之前, 必须先调用 SelectQuery(...) 165 | if (m_result == NULL) 166 | return NULL; 167 | //从结果集中取出一行 168 | m_row = mysql_fetch_row(m_result); 169 | return m_row; 170 | } 171 | 172 | char* EncapMysql::GetField(const char* szFieldName) { 173 | return GetField(m_mapFieldNameIndex[szFieldName]); 174 | } 175 | 176 | char* EncapMysql::GetField(unsigned int iFieldIndex) { 177 | //防止索引超出范围 178 | if (iFieldIndex >= m_iFields) 179 | return NULL; 180 | return m_row[iFieldIndex]; 181 | } 182 | 183 | void EncapMysql::FreePreResult() { 184 | 185 | if (m_result != NULL) { 186 | mysql_free_result(m_result); 187 | m_result = NULL; 188 | } 189 | } 190 | 191 | const char* EncapMysql::GetErrMsg() { 192 | return m_szErrMsg; 193 | } 194 | 195 | bool EncapMysql::IsConnected() { 196 | return m_bConnected; 197 | } 198 | 199 | void EncapMysql::SetConnected(bool bTrueFalse) { 200 | m_bConnected = bTrueFalse; 201 | } 202 | 203 | void EncapMysql::SaveParam(const char* szDbIp, const char* szUser, 204 | const char* szPassword) { 205 | m_sDbIp = szDbIp; //数据库服务器IP 206 | m_sUser = szUser; //用户名 207 | m_sPassword = szPassword; //口令 208 | } 209 | 210 | int EncapMysql::ReConnect() { 211 | CloseConnect(); 212 | //连接数据库 213 | if (mysql_real_connect(&m_connection, m_sDbIp.c_str(), m_sUser.c_str(), 214 | m_sPassword.c_str(), NULL, 0, NULL, 0) == NULL) { 215 | ERROR("mysql error:%s \n", mysql_error(&m_connection)); 216 | return -1; 217 | } 218 | //设置连接标志为 true 219 | SetConnected(true); 220 | return 0; 221 | } 222 | ///////////////////////// 连接池那个类需要用到这3个函数。 223 | void EncapMysql::SetUsed() { 224 | m_bUseIdle = true; 225 | } 226 | void EncapMysql::SetIdle() { 227 | m_bUseIdle = false; 228 | } 229 | //如果空闲,返回true 230 | bool EncapMysql::IsIdle() { 231 | return !m_bUseIdle; 232 | } 233 | -------------------------------------------------------------------------------- /core/EncapMysql.h: -------------------------------------------------------------------------------- 1 | /* 2 | * encapmysql.h 3 | * 4 | * Created on: 5 | * Author: 6 | */ 7 | 8 | #ifndef ENCAPMYSQL_H_ 9 | #define ENCAPMYSQL_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "Mutex.h" 29 | 30 | using namespace std; 31 | 32 | class EncapMysql { 33 | typedef map MapFieldNameIndex; 34 | public: 35 | static EncapMysql * GetInstance(); 36 | private: 37 | EncapMysql(); 38 | ~EncapMysql(); 39 | public: 40 | 41 | int Connect(const char* szDbIp, const char* szUser, const char* szPassword,const char* szDb, uint32_t port); 42 | 43 | void CloseConnect(); 44 | 45 | int SelectQuery(const char* szSQL); 46 | 47 | int ModifyQuery(const char* szSQL); 48 | 49 | const char* GetErrMsg(); 50 | 51 | char** FetchRow(); 52 | 53 | char* GetField(const char* szFieldName); 54 | 55 | ////////连接池那个类需要用到这3个函数。 2011-01-20 56 | public: 57 | void SetUsed(); 58 | void SetIdle(); 59 | bool IsIdle(); //返回 true 标识 Idle 60 | private: 61 | bool m_bUseIdle; // true: use; false:idle 62 | 63 | private: 64 | 65 | bool IsConnected(); 66 | 67 | void SetConnected(bool bTrueFalse); 68 | 69 | char* GetField(unsigned int iFieldIndex); 70 | 71 | void FreePreResult(); 72 | 73 | int ReConnect(); 74 | 75 | void SaveParam(const char* szDbIp, const char* szUser, 76 | const char* szPassword); 77 | 78 | public: 79 | bool m_bConnected; //数据库连接了吗? true--已经连接; false--还没有连接 80 | char m_szErrMsg[1024]; //函数出错后, 错误信息放在此处 81 | unsigned int m_iFields; //字段个数 82 | MapFieldNameIndex m_mapFieldNameIndex; //是一个map, key是字段名, value是字段索引 83 | public: 84 | MYSQL m_connection; //连接 85 | MYSQL_RES* m_result; //结果集指针 86 | MYSQL_ROW m_row; //一行, typedef char **MYSQL_ROW; 87 | 88 | private: 89 | string m_sDbIp; //数据库服务器IP 90 | string m_sUser; //用户名 91 | string m_sPassword; //口令 92 | static Mutex m_mutex; 93 | static EncapMysql * m_instance; 94 | }; 95 | 96 | #endif /* ENCAPMYSQL_H_ */ 97 | -------------------------------------------------------------------------------- /core/FileHelper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * FileHelper.h 3 | * 4 | * Created on: 2013年9月10日 5 | * Author: Administrator 6 | */ 7 | 8 | #ifndef FILEHELPER_H_ 9 | #define FILEHELPER_H_ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #ifdef _WIN32 15 | #include 16 | #include 17 | #else 18 | #include 19 | #include 20 | #endif 21 | 22 | #ifdef _WIN32 23 | #define ACCESS _access 24 | #define MKDIR(a) _mkdir((a)) 25 | #else 26 | #define ACCESS access 27 | #define MKDIR(a) mkdir((a),0755) 28 | #endif 29 | 30 | class FileHelper 31 | { 32 | public: 33 | static bool save(const std::string filename, std::string& content) 34 | { 35 | FILE *file = fopen(filename.c_str(), "wb"); 36 | 37 | if (file == NULL) 38 | return false; 39 | fwrite(content.c_str(),sizeof(char),content.size(),file); 40 | fclose(file); 41 | return true; 42 | } 43 | 44 | // used to open binary file 45 | static bool open(const std::string filename, std::string& content) 46 | { 47 | FILE *file = fopen(filename.c_str(), "rb"); 48 | 49 | if (file == NULL) 50 | return false; 51 | 52 | fseek(file, 0, SEEK_END); 53 | int len = ftell(file); 54 | rewind(file); 55 | content.clear(); 56 | char *buffer = new char[len]; 57 | fread(buffer, sizeof(char), len, file); 58 | content.assign(buffer, len); 59 | delete []buffer; 60 | 61 | //int nRead; 62 | //content.clear(); 63 | //char buffer[80]; 64 | //while(!feof(file)){ 65 | // nRead = fread(buffer,sizeof(char),sizeof(buffer),file); 66 | // if(nRead > 0){ 67 | // content.append(buffer); 68 | // } 69 | //} 70 | fclose(file); 71 | return true; 72 | } 73 | 74 | // used to open text file 75 | static bool open(const std::string file_name, std::vector& lines) 76 | { 77 | std::ifstream file(file_name.c_str(), std::ios::in); 78 | if (!file) 79 | { 80 | return false; 81 | } 82 | 83 | lines.clear(); 84 | char buffer[BUFFER_SIZE]; 85 | 86 | while (file.getline(buffer, BUFFER_SIZE, '\n')) 87 | { 88 | lines.push_back(buffer); 89 | } 90 | 91 | return true; 92 | } 93 | static bool CreateDir(const char *pszDir) 94 | { 95 | size_t i = 0; 96 | size_t iRet; 97 | size_t iLen = strlen(pszDir); 98 | char* buf=new char[iLen+1]; 99 | strncpy(buf,pszDir,iLen+1); 100 | for (i = 1;i < iLen;i ++) { 101 | if (pszDir[i] == '\\' || pszDir[i] == '/') { 102 | buf[i] = '\0'; 103 | //如果不存在,创建 104 | iRet = ACCESS(buf,0); 105 | if (iRet != 0) { 106 | iRet = MKDIR(buf); 107 | if (iRet != 0) { 108 | delete[] buf; 109 | return false; 110 | } 111 | } 112 | //支持linux,将所有\换成/ 113 | buf[i] = '/'; 114 | } 115 | } 116 | delete[] buf; 117 | return true; 118 | } 119 | 120 | private: 121 | enum { BUFFER_SIZE = 3000 }; 122 | 123 | }; 124 | 125 | #endif /* FILEHELPER_H_ */ 126 | -------------------------------------------------------------------------------- /core/Inet.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Inet.cpp 3 | * 4 | * Created on: Jun 14, 2015 5 | * Author: root 6 | */ 7 | 8 | #include "Inet.h" 9 | 10 | Inet::Inet():m_netFd(-1) 11 | { 12 | 13 | } 14 | 15 | Inet::~Inet() 16 | { 17 | 18 | } 19 | -------------------------------------------------------------------------------- /core/Inet.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Inet.h 3 | * Des:通讯接口类 4 | * Created on: Jun 14, 2015 5 | * Author: root 6 | */ 7 | 8 | #ifndef INET_H_ 9 | #define INET_H_ 10 | 11 | #include 12 | 13 | class Inet { 14 | public: 15 | Inet(); 16 | /* 17 | * @Desc: 进行通讯连接 18 | * @Return: 连接成功或失败 19 | */ 20 | virtual bool Connect() = 0; 21 | /* 22 | * @Desc: 读取数据 23 | * @Param: 读取数据存放地址 24 | * @Param: 读取数据的最大长度 25 | * @Return: 读取的数据长度 26 | */ 27 | virtual int32_t Read(char * pRecvData, uint32_t dataMaxLen) = 0; 28 | /* 29 | * @Desc: 发送数据 30 | * @Param: 发送数据存放地址 31 | * @Param: 发送的数据的长度 32 | * @Return: 发送的数据长度 33 | */ 34 | virtual int32_t Write(const char * pSendData, uint32_t dataLen) = 0; 35 | /* 36 | * @Desc: 断开通讯连接 37 | * @Return: 成功或失败 38 | */ 39 | virtual bool DisConnect() = 0; 40 | virtual ~Inet(); 41 | protected: 42 | int32_t m_netFd; 43 | }; 44 | 45 | #endif /* INET_H_ */ 46 | -------------------------------------------------------------------------------- /core/Logger.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Logger.cpp 3 | * 4 | * Created on: 2013Äê9ÔÂ10ÈÕ 5 | * Author: liu wenhui 6 | */ 7 | 8 | #include "Logger.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "FileHelper.h" 15 | #include "Mutex.h" 16 | 17 | Mutex LogMessage::mutex; 18 | static char _defaltFolder[]="/var/tmp/"; 19 | static char _appName[MaxFilePathLen]; 20 | static char _appFolder[MaxFilePathLen]; 21 | static char _destFolder[MaxFilePathLen]; 22 | static char _destPrefix[MaxFilePathLen]; 23 | static LogLevel _destLevel; 24 | static char _levelInfos[][16]={ 25 | "Debug","Info","Warn","Error","Fatal" 26 | }; 27 | const int BUFFER_SIZE = 8196; 28 | static char _gBuffer[BUFFER_SIZE]; 29 | void combine_folder(char** destpath, char* basefolder,char* relativefolder) 30 | { 31 | int lenb = strlen(basefolder); 32 | int lenr = strlen(relativefolder); 33 | char* pret = (char*)malloc((lenb+lenr+1)*sizeof(char)); 34 | int pos=lenb-1; 35 | memset(pret,0,lenb+lenr+1); 36 | while(pos>0 && ( basefolder[pos]!='/')) 37 | pos--; 38 | strncpy(*destpath,basefolder,pos+1); 39 | if(relativefolder[0] == '\\' || relativefolder[0] == '/'){ 40 | strncpy(*destpath+pos+1,relativefolder+1,lenr-1); 41 | }else{ 42 | strncpy(*destpath+pos+1,relativefolder,lenr); 43 | } 44 | } 45 | 46 | static void InitPaths(const char* filename,const char* destFolder) 47 | { 48 | memset(_appName,0,MaxFilePathLen); 49 | memset(_appFolder,0,MaxFilePathLen); 50 | memset(_destFolder,0,MaxFilePathLen); 51 | memset(_destPrefix,0,MaxFilePathLen); 52 | 53 | strcpy(_appName,filename); 54 | int len = strlen(filename),lend; 55 | int pos = len-1,posd,start; 56 | while(pos >0 && filename[pos] != PathSplitChar) 57 | pos--; 58 | strncpy(_appFolder,filename,pos+1); 59 | lend = strlen(destFolder); 60 | posd = lend-1; 61 | if(destFolder[lend-1] != PathSplitChar) { 62 | //has prefix 63 | while(posd >0 && destFolder[posd] != PathSplitChar) 64 | posd--; 65 | } 66 | if(destFolder[0] == '.' && destFolder[1] == PathSplitChar){ 67 | strncpy(_destFolder,filename,pos+1); 68 | start = 2; 69 | } else{ 70 | pos = 8; 71 | strcpy(_destFolder,_defaltFolder); 72 | if(destFolder[0] != PathSplitChar){ 73 | start = 0; 74 | }else{ 75 | start = 1; 76 | } 77 | } 78 | strncpy(_destFolder+pos+1,destFolder+start,posd-start+1); 79 | strncpy(_destPrefix,filename,pos+1); 80 | strncpy(_destPrefix+pos+1,destFolder+start,lend-start); 81 | } 82 | 83 | void InitLogging(const char* filename,LogLevel minlevel,const char* destFolder) 84 | { 85 | InitPaths(filename,destFolder); 86 | _destLevel = minlevel; 87 | } 88 | 89 | 90 | 91 | static string GetLocalDate(void) 92 | { 93 | time_t t = time(0); 94 | tm *ld; 95 | char tmp[64] = ""; 96 | ld=localtime(&t); 97 | strftime(tmp,sizeof(tmp),"%Y-%m-%d",ld); 98 | return string(tmp); 99 | } 100 | static string GetCurTime(void) 101 | { 102 | time_t t = time(0); 103 | tm *ld; 104 | char tmp[64] = ""; 105 | ld=localtime(&t); 106 | strftime(tmp,sizeof(tmp),"%Y-%m-%d %H:%M:%S",ld); 107 | return string(tmp); 108 | } 109 | 110 | Logger::Logger(LogLevel level,char * folder,char * prefix) 111 | :level(level) 112 | { 113 | std::string path; 114 | path.append(prefix); 115 | path.append(GetLocalDate()); 116 | path.append(".log"); 117 | FileHelper::CreateDir(folder); 118 | logPrefix.append(prefix); 119 | logPath = path; 120 | logFile.open(path.c_str(),ios::app|ios::out); 121 | logFile<<"Log file opened at:"<Log(file,line,lv,""); 230 | } 231 | 232 | LogMessage::~LogMessage() { 233 | logger->stream()<stream().flush(); 235 | mutex.Unlock(); 236 | } 237 | 238 | -------------------------------------------------------------------------------- /core/Logger.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Logger.h 3 | * 4 | * Created on: 2013Äê9ÔÂ10ÈÕ 5 | * Author: Administrator 6 | */ 7 | 8 | #ifndef LOGGER_H_ 9 | #define LOGGER_H_ 10 | 11 | //#include "ILogger.h" 12 | #include "Mutex.h" 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | const int MaxFilePathLen = 1024; 19 | const char PathSplitChar = '/'; 20 | 21 | enum LogLevel{ 22 | /// 23 | /// 调试 24 | /// 25 | DEBUG = 0, 26 | /// 27 | /// 普通日志 28 | /// 29 | INFO = 1, 30 | /// 31 | /// 警告 32 | /// 33 | WARN = 2, 34 | /// 35 | /// 错误 36 | /// 37 | ERROR = 3, 38 | /// 39 | /// 崩溃 40 | /// 41 | FATAL = 4, 42 | /// 43 | /// 超出错误级别 44 | /// 45 | OFF = 5 46 | 47 | }; 48 | 49 | 50 | class ILogger { 51 | public: 52 | // 53 | virtual ~ILogger(){} 54 | #define ABSTRACT_LOG_FUNC(name) \ 55 | virtual void name(string msg)=0; \ 56 | virtual void name(const char* fmt,...)=0; 57 | 58 | ABSTRACT_LOG_FUNC(Debug) 59 | ABSTRACT_LOG_FUNC(Info) 60 | ABSTRACT_LOG_FUNC(Warn) 61 | ABSTRACT_LOG_FUNC(Error) 62 | ABSTRACT_LOG_FUNC(Fatal) 63 | 64 | #undef ABSTRACT_LOG_FUNC 65 | #define ABSTRACT_LOG_FUNC_X(name) \ 66 | virtual void name(LogLevel lv,string msg)=0; \ 67 | virtual void name(LogLevel lv,const char* fmt,...)=0;\ 68 | virtual void name(const char* file,int line,LogLevel lv,string msg)=0;\ 69 | virtual void name(const char* file,int line,LogLevel lv,const char* fmt,...)=0; 70 | ABSTRACT_LOG_FUNC_X(Log) 71 | 72 | #undef LOG_FUNC_X 73 | }; 74 | 75 | 76 | class Logger: public ILogger { 77 | std::string logPath; 78 | std::string logPrefix; 79 | std::fstream logFile; 80 | LogLevel level; 81 | Mutex mutex; 82 | 83 | Logger(LogLevel level,char * folder,char * prefix); 84 | 85 | public: 86 | static Logger& GetInstance(); 87 | static Logger* GetInstancePtr(); 88 | virtual ~Logger(); 89 | inline fstream & stream(){return logFile;} 90 | 91 | #define DECLARE_LOG_FUNC(name) \ 92 | virtual void name(string msg); \ 93 | virtual void name(const char* fmt,...); 94 | 95 | #define DECLARE_LOG_FUNC_X(name) \ 96 | virtual void name(LogLevel lv,string msg); \ 97 | virtual void name(LogLevel lv,const char* fmt,...);\ 98 | virtual void name(const char* file,int line,LogLevel lv,string msg);\ 99 | virtual void name(const char* file,int line,LogLevel lv,const char* fmt,...); 100 | 101 | DECLARE_LOG_FUNC(Debug) 102 | DECLARE_LOG_FUNC(Info) 103 | DECLARE_LOG_FUNC(Warn) 104 | DECLARE_LOG_FUNC(Error) 105 | DECLARE_LOG_FUNC(Fatal) 106 | 107 | DECLARE_LOG_FUNC_X(Log) 108 | 109 | #undef DECLARE_LOG_FUNC_X 110 | #undef DECLARE_LOG_FUNC 111 | 112 | }; 113 | 114 | class LogMessage { 115 | Logger* logger; 116 | static Mutex mutex; 117 | public: 118 | LogMessage(const char* file, int line,LogLevel lv); 119 | ostream& stream(){return logger->stream();} 120 | virtual ~LogMessage(); 121 | }; 122 | 123 | 124 | void InitLogging(const char* filename,LogLevel minlevel,const char* destFolder); 125 | void CloseLogging(); 126 | 127 | //#define LOG(level) LogMessage(__FILE__, __LINE__,level).stream() 128 | #define DEBUG(format, ...) Logger::GetInstance().Log(__FILE__, __LINE__,DEBUG,format, ##__VA_ARGS__) 129 | #define INFO(format, ...) Logger::GetInstance().Log(__FILE__, __LINE__,INFO,format, ##__VA_ARGS__) 130 | #define WARN(format, ...) Logger::GetInstance().Log(__FILE__, __LINE__,WARN,format, ##__VA_ARGS__) 131 | #define ERROR(format, ...) Logger::GetInstance().Log(__FILE__, __LINE__,ERROR,format, ##__VA_ARGS__) 132 | //#define DEBUG() LOG(DEBUG) 133 | //#define INFO() LOG(INFO) 134 | //#define WARN() LOG(WARN) 135 | //#define ERROR() LOG(ERROR) 136 | #define LOG_IF(severity, condition) \ 137 | !(condition) ? (void) 0 : LOG(severity) 138 | #define LOG_ASSERT(condition) \ 139 | LOG_IF(FATAL, !(condition)) << "Assert failed: " #condition 140 | #define CHECK(condition) \ 141 | LOG_IF(FATAL, !(condition)) \ 142 | << "Check failed: " #condition " " 143 | 144 | #endif /* LOGGER_H_ */ 145 | -------------------------------------------------------------------------------- /core/MemCache.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * MemCache.cpp 3 | * 4 | * Created on: Jun 16, 2015 5 | * Author: root 6 | */ 7 | #include 8 | #include 9 | #include "MemCache.h" 10 | #include "Logger.h" 11 | #include "Config.h" 12 | #include "WarningLib.h" 13 | 14 | #define REDIS_NAME "redis.so" 15 | 16 | MemCache * MemCache::m_instance = NULL; 17 | 18 | MemCache::MemCache():m_handle(NULL),m_redisAddr(""),m_redisPort(0) { 19 | Pfun_InitDB = NULL; 20 | Pfun_UnInitDB = NULL; 21 | Pfun_Connect = NULL; 22 | Pfun_DisConnect = NULL; 23 | Pfun_WritePointsValue_C = NULL; 24 | Pfun_WritePointsValue_V = NULL; 25 | Pfun_WritePointValue = NULL; 26 | } 27 | 28 | MemCache::~MemCache() 29 | { 30 | Free(); 31 | } 32 | 33 | MemCache * MemCache::GetInstance() 34 | { 35 | if(NULL == m_instance) 36 | { 37 | m_instance = new MemCache(); 38 | } 39 | return m_instance; 40 | } 41 | 42 | bool MemCache::Init(const std::string & redisAddr, uint16_t redisPort) 43 | { 44 | m_redisAddr = redisAddr; 45 | m_redisPort = redisPort; 46 | char buf[512] = {0}; 47 | getcwd(buf, sizeof(buf)); 48 | std::string strRedisPath(buf); 49 | strRedisPath.append("/").append(REDIS_NAME); 50 | 51 | m_handle = dlopen(strRedisPath.c_str(), RTLD_LAZY); /*打开动态链接库*/ 52 | if(m_handle == NULL) 53 | { 54 | ERROR("dlopen error:%s \n", dlerror()); 55 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "redis.so dlopen error"); 56 | return false; 57 | } 58 | 59 | //获取函数指针 60 | if(!GetFunction(reinterpret_cast(&Pfun_InitDB), "InitDB")) 61 | { 62 | return false; 63 | } 64 | 65 | if(!GetFunction(reinterpret_cast(&Pfun_UnInitDB), "UnInitDB")) 66 | { 67 | return false; 68 | } 69 | 70 | if(!GetFunction(reinterpret_cast(&Pfun_Connect), "Connect")) 71 | { 72 | return false; 73 | } 74 | 75 | if(!GetFunction(reinterpret_cast(&Pfun_DisConnect), "DisConnect")) 76 | { 77 | return false; 78 | } 79 | 80 | if(!GetFunction(reinterpret_cast(&Pfun_WritePointsValue_C), "WritePointsValue_C")) 81 | { 82 | return false; 83 | } 84 | 85 | if(!GetFunction(reinterpret_cast(&Pfun_WritePointsValue_V), "WritePointsValue_V")) 86 | { 87 | return false; 88 | } 89 | 90 | if(!GetFunction(reinterpret_cast(&Pfun_WritePointValue), "WritePointValue")) 91 | { 92 | return false; 93 | } 94 | if(!GetFunction(reinterpret_cast(&Pfun_post), "post")) 95 | { 96 | return false; 97 | } 98 | if(!GetFunction(reinterpret_cast(&Pfun_CheckConnection), "check_connection")) 99 | { 100 | return false; 101 | } 102 | 103 | if(!Pfun_InitDB()) 104 | { 105 | ERROR("redis init error \n"); 106 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "redis init error"); 107 | return false; 108 | } 109 | 110 | if(!Pfun_Connect(0, m_redisAddr.c_str(), m_redisPort)) 111 | { 112 | ERROR("redis Connect error \n"); 113 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "redis Connect error"); 114 | return false; 115 | } 116 | 117 | return true; 118 | } 119 | 120 | bool MemCache::GetFunction(Handle * handle, const char* funcName) 121 | { 122 | *handle = dlsym(m_handle,funcName); 123 | char * errorInfo = dlerror(); 124 | if (errorInfo != NULL){ 125 | ERROR("%s method get failed%s\n", funcName, errorInfo); 126 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, " redis dlsym error"); 127 | return false; 128 | } 129 | return true; 130 | } 131 | 132 | bool MemCache::WritePointsValue_V(std::vector& m_tag_ver) 133 | { 134 | int count = 0; 135 | while(true) 136 | { 137 | if(!Pfun_CheckConnection(0)) 138 | { 139 | if(3 == count) 140 | { 141 | ERROR("WritePointsValue_V error \n"); 142 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, " WritePointsValue_V error"); 143 | return false; 144 | } 145 | WARN("redis reconnect \n"); 146 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV0, "redis reconnect"); 147 | sleep(3); 148 | Pfun_DisConnect(); 149 | Pfun_Connect(0, m_redisAddr.c_str(), m_redisPort); 150 | ++count; 151 | 152 | continue; 153 | } 154 | else 155 | { 156 | break; 157 | } 158 | } 159 | 160 | bool ret = true; 161 | if(!Pfun_WritePointsValue_C(&m_tag_ver[0], m_tag_ver.size())) 162 | { 163 | ret = false; 164 | } 165 | Post(Config::GetInstance()->GetRedisPostName(), Config::GetInstance()->GetRedisPostSize()); 166 | return ret; 167 | } 168 | 169 | /* 170 | * @Desc: 数据更新通知 171 | * @Param: pCh通道名数组 172 | * @Param: m_ch_size 通道个数 173 | * @Return: 成功或失败 174 | */ 175 | void MemCache::Post( char *pCh,int m_ch_size) 176 | { 177 | return Pfun_post(pCh, m_ch_size); 178 | } 179 | 180 | void MemCache::Free() 181 | { 182 | if((Pfun_DisConnect != NULL) 183 | &&(Pfun_UnInitDB != NULL)) 184 | { 185 | Pfun_DisConnect(); 186 | Pfun_UnInitDB(); 187 | } 188 | 189 | } 190 | -------------------------------------------------------------------------------- /core/MemCache.h: -------------------------------------------------------------------------------- 1 | /* 2 | * MemCache.h 3 | * 4 | * Created on: Jun 16, 2015 5 | * Author: root 6 | */ 7 | 8 | #ifndef MEMCACHE_H_ 9 | #define MEMCACHE_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "DBHelper.h" 17 | 18 | class MemCache { 19 | public: 20 | static MemCache * GetInstance(); 21 | /* 22 | * @Desc: 初始化,读取so,连接内存数据库 23 | * @Return: 成功或失败 24 | */ 25 | bool Init(const std::string & redisAddr, uint16_t redisPort); 26 | /* 27 | * @Desc: 释放内存数据库 28 | * @Return: 成功或失败 29 | */ 30 | void Free(); 31 | /* 32 | * @Desc: 更新点到内存数据库 33 | * @Param: m_tag_ver要更新的点集合 34 | * @Return: 成功或失败 35 | */ 36 | bool WritePointsValue_V(std::vector& m_tag_ver); 37 | /* 38 | * @Desc: 数据更新通知 39 | * @Param: pCh通道名数组 40 | * @Param: m_ch_size 通道个数 41 | * @Return: 成功或失败 42 | */ 43 | void Post( char *pCh,int m_ch_size); 44 | typedef void * Handle; 45 | private: 46 | MemCache(); 47 | virtual ~MemCache(); 48 | private: 49 | bool GetFunction(Handle * handle, const char* funcName); 50 | private: 51 | //初始化 52 | bool (*Pfun_InitDB)(); 53 | //卸载数据库 54 | bool (*Pfun_UnInitDB)(); 55 | //连接内存数据库函数 56 | bool (*Pfun_Connect)(int ConnectTpye,const char* host,unsigned short u_port); 57 | //断开数据库 58 | bool (*Pfun_DisConnect)(); 59 | //写点数据 60 | bool (*Pfun_WritePointsValue_C)(Tag * pTags,int m_count); 61 | //写多点容器 62 | bool (*Pfun_WritePointsValue_V)(std::vector& m_tag_ver); 63 | //写单点 64 | bool (*Pfun_WritePointValue)(Tag *m_tag); 65 | //更新通知 66 | void (*Pfun_post)(char *pch, int m_ch_size); 67 | bool (*Pfun_CheckConnection)(int ConnectTpye); 68 | private: 69 | static MemCache * m_instance; 70 | void *m_handle; 71 | std::string m_redisAddr; 72 | uint16_t m_redisPort; 73 | }; 74 | 75 | #endif /* MEMCACHE_H_ */ 76 | -------------------------------------------------------------------------------- /core/Mutex.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Mutex.h 3 | * 4 | * Created on: 5 | * Author: Administrator 6 | */ 7 | 8 | #ifndef MUTEX_H_ 9 | #define MUTEX_H_ 10 | #include 11 | #include 12 | 13 | typedef pthread_mutex_t MutexType; 14 | 15 | class Mutex { 16 | public: 17 | // Create a Mutex that is not held by anybody. This constructor is 18 | // typically used for Mutexes allocated on the heap or the stack. 19 | // See below for a recommendation for constructing global Mutex 20 | // objects. 21 | inline Mutex(); 22 | 23 | // Destructor 24 | inline ~Mutex(); 25 | 26 | inline void Lock(); // Block if needed until free then acquire exclusively 27 | inline void Unlock(); // Release a lock acquired via Lock() 28 | inline bool TryLock(); // If free, Lock() and return true, else return false 29 | // Note that on systems that don't support read-write locks, these may 30 | // be implemented as synonyms to Lock() and Unlock(). So you can use 31 | // these for efficiency, but don't use them anyplace where being able 32 | // to do shared reads is necessary to avoid deadlock. 33 | inline void ReaderLock(); // Block until free or shared then acquire a share 34 | inline void ReaderUnlock(); // Release a read share of this Mutex 35 | inline void WriterLock() { Lock(); } // Acquire an exclusive lock 36 | inline void WriterUnlock() { Unlock(); } // Release a lock from WriterLock() 37 | 38 | // TODO(hamaji): Do nothing, implement correctly. 39 | inline void AssertHeld() {} 40 | private: 41 | MutexType mutex_; 42 | // We want to make sure that the compiler sets is_safe_ to true only 43 | // when we tell it to, and never makes assumptions is_safe_ is 44 | // always true. volatile is the most reliable way to do that. 45 | volatile bool is_safe_; 46 | 47 | inline void SetIsSafe() { is_safe_ = true; } 48 | 49 | // Catch the error of writing Mutex when intending MutexLock. 50 | Mutex(Mutex* /*ignored*/) {} 51 | // Disallow "evil" constructors 52 | Mutex(const Mutex&); 53 | void operator=(const Mutex&); 54 | }; 55 | #define SAFE_PTHREAD(fncall) do { /* run fncall if is_safe_ is true */ \ 56 | if (is_safe_ && fncall(&mutex_) != 0) abort(); \ 57 | } while (0) 58 | 59 | Mutex::Mutex() { 60 | SetIsSafe(); 61 | if (is_safe_ && pthread_mutex_init(&mutex_, NULL) != 0) abort(); 62 | } 63 | Mutex::~Mutex() { SAFE_PTHREAD(pthread_mutex_destroy); } 64 | void Mutex::Lock() { SAFE_PTHREAD(pthread_mutex_lock); } 65 | void Mutex::Unlock() { SAFE_PTHREAD(pthread_mutex_unlock); } 66 | bool Mutex::TryLock() { return is_safe_ ? 67 | pthread_mutex_trylock(&mutex_) == 0 : true; } 68 | void Mutex::ReaderLock() { Lock(); } 69 | void Mutex::ReaderUnlock() { Unlock(); } 70 | class MutexLock { 71 | public: 72 | explicit MutexLock(Mutex *mu) : mu_(mu) { mu_->Lock(); } 73 | ~MutexLock() { mu_->Unlock(); } 74 | private: 75 | Mutex * const mu_; 76 | // Disallow "evil" constructors 77 | MutexLock(const MutexLock&); 78 | void operator=(const MutexLock&); 79 | }; 80 | 81 | // ReaderMutexLock and WriterMutexLock do the same, for rwlocks 82 | class ReaderMutexLock { 83 | public: 84 | explicit ReaderMutexLock(Mutex *mu) : mu_(mu) { mu_->ReaderLock(); } 85 | ~ReaderMutexLock() { mu_->ReaderUnlock(); } 86 | private: 87 | Mutex * const mu_; 88 | // Disallow "evil" constructors 89 | ReaderMutexLock(const ReaderMutexLock&); 90 | void operator=(const ReaderMutexLock&); 91 | }; 92 | 93 | class WriterMutexLock { 94 | public: 95 | explicit WriterMutexLock(Mutex *mu) : mu_(mu) { mu_->WriterLock(); } 96 | ~WriterMutexLock() { mu_->WriterUnlock(); } 97 | private: 98 | Mutex * const mu_; 99 | // Disallow "evil" constructors 100 | WriterMutexLock(const WriterMutexLock&); 101 | void operator=(const WriterMutexLock&); 102 | }; 103 | 104 | #endif /* MUTEX_H_ */ 105 | -------------------------------------------------------------------------------- /core/SerialNet.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * SerialNet.cpp 3 | * 4 | * Created on: Jun 14, 2015 5 | * Author: root 6 | */ 7 | 8 | #include "SerialNet.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include "Logger.h" 21 | #include "../business/IEC103Type.h" 22 | #include "WarningLib.h" 23 | 24 | #define SERIAL_SO_NAME "Serial.so" 25 | 26 | SerialNet::SerialNet(const std::string & portPath, int32_t speed, int32_t databits, int32_t stopbits, char parity, int32_t outTime) 27 | :Inet(), 28 | m_SerialPath(portPath), 29 | m_speed(speed), 30 | m_databits(databits), 31 | m_stopbits(stopbits), 32 | m_parity(parity), 33 | m_outTime(outTime) 34 | { 35 | m_handle = NULL; 36 | Pfun_InitSerial = NULL; 37 | Pfun_Connect = NULL; 38 | Pfun_Broken = NULL; 39 | Pfun_Recv = NULL; 40 | Pfun_Send = NULL; 41 | Pfun_UnInitSerial = NULL; 42 | } 43 | 44 | SerialNet::~SerialNet() 45 | { 46 | if(-1 != m_netFd) 47 | { 48 | close(m_netFd); 49 | } 50 | if((Pfun_Broken != NULL) 51 | &&(Pfun_UnInitSerial != NULL)) 52 | { 53 | Pfun_Broken(); 54 | Pfun_UnInitSerial(); 55 | } 56 | 57 | } 58 | 59 | /* 60 | * @Desc: 进行通讯连接 61 | * @Return: 连接成功或失败 62 | */ 63 | bool SerialNet::Connect() 64 | { 65 | char buf[512] = {0}; 66 | getcwd(buf, sizeof(buf)); 67 | std::string strRedisPath(buf); 68 | strRedisPath.append("/").append(SERIAL_SO_NAME); 69 | 70 | m_handle = dlopen(strRedisPath.c_str(),RTLD_LAZY ); /*打开动态链接库*/ 71 | if(m_handle == NULL) 72 | { 73 | ERROR("dlopen error:%s \n", dlerror()); 74 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "serial dlopen error"); 75 | return false; 76 | } 77 | 78 | //获取函数指针 79 | if(!GetFunction(reinterpret_cast(Pfun_InitSerial), "InitSerial")) 80 | { 81 | return false; 82 | } 83 | //获取函数指针 84 | if(!GetFunction(reinterpret_cast(Pfun_Connect), "Connect")) 85 | { 86 | return false; 87 | } 88 | //获取函数指针 89 | if(!GetFunction(reinterpret_cast(Pfun_Broken), "Broken")) 90 | { 91 | return false; 92 | } 93 | //获取函数指针 94 | if(!GetFunction(reinterpret_cast(Pfun_Recv), "Recv")) 95 | { 96 | return false; 97 | } 98 | //获取函数指针 99 | if(!GetFunction(reinterpret_cast(Pfun_Send), "Send")) 100 | { 101 | return false; 102 | } 103 | //获取函数指针 104 | if(!GetFunction(reinterpret_cast(Pfun_UnInitSerial), "UnInitSerial")) 105 | { 106 | return false; 107 | } 108 | if(!Pfun_InitSerial(m_SerialPath.c_str(), m_speed, m_databits, m_parity, m_stopbits,MAX_SIZE, 100,4)) 109 | { 110 | char szMsg[128]; 111 | sprintf(szMsg,"InitSerial failed comName=%s speed=%d m_databits=%d parity=%d \n", 112 | m_SerialPath.c_str(), 113 | m_speed, 114 | m_databits, 115 | m_parity); 116 | 117 | ERROR(szMsg); 118 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "InitSerial failed"); 119 | return false; 120 | } 121 | if(!Pfun_Connect()) 122 | { 123 | ERROR("Connect failed \n"); 124 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "Connect failed"); 125 | return false; 126 | } 127 | // //打开串口 128 | // if(-1 == (m_netFd = open(m_SerialPath.c_str(), O_RDWR | O_NOCTTY))) 129 | // { 130 | // ERROR("serial[%s]open failed\n", m_SerialPath.c_str()); 131 | // return false; 132 | // } 133 | 134 | //设置为阻塞模式 135 | // if(fcntl(m_netFd, F_SETFL, 0)<0) 136 | // { 137 | // ERROR("fcntl failed\n"); 138 | // return false; 139 | // } 140 | // //设置波特率 141 | // if(!SetSpeed()) 142 | // { 143 | // ERROR("set speed failed \n"); 144 | // return false; 145 | // } 146 | // // 设置数据位 停止位 奇偶较验 超时时间 147 | // if(!SetParity()) 148 | // { 149 | // return false; 150 | // } 151 | return true; 152 | } 153 | 154 | bool SerialNet::GetFunction(Handle & handle, const char* funcName) 155 | { 156 | handle = dlsym(m_handle,funcName); 157 | char * errorInfo = dlerror(); 158 | if (errorInfo != NULL){ 159 | ERROR("%s method get failed%s\n", funcName, errorInfo); 160 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "serial.so dlsys error"); 161 | return false; 162 | } 163 | return true; 164 | } 165 | 166 | /* 167 | * @Desc: 读取数据 168 | * @Param: pRecvData 读取数据存放地址 169 | * @Param: dataMaxLen 读取数据的最大长度 170 | * @Return: 读取的数据长度 错误的数据返回-2 171 | */ 172 | int32_t SerialNet::Read(char * pRecvData, uint32_t dataMaxLen) 173 | { 174 | int32_t readLen = 0; 175 | int32_t readAllLen = 0; 176 | uint64_t startTime = time(NULL); 177 | 178 | while((readLen = Pfun_Recv((unsigned char*)(pRecvData + readAllLen), dataMaxLen - readAllLen)) >= 0) 179 | { 180 | readAllLen += readLen; 181 | if(readAllLen >= (int32_t)dataMaxLen) 182 | { 183 | break; 184 | } 185 | if((5 == readAllLen) 186 | &&(START_10H == pRecvData[0]) 187 | && (END_16H == pRecvData[4])) 188 | { 189 | if(SumCheck( pRecvData + 1, 2) == (uint8_t)pRecvData[3]) 190 | { 191 | return readAllLen; 192 | } 193 | else 194 | { 195 | break; 196 | } 197 | } 198 | else if(readAllLen >= 14 ) 199 | { 200 | if((START_68H == pRecvData[0]) 201 | && (pRecvData[1] == pRecvData[2]) 202 | && (START_68H == pRecvData[3]) 203 | && ((6 + pRecvData[1])== readAllLen) 204 | && (END_16H == pRecvData[readAllLen -1 ]) 205 | && (SumCheck(pRecvData + 4, pRecvData[1]) == (uint8_t)(pRecvData[pRecvData[1]+4]))) 206 | { 207 | return readAllLen; 208 | } 209 | } 210 | 211 | if(abs(time(NULL) - startTime) > m_outTime) 212 | { 213 | break; 214 | } 215 | } 216 | if(-1 == readLen) 217 | { 218 | ERROR("read error:%s \n", strerror(errno)); 219 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "serial read error"); 220 | return -1; 221 | } 222 | if(0 == readAllLen) 223 | { 224 | return 0; 225 | } 226 | 227 | WARN("recv invalied data: %s\n", ToHexString(pRecvData, readAllLen).c_str()); 228 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV0, "recv invalied data"); 229 | return -2; 230 | } 231 | 232 | /* 233 | * @Desc: 发送数据 234 | * @Param: pSendData 发送数据存放地址 235 | * @Param: uint32_t 发送的数据的长度 236 | * @Return: 发送的数据长度 237 | */ 238 | int32_t SerialNet::Write(const char * pSendData, uint32_t dataLen) 239 | { 240 | int32_t writeLen = 0; 241 | if(-1 == (writeLen = Pfun_Send((unsigned char*)(pSendData), dataLen))) 242 | { 243 | ERROR("write error:%s \n", strerror(errno)); 244 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV2, "serial write error"); 245 | return -1; 246 | } 247 | return writeLen; 248 | } 249 | 250 | /* 251 | * @Desc: 断开通讯连接 252 | * @Return: 成功或失败 253 | */ 254 | bool SerialNet::DisConnect() 255 | { 256 | close(m_netFd); 257 | m_netFd = -1; 258 | return true; 259 | } 260 | 261 | /* 262 | * @Desc:设置波特率 263 | * @Return: 设置成功或失败 264 | */ 265 | bool SerialNet::SetSpeed() 266 | { 267 | int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, }; 268 | int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, }; 269 | struct termios Opt; //定义termios结构 270 | 271 | //获取终端参数 272 | if(tcgetattr(m_netFd, &Opt) != 0) 273 | { 274 | ERROR("tcgetattr failed:%s \n", strerror(errno)); 275 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "tcgetattr failed"); 276 | return false; 277 | } 278 | for(uint32_t i = 0; i < sizeof(speed_arr) / sizeof(speed_arr[0]); i++) 279 | { 280 | if(m_speed == name_arr[i]) 281 | { 282 | tcflush(m_netFd, TCIOFLUSH); // 清除所有正在发生的I/O数据 283 | cfsetispeed(&Opt, speed_arr[i]); // 设置输入波特率 284 | cfsetospeed(&Opt, speed_arr[i]); // 设置输出波特率 285 | //设置属性生效 286 | if(tcsetattr(m_netFd, TCSANOW, &Opt) != 0) 287 | { 288 | ERROR("tcsetattr failed:%s \n",strerror(errno)); 289 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "tcsetattr failed"); 290 | return false; 291 | } 292 | tcflush(m_netFd, TCIOFLUSH); 293 | break; 294 | } 295 | } 296 | return true; 297 | } 298 | 299 | /* 300 | * @Desc:设置数据位、停止位和校验位 301 | * @Return: 设置成功或失败 302 | */ 303 | bool SerialNet::SetParity() 304 | { 305 | struct termios newtio,oldtio; 306 | if ( tcgetattr( m_netFd,&oldtio) != 0) 307 | { 308 | ERROR("tcgetattr failed: \n",strerror(errno)); 309 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "tcgetattr failed"); 310 | return false; 311 | } 312 | 313 | bzero( &newtio, sizeof( newtio ) ); 314 | newtio.c_cflag |= CLOCAL | CREAD; 315 | newtio.c_cflag &= ~CSIZE; 316 | newtio.c_oflag &= ~(ONLCR | OCRNL); 317 | newtio.c_iflag &= ~(IXON | IXOFF | IXANY); 318 | 319 | //设置数据位 320 | switch( m_databits ) 321 | { 322 | case 7: 323 | newtio.c_cflag |= CS7; 324 | break; 325 | case 8: 326 | newtio.c_cflag |= CS8; 327 | break; 328 | default: 329 | ERROR("set databits failed \n"); 330 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "set databits failed"); 331 | return false; 332 | } 333 | 334 | // 设置奇偶较验位 335 | switch( m_parity ) 336 | { 337 | case 'O': 338 | newtio.c_cflag |= PARENB; 339 | newtio.c_cflag |= PARODD; 340 | newtio.c_iflag |= (INPCK | ISTRIP); 341 | break; 342 | case 'E': 343 | newtio.c_iflag |= (INPCK | ISTRIP); 344 | newtio.c_cflag |= PARENB; 345 | newtio.c_cflag &= ~PARODD; 346 | break; 347 | case 'N': 348 | newtio.c_cflag &= ~PARENB; 349 | break; 350 | default: 351 | ERROR("set parity failed \n"); 352 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "set parity failed"); 353 | return false; 354 | } 355 | 356 | // 设置停止位 357 | if( m_stopbits == 1 ) 358 | { 359 | newtio.c_cflag &= ~CSTOPB; 360 | } 361 | else if ( m_stopbits == 2 ) 362 | { 363 | newtio.c_cflag |= CSTOPB; 364 | } 365 | else 366 | { 367 | ERROR("set stopbits failed \n"); 368 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "set stopbits failed"); 369 | return false; 370 | } 371 | newtio.c_cc[VTIME] =m_outTime; //测试时该大一点 372 | newtio.c_cc[VMIN] = 0;//set min read byte! 373 | tcflush(m_netFd,TCIFLUSH); 374 | 375 | if((tcsetattr(m_netFd,TCSANOW,&newtio))!=0) 376 | { 377 | ERROR("tcsetattr failed:%s \n", strerror(errno)); 378 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "tcsetattr failed"); 379 | return false; 380 | } 381 | 382 | return true; 383 | } 384 | 385 | uint8_t SerialNet::SumCheck( const char* buffer, int32_t count ) 386 | { 387 | uint8_t result = 0; 388 | for( int32_t i = 0; i < count; i++ ) 389 | { 390 | result += buffer[i]; 391 | } 392 | return result; 393 | } 394 | 395 | std::string SerialNet::ToHexString(const char* data, int32_t dataLen) 396 | { 397 | uint16_t len =(dataLen+1)*3; 398 | char * hexStr = new char[len]; 399 | memset(hexStr, 0, len); 400 | for(int i = 0; i < dataLen; ++i) 401 | { 402 | sprintf(hexStr + 3*i, "%02x ", 0xff & (uint8_t)data[i]); 403 | } 404 | std::string retStr = hexStr; 405 | delete [] hexStr; 406 | return retStr; 407 | } 408 | -------------------------------------------------------------------------------- /core/SerialNet.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SerialNet.h 3 | * 4 | * Created on: Jun 14, 2015 5 | * Author: root 6 | */ 7 | 8 | #ifndef SERIALNET_H_ 9 | #define SERIALNET_H_ 10 | 11 | #include 12 | #include "Inet.h" 13 | 14 | class SerialNet : public Inet 15 | { 16 | public: 17 | /* 18 | * @Desc: 初始化 19 | * @Param: portPath 串口路径 20 | * @Param: speed 波特率 21 | * @Param: databits 数据位的个数 取值 为 7 或者8 22 | * @Param: stopbits 停止位使用格式 取值为 1 或者2 23 | * @Param: parity 奇偶较验位 取值为N(清除),E(偶较验),O(奇较验) 24 | * @Param: outTime 超时时间 单位秒 25 | */ 26 | SerialNet(const std::string & portPath, int32_t speed = 9600, int32_t databits = 8, int32_t stopbits = 1, char parity = 'N', int32_t outTime=1); 27 | 28 | /* 29 | * @Desc: 进行通讯连接 30 | * @Return: 连接成功或失败 31 | */ 32 | virtual bool Connect(); 33 | 34 | /* 35 | * @Desc: 读取数据 36 | * @Param: pRecvData 读取数据存放地址 37 | * @Param: dataMaxLen 读取数据的最大长度 38 | * @Return: 读取的数据长度 39 | */ 40 | virtual int32_t Read(char * pRecvData, uint32_t dataMaxLen); 41 | 42 | /* 43 | * @Desc: 发送数据 44 | * @Param: pSendData 发送数据存放地址 45 | * @Param: dataLen 发送的数据的长度 46 | * @Return: 发送的数据长度 47 | */ 48 | virtual int32_t Write(const char * pSendData, uint32_t dataLen); 49 | 50 | /* 51 | * @Desc: 断开通讯连接 52 | * @Return: 成功或失败 53 | */ 54 | virtual bool DisConnect(); 55 | 56 | /* 57 | * @Desc: 生成较验码 58 | * @Param: buffer 开始地址 59 | * @Param: count 开始地址 60 | * @Return: 较验码 61 | */ 62 | uint8_t SumCheck( const char* buffer, int32_t count ); 63 | 64 | std::string ToHexString(const char* data, int32_t dataLen); 65 | 66 | virtual ~SerialNet(); 67 | typedef void * Handle; 68 | private: 69 | 70 | /* 71 | * @Desc:设置波特率 72 | * @Return: 设置成功或失败 73 | */ 74 | bool SetSpeed(); 75 | 76 | /* 77 | * @Desc:设置数据位、停止位和校验位 78 | * @Return: 设置成功或失败 79 | */ 80 | bool SetParity(); 81 | private: 82 | bool GetFunction(Handle & handle, const char* funcName); 83 | private: 84 | //初始化 85 | bool (*Pfun_InitSerial)(const char* m_Name,int m_badb,short m_dataSize,short m_parity_,short m_stop_bit,short m_buf_size,short m_timeOut,short m_read_Mode); 86 | //连接 87 | bool (*Pfun_Connect)(); 88 | //断开 89 | bool (*Pfun_Broken)(); 90 | //接收 91 | int (*Pfun_Recv)(unsigned char *pData,int len); 92 | //发送数据 93 | int (*Pfun_Send)(unsigned char *pData,int len); 94 | //卸载 95 | bool (*Pfun_UnInitSerial)(); 96 | 97 | 98 | private: 99 | std::string m_SerialPath; 100 | int32_t m_speed; 101 | int32_t m_databits; //数据位的个数 102 | int32_t m_stopbits; //停止位使用格式 103 | uint16_t m_parity; //奇偶较验位 104 | int32_t m_outTime; //超时时间 105 | void *m_handle; 106 | 107 | }; 108 | 109 | 110 | #endif /* SERIALNET_H_ */ 111 | -------------------------------------------------------------------------------- /core/TcpNet.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * TcpNet.cpp 3 | * 4 | * Created on: Jun 14, 2015 5 | * Author: root 6 | */ 7 | 8 | #include "TcpNet.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include "WarningLib.h" 20 | #include "Logger.h" 21 | 22 | 23 | TcpNet::TcpNet(const std::string & serverAddr, uint16_t serverPort):Inet() 24 | { 25 | m_serverAddrStr = serverAddr; 26 | 27 | m_serverAddr.sin_family = AF_INET; 28 | m_serverAddr.sin_port = htons(serverPort); 29 | m_serverAddr.sin_addr.s_addr = inet_addr(serverAddr.c_str()); 30 | } 31 | 32 | TcpNet::~TcpNet() 33 | { 34 | 35 | } 36 | 37 | /* 38 | * @Desc: 进行通讯连接 39 | * @Return: 连接成功或失败 40 | */ 41 | bool TcpNet::Connect() 42 | { 43 | 44 | //创建socket 45 | if((m_netFd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 46 | { 47 | ERROR(":%s \n", strerror(errno)); 48 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "socket failed"); 49 | return false; 50 | } 51 | 52 | //tcp连接服务端 53 | if(connect(m_netFd, (struct sockaddr *)&m_serverAddr, sizeof(m_serverAddr)) < 0) 54 | { 55 | ERROR("tcp connect failed:%s \n", strerror(errno)); 56 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "tcp connect failed"); 57 | return false; 58 | } 59 | int flags=fcntl(m_netFd,F_GETFL,0); //获取建立的sockfd的当前状态(非阻塞) 60 | fcntl(m_netFd,F_SETFL,flags|O_NONBLOCK); //将当前sockfd设置为非阻塞 61 | return true; 62 | } 63 | 64 | /* 65 | * @Desc: 读取数据 66 | * @Param: 读取数据存放地址 67 | * @Param: 读取数据的最大长度 68 | * @Return: 读取的数据长度 69 | */ 70 | int32_t TcpNet::Read(char * pRecvData, uint32_t dataMaxLen) 71 | { 72 | int32_t readLen = 0; 73 | int32_t readAllLen = 0; 74 | 75 | struct timeval tv; /* 声明一个时间变量来保存时间 */ 76 | tv.tv_sec = 2; 77 | tv.tv_usec = 0; 78 | 79 | fd_set watchset; 80 | FD_ZERO(&watchset); 81 | int32_t rcd = select(m_netFd + 1, &watchset, NULL, NULL, &tv); 82 | 83 | while((readLen = recv(m_netFd, pRecvData, dataMaxLen - readAllLen, 0)) > 0) 84 | { 85 | if(-1 == readLen) 86 | { 87 | ERROR("read failed:%s \n", strerror(errno)); 88 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "tcp read failed"); 89 | return -1; 90 | } 91 | readAllLen += readLen; 92 | } 93 | return readAllLen; 94 | } 95 | 96 | /* 97 | * @Desc: 发送数据 98 | * @Param: 发送数据存放地址 99 | * @Param: 发送的数据的长度 100 | * @Return: 发送的数据长度 101 | */ 102 | int32_t TcpNet::Write(const char * pSendData, uint32_t dataLen) 103 | { 104 | int32_t writeLen = 0; 105 | if(-1 == (writeLen = send(m_netFd, pSendData, dataLen, 0))) 106 | { 107 | ERROR("write failed:%s \n", strerror(errno)); 108 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "tcp write failed"); 109 | DisConnect(); 110 | Connect(); 111 | return -1; 112 | } 113 | return writeLen; 114 | } 115 | 116 | /* 117 | * @Desc: 断开通讯连接 118 | * @Return: 成功或失败 119 | */ 120 | bool TcpNet::DisConnect() 121 | { 122 | close(m_netFd); 123 | m_netFd = -1; 124 | return true; 125 | } 126 | -------------------------------------------------------------------------------- /core/TcpNet.h: -------------------------------------------------------------------------------- 1 | /* 2 | * TcpNet.h 3 | * 4 | * Created on: Jun 14, 2015 5 | * Author: root 6 | */ 7 | 8 | #ifndef TCPNET_H_ 9 | #define TCPNET_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "Inet.h" 15 | 16 | class TcpNet : public Inet 17 | { 18 | public: 19 | /* 20 | * @Desc: 初始化 21 | * @Param: 读取数据存放地址 22 | * @Param: 读取数据存放地址 23 | */ 24 | TcpNet(const std::string & serverAddr, uint16_t serverPort); 25 | virtual ~TcpNet(); 26 | 27 | /* 28 | * @Desc: 进行通讯连接 29 | * @Return: 连接成功或失败 30 | */ 31 | virtual bool Connect(); 32 | 33 | /* 34 | * @Desc: 读取数据 35 | * @Param: 读取数据存放地址 36 | * @Param: 读取数据的最大长度 37 | * @Return: 读取的数据长度 38 | */ 39 | virtual int32_t Read(char * pRecvData, uint32_t dataMaxLen); 40 | 41 | /* 42 | * @Desc: 发送数据 43 | * @Param: 发送数据存放地址 44 | * @Param: 发送的数据的长度 45 | * @Return: 发送的数据长度 46 | */ 47 | virtual int32_t Write(const char * pSendData, uint32_t dataLen); 48 | 49 | /* 50 | * @Desc: 断开通讯连接 51 | * @Return: 成功或失败 52 | */ 53 | virtual bool DisConnect(); 54 | private: 55 | sockaddr_in m_serverAddr; 56 | std::string m_serverAddrStr; 57 | }; 58 | 59 | #endif /* TCPNET_H_ */ 60 | -------------------------------------------------------------------------------- /core/UdpNet.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * UdpNet.cpp 3 | * 4 | * Created on: Jun 14, 2015 5 | * Author: root 6 | */ 7 | 8 | #include "UdpNet.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "Logger.h" 18 | #include "WarningLib.h" 19 | 20 | 21 | UdpNet::UdpNet(const std::string & serverAddr, uint16_t serverPort, uint16_t localPort):Inet() 22 | { 23 | m_serverAddrStr = serverAddr; 24 | 25 | m_serverAddr.sin_family = AF_INET; 26 | m_serverAddr.sin_port = htons(serverPort); 27 | m_serverAddr.sin_addr.s_addr = inet_addr(serverAddr.c_str()); 28 | 29 | m_localAddr.sin_family = AF_INET; 30 | m_localAddr.sin_port = htons(localPort); 31 | m_localAddr.sin_addr.s_addr = INADDR_ANY; 32 | } 33 | 34 | UdpNet::~UdpNet() 35 | { 36 | 37 | } 38 | 39 | /* 40 | * @Desc: 进行通讯连接 41 | * @Return: 连接成功或失败 42 | */ 43 | bool UdpNet::Connect() 44 | { 45 | 46 | //创建socket 47 | if((m_netFd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 48 | { 49 | ERROR("socket failed:%s \n", strerror(errno)); 50 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "udp socket failed"); 51 | return false; 52 | } 53 | //绑定端口 54 | if(-1 == bind(AF_INET, (sockaddr *)&m_localAddr, sizeof(m_localAddr))) 55 | { 56 | ERROR("bind failed:%s \n", strerror(errno)); 57 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "udp bind failed"); 58 | return false; 59 | } 60 | 61 | return true; 62 | } 63 | 64 | /* 65 | * @Desc: 读取数据 66 | * @Param: 读取数据存放地址 67 | * @Param: 读取数据的最大长度 68 | * @Return: 读取的数据长度 69 | */ 70 | int32_t UdpNet::Read(char * pRecvData, uint32_t dataMaxLen) 71 | { 72 | sockaddr_in serverAddr; 73 | socklen_t addr_len = sizeof(struct sockaddr_in); 74 | int32_t readLen = 0; 75 | readLen = recvfrom(m_netFd,pRecvData,dataMaxLen,0,(struct sockaddr*)&serverAddr,&addr_len); 76 | if(-1 == readLen) 77 | { 78 | ERROR("read failed:%s \n", strerror(errno)); 79 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "udp read failed"); 80 | } 81 | 82 | return readLen; 83 | } 84 | 85 | /* 86 | * @Desc: 发送数据 87 | * @Param: 发送数据存放地址 88 | * @Param: 发送的数据的长度 89 | * @Return: 发送的数据长度 90 | */ 91 | int32_t UdpNet::Write(const char * pSendData, uint32_t dataLen) 92 | { 93 | int32_t writeLen = 0; 94 | if(-1 == (writeLen = sendto(m_netFd, pSendData, dataLen, 0, (struct sockaddr*)&m_serverAddr, sizeof(m_serverAddr)))) 95 | { 96 | ERROR("write failed:%s \n", strerror(errno)); 97 | WarningLib::GetInstance()->WriteWarn2(WARNING_LV3, "udp write failed"); 98 | return -1; 99 | } 100 | return writeLen; 101 | } 102 | 103 | /* 104 | * @Desc: 断开通讯连接 105 | * @Return: 成功或失败 106 | */ 107 | bool UdpNet::DisConnect() 108 | { 109 | close(m_netFd); 110 | m_netFd = -1; 111 | return true; 112 | } 113 | -------------------------------------------------------------------------------- /core/UdpNet.h: -------------------------------------------------------------------------------- 1 | /* 2 | * UdpNet.h 3 | * 4 | * Created on: Jun 14, 2015 5 | * Author: root 6 | */ 7 | 8 | #ifndef UDPNET_H_ 9 | #define UDPNET_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "Inet.h" 15 | 16 | class UdpNet : public Inet 17 | { 18 | public: 19 | /* 20 | * @Desc: 初始化 21 | * @Param: serverAddr 从站IP地址 22 | * @Param: serverPort 从站udp端口 23 | * @Param: localPort 本地udp端口 24 | */ 25 | UdpNet(const std::string & serverAddr, uint16_t serverPort, uint16_t localPort); 26 | virtual ~UdpNet(); 27 | 28 | /* 29 | * @Desc: 进行通讯连接 30 | * @Return: 连接成功或失败 31 | */ 32 | virtual bool Connect(); 33 | 34 | /* 35 | * @Desc: 读取数据 36 | * @Param: 读取数据存放地址 37 | * @Param: 读取数据的最大长度 38 | * @Return: 读取的数据长度 39 | */ 40 | virtual int32_t Read(char * pRecvData, uint32_t dataMaxLen); 41 | 42 | /* 43 | * @Desc: 发送数据 44 | * @Param: 发送数据存放地址 45 | * @Param: 发送的数据的长度 46 | * @Return: 发送的数据长度 47 | */ 48 | virtual int32_t Write(const char * pSendData, uint32_t dataLen); 49 | 50 | /* 51 | * @Desc: 断开通讯连接 52 | * @Return: 成功或失败 53 | */ 54 | virtual bool DisConnect(); 55 | private: 56 | sockaddr_in m_serverAddr; 57 | std::string m_serverAddrStr; 58 | sockaddr_in m_localAddr; 59 | }; 60 | 61 | #endif /* UDPNET_H_ */ 62 | -------------------------------------------------------------------------------- /core/WarningLib.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * WarningLib.cpp 3 | * 4 | * Created on: Jul 30, 2015 5 | * Author: root 6 | */ 7 | 8 | #include "WarningLib.h" 9 | #include 10 | #include 11 | #include "Logger.h" 12 | #include "Config.h" 13 | 14 | WarningLib * WarningLib::m_instance = NULL; 15 | 16 | 17 | WarningLib::WarningLib() 18 | { 19 | 20 | } 21 | 22 | WarningLib::~WarningLib() { 23 | 24 | } 25 | 26 | WarningLib * WarningLib::GetInstance() 27 | { 28 | if(NULL == m_instance) 29 | { 30 | m_instance = new WarningLib(); 31 | } 32 | return m_instance; 33 | } 34 | 35 | /* 36 | * @Desc: 初始化链接 37 | * @Param: szDbIp 要链接的mysql数据库IP地址 38 | * @Param: szUser 要链接的mysql数据库用户名 39 | * @Param: szPassword 要链接的mysql数据库密码 40 | * @Param: szDb 要链接的mysql数据库名 41 | * @Param: port 要链接的mysql数据库端口号 42 | * @Return:成功或失败 43 | */ 44 | bool WarningLib::Init(const char* szDbIp, const char* szUser, 45 | const char* szPassword,const char* szDb, uint32_t port) 46 | { 47 | char buf[512] = {0}; 48 | getcwd(buf, sizeof(buf)); 49 | std::string strRedisPath(buf); 50 | strRedisPath.append("/").append("libWarning.so"); 51 | 52 | m_handle = dlopen(strRedisPath.c_str(), RTLD_LAZY); /*打开动态链接库*/ 53 | if(m_handle == NULL) 54 | { 55 | ERROR("dlopen error:%s \n", dlerror()); 56 | return false; 57 | } 58 | 59 | if(!GetFunction(reinterpret_cast(pInit), "Init")) 60 | { 61 | return false; 62 | } 63 | if(!GetFunction(reinterpret_cast( pStart), "Start")) 64 | { 65 | return false; 66 | } 67 | if(!GetFunction(reinterpret_cast( pStop), "Stop")) 68 | { 69 | return false; 70 | } 71 | if(!GetFunction(reinterpret_cast( pWriteWarn), "WriteWarn")) 72 | { 73 | return false; 74 | } 75 | if(!pInit(szDbIp, szUser, szPassword, szDb, port, NULL)) 76 | { 77 | ERROR("libwarning init error \n"); 78 | return false; 79 | } 80 | return true; 81 | } 82 | 83 | bool WarningLib::GetFunction(Handle & handle, const char* funcName) 84 | { 85 | handle = dlsym(m_handle,funcName); 86 | char * errorInfo = dlerror(); 87 | if (errorInfo != NULL){ 88 | ERROR("%s method get failed%s\n", funcName, errorInfo); 89 | return false; 90 | } 91 | return true; 92 | } 93 | 94 | /* 95 | * @Desc: 启动告警链接,调用前需调用Init 96 | * @Return:成功或失败 97 | */ 98 | bool WarningLib::Start() 99 | { 100 | if(!pStart()) 101 | { 102 | return false; 103 | } 104 | return true; 105 | } 106 | 107 | /* 108 | * @Desc: 将告警数据写入数据库 109 | * @Param: warnInfo 要写入的告警信息 110 | * @Return:成功或失败 111 | */ 112 | bool WarningLib::WriteWarn(const WarnInfo * warnInfo ) 113 | { 114 | if(!pWriteWarn(warnInfo)) 115 | { 116 | return false; 117 | } 118 | return true; 119 | } 120 | 121 | bool WarningLib::WriteWarn2(WarningLevlel warninglv, const char* errStr) 122 | { 123 | WarnInfo warnInfo; 124 | warnInfo.processIndex = Config::GetInstance()->GetId(); 125 | warnInfo.warnLv = warninglv; 126 | warnInfo.warnClass = 0; 127 | warnInfo.warnReason = 0; 128 | warnInfo.warnType = 0; 129 | warnInfo.warnDesc = errStr; 130 | WriteWarn(&warnInfo); 131 | return true; 132 | } 133 | 134 | /* 135 | * @Desc: 停止告警链接 136 | * @Return:成功或失败 137 | */ 138 | bool WarningLib::Stop() 139 | { 140 | if(!pStop()) 141 | { 142 | return false; 143 | } 144 | return true; 145 | } 146 | -------------------------------------------------------------------------------- /core/WarningLib.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Warning.h 3 | * 4 | * Created on: Jul 30, 2015 5 | * Author: root 6 | */ 7 | 8 | #ifndef WARNINGLIB_H_ 9 | #define WARNINGLIB_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | struct WarnInfo 17 | { 18 | int32_t processIndex; 19 | int32_t warnLv; 20 | int32_t warnClass; 21 | int32_t warnType; 22 | int32_t warnReason; 23 | const char* warnDesc; 24 | }; 25 | 26 | enum WarningLevlel 27 | { 28 | WARNING_LV0 = 66, // 告警 29 | WARNING_LV1 = 77, // 次要 30 | WARNING_LV2 = 88, // 主要 31 | WARNING_LV3 = 99 // 紧急 32 | }; 33 | 34 | class WarningLib { 35 | public: 36 | static WarningLib * GetInstance(); 37 | /* 38 | * @Desc: 初始化链接 39 | * @Param: szDbIp 要链接的mysql数据库IP地址 40 | * @Param: szUser 要链接的mysql数据库用户名 41 | * @Param: szPassword 要链接的mysql数据库密码 42 | * @Param: szDb 要链接的mysql数据库名 43 | * @Param: port 要链接的mysql数据库端口号 44 | * @Return:成功或失败 45 | */ 46 | bool Init(const char* szDbIp, const char* szUser, 47 | const char* szPassword,const char* szDb, uint32_t port); 48 | 49 | /* 50 | * @Desc: 启动告警链接,调用前需调用Init 51 | * @Return:成功或失败 52 | */ 53 | bool Start(); 54 | 55 | /* 56 | * @Desc: 将告警数据写入数据库 57 | * @Param: warnInfo 要写入的告警信息 58 | * @Return:成功或失败 59 | */ 60 | bool WriteWarn(const WarnInfo * warnInfo ); 61 | 62 | bool WriteWarn2(WarningLevlel warninglv, const char* errStr); 63 | 64 | /* 65 | * @Desc: 停止告警链接 66 | * @Return:成功或失败 67 | */ 68 | bool Stop(); 69 | private: 70 | typedef void * Handle; 71 | bool GetFunction(Handle & handle, const char* funcName); 72 | private: 73 | bool (*pInit)(const char* szDbIp, const char* szUser, 74 | const char* szPassword,const char* szDb, uint32_t port, MYSQL * sqlConnection); 75 | bool (*pStart)(); 76 | 77 | bool (*pStop)(); 78 | 79 | bool (*pWriteWarn)(const WarnInfo * warnInfo); 80 | private: 81 | WarningLib(); 82 | virtual ~WarningLib(); 83 | private: 84 | void *m_handle; 85 | static WarningLib * m_instance; 86 | }; 87 | 88 | #endif /* WARNINGLIB_H_ */ 89 | --------------------------------------------------------------------------------