#include "hostadsbf.h" #include #include #include #include #define MAX_BLOCKF_SIZE 512 #define DATA_BLOCK_BOUNDARY 1000 #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 struDataLengthMBAddr m_datalen_mbaddr[] = { { 2, 200 }, { 2, 201 }, { 2, 202 }, { 2, 203 }, { 2, 204 }, { 2, 205 }, { 2, 206 }, { 2, 207 }, { 2, 208 }, { 2, 209 }, { 2, 210 }, { 2, 211 }, { 2, 212 }, { 2, 213 }, { 2, 214 }, { 2, 215 }, { 2, 216 }, { 2, 217 }, { 2, 218 }, { 2, 219 }, { 2, 220 }, { 2, 221 }, { 2, 222 }, { 2, 223 }, { 2, 224 }, { 2, 225 }, { 2, 226 }, { 2, 227 }, { 2, 228 }, { 2, 229 }, { 2, 230 }, { 2, 231 }, { 2, 232 }, { 2, 233 }, { 2, 234 }, { 4, 235 }, { 4, 237 }, { 4, 239 }, { 4, 241 }, { 4, 243 }, { 4, 245 }, { 4, 247 }, { 4, 249 }, { 2, 251 }, { 2, 252 }, { 2, 253 }, { 2, 254 }, { 2, 255 }, { 2, 256 }, { 2, 257 }, { 2, 258 }, { 2, 259 }, { 2, 260 }, { 2, 261 }, { 2, 262 }, { 2, 263 }, { 2, 264 }, { 2, 265 }, { 2, 266 }, { 2, 267 }, { 2, 268 }, { 2, 269 }, { 2, 270 }, { 2, 271 }, { 2, 272 }, { 2, 273 }, { 2, 274 }, { 2, 275 }, { 2, 276 }, { 2, 277 }, { 2, 278 }, { 2, 279 }, { 2, 280 }, { 2, 281 }, { 2, 282 }, { 2, 283 }, { 2, 284 }, { 2, 285 }, { 2, 286 }, { 2, 287 }, { 2, 288 }, { 2, 289 }, { 2, 290 }, { 2, 291 }, { 2, 292 }, { 2, 293 }, { 2, 294 }, { 2, 295 }, { 2, 296 }, { 2, 297 }, { 2, 298 }, { 2, 299 }, { 2, 300 }, { 2, 301 }, { 2, 302 }, { 2, 303 }, { 2, 304 }, { 2, 305 }, { 2, 306 }, { 2, 307 }, { 4, 308 }, { 4, 310 }, { 4, 312 }, { 4, 314 }, { 4, 316 }, { 4, 318 }, { 2, 320 }, { 2, 321 }, { 2, 322 }, { 2, 323 }, { 2, 324 }, { 2, 325 }, { 2, 326 }, { 2, 327 }, { 2, 328 }, { 2, 329 }, { 2, 330 }, { 2, 331 }, { 2, 332 }, { 2, 333 }, { 2, 334 }, { 2, 335 }, { 2, 336 }, { 2, 337 }, { 2, 338 }, { 2, 339 }, { 2, 340 }, { 2, 341 }, { 2, 342 }, { 2, 343 }, { 2, 344 }, { 2, 345 }, { 2, 346 }, { 2, 347 }, { 2, 348 }, { 2, 349 }, { 2, 350 }, { 2, 351 }, { 2, 352 }, { 2, 353 }, { 2, 354 }, { 2, 355 }, { 2, 356 }, { 2, 357 }, { 2, 358 }, { 2, 359 }, { 2, 360 }, { 2, 361 }, { 2, 362 }, { 2, 363 }, { 2, 364 }, { 2, 365 }, { 2, 366 }, { 2, 367 }, { 2, 368 }, { 2, 369 }, { 2, 370 }, { 2, 371 }, { 2, 372 }, { 2, 373 }, { 2, 374 }, { 2, 375 }, { 2, 376 }, { 2, 377 }, { 4, 378 }, { 4, 380 }, { 4, 382 }, { 2, 384 }, { 2, 385 }, { 2, 386 }, { 2, 387 }, { 2, 388 }, { 2, 389 }, { 2, 390 }, { 2, 391 }, { 2, 392 }, { 2, 393 }, { 2, 394 } }; 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_mbaddr) / sizeof(m_datalen_mbaddr[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_mbaddr) / sizeof(m_datalen_mbaddr[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; } 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; } 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->GetCurProcessName()); //配置远方路径 char* escaped_string = escape_char_in_string(mbt->m_remotePath, ' '); if (escaped_string == NULL) { vLog(LOG_DEBUG, "路径转义错误!\n"); 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_mbaddr) / sizeof(m_datalen_mbaddr[0])); i++) { m_datalen2mbaddr_map.insert(datalen2mbaddrmap::value_type(m_datalen_mbaddr[i].address, i + 1)); } int len = 0; //struRYDeviceData t_data; FIELDDES fields[1024]; len = 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-数据文件序号 //vLog(LOG_DEBUG, "register_addr is: %d, point is: %d, and order is: %d\n", 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-数据文件序号 //vLog(LOG_DEBUG, "register_addr is: %d, point is: %d, and order is: %d\n", 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); //fprintf(stderr, "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, "aaaa 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); int result = ftpget(remote, name, user, password, 3, &chunk); 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); ftpget_retry_count = 0; if (chunk.size <= (int)(sizeof(struRYDeviceData) << 5)) { vLog(LOG_DEBUG, "PLC文件生成未完成!\n"); 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 //如何将结构化数据传入,且快速获取 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 (GetUnitYCIsFloat(uid, order)) { highspeedvalues[(const char *)config.units[uid].ycs[order].name] = GetUnitYCRealFromValue(uid, order, 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 (GetUnitYCIsFloat(uid, order)) { lowspeedvalues[(const char *)config.units[uid].ycs[order].name] = GetUnitYCRealFromValue(uid, order, 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; } //此处空闲读取未读的文件 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_pid = 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); } } } 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; } BOOLEAN CHostADSBFProcess::OnPreCreate(int id) { if (!CProcess::OnPreCreate(id)) return FALSE; if (!GetOption(&m_nOptions, sizeof(m_nOptions))) { vLog(LOG_DEBUG, "润阳ADS读取配置错误。"); return FALSE; } #if 0 m_localIp = m_nOptions.localIp; //本机IP地址 m_localNetId = m_nOptions.localNetId; //本机IP地址 m_remoteIp = m_nOptions.remoteIp; //PLC设备ip地址 m_remoteNetId = m_nOptions.remoteNetId; #endif char ipaddress[32]; //本机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, "local ip is: %s, netid is: %s, remote ip is: %s, and netid is: %s\n", m_localIp.c_str(), m_localNetId.c_str(), m_remoteIp.c_str(), m_remoteNetId.c_str()); SetLocalAmsNetId(AmsNetId(m_localNetId)); //192.168.0.231 addroute --addr=192.168.0.1 --netid=192.168.0.1.1.1 --password=1 --username=guest --routename=Testroute //AddRemoteRoute(m_remoteIp, m_localNetId, m_localIp, std::string("isoftstone"), std::string("guest"), std::string("1")); //m_remotePort //m_turbine = new AdsDevice{m_remoteIp, AmsNetId(m_remoteNetId), AMSPORT_R0_PLC_RTS1}; m_turbine = new AdsDevice{m_remoteIp, AmsNetId(m_remoteNetId), m_remotePort}; if (m_turbine->IsConnected()) { if (!readDeviceState(*m_turbine)) { // delete m_turbine; // m_turbine = NULL; // m_turbine = new AdsDevice{m_remoteIp, AmsNetId(m_remoteNetId), m_remotePort}; } } 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_pid <= 0) { m_bFtpRun = TRUE; vLog(LOG_DEBUG, "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_pid, &attr, ryftp_process, this) < 0) { vLog(LOG_ERROR, "create ryftp_process error(%d,%s).\n", errno, strerror(errno)); return TRUE; } char name[17]; snprintf(name, 16, "%s_ftp", GetCurProcessName()); pthread_setname_np(m_pid, 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->IsConnected()) { if (m_bHaveFTP) { //启动时读取一次,后面自己维护序号 if ((m_currentDirNo == -1) && (m_currentFileNo == -1)) { //当前文件和目录都为-1,程序第一次启动。需要获取ftp目录及文件ID readFileID(); } } readRealData(); } } 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) { vLog(LOG_DEBUG, "try to add a route to remote device.\n"); AddRemoteRoute(m_remoteIp, m_localNetId, m_localIp, std::string("isoftstone"), std::string("guest"), std::string("1")); return FALSE; } return TRUE; } BOOLEAN CHostADSBFProcess::readFileID() { int uid = GetCurUnitID(); if (uid < 0 || uid >= UNIT_NUM) return TRUE; AdsVariable> turbineData {*m_turbine, ADSIGRP_IOIMAGE_RWOB, ADSP_READ_ID_REGISTER_ADDRESS}; BYTE buffer[1024]; BYTE *pData = buffer; pData = ((std::array)turbineData).data(); WORD wPathInfoInvalid = (WORD)((pData[1] << 8) | pData[0]); pData += 2; DWORD wCurrentFolderNo = (DWORD)(pData[3] << 24 | pData[2] << 16 | pData[1] << 8 | pData[0]); pData += 4; DWORD wCurrentFileNo = (DWORD)(pData[3] << 24 | pData[2] << 16 | pData[1] << 8 | pData[0]); pData += 4; DWORD wFirstFileNoInFolder = (DWORD)(pData[3] << 24 | pData[2] << 16 | pData[1] << 8 | pData[0]); pData += 4; DWORD wFileCountInFolder = (DWORD)(pData[3] << 24 | pData[2] << 16 | pData[1] << 8 | pData[0]); pData += 4; DWORD wFirstFolderNoRecoverable = (DWORD)(pData[3] << 24 | pData[2] << 16 | pData[1] << 8 | pData[0]); pData += 4; DWORD wFirstFileNoRecoverable = (DWORD)(pData[3] << 24 | pData[2] << 16 | pData[1] << 8 | pData[0]); pData += 4; m_iv = wPathInfoInvalid; if (m_iv) { vLog(LOG_DEBUG, "路径信息无效\n"); return FALSE; } //当前文件夹路径名 m_currentDirNo = wCurrentFolderNo; //当前文件夹下最后新文件 m_currentFileNo = wCurrentFileNo; //当前目录文件开始编号 m_currentDirStartFileNo = wFirstFileNoInFolder; m_curStartDirNo = m_currentDirNo; //当前开始目录 m_curStartFileNo = m_currentFileNo; //当前开始文件 //判断是否有要读取的文件 if (m_curStartDirNo <= m_lastReadDirNo && m_curStartFileNo <= m_lastReadFileNo) { vLog(LOG_DEBUG, "不存在未读的文件。\n"); 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", GetCurProcessName(), dir_count, file_count); } vLog(LOG_DEBUG, "%s 最新文件夹编号: %ld, 最新文件名编号: %ld: 最新文件夹中第一个文件的编号: %ld\n", GetCurProcessName(), 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; AdsVariable> turbineData {*m_turbine, ADSIGRP_IOIMAGE_RWOB, m_adsOverviewDataMemAddr}; BYTE buffer[1024]; BYTE *pData = buffer; BYTE params[MAX_UNIT_POINT_PARAM_SIZE]; BYTE* pParam = params; 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; 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; }