#include "hostadsbf.h" #include #include #include #define MAX_BLOCKF_SIZE 512 #define DATA_BLOCK_BOUNDARY 400 #define REGISTER_DATA_TYPE_YC 1 #define REGISTER_DATA_TYPE_YM 2 #define REGISTER_DATA_TYPE_YX_BYTE 3 #define REGISTER_DATA_TYPE_YX_WORD 4 #define REGISTER_DATA_TYPE_YX_DWORD 5 #define ADSP_READ_ID 100 //读取文件及文件夹ID #define ADSP_READ_ID_FUNCCODE 0x03 //读取文件及文件夹ID功能码。 #define ADSP_READ_ID_REGISTER_ADDRESS 300 //读取文件及文件夹ID寄存器地址。 #define ADSP_READ_ID_REGISTER_LENGTH 32 //读取文件及文件夹ID寄存器长度。 static datalen2mbaddrmap m_datalen2mbaddr_map; static struDataLengthADSAddr m_datalen_adsaddr[] = { { 2,421,0.1 }, { 2,409,0.1 }, { 2,445,0.01 }, { 2,659,0.001 }, { 2,663,0.001 }, { 2,400,1 }, { 2,402,1 }, { 2,404,1 }, { 2,449,0.01 }, { 2,425,0.1 }, { 2,413,0.1 }, { 2,-600,0.1 }, { 2,655,0.1 }, { 2,715,0.1 }, { 2,461,0.1 }, { 2,493,0.1 }, { 2,-600,0.1 }, { 2,497,0.1 }, { 2,501,0.01 }, { 2,433,0.01 }, { 2,437,0.01 }, { 2,441,0.01 }, { 2,687,0.01 }, { 2,691,0.01 }, { 2,695,0.01 }, { 2,517,0.1 }, { 2,-600,0.1 }, { 2,-600,1 }, { 2,-600,1 }, { 2,-600,1 }, { 2,-600,1 }, { 2,-600,1 }, { 2,-600,1 }, { 2,-600,1 }, { 2,-600,1 }, { 4,-600,1 }, { 4,-600,1 }, { 4,-600,1 }, { 4,-600,1 }, { 4,-600,1 }, { 4,-600,1 }, { 4,-600,1 }, { 4,-600,1 }, { 2,465,0.01 }, { 2,469,0.1 }, { 2,473,0.1 }, { 2,477,0.1 }, { 2,481,0.1 }, { 2,485,0.1 }, { 2,489,0.1 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,-600,0.01 }, { 2,-600,0.01 }, { 2,-600,0.01 }, { 2,457,0.001 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,675,0.1 }, { 2,505,0.1 }, { 2,509,0.1 }, { 2,513,0.1 }, { 2,2,0.1 }, { 2,14,0.1 }, { 2,26,0.1 }, { 2,38,0.1 }, { 2,50,0.1 }, { 2,62,0.1 }, { 2,74,0.1 }, { 2,-600,0.1 }, { 2,98,0.1 }, { 2,110,0.1 }, { 2,122,0.1 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,-600,0.1 }, { 2,134,0.1 }, { 2,146,0.1 }, { 2,158,0.1 }, { 2,170,0.1 }, { 2,182,0.1 }, { 2,206,0.1 }, { 2,218,0.1 }, { 2,230,0.1 }, { 2,242,0.1 }, { 2,254,0.1 }, { 2,266,0.1 }, { 2,521,0.001 }, { 2,525,0.001 }, { 4,537,1 }, { 4,533,1 }, { 4,545,1 }, { 4,541,1 }, { 4,-600,1 }, { 4,-600,1 }, { 2,549,1 }, { 2,551,1 }, { 2,553,1 }, { 2,555,1 }, { 2,557,1 }, { 2,559,1 }, { 2,561,1 }, { 2,563,1 }, { 2,565,1 }, { 2,567,1 }, { 2,569,1 }, { 2,571,1 }, { 2,573,1 }, { 2,575,1 }, { 2,577,1 }, { 2,579,1 }, { 2,581,1 }, { 2,583,1 }, { 2,585,1 }, { 2,587,1 }, { 2,589,1 }, { 2,591,1 }, { 2,593,1 }, { 2,595,1 }, { 2,597,1 }, { 2,599,1 }, { 2,601,1 }, { 2,603,1 }, { 2,605,1 }, { 2,607,1 }, { 2,609,1 }, { 2,611,1 }, { 2,613,1 }, { 2,615,1 }, { 2,617,1 }, { 2,619,1 }, { 2,621,1 }, { 2,623,1 }, { 2,625,1 }, { 2,627,1 }, { 2,629,1 }, { 2,-600,1 }, { 2,-600,1 }, { 2,-600,1 }, { 2,-600,1 }, { 2,-600,1 }, { 2,-600,1 }, { 2,-600,1 }, { 2,-600,1 }, { 2,-600,1 }, { 2,-600,0.1 }, { 2,429,0.1 }, { 2,-600,0.1 }, { 2,417,0.1 }, { 2,-600,0.01 }, { 2,453,0.01 }, { 2,683,0.01 }, { 2,-600,0.1 }, { 4,639,1 }, { 4,631,1 }, { 4,635,1 }, { 2,643,0.01 }, { 2,647,0.01 }, { 2,651,0.01 }, { 2,679,0.1 }, { 2,703,0.001 }, { 2,707,0.001 }, { 2,667,0.001 }, { 2,671,0.001 }, { 2,194,0.1 }, { 2,699,1 }, { 2,10,0.1 } }; float adsGetUnitYCRealFromValue(int uid, int order, LONG value) { if (uid < 0 || uid >= UNIT_NUM) return 0; if (order < 1 || order > (int)(sizeof(m_datalen_adsaddr) / sizeof(m_datalen_adsaddr[0]))) return FALSE; float coef = m_datalen_adsaddr[order - 1].coef; return (float)(value * coef); } BOOLEAN adsGetUnitYCIsFloat(int uid, int order) { float coef = 1.0f; if (uid < 0 || uid >= UNIT_NUM) return FALSE; if (order < 1 || order > (int)(sizeof(m_datalen_adsaddr) / sizeof(m_datalen_adsaddr[0]))) return FALSE; coef = m_datalen_adsaddr[order - 1].coef; if (fabsf(coef) <= 1E-8) coef = 1.0f; if (fabsf(coef - 1.0f) <= 1E-8) return FALSE; return TRUE; } static bool publish_sensor_data(const char* command, const Json::Value payload) { Json::StreamWriterBuilder builder; builder["indentation"] = ""; builder["emitUTF8"] = true; Json::Value jsonRoot; jsonRoot["cmd"] = command; char str[128]; #ifdef NOPOLL_64BIT_PLATFORM snprintf(str, sizeof(str), "%ld", snowflake_next_id()); #else snprintf(str, sizeof(str), "%lld", snowflake_next_id()); #endif jsonRoot["cmdId"] = str; Json::Int64 mtime = (Json::Int64)time(NULL); mtime *= 1000; jsonRoot["time"] = mtime; jsonRoot["data"] = payload; std::string outputConfig = Json::writeString(builder, jsonRoot); g_conn->sendMsg(outputConfig); return true; } static WORD GetUnitYCRegisterAddr(int uid, int point) { struUnit* pUnit; struUnitYC* pYC; if (uid < 0 || uid >= UNIT_NUM) return (WORD)65535; pUnit = &config.units[uid]; if (pUnit->yccount <= 0) return (WORD)65535; if (point < 0 || point >= pUnit->yccount) return (WORD)65535; pYC = &pUnit->ycs[point]; return (MAKEWORD(pYC->m_param[0], pYC->m_param[1])); } static WORD GetUnitYXRegisterAddr(int uid, int point) { struUnit* pUnit; struUnitYX* pYX; if (uid < 0 || uid >= UNIT_NUM) return (WORD)65535; pUnit = &config.units[uid]; if (pUnit->yxcount <= 0) return (WORD)65535; if (point < 0 || point >= pUnit->yxcount) return (WORD)65535; pYX = &pUnit->yxs[point]; return (MAKEWORD(pYX->m_param[0], pYX->m_param[1])); } static BYTE GetUnitYXDataPos(int uid, int point) { struUnit* pUnit; struUnitYX* pYX; if (uid < 0 || uid >= UNIT_NUM) return (BYTE)0; pUnit = &config.units[uid]; if (pUnit->yxcount <= 0) return (BYTE)0; if (point < 0 || point >= pUnit->yxcount) return (BYTE)0; pYX = &pUnit->yxs[point]; return (pYX->m_param[3]); } static BOOLEAN GetYCValue(const int order, const FIELDDES* fields, const char* pData, LONG& value) { if (pData == NULL) return FALSE; if (fields == NULL) return FALSE; if (order < 0 || order >= (int)(sizeof(m_datalen_adsaddr) / sizeof(m_datalen_adsaddr[0]))) return FALSE; int start = fields[order].start; if (fields[order].length == sizeof(DWORD)) { //4字节 value = *(LONG *)(pData + start); return TRUE; } else if (fields[order].length == sizeof(WORD)) { short tmp = *(short *)(pData + start); value = (LONG)tmp; return TRUE; } return FALSE; } static BOOLEAN GetYXValue(const int order, const FIELDDES* fields, const char* pData, const int pos, BOOLEAN& value) { if (pData == NULL) return FALSE; if (fields == NULL) return FALSE; if (pos < 0 || pos >= 16) return FALSE; if (order < 0 || order >= (int)(sizeof(m_datalen_adsaddr) / sizeof(m_datalen_adsaddr[0]))) return FALSE; int start = fields[order].start; if (fields[order].length == sizeof(WORD)) { WORD tmp = *(WORD *)(pData + start); WORD nTemp = 0x0001; nTemp <<= pos; if (tmp & nTemp) value = TRUE; else value = FALSE; return TRUE; } return FALSE; } static bool publishhistoryHighSpeedData(const int uid, const QWORD dt, const Json::Value values) { if (uid < 0 || uid >= UNIT_NUM) return false; Json::Value root; if (values.size()) { root["dataTime"] = (Json::Int64)dt; root["deviceId"] = static_units[uid].deviceId; root["values"] = values; return publish_sensor_data("historyHighSpeedData", root); } return false; } #ifndef USE_NOPOLL_WEBSOCKET static bool publishhistoryLowSpeedData(const int uid, const QWORD dt, const Json::Value values) #else static bool publishhistoryLowSpeedData(const noPollConn* conn, const int uid, const QWORD dt, const Json::Value values) #endif { if (uid < 0 || uid >= UNIT_NUM) return false; Json::Value root; if (values.size()) { root["dataTime"] = (Json::Int64)(dt / 1000 * 1000); //取整 root["deviceId"] = static_units[uid].deviceId; root["values"] = values; #ifndef USE_NOPOLL_WEBSOCKET return publish_sensor_data("historyLowSpeedData", root); #else return publish_sensor_data(conn, "historyLowSpeedData", root); #endif } return false; } #if 0 static int ftpget(const char* remote, const char* local, const char* user, const char* pwd, const long timeout = 3, struct memory* chunk = NULL) { //vLog(LOG_DEBUG, "start to get %s to local %s, with name: %s, and password: %s.\n", remote, local, user, pwd); curl_global_init(CURL_GLOBAL_ALL); CURL* curl = curl_easy_init(); char user_key[1024] = {0}; snprintf(user_key, sizeof(user_key), "%s:%s", user, pwd); CURLcode ret = CURLE_GOT_NOTHING; curl_easy_setopt(curl, CURLOPT_URL, remote); curl_easy_setopt(curl, CURLOPT_USERPWD, user_key); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, timeout); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)chunk); curl_easy_setopt(curl, CURLOPT_FTP_USE_EPSV, 0L); // Optional: depending on your FTP server ret = curl_easy_perform(curl); curl_easy_cleanup(curl); curl_global_cleanup(); return ret; } #endif static void* ryftp_process(void* param) { if (param == NULL) return ((void*)0); CHostADSBFProcess* mbt = (CHostADSBFProcess *)param; //获取此协议配置里面的ftp信息 char remote[512]; //char name[512]; //默认参数,或是通过协议配置获取 char user[128] = "administrator"; char password[128] = "123456"; char ipaddress[128] = "127.0.0.1"; char remotePath[128] = "Hard Disk2/data/rtdatalog"; //char pathName[128] = "./"; char processName[128]; snprintf(processName, sizeof(processName), "%s", mbt->m_pidName.c_str()); //配置远方路径 char* escaped_string = escape_char_in_string(mbt->m_remotePath, ' '); if (escaped_string == NULL) { vLog(LOG_DEBUG, "%s 路径转义错误!\n", processName); return ((void*)0); } snprintf(remotePath, sizeof(remotePath), "%s", escaped_string); free(escaped_string); #if 0 //根据协议创s建一个本地协议目录 int pid = mbt->GetCurID(); if (pid < 0 || pid >= PROCESSES_NUM) return ((void*)0); char pathName[128]; snprintf(pathName, sizeof(pathName), "%d", pid); if (mbt->_mkdir(pathName) < 0) return ((void*)0); #endif //配置的用户名和密码 snprintf(user, sizeof(user), "%s", mbt->m_user); snprintf(password, sizeof(password), "%s", mbt->m_password); //配置ip地址 memset(ipaddress, '\0', sizeof(ipaddress)); snprintf(ipaddress, sizeof(ipaddress), "%s", mbt->getRemoteIp()); for (int i = 0; i < (int)(sizeof(m_datalen_adsaddr) / sizeof(m_datalen_adsaddr[0])); i++) { m_datalen2mbaddr_map.insert(datalen2mbaddrmap::value_type(m_datalen_adsaddr[i].address, i + 1)); } //struRYDeviceData t_data; FIELDDES fields[1024]; calcFields(fields); //判断是否链接单元 int uid = mbt->GetUnitID(0); //默认只接一个设备 if (uid < 0 || uid >= UNIT_NUM) return ((void*)0); datatypemap highspeedmap; datatypemap lowspeedmap; datatypeposmap yxdatamap; int yccount = GetUnitYCCount(uid); for (int i = 0; i < yccount; i++) { //根据遥测参数配置寄存器,获取高频数据寄存器 WORD register_addr = GetUnitYCRegisterAddr(uid, i); if (GetUnitYCType(uid, i)) { if (m_datalen2mbaddr_map.find(register_addr) != m_datalen2mbaddr_map.end()) { highspeedmap.insert(datatypemap::value_type(i, m_datalen2mbaddr_map[register_addr])); //point-配置的序号,order-数据文件序号 //fprintf(stderr, "%s register_addr is: %d, point is: %d, and order is: %d\n", config.units[uid].ycs[i].name, register_addr, i, m_datalen2mbaddr_map[register_addr]); } } else { if (m_datalen2mbaddr_map.find(register_addr) != m_datalen2mbaddr_map.end()) { lowspeedmap.insert(datatypemap::value_type(i, m_datalen2mbaddr_map[register_addr])); //point-配置的序号,order-数据文件序号 //fprintf(stderr, "%s register_addr is: %d, point is: %d, and order is: %d\n", config.units[uid].ycs[i].name, register_addr, i, m_datalen2mbaddr_map[register_addr]); } } } int yxcount = GetUnitYXCount(uid); for (int i = 0; i < yxcount; i++) { //根据遥测参数配置寄存器,获取高频数据寄存器 WORD register_addr = GetUnitYXRegisterAddr(uid, i); BYTE data_pos = GetUnitYXDataPos(uid, i); //vLog(LOG_DEBUG, "register_addr is: %d, pos is: %d.\n", register_addr, data_pos); struDataPos pos; if (m_datalen2mbaddr_map.find(register_addr) != m_datalen2mbaddr_map.end()) { pos.point = m_datalen2mbaddr_map[register_addr]; pos.pos = data_pos; yxdatamap.insert(datatypeposmap::value_type(i, pos)); //point-配置的序号,order-数据文件序号 //vLog(LOG_DEBUG, "register_addr is: %d, point is: %d, and order is: %d\n", register_addr, i, m_datalen2mbaddr_map[register_addr]); } } //根据实际配置表将 WORD ftpget_retry_count = 0; BOOLEAN bReadCurrentFile = TRUE; //读取当前文件标识 while (TRUE) { sleep(1); //每秒执行一次 if (!mbt->m_bFtpRun) break; //ftp获取文件 if (mbt->m_iv == 1) { //文件目录无效 continue; } if (bReadCurrentFile) { //读取当前文件 //vLog(LOG_DEBUG, "读取当前文件.\n"); //snprintf(name, sizeof(name), "%s/%d", pathName, mbt->m_currentFileNo); snprintf(remote, sizeof(remote), "ftp://%s/%s/%d/%d", ipaddress, remotePath, mbt->m_currentDirNo, mbt->m_currentFileNo); } else { //读取未读的文件 //vLog(LOG_DEBUG, "读取未读的文件.\n"); //snprintf(name, sizeof(name), "%s/%d", pathName, mbt->m_lastReadFileNo); snprintf(remote, sizeof(remote), "ftp://%s/%s/%d/%d", ipaddress, remotePath, mbt->m_lastReadDirNo, mbt->m_lastReadFileNo); } struct memory chunk = {0}; // For storing the downloaded data //vLog(LOG_DEBUG, "start to read %s\n", remote); CURLcode result = ftpget(remote, user, password, 3, &chunk); //vLog(LOG_DEBUG, "%s ftpget result is: %d,%s\n", processName, result, curl_easy_strerror(result)); if (result == CURLE_OK) { //成功,处理文件 vLog(LOG_DEBUG, "%s get %s to local memory, with name: %s, and password: %s okay, and file length is: %d.\n", processName, remote, user, password, chunk.size); config.units[uid].value &= ~0x02; ftpget_retry_count = 0; if (chunk.size <= (int)(sizeof(struRYDeviceData) << 5)) { vLog(LOG_DEBUG, "%s PLC文件生成未完成!\n", processName); continue; } struRYDeviceData *data = (struRYDeviceData *)chunk.response; int uid = mbt->GetCurUnitID(); for (int i = 0; i < 250; i++, data++) { //每个文件有250个数据块 QLONG unix_time = filetime_to_unix(data->localtime); DWORD localtime = ((unix_time / 1000) - 28800L); DWORD millisec = unix_time % 1000; unix_time = localtime; unix_time *= 1000; unix_time += millisec; #if 0 unionCP56Time st; st = Time_ttounionCP56Time(localtime); vLog(LOG_DEBUG, "data<%d> time is: %04d/%02d/%02d %02d:%02d:%02d.%03d\n", \ i, \ st.year + 2000, st.month, st.dayofmonth, \ st.hour, st.minute, st.millisecond/1000, st.millisecond%1000); #endif //vLog(LOG_DEBUG, "data.iPitchAngle1 is: %d, data.iPitchAngle2 is: %d, and data.iPitchAngle3 is: %d\n", data->iPitchAngle1, data->iPitchAngle2, data->iPitchAngle3); //如何将结构化数据传入,且快速获取 Json::Value highspeedvalues; for (datatypemap::iterator it = highspeedmap.begin(); it != highspeedmap.end(); it++) { //获取数据 LONG dvalue; int order = it->first; int point = it->second; if (GetYCValue(point, fields, (const char *)data, dvalue)) { if (adsGetUnitYCIsFloat(uid, point)) { //fprintf(stderr, "%s, ", config.units[uid].ycs[order].name); highspeedvalues[(const char *)config.units[uid].ycs[order].name] = adsGetUnitYCRealFromValue(uid, point, dvalue); } else { highspeedvalues[(const char *)config.units[uid].ycs[order].name] = dvalue; } } else { highspeedvalues[(const char *)config.units[uid].ycs[order].name] = 0.0f; } } #ifndef USE_NOPOLL_WEBSOCKET publishhistoryHighSpeedData(uid, unix_time, highspeedvalues); #else publishhistoryHighSpeedData(g_conn, uid, unix_time, highspeedvalues); #endif if (i % 25 == 0) { //40ms一个值,每25次位1s Json::Value lowspeedvalues; for (datatypemap::iterator it = lowspeedmap.begin(); it != lowspeedmap.end(); it++) { //获取数据 LONG dvalue; int order = it->first; int point = it->second; if (GetYCValue(point, fields, (const char *)data, dvalue)) { //fprintf(stderr, "get<%d> value is: %d.\n", point, dvalue); if (adsGetUnitYCIsFloat(uid, point)) { //fprintf(stderr, "%s, ", config.units[uid].ycs[order].name); lowspeedvalues[(const char *)config.units[uid].ycs[order].name] = adsGetUnitYCRealFromValue(uid, point, dvalue); } else { lowspeedvalues[(const char *)config.units[uid].ycs[order].name] = dvalue; } } else { lowspeedvalues[(const char *)config.units[uid].ycs[order].name] = 0.0f; } } for (datatypeposmap::iterator it = yxdatamap.begin(); it != yxdatamap.end(); it++) { BOOLEAN bvalue; int order = it->first; int point = it->second.point; int pos = it->second.pos; //vLog(LOG_DEBUG, "start to get point is: %d, pos is: %d\n", point, pos); if (GetYXValue(point, fields, (const char *)data, pos, bvalue)) { lowspeedvalues[(const char *)config.units[uid].yxs[order].name] = (int)bvalue; } else { lowspeedvalues[(const char *)config.units[uid].yxs[order].name] = 0; } } #ifndef USE_NOPOLL_WEBSOCKET publishhistoryLowSpeedData(uid, unix_time, lowspeedvalues); #else publishhistoryLowSpeedData(g_conn, uid, unix_time, lowspeedvalues); #endif } } if (chunk.response) free(chunk.response); if (bReadCurrentFile) { //读取的是当前文件 mbt->m_lastFileNo = mbt->m_currentFileNo; mbt->m_currentFileNo++; if ((mbt->m_currentFileNo - mbt->m_currentDirStartFileNo) % 1000 == 0) { //一个文件夹最多存放1000个文件, mbt->m_currentFileNo = 0; mbt->m_currentDirNo++; mbt->m_currentDirStartFileNo = mbt->m_currentFileNo; } } else { //读取的是未读历史文件 mbt->m_lastReadFileNo++; if ((mbt->m_lastReadFileNo - mbt->m_lastReadDirStartFileNo) % 1000 == 0) { //一个文件夹最多存放1000个文件, mbt->m_currentFileNo = 0; mbt->m_lastReadDirNo++; } if (mbt->m_curStartDirNo <= mbt->m_lastReadDirNo && mbt->m_curStartFileNo <= mbt->m_lastReadFileNo) { vLog(LOG_DEBUG, "%s a已读取完成所有未读的文件。\n", processName); mbt->m_bHaveUnReadFile = FALSE; } } bReadCurrentFile = TRUE; } else if (result == CURLE_REMOTE_FILE_NOT_FOUND) { //文件不存在,尝试60次(1分钟,正常情况下PLC10s生成一个文件) //vLog(LOG_DEBUG, "文件不存在, ftpget_retry_count is: %d\n", ftpget_retry_count); ftpget_retry_count++; if (ftpget_retry_count >= 60) { //重新通过modbus程序获取文件夹和最新文件信息 mbt->m_iv = 0; mbt->m_currentDirNo = -1; mbt->m_currentFileNo = -1; config.units[uid].value |= 0x02; // } //此处空闲读取未读的文件 if (mbt->m_bHaveUnReadFile) { bReadCurrentFile = FALSE; } } else if (result == CURLE_REMOTE_ACCESS_DENIED) { vLog(LOG_DEBUG, "%s b已读取完成所有未读的文件。\n", processName); mbt->m_bHaveUnReadFile = FALSE; bReadCurrentFile = TRUE; } } pthread_exit(0); return ((void*)0); } CHostADSBFProcess::CHostADSBFProcess() { m_adsDatas[0].inuse = FALSE; m_adsDatas[1].inuse = FALSE; m_adsDatas[2].inuse = FALSE; m_adsDatas[3].inuse = FALSE; m_adsDatas[0].adsDataMemAddr = 65535; m_adsDatas[1].adsDataMemAddr = 65535; m_adsDatas[2].adsDataMemAddr = 65535; m_adsDatas[3].adsDataMemAddr = 65535; m_localIp = "192.168.0.1"; //本机IP地址 m_localNetId = "192.168.0.1.1.1"; //本机IP地址 m_remoteIp = "192.168.0.2"; //PLC设备ip地址 m_remoteNetId = "192.168.0.2.1.1"; //websocket接口 m_cpid = 0; //目录无效 m_iv = 1; m_currentDirNo = -1; //当前目录编号 m_currentFileNo = -1; //当前文件编号 m_lastDirNo = -1; //上一目录编号 m_lastFileNo = -1; //上一文件编号 m_bFtpRun = FALSE; } CHostADSBFProcess::~CHostADSBFProcess() { if (m_bHaveFTP) { m_bFtpRun = FALSE; vLog(LOG_DEBUG, "保存本协议读取到的那个目录和文件\n"); char fileName[260]; snprintf(fileName, sizeof(fileName), "hostads_%d.mem", GetCurID()); FILE *pf = fopen(fileName, "w+"); if (pf) { fwrite(&m_currentDirNo, sizeof(LONG), 1, pf); fwrite(&m_currentFileNo, sizeof(LONG), 1, pf); fwrite(&m_currentDirStartFileNo, sizeof(LONG), 1, pf); fclose(pf); } char name[16]; memset(name, '\0', sizeof(name)); if (pthread_getname_np(m_cpid, name, sizeof(name)) != 0) { memset(name, '\0', sizeof(name)); } vLog(LOG_DEBUG, "waiting for child thread [%s] destroy.\n", (name[0] != '\0') ? name : "unknow"); pthread_join(m_cpid, NULL); vLog(LOG_DEBUG, "child protocol thread [%s] is destroyed.\n", (name[0] != '\0') ? name : "unknow"); } #if 0 if (m_threadRun) { m_threadRun = FALSE; m_startup.join(); } #endif } BOOLEAN CHostADSBFProcess::calc(void) { int n, uid; uid = GetCurUnitID(); if (uid < 0 || uid >= UNIT_NUM) return FALSE; m_adsDatas[0].inuse = FALSE; m_adsDatas[1].inuse = FALSE; m_adsDatas[2].inuse = FALSE; m_adsDatas[3].inuse = FALSE; m_adsDatas[0].adsDataMemAddr = 65535; m_adsDatas[1].adsDataMemAddr = 65535; m_adsDatas[2].adsDataMemAddr = 65535; m_adsDatas[3].adsDataMemAddr = 65535; //需要给单元添加一个是否有ftp数据的标识 if (m_bHaveFTP) config.units[uid].state |= 0x20; //存在ftp标识 int yccount, ymcount, yxcount; yccount = GetUnitYCCount(uid); ymcount = GetUnitYMCount(uid); yxcount = GetUnitYXCount(uid); //vLog(LOG_DEBUG, "unit %d, yc count is: %d, and yx count is: %d\n", uid, yccount, yxcount); BYTE params[MAX_UNIT_POINT_PARAM_SIZE]; BYTE* pData = params; WORD registerAddr = 0; BYTE value_type = 0; for (n = 0; n < yccount; n++) { pData = GetUnitYCParamByPoint(uid, n); if (pData[4] == 1) continue; registerAddr = MAKEWORD(pData[0], pData[1]); if (registerAddr < DATA_BLOCK_BOUNDARY) { if (!m_adsDatas[0].inuse) m_adsDatas[0].inuse = TRUE; if (registerAddr < m_adsDatas[0].adsDataMemAddr) m_adsDatas[0].adsDataMemAddr = registerAddr; if (m_adsDatas[0].adsDataBlocks.find(registerAddr) == m_adsDatas[0].adsDataBlocks.end()) { m_adsDatas[0].adsDataBlocks.insert(register2typemap::value_type(registerAddr, REGISTER_DATA_TYPE_YC)); } else { //vLog(LOG_WARN, "遥测测点配置了相同的寄存器地址\n"); } } else { if (!m_adsDatas[1].inuse) m_adsDatas[1].inuse = TRUE; if (registerAddr < m_adsDatas[1].adsDataMemAddr) m_adsDatas[1].adsDataMemAddr = registerAddr; if (m_adsDatas[1].adsDataBlocks.find(registerAddr) == m_adsDatas[1].adsDataBlocks.end()) { m_adsDatas[1].adsDataBlocks.insert(register2typemap::value_type(registerAddr, REGISTER_DATA_TYPE_YC)); } else { //vLog(LOG_WARN, "遥测测点配置了相同的寄存器地址\n"); } } } for (n = 0; n < ymcount; n++) { pData = GetUnitYMParamByPoint(uid, n); if (pData[4] == 1) continue; registerAddr = MAKEWORD(pData[0], pData[1]); if (registerAddr < DATA_BLOCK_BOUNDARY) { if (!m_adsDatas[0].inuse) m_adsDatas[0].inuse = TRUE; if (registerAddr < m_adsDatas[0].adsDataMemAddr) m_adsDatas[0].adsDataMemAddr = registerAddr; if (m_adsDatas[0].adsDataBlocks.find(registerAddr) == m_adsDatas[0].adsDataBlocks.end()) { m_adsDatas[0].adsDataBlocks.insert(register2typemap::value_type(registerAddr, REGISTER_DATA_TYPE_YM)); } else { //vLog(LOG_WARN, "遥脉测点配置了相同的寄存器地址\n"); } } else { if (!m_adsDatas[1].inuse) m_adsDatas[1].inuse = TRUE; if (registerAddr < m_adsDatas[1].adsDataMemAddr) m_adsDatas[1].adsDataMemAddr = registerAddr; if (m_adsDatas[1].adsDataBlocks.find(registerAddr) == m_adsDatas[1].adsDataBlocks.end()) { m_adsDatas[1].adsDataBlocks.insert(register2typemap::value_type(registerAddr, REGISTER_DATA_TYPE_YM)); } else { //vLog(LOG_WARN, "遥脉测点配置了相同的寄存器地址\n"); } } } for (n = 0; n < yxcount; n++) { pData = GetUnitYXParamByPoint(uid, n); if (pData[4] == 1) continue; registerAddr = MAKEWORD(pData[0], pData[1]); value_type = pData[2]; if (registerAddr < DATA_BLOCK_BOUNDARY) { if (!m_adsDatas[0].inuse) m_adsDatas[0].inuse = TRUE; if (registerAddr < m_adsDatas[0].adsDataMemAddr) m_adsDatas[0].adsDataMemAddr = registerAddr; if (m_adsDatas[0].adsDataBlocks.find(registerAddr) == m_adsDatas[0].adsDataBlocks.end()) { m_adsDatas[0].adsDataBlocks.insert(register2typemap::value_type(registerAddr, REGISTER_DATA_TYPE_YX_BYTE + value_type)); } } else { if (!m_adsDatas[1].inuse) m_adsDatas[1].inuse = TRUE; if (registerAddr < m_adsDatas[1].adsDataMemAddr) m_adsDatas[1].adsDataMemAddr = registerAddr; if (m_adsDatas[1].adsDataBlocks.find(registerAddr) == m_adsDatas[1].adsDataBlocks.end()) { m_adsDatas[1].adsDataBlocks.insert(register2typemap::value_type(registerAddr, REGISTER_DATA_TYPE_YX_BYTE + value_type)); } } } return TRUE; } void CHostADSBFProcess::tryStartup() { m_turbine = NULL; pthread_setname_np(pthread_self(), m_pidName.c_str()); while (m_threadRun) { if (m_turbine == NULL) { SetLocalAmsNetId(AmsNetId(m_localNetId)); m_turbine = new AdsDevice{m_remoteIp, AmsNetId(m_remoteNetId), m_remotePort}; const auto state = m_turbine->GetState(); vLog(LOG_DEBUG, "%s ADS state: %d devState: %d\n", m_pidName.c_str(), (uint16_t)state.ads, (uint16_t)state.device); if ((uint16_t)state.ads >= ADSSTATE::ADSSTATE_MAXSTATES || (uint16_t)state.device >= ADSSTATE::ADSSTATE_MAXSTATES) { vLog(LOG_DEBUG, "read device state error.\n"); long ret = AddRemoteRoute(m_remoteIp, m_localNetId, m_localIp, std::string("isoftstone"), std::string("admin"), std::string("admin")); vLog(LOG_DEBUG, "bbb %s add route return value is: %d\n", m_pidName.c_str(), ret); delete m_turbine; m_turbine = NULL; } } else { if (m_turbine->IsConnected()) continue; delete m_turbine; m_turbine = NULL; } sleep(5); } } BOOLEAN CHostADSBFProcess::OnPreCreate(int id) { if (!CProcess::OnPreCreate(id)) return FALSE; if (!GetOption(&m_nOptions, sizeof(m_nOptions))) { vLog(LOG_DEBUG, "润阳ADS读取配置错误。"); return FALSE; } char ipaddress[32]; m_pidName = std::string(GetCurProcessName()); //本机IP和netid memset(ipaddress, '\0', sizeof(ipaddress)); inet_ntop(AF_INET, &m_nOptions.net.bind_addr, ipaddress, 16); m_localIp = std::string(ipaddress); m_localNetId = m_localIp + std::string(".1.1"); //目标IP和netid memset(ipaddress, '\0', sizeof(ipaddress)); inet_ntop(AF_INET, &m_nOptions.net.target_addr, ipaddress, 16); m_remoteIp = std::string(ipaddress); m_remoteNetId = m_remoteIp + std::string(".1.1"); //目标端口 m_remotePort = m_nOptions.net.target_port; m_bHaveFTP = m_nOptions.bHaveFTP; calc(); //vLog(LOG_DEBUG, "%s local ip is: %s, netid is: %s, remote ip is: %s, and netid is: %s\n", m_pidName.c_str(), m_localIp.c_str(), m_localNetId.c_str(), m_remoteIp.c_str(), m_remoteNetId.c_str()); m_turbine = NULL; m_bRouteAdded = FALSE; m_apdu_t0_begin = 10; SetLocalAmsNetId(AmsNetId(m_localNetId)); #if 0 m_threadRun = TRUE; m_startup = std::thread(&CHostADSBFProcess::tryStartup, this); #endif if (m_bHaveFTP) { snprintf(m_user, sizeof(m_user), "%s", m_nOptions.ftp.user); snprintf(m_password, sizeof(m_password), "%s", m_nOptions.ftp.password); snprintf(m_remotePath, sizeof(m_remotePath), "%s", m_nOptions.ftp.remotePath); snprintf(m_localPath, sizeof(m_localPath), "%s", m_nOptions.ftp.localPath); //读取文件 m_lastReadDirNo = 1; m_lastReadFileNo = 1; m_lastReadDirStartFileNo = 1; m_bHaveUnReadFile = TRUE; char fileName[260]; snprintf(fileName, sizeof(fileName), "hostads_%d.mem", GetCurID()); FILE *pf = fopen(fileName, "rb"); if (pf) { fread(&m_lastReadDirNo, sizeof(LONG), 1, pf); fread(&m_lastReadFileNo, sizeof(LONG), 1, pf); fread(&m_lastReadDirStartFileNo, sizeof(LONG), 1, pf); fclose(pf); } //启动后,创建ftp线程 if (m_cpid <= 0) { m_bFtpRun = TRUE; vLog(LOG_DEBUG, "ads create a ftp thread.\n"); pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, MEMERY_1M); pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); if (pthread_create(&m_cpid, &attr, ryftp_process, this) < 0) { vLog(LOG_ERROR, "ads create ryftp_process error(%d,%s).\n", errno, strerror(errno)); return TRUE; } char name[17]; snprintf(name, 16, "%s_ftp", m_pidName.c_str()); pthread_setname_np(m_cpid, name); pthread_attr_destroy(&attr); } } return TRUE; } BOOLEAN CHostADSBFProcess::Run(void) { if (!CProcess::Run()) return FALSE; return TRUE; } BOOLEAN CHostADSBFProcess::OnTimer(void) { if (!CProcess::OnTimer()) return FALSE; BOOLEAN sec_changed = FALSE; if (last_sec != system32.timers) { last_sec = system32.timers; sec_changed = TRUE; } if (sec_changed) { if (m_turbine == NULL) { if ((m_apdu_t0_begin + 20) < system32.timers) { m_apdu_t0_begin = system32.timers; //先添加一条路由 if (m_bRouteAdded == FALSE) { long ret = AddRemoteRoute(m_remoteIp, AmsNetId(m_localNetId), m_localIp, std::string("isoftstone"), std::string("admin"), std::string("admin")); vLog(LOG_DEBUG, "%s add route(%s to %s) return value is: %d\n", m_pidName.c_str(), m_localIp.c_str(), m_remoteIp.c_str(), ret); if (ret != 0) return TRUE; } m_bRouteAdded = TRUE; //添加成功 vLog(LOG_DEBUG, "%s start to connect(%s:%d)\n", m_pidName.c_str(), m_remoteIp.c_str(), m_remotePort); m_turbine = new AdsDevice{m_remoteIp, AmsNetId(m_remoteNetId), m_remotePort}; const auto state = m_turbine->GetState(); if ((uint16_t)state.ads >= ADSSTATE::ADSSTATE_MAXSTATES || (uint16_t)state.device >= ADSSTATE::ADSSTATE_MAXSTATES) { vLog(LOG_DEBUG, "%s read device state error.\n", m_pidName.c_str()); delete m_turbine; m_turbine = NULL; } } return TRUE; } if (!m_turbine->IsConnected()) return TRUE; m_apdu_t0_begin = system32.timers; if (m_bHaveFTP) { //启动时读取一次,后面自己维护序号 if ((m_currentDirNo == -1) && (m_currentFileNo == -1)) { //当前文件和目录都为-1,程序第一次启动。需要获取ftp目录及文件ID readFileID(); } } readRealData(); FeedDog(); } return TRUE; } BOOLEAN CHostADSBFProcess::readDeviceState(const AdsDevice& route) { const auto state = route.GetState(); vLog(LOG_DEBUG, "ADS state: %d devState: %d\n", (uint16_t)state.ads, (uint16_t)state.device); if ((uint16_t)state.ads >= ADSSTATE::ADSSTATE_MAXSTATES && (uint16_t)state.device >= ADSSTATE::ADSSTATE_MAXSTATES) { return FALSE; } return TRUE; } BOOLEAN CHostADSBFProcess::readFileID() { int uid = GetCurUnitID(); if (uid < 0 || uid >= UNIT_NUM) return TRUE; vLog(LOG_DEBUG, "%s here read file info\n", m_pidName.c_str()); AdsVariable wPathInfoInvalid {*m_turbine, ".gwPathInfoInvalid"}; //vLog(LOG_DEBUG, "Read back with first value %d\n", (WORD)wPathInfoInvalid); AdsVariable wCurrentFolderNo {*m_turbine, ".gwCurrentFolderNo"}; //vLog(LOG_DEBUG, "Read back with first value %d\n", (DWORD)wCurrentFolderNo); AdsVariable wCurrentFileNo {*m_turbine, ".gwCurrentFileNo"}; //vLog(LOG_DEBUG, "Read back with first value %d\n", (DWORD)wCurrentFileNo); AdsVariable wFirstFileNoInFolder {*m_turbine, ".gwFirstFileNoInFolder"}; //vLog(LOG_DEBUG, "Read back with first value %d\n", (DWORD)wFirstFileNoInFolder); AdsVariable wFileCountInFolder {*m_turbine, ".gwFileCountInFolder"}; //vLog(LOG_DEBUG, "Read back with first value %d\n", (DWORD)wFileCountInFolder); AdsVariable wFirstFolderNoRecoverable {*m_turbine, ".gwFirstFolderNoRecoverable"}; //vLog(LOG_DEBUG, "Read back with first value %d\n", (DWORD)wFirstFolderNoRecoverable); AdsVariable wFirstFileNoRecoverable {*m_turbine, ".gwFirstFileNoRecoverable"}; //vLog(LOG_DEBUG, "Read back with first value %d\n", (DWORD)wFirstFileNoRecoverable); m_iv = (WORD)wPathInfoInvalid; if (m_iv) { vLog(LOG_DEBUG, "路径信息无效\n"); return FALSE; } //当前文件夹路径名 m_currentDirNo = (DWORD)wCurrentFolderNo; //当前文件夹下最后新文件 m_currentFileNo = (DWORD)wCurrentFileNo; //当前目录文件开始编号 m_currentDirStartFileNo = (DWORD)wFirstFileNoInFolder; m_curStartDirNo = m_currentDirNo; //当前开始目录 m_curStartFileNo = m_currentFileNo; //当前开始文件 //判断是否有要读取的文件 if (m_curStartDirNo <= m_lastReadDirNo && m_curStartFileNo <= m_lastReadFileNo) { vLog(LOG_DEBUG, "%s 不存在未读的文件。\n", m_pidName.c_str()); m_bHaveUnReadFile = FALSE; } else { m_bHaveUnReadFile = TRUE; int dir_count = m_curStartDirNo - m_lastReadDirNo + 1; int file_count = m_curStartFileNo - m_lastReadFileNo; vLog(LOG_DEBUG, "%s 总共有%d个目录的%d个文件未读取。\n", m_pidName.c_str(), dir_count, file_count); } vLog(LOG_DEBUG, "%s 最新文件夹编号: %ld, 最新文件名编号: %ld: 最新文件夹中第一个文件的编号: %ld\n", m_pidName.c_str(), m_currentDirNo, m_currentFileNo, m_currentDirStartFileNo); return TRUE; } BOOLEAN CHostADSBFProcess::readRealData() { int uid = GetCurUnitID(); if (uid < 0 || uid >= UNIT_NUM) return TRUE; for (int k = 0; k < 4; k++) { if (!m_adsDatas[k].inuse) continue; WORD m_adsOverviewDataMemAddr = m_adsDatas[k].adsDataMemAddr; register2typemap m_register2type_map = m_adsDatas[k].adsDataBlocks; BYTE buffer[1024]; BYTE *pData = buffer; BYTE params[MAX_UNIT_POINT_PARAM_SIZE]; BYTE* pParam = params; AdsVariable> turbineData {*m_turbine, ADSIGRP_IOIMAGE_RWOB, m_adsOverviewDataMemAddr}; pData = ((std::array)turbineData).data(); WORD registerAddr = m_adsOverviewDataMemAddr; float f_val; DWORD dw[2]; //双精度转换中间变量 double d_val; DWORD bin_value; DWORD nValue = 0; int point; UnitFeedDog(uid); for (int i = 0; i < MAX_BLOCKF_SIZE;) { //vLog(LOG_DEBUG, "registerAddr is: %d\n", registerAddr); if (m_register2type_map.find(registerAddr) != m_register2type_map.end()) { int type = m_register2type_map[registerAddr]; if (type == REGISTER_DATA_TYPE_YC) { //遥测 point = GetUnitYCPointByParam(uid, (BYTE *)®isterAddr, 2); if (point >= 0) { pParam = GetUnitYCParamByPoint(uid, point); BYTE value_type = pParam[2]; //数据类型 BYTE sign_mark = pParam[3]; //vLog(LOG_DEBUG, "value type is: %d, ", value_type); //32位测量值 if (0 == value_type) { //浮点数,高位在第一个寄存器 nValue = (DWORD)(pData[1] << 24 | pData[0] << 16 | pData[3] << 8 | pData[2]); memcpy(&f_val, &nValue, 4); SetUnitYC(uid, point, f_val); registerAddr += 4; i += 4; pData += 4; } else if (1 == value_type) { nValue = (DWORD)(pData[3] << 24 | pData[2] << 16 | pData[1] << 8 | pData[0]); memcpy(&f_val, &nValue, 4); SetUnitYC(uid, point, f_val); registerAddr += 4; i += 4; pData += 4; } //16位归一化值 else if (2 == value_type) { if (sign_mark == 0) nValue = (DWORD)(WORD)((pData[1] << 8) | pData[0]); else nValue = (DWORD)(short)((pData[1] << 8) | pData[0]); SetUnitYC(uid, point, (LONG)nValue); //vLog(LOG_DEBUG, "value is: %d \n", nValue); registerAddr += 2; i += 2; pData += 2; } else if (3 == value_type) { //归一化值,高位在第一个寄存器 nValue = (DWORD)(pData[1] << 24 | pData[0] << 16 | pData[3] << 8 | pData[2]); SetUnitYC(uid, point, (LONG)nValue); registerAddr += 2; i += 2; pData += 2; } else if (4 == value_type) { //归一化值,高位在第二个寄存器 nValue = (DWORD)(pData[3] << 24 | pData[2] << 16 | pData[1] << 8 | pData[0]); SetUnitYC(uid, point, (LONG)nValue); registerAddr += 4; i += 4; pData += 4; //vLog(LOG_DEBUG, "value is: %d\n", nValue); } else if (5 == value_type) { //小端系统浮点值 nValue = (DWORD)(pData[3] << 24 | pData[2] << 16 | pData[1] << 8 | pData[0]); memcpy(&f_val, &nValue, 4); SetUnitYC(uid, point, f_val); //vLog(LOG_DEBUG, "value is: %f\n", f_val); registerAddr += 4; i += 4; pData += 4; } else if (6 == value_type) { //32位bcd数据高位在第一个寄存器 nValue = (DWORD)((pData[1] << 24) | (pData[0] << 16) | (pData[3] << 8) | pData[2]); bin_value = bcd_to_int((const BYTE*)&nValue, sizeof(DWORD)); SetUnitYC(uid, point, (LONG)bin_value); registerAddr += 4; i += 4; pData += 4; } else if (7 == value_type) { //32位bcd数据高位在第二个寄存器 nValue = (DWORD)((pData[3] << 24) | (pData[2] << 16) | (pData[1] << 8) | pData[0]); bin_value = bcd_to_int((const BYTE*)&nValue, sizeof(DWORD)); SetUnitYC(uid, point, (LONG)bin_value); registerAddr += 4; i += 4; pData += 4; } else if (8 == value_type) { //16位BCD if (sign_mark == 0) nValue = (DWORD)(WORD)((pData[1] << 8) | pData[0]); else nValue = (DWORD)(short)((pData[1] << 8) | pData[0]); nValue = bcd_to_int((const BYTE*)&nValue, sizeof(WORD)); SetUnitYC(uid, point, (LONG)nValue); registerAddr += 2; i += 2; pData += 2; //vLog(LOG_DEBUG, "value is: %d\n", nValue); } else if (9 == value_type) { // if (sign_mark == 0) nValue = (DWORD)(BYTE)(pData[0]); else nValue = (DWORD)(short)(pData[0]); SetUnitYC(uid, point, (LONG)nValue); registerAddr++; i++; pData++; //vLog(LOG_DEBUG, "value is: %d\n", nValue); } else { registerAddr++; i++; pData++; } } } else if (type == REGISTER_DATA_TYPE_YM) { //遥脉 point = GetUnitYMPointByParam(uid, (BYTE *)®isterAddr, 2); if (point >= 0) { pParam = GetUnitYMParamByPoint(uid, point); BYTE value_type = pParam[2]; //数据类型 if (0 == value_type) { //16位无符号整型 nValue = (pData[1] << 8) | pData[0]; SetUnitYM(uid, point, nValue); registerAddr += 2; i += 2; pData += 2; } else if (1 == value_type) { //32位无符号整型高位在第一个寄存器 nValue = (DWORD)((pData[1] << 24) | (pData[0] << 16) | (pData[3] << 8) | pData[2]); SetUnitYM(uid, point, nValue); registerAddr += 4; i += 4; pData += 4; } else if (2 == value_type) { //32位整型高位在第一个寄存器 nValue = (DWORD)((pData[1] << 24) | (pData[0] << 16) | (pData[3] << 8) | pData[2]); SetUnitYM(uid, point, nValue); registerAddr += 4; i += 4; pData += 4; } else if (3 == value_type) { //32位无符号整型高位在第二个寄存器 nValue = (DWORD)((pData[3] << 24) | (pData[2] << 16) | (pData[1] << 8) | pData[0]); SetUnitYM(uid, point, nValue); registerAddr += 4; i += 4; pData += 4; } else if (4 == value_type) { //32位整型高位在第二个寄存器 nValue = (DWORD)((pData[3] << 24) | (pData[2] << 16) | (pData[1] << 8) | pData[0]); SetUnitYM(uid, point, nValue); registerAddr += 4; i += 4; pData += 4; } else if (5 == value_type) { //32位浮点数高位在第一个寄存器 nValue = (DWORD)((pData[1] << 24) | (pData[0] << 16) | (pData[3] << 8) | pData[2]); memcpy(&f_val, &nValue, 4); SetUnitYM(uid, point, (DWORD)f_val); registerAddr += 4; i += 4; pData += 4; } else if (6 == value_type) { //32位浮点数高位在第二个寄存器 nValue = (DWORD)((pData[3] << 24) | (pData[2] << 16) | (pData[1] << 8) | pData[0]); memcpy(&f_val, &nValue, 4); SetUnitYM(uid, point, (DWORD)f_val); registerAddr += 4; i += 4; pData += 4; } else if (7 == value_type) { //64位浮点数高位在第一个寄存器 dw[1] = (DWORD)((pData[3] << 24) | (pData[2] << 16) | (pData[1] << 8) | pData[0]); dw[0] = (DWORD)((pData[7] << 24) | (pData[6] << 16) | (pData[5] << 8) | pData[4]); memcpy(&d_val, dw, 8); SetUnitYM(uid, point, (DWORD)(d_val)); registerAddr += 8; i += 8; pData += 8; } else if (8 == value_type) { dw[0] = (DWORD)((pData[3] << 24) | (pData[2] << 16) | (pData[1] << 8) | pData[0]); dw[1] = (DWORD)((pData[7] << 24) | (pData[6] << 16) | (pData[5] << 8) | pData[4]); memcpy(&d_val, dw, 8); SetUnitYM(uid, point, (DWORD)(d_val)); registerAddr += 8; i += 8; pData += 8; } else if (9 == value_type) { nValue = (DWORD)((pData[3] << 24) | (pData[2] << 16) | (pData[1] << 8) | pData[0]); memcpy(&f_val, &nValue, 4); SetUnitYM(uid, point, (DWORD)(f_val * 10)); registerAddr += 4; i += 4; pData += 4; } else { registerAddr++; i++; pData++; } } } else { //遥信 int data_bits = 8; BYTE params[4]; params[0] = (BYTE)(registerAddr & 0xff); params[1] = (BYTE)((registerAddr >> 8) & 0xff); params[2] = type - REGISTER_DATA_TYPE_YX_BYTE; if (type == REGISTER_DATA_TYPE_YX_BYTE) { nValue = (DWORD)pData[0]; registerAddr++; i++; pData++; data_bits = 8; } else if (type == REGISTER_DATA_TYPE_YX_WORD) { nValue = (DWORD)((pData[1] << 8) | pData[0]); registerAddr += 2; i += 2; pData += 2; data_bits = 16; } else if (type == REGISTER_DATA_TYPE_YX_DWORD) { nValue = (DWORD)((pData[3] << 24) | (pData[2] << 16) | (pData[1] << 8) | pData[0]); registerAddr += 4; i += 4; pData += 4; data_bits = 32; } else { registerAddr++; i++; pData++; } DWORD nTemp = 0x00000001; for (int j = 0; j < data_bits; j++) { params[3] = j; point = GetUnitYXPointByParam(uid, (BYTE *)params, 4); if (point >= 0) { BOOLEAN yxVal = SPI_OFF; if ((nValue) & nTemp) { yxVal = SPI_ON; } SetUnitYX(uid, point, yxVal); } nTemp <<= 1; } } } else { registerAddr++; i++; pData++; } } } return TRUE; }