diff --git a/das-dn/CMakeLists.txt b/das-dn/CMakeLists.txt index 4bd84e89..88cc8cca 100644 --- a/das-dn/CMakeLists.txt +++ b/das-dn/CMakeLists.txt @@ -45,14 +45,15 @@ else () message ("else:${CMAKE_C_FLAGS_RELEASE}") endif() -option (HAVE_FTP_PROCESS "use ry ftp" ON) -if (HAVE_FTP_PROCESS) - add_definitions(-DHAVE_FTP_PROCESS) - set (APP_LIBS ${APP_LIBS} curl) -endif () +# option (HAVE_FTP_PROCESS "use ry ftp" ON) +# if (HAVE_FTP_PROCESS) +# add_definitions(-DHAVE_FTP_PROCESS) +# set (APP_LIBS ${APP_LIBS} curl) +# endif () find_package(miniocpp REQUIRED) -target_link_libraries(application PRIVATE miniocpp::miniocpp) +set (APP_LIBS ${APP_LIBS} miniocpp::miniocpp) +# target_link_libraries(application PRIVATE miniocpp::miniocpp) include_directories ( inc @@ -80,8 +81,10 @@ set (APP_SRCS hostiec104/host_iec104.cpp hostmodbusrtu/host_modbus_rtu.cpp hostmodbustcp/host_modbus_tcp.cpp + hostmodbustcpbf/host_modbus_tcp_bf.cpp rtustatusproc/rtustatus.cpp subiec104/sub_iec104.cpp + submodbustcp/sub_modbus_tcp.cpp zjd3100proc/zjd3100pro.cpp minio/ftp2minio.cpp ) @@ -220,12 +223,9 @@ endif () include_directories ("${CMAKE_CURRENT_BINARY_DIR}") link_directories (${LINK_DIR}) -if (UNIX) - set (APP_LIBS ${APP_LIBS} pthread) - set (APP_LIBS ${APP_LIBS} dl) - set (APP_LIBS ${APP_LIBS} rt) - #set (APP_LIBS ${APP_LIBS} websockets) -endif() +set (APP_LIBS ${APP_LIBS} pthread) +set (APP_LIBS ${APP_LIBS} dl) +set (APP_LIBS ${APP_LIBS} rt) #add_link_options (-static) add_executable (application ${APP_SRCS}) diff --git a/das-dn/CMakePresets.json b/das-dn/CMakePresets.json index a24419ba..7b6f5cef 100644 --- a/das-dn/CMakePresets.json +++ b/das-dn/CMakePresets.json @@ -3,10 +3,11 @@ "configurePresets": [ { - "name": "debug", + "name": "default", "binaryDir": "${sourceDir}/build", "cacheVariables": { - "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", + "CMAKE_BUILD_TYPE": "Release" } } ] diff --git a/das-dn/cmg/changemaster.cpp b/das-dn/cmg/changemaster.cpp index 004fc834..b48d847e 100644 --- a/das-dn/cmg/changemaster.cpp +++ b/das-dn/cmg/changemaster.cpp @@ -7,9 +7,8 @@ #include "../rtustatusproc/rtustatus.h" #include "../zjd3100proc/zjd3100pro.h" #include "../minio/ftp2minio.h" -//#include "../bfftpfile2issmqtt/bfftpfile2issmqtt.h" -#ifdef USE_WEBSOCKET -#endif +#include "../hostmodbustcpbf/host_modbus_tcp_bf.h" + BYTE CChangeMaster::m_tcitype; @@ -355,11 +354,6 @@ void CChangeMaster::StartUp(void) vLog(LOG_INFO, "协议<%d>创建为: iec104从协议.\n", i); procs[i] = new CSubIEC104Process(); } - else if (PROTOCOL_FTP2MINIO == config.processes[i].proto) - { - vLog(LOG_INFO, "协议<%d>创建为: FTP读取转MINIO存储协议.\n", i); - procs[i] = new CFtp2MinioProcess(); - } else if (PROTOCOL_LOCAL_DEBUG == config.processes[i].proto) {//Local debug vLog(LOG_INFO, "协议<%d>创建为: 本地调试协议.\n", i); @@ -370,6 +364,21 @@ void CChangeMaster::StartUp(void) vLog(LOG_INFO, "协议<%d>创建为: 网关状态协议.\n", i); procs[i] = new CRTUStatusProcess(); } + else if (PROTOCOL_FTP2MINIO == config.processes[i].proto) + { + vLog(LOG_INFO, "协议<%d>创建为: FTP读取转MINIO存储协议.\n", i); + procs[i] = new CFtp2MinioProcess(); + } + else if (PROTOCOL_HOST_BF_MODBUSTCP == config.processes[i].proto) + { + vLog(LOG_INFO, "协议<%d>创建为: 倍福modbus tcp主协议.\n", i); + procs[i] = new CHostModbusTcpBFProcess(); + } + else if (PROTOCOL_HOST_BF_ADS == config.processes[i].proto) + { + vLog(LOG_INFO, "协议<%d>创建为: 倍福ADS采集协议.\n", i); + //procs[i] = new CHostModbusTcpProcess(); + } else { vLog(LOG_ERROR, "(%s,%d)系统不支持该协议或该协议未知.\n", config.processes[i].name, config.processes[i].proto); diff --git a/das-dn/cmg/main.cpp b/das-dn/cmg/main.cpp index 4b9bb7ca..fd139848 100644 --- a/das-dn/cmg/main.cpp +++ b/das-dn/cmg/main.cpp @@ -221,7 +221,7 @@ int main(int argc, char** argv) } //此处增加一条协议配置 -#if 1 +#if 0 int i; for (i = 0; i < PROCESSES_NUM; i++) { @@ -229,6 +229,7 @@ int main(int argc, char** argv) } memcpy(&config.processes[i], &config.processes[0], sizeof(struProcess)); config.processes[i].proto = PROTOCOL_FTP2MINIO; + snprintf(config.processes[i].option.ftp2minio.ftp.user, sizeof(config.processes[i].option.ftp2minio.ftp.user), "%s", "administrator"); #endif unsigned int m_runCount = 0; unsigned int count = 0; diff --git a/das-dn/hostmodbustcp/host_modbus_tcp.cpp b/das-dn/hostmodbustcp/host_modbus_tcp.cpp index d27d28d9..1c4214fd 100644 --- a/das-dn/hostmodbustcp/host_modbus_tcp.cpp +++ b/das-dn/hostmodbustcp/host_modbus_tcp.cpp @@ -1,1235 +1,10 @@ #include "host_modbus_tcp.h" -#include -#include -#include -#include -#include -#define MODBUSP_READ_ID 100 //读取文件及文件夹ID -#define MODBUSP_READ_ID_FUNCCODE 0x03 //读取文件及文件夹ID功能码。 -#define MODBUSP_READ_ID_REGISTER_ADDRESS 150 //读取文件及文件夹ID寄存器地址。 -#define MODBUSP_READ_ID_REGISTER_LENGTH 9 //读取文件及文件夹ID寄存器长度。 - -typedef std::unordered_map datalen2mbaddrmap; -datalen2mbaddrmap m_datalen2mbaddr_map; - -typedef struct { - short point; - short pos; -} struDataPos; -typedef std::unordered_map datatypeposmap; -typedef std::unordered_map datatypemap; - -typedef struct -{ - int start; - int length; -} FIELDDES; - -struct { - int length; - int address; -} 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 }, - { 2, 312 }, - { 4, 313 }, - { 2, 315 }, - { 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 } -}; - -static int websocket_write(const noPollConn* conn, const char * buffer, int buffer_len) -{ - int result; - result = nopoll_conn_send_text((noPollConn *)conn, (const char *)buffer, buffer_len); - /* ensure we have written all bytes but limit operation to 2 seconds */ - result = nopoll_conn_flush_writes((noPollConn *)conn, 2000000, result); - return (result == buffer_len) ? 0 : -1; -} - -static bool publish_sensor_data(const noPollConn* conn, const char* command, const Json::Value payload) -{ - Json::StreamWriterBuilder builder; - builder["indentation"] = ""; - builder["emitUTF8"] = true; - - Json::Value jsonRoot; - jsonRoot["cmd"] = command; - - char str[128]; - snprintf(str, sizeof(str), "%lld", snowflake_next_id()); - - 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); - int rc = websocket_write(conn, outputConfig.c_str(), outputConfig.length()); - //vLog(LOG_DEBUG, "send cmd: %s, payload: %d\n", command, outputConfig.length()/*, outputConfig.c_str()*/); - if (rc != 0) { - vLog(LOG_DEBUG, "websocket write is error<%d>,insert into database.\n", rc); - //插入数据库 - return false; - } - - return true; -} - -static float GetUnitYCRealFromValue(int uid, int order, DWORD value) -{ - int udb; - float coef; - float base; - struUnit* pUnit; - struUnitYC* pYC; - - if (uid < 0 || uid >= UNIT_NUM) return 0; - pUnit = &config.units[uid]; - if ((pUnit->state & 0x01) != TRUE) return 0; - if (order < 0 || order >= pUnit->yccount) return 0; - pYC = &pUnit->ycs[order]; - udb = pYC->order; - if (udb < 0 || udb >= DATABASE_YC_NUM) { - coef = 1.0f; - base = 0.0f; - } else { - coef = pYC->coef; - base = pYC->base; - } - return (float)(value * coef + base); -} - -BOOLEAN GetUnitYCIsFloat(int uid, int order) -{ - int udb; - float coef = 1.0f; - struUnit* pUnit; - struUnitYC* pYC; - if (uid < 0 || uid >= UNIT_NUM) return 0; - pUnit = &config.units[uid]; - if ((pUnit->state & 0x01) != TRUE) return 0; - if (order < 0 || order >= pUnit->yccount) return 0; - pYC = &pUnit->ycs[order]; - udb = pYC->order; - if (udb < 0 || udb >= DATABASE_YC_NUM) - { - coef = 1.0f; - } - else - { - coef = pYC->coef; - } - - if (fabsf(coef) <= 1E-8) coef = 1.0f; - if (fabsf(coef - 1.0f) <= 1E-8) return FALSE; - return TRUE; -} - -static int GetUnitYXCount(int uid) -{ - if (uid < 0 || uid >= UNIT_NUM) return 0; - return config.units[uid].yxcount; -} - -static int GetUnitYCCount(int uid) -{ - if (uid < 0 || uid >= UNIT_NUM) return 0; - return config.units[uid].yccount; -} - -static BOOLEAN GetUnitYCType(int uid, int order) -{ - struUnit* pUnit; - struUnitYC* pYC; - - if (uid < 0 || uid >= UNIT_NUM) return 0; - pUnit = &config.units[uid]; - if ((pUnit->state & 0x01) != TRUE) return 0; - if (order < 0 || order >= pUnit->yccount) return 0; - pYC = &pUnit->ycs[order]; - return pYC->highSpeed; -} - -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[1], pYC->m_param[2])); -} - -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[1], pYX->m_param[2])); -} - -static BYTE GetUnitYXDataPos(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 (pYX->m_param[3]); -} - -static BOOLEAN GetYCValue(const int order, const FIELDDES* fields, const char* pData, DWORD& value) -{ - if (pData == NULL) return FALSE; - if (fields == NULL) return FALSE; - if (order < 0 || order >= sizeof(m_datalen_mbaddr) / sizeof(m_datalen_mbaddr[0])) return FALSE; - int start = fields[order].start; - if (fields[order].length == sizeof(DWORD)) - { //4字节 - value = *(DWORD *)(pData + start); - return TRUE; - } - else if (fields[order].length == sizeof(WORD)) - { - WORD tmp = *(WORD *)(pData + start); - value = 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 >= 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; - value = FALSE; - return TRUE; - } - - return FALSE; -} - -static bool publishhistoryHighSpeedData(const noPollConn* conn, 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(conn, "historyHighSpeedData", root); - } - return false; -} - -static bool publishhistoryLowSpeedData(const noPollConn* conn, 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 / 1000 * 1000); //取整 - root["deviceId"] = static_units[uid].deviceId; - root["values"] = values; - return publish_sensor_data(conn, "historyLowSpeedData", root); - } - return false; -} - - -#define USE_MEMORY - -#ifdef USE_MEMORY - -struct memory { - char *response; - size_t size; -}; - -static size_t write_callback(void *ptr, size_t size, size_t nmemb, struct memory *mem) { - size_t new_size = mem->size + size * nmemb; - //fprintf(stderr, "mem is: %u", mem->response); - mem->response = (char *)realloc(mem->response, new_size + 1); - if (mem->response == NULL) { - fprintf(stderr, "Failed to allocate memory.\n"); - return 0; // Out of memory - } - memcpy(&(mem->response[mem->size]), ptr, size * nmemb); - mem->size = new_size; - mem->response[new_size] = '\0'; - return size * nmemb; -} - -#else -struct CustomProgress -{ - curl_off_t lastruntime; - CURL *curl; -}; - -static int progressCallback(void* p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) -{ - struct CustomProgress *progress = (struct CustomProgress *)p; - CURL *curl = progress->curl; - curl_off_t curtime = 0; - - curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &curtime); - if ((curtime - progress->lastruntime) >= 3000000) { - progress->lastruntime = curtime; - fprintf(stderr, "Total time: %f\n", curtime); - } - fprintf(stderr, "UP: %ld bytes of %ld bytes, DOWN: %ld bytes of %ld bytes.\n", ulnow, ultotal, dlnow, dltotal); - if (ultotal) fprintf(stderr, "UP progress: %0.2f\n", float(ulnow /ultotal)); - if (dltotal) fprintf(stderr, "DOWN progress: %0.2f\n", float(dlnow /dltotal)); - return 0; -} - -static size_t getContentLengthFunc(void *ptr, size_t size, size_t nmemb, void *stream) -{ - int r; - long len = 0; - - r = sscanf((const char*)ptr, "Content-Length: %ld\n", &len); - if (r) *((long *)stream) = len; - return size * nmemb; -} - -static size_t discardFunc(void *ptr, size_t size, size_t nmemb, void *stream) -{ - return size * nmemb; -} - -static size_t writefunc(void* ptr, size_t size, size_t nmemb, FILE* stream) -{ - return fwrite(ptr, size, nmemb, stream); -} -#endif - -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; -#ifndef USE_MEMORY - FILE *file; - curl_off_t local_file_len = -1; - long filesize = 0; - struct stat file_info; - int use_resume = 0; - - if (stat(local, &file_info) == 0) { - local_file_len = file_info.st_size; - use_resume = 1; - } -#if 0 - file = fopen(local, "ab+"); - if (file == NULL) { - vLog(LOG_ERROR, "open file error(%d,%s)\n", errno, strerror(errno)); - return 0; - } -#endif - 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_HEADERFUNCTION, getContentLengthFunc); - curl_easy_setopt(curl, CURLOPT_HEADERDATA, &filesize); - curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, use_resume ? local_file_len : 0); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); - ret = curl_easy_perform(curl); - fclose(file); -#else - 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); -#endif - curl_easy_cleanup(curl); - curl_global_cleanup(); - - return ret; -} - -static void* ryftp_process(void* param) -{ - if (param == NULL) return ((void*)0); - - CHostModbusTcpProcess* mbt = (CHostModbusTcpProcess *)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* 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地址 - DWORD target_addr = mbt->target_addr; - memset(ipaddress, '\0', sizeof(ipaddress)); - inet_ntop(AF_INET, &target_addr, ipaddress, 16); - - for (int i = 0; i < 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]; - fields[len].start = reinterpret_cast(&t_data.localtime) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.localtime); - len++; - fields[len].start = reinterpret_cast(&t_data.iGenSpeed) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iGenSpeed); - len++; - fields[len].start = reinterpret_cast(&t_data.iGenPower) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iGenPower); - len++; - // - fields[len].start = reinterpret_cast(&t_data.iWindSpeed) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iWindSpeed); - len++; - fields[len].start = reinterpret_cast(&t_data.iVibrationY) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iVibrationY); - len++; - fields[len].start = reinterpret_cast(&t_data.iVibrationZ) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iVibrationZ); - len++; - fields[len].start = reinterpret_cast(&t_data.iTurbineOperationMode) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTurbineOperationMode); - len++; - fields[len].start = reinterpret_cast(&t_data.iBPLevel) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBPLevel); - len++; - fields[len].start = reinterpret_cast(&t_data.iYPLevel) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iYPLevel); - len++; - fields[len].start = reinterpret_cast(&t_data.iWindSpeed_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iWindSpeed_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iGenSpeed_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iGenSpeed_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iGenPower_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iGenPower_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iGenToruqe_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iGenToruqe_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iRotorSpeed) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iRotorSpeed); - len++; - fields[len].start = reinterpret_cast(&t_data.iTheoreticalPower) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTheoreticalPower); - len++; - fields[len].start = reinterpret_cast(&t_data.iReactivePower) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iReactivePower); - len++; - fields[len].start = reinterpret_cast(&t_data.iActivePowerSetPointValue) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iActivePowerSetPointValue); - len++; - fields[len].start = reinterpret_cast(&t_data.iCosPhiSetValue) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iCosPhiSetValue); - len++; - fields[len].start = reinterpret_cast(&t_data.iSetValueGenSpeed) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iSetValueGenSpeed); - len++; - fields[len].start = reinterpret_cast(&t_data.iSetValuePitchAngle) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iSetValuePitchAngle); - len++; - fields[len].start = reinterpret_cast(&t_data.iPitchAngle1RefValue) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iPitchAngle1RefValue); - len++; - fields[len].start = reinterpret_cast(&t_data.iPitchAngle2RefValue) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iPitchAngle2RefValue); - len++; - fields[len].start = reinterpret_cast(&t_data.iPitchAngle3RefValue) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iPitchAngle3RefValue); - len++; - fields[len].start = reinterpret_cast(&t_data.iPitchAngle1) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iPitchAngle1); - len++; - fields[len].start = reinterpret_cast(&t_data.iPitchAngle2) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iPitchAngle2); - len++; - fields[len].start = reinterpret_cast(&t_data.iPitchAngle3) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iPitchAngle3); - len++; - fields[len].start = reinterpret_cast(&t_data.iVaneDirection) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iVaneDirection); - len++; - fields[len].start = reinterpret_cast(&t_data.iWindDirection) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iWindDirection); - len++; - fields[len].start = reinterpret_cast(&t_data.StateWord01) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.StateWord01); - len++; - fields[len].start = reinterpret_cast(&t_data.StateWord02) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.StateWord02); - len++; - fields[len].start = reinterpret_cast(&t_data.StateWord03) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.StateWord03); - len++; - fields[len].start = reinterpret_cast(&t_data.StateWord04) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.StateWord04); - len++; - fields[len].start = reinterpret_cast(&t_data.StateWord05) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.StateWord05); - len++; - fields[len].start = reinterpret_cast(&t_data.StateWord06) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.StateWord06); - len++; - fields[len].start = reinterpret_cast(&t_data.StateWord07) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.StateWord07); - len++; - fields[len].start = reinterpret_cast(&t_data.StateWord08) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.StateWord08); - len++; - fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode01) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.ActiveStatusCode01); - len++; - fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode02) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.ActiveStatusCode02); - len++; - fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode03) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.ActiveStatusCode03); - len++; - fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode04) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.ActiveStatusCode04); - len++; - fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode05) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.ActiveStatusCode05); - len++; - fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode06) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.ActiveStatusCode06); - len++; - fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode07) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.ActiveStatusCode07); - len++; - fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode08) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.ActiveStatusCode08); - len++; - fields[len].start = reinterpret_cast(&t_data.iFrequency) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iFrequency); - len++; - fields[len].start = reinterpret_cast(&t_data.iUL1_690V) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iUL1_690V); - len++; - fields[len].start = reinterpret_cast(&t_data.iUL2_690V) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iUL2_690V); - len++; - fields[len].start = reinterpret_cast(&t_data.iUL3_690V) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iUL3_690V); - len++; - fields[len].start = reinterpret_cast(&t_data.iIL1_690V) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iIL1_690V); - len++; - fields[len].start = reinterpret_cast(&t_data.iIL2_690V) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iIL2_690V); - len++; - fields[len].start = reinterpret_cast(&t_data.iIL3_690V) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iIL3_690V); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade1MotorCurrent) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade1MotorCurrent); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade2MotorCurrent) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade2MotorCurrent); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade3MotorCurrent) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade3MotorCurrent); - len++; - fields[len].start = reinterpret_cast(&t_data.iPitchAngleBk1) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iPitchAngleBk1); - len++; - fields[len].start = reinterpret_cast(&t_data.iPitchAngleBk2) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iPitchAngleBk2); - len++; - fields[len].start = reinterpret_cast(&t_data.iPitchAngleBk3) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iPitchAngleBk3); - len++; - fields[len].start = reinterpret_cast(&t_data.iCosPhi) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iCosPhi); - len++; - fields[len].start = reinterpret_cast(&t_data.iGearPressA) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iGearPressA); - len++; - fields[len].start = reinterpret_cast(&t_data.iGearPressB) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iGearPressB); - len++; - fields[len].start = reinterpret_cast(&t_data.iHydrPress) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iHydrPress); - len++; - fields[len].start = reinterpret_cast(&t_data.iNacellePositionLtd) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iNacellePositionLtd); - len++; - fields[len].start = reinterpret_cast(&t_data.iCableTwistTotal) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iCableTwistTotal); - len++; - fields[len].start = reinterpret_cast(&t_data.iNacellePositionTotal) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iNacellePositionTotal); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempOutdoor_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempOutdoor_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempHub_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempHub_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempNacelle_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempNacelle_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempTowerBase_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempTowerBase_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempCabinetNacelle_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempCabinetNacelle_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempCabinetTowerBase_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempCabinetTowerBase_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempTransformer690_400V_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempTransformer690_400V_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempMV_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempMV_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade1TempMotor_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade1TempMotor_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade2TempMotor_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade2TempMotor_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade3TempMotor_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade3TempMotor_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade1TempBattBox_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade1TempBattBox_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade2TempBattBox_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade2TempBattBox_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade3TempBattBox_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade3TempBattBox_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempCntr_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempCntr_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade1TempInvBox_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade1TempInvBox_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade2TempInvBox_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade2TempInvBox_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade3TempInvBox_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade3TempInvBox_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade1TempPMMHeatsink_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade1TempPMMHeatsink_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade2TempPMMHeatsink_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade2TempPMMHeatsink_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade3TempPMMHeatsink_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade3TempPMMHeatsink_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade1TempPMCHeatsink_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade1TempPMCHeatsink_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade2TempPMCHeatsink_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade2TempPMCHeatsink_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iBlade3TempPMCHeatsink_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iBlade3TempPMCHeatsink_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempRotorBearA_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempRotorBearA_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempRotorBearB_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempRotorBearB_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTemp1GearOil_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTemp1GearOil_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempGearBearDE_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempGearBearDE_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempGearBearNDE_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempGearBearNDE_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempGenBearDE_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempGenBearDE_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempGenBearNDE_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempGenBearNDE_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempGenStatorU_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempGenStatorU_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempGenStatorV_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempGenStatorV_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempGenStatorW_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempGenStatorW_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iTempGenCoolingAir_1sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iTempGenCoolingAir_1sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iAvailabillityToday) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iAvailabillityToday); - len++; - fields[len].start = reinterpret_cast(&t_data.iAvailabillityTotal) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iAvailabillityTotal); - len++; - fields[len].start = reinterpret_cast(&t_data.iKWhThisDay) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iKWhThisDay); - len++; - fields[len].start = reinterpret_cast(&t_data.iKWhOverall) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iKWhOverall); - len++; - fields[len].start = reinterpret_cast(&t_data.iOperationHoursDay) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iOperationHoursDay); - len++; - fields[len].start = reinterpret_cast(&t_data.iOperationHoursOverall) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iOperationHoursOverall); - len++; - fields[len].start = reinterpret_cast(&t_data.iLostKWhThisDay) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iLostKWhThisDay); - len++; - fields[len].start = reinterpret_cast(&t_data.iLostKWhOverall) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iLostKWhOverall); - len++; - fields[len].start = reinterpret_cast(&t_data.FirstTriggeredCode) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.FirstTriggeredCode); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW001) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW001); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW002) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW002); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW003) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW003); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW004) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW004); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW005) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW005); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW006) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW006); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW007) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW007); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW008) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW008); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW009) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW009); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW010) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW010); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW011) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW011); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW012) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW012); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW013) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW013); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW014) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW014); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW015) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW015); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW016) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW016); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW017) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW017); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW018) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW018); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW019) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW019); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW020) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW020); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW021) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW021); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW022) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW022); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW023) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW023); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW024) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW024); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW025) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW025); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW026) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW026); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW027) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW027); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW028) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW028); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW029) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW029); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW030) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW030); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW031) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW031); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW032) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW032); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW033) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW033); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW034) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW034); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW035) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW035); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW036) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW036); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW037) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW037); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW038) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW038); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW039) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW039); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW040) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW040); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW041) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW041); - len++; - fields[len].start = reinterpret_cast(&t_data.SCW042) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.SCW042); - len++; - fields[len].start = reinterpret_cast(&t_data.iGenSpeed_10sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iGenSpeed_10sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iGenSpeed_30sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iGenSpeed_30sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iGenPower_10sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iGenPower_10sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iGenPower_30sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iGenPower_30sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iWindSpeed_10sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iWindSpeed_10sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iWindSpeed_30sec) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iWindSpeed_30sec); - len++; - fields[len].start = reinterpret_cast(&t_data.iAvailablePower) - reinterpret_cast(&t_data); - fields[len].length = sizeof(t_data.iAvailablePower); - len++; - - - //判断是否链接单元 - 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-数据文件序号 - } - } 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-数据文件序号 - } - } - } - 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-数据文件序号 - } - } - - //根据实际配置表将 - 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) - { //读取当前文件 - 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 - { //读取未读的文件 - 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 - int result = ftpget(remote, name, user, password, 3, &chunk); - - if (result == CURLE_OK) { - //成功,处理文件 - vLog(LOG_DEBUG, "get %s to local %s, with name: %s, and password: %s okay.\n", remote, name, user, password); - ftpget_retry_count = 0; - - struRYDeviceData *data = (struRYDeviceData *)chunk.response; - unionCP56Time st; - 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; - st = Time_ttounionCP56Time(localtime); - - //如何将结构化数据传入,且快速获取 - Json::Value highspeedvalues; - for (datatypemap::iterator it = highspeedmap.begin(); it != highspeedmap.end(); it++) { - //获取数据 - DWORD 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; - } - } - publishhistoryHighSpeedData(g_conn, uid, unix_time, highspeedvalues); - - if (i % 25 == 0) { //40ms一个值,每25次位1s - Json::Value lowspeedvalues; - for (datatypemap::iterator it = lowspeedmap.begin(); it != lowspeedmap.end(); it++) { - //获取数据 - DWORD 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; - 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; - } - } - publishhistoryLowSpeedData(g_conn, uid, unix_time, lowspeedvalues); - } - } - - 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, "已读取完成所有未读的文件。\n"); - mbt->m_bHaveUnReadFile = FALSE; - } - } - bReadCurrentFile = TRUE; - } else if (result == CURLE_REMOTE_FILE_NOT_FOUND) { - //文件不存在,尝试60次(1分钟,正常情况下PLC10s生成一个文件) - 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; - } - } - } - - pthread_exit(0); - - return ((void*)0); -} +/////////////////////////////////////////////////////////////////////////////////// +//Valid slave device addresses are in the range of 0 锟?C 247 decimal. // +//The individual slave devices are assigned addresses in the range of 1 锟?C 247. // +//Address 0 is used for the broadcast address, which all slave devices recognize.// +/////////////////////////////////////////////////////////////////////////////////// CHostModbusTcpProcessItem::CHostModbusTcpProcessItem() { @@ -1326,35 +101,10 @@ CHostModbusTcpProcess::CHostModbusTcpProcess() m_nSendPoint = 0; m_nCurBeginReg = 0; m_nNeedSend = FALSE; - - //websocket接口 - m_pid = 0; - //目录无效 - m_iv = 1; - m_currentDirNo = -1; //当前目录编号 - m_currentFileNo = -1; //当前文件编号 - m_lastDirNo = -1; //上一目录编号 - m_lastFileNo = -1; //上一文件编号 - m_bFtpRun = FALSE; } CHostModbusTcpProcess::~CHostModbusTcpProcess() { - if (m_bHaveFTP) - { - m_bFtpRun = FALSE; - vLog(LOG_DEBUG, "保存本协议读取到的那个目录和文件\n"); - char fileName[260]; - snprintf(fileName, sizeof(fileName), "hostmodbustcp_%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); - } - } } CNetProcessItem *CHostModbusTcpProcess::CreateItem(int ord) @@ -1499,7 +249,7 @@ void CHostModbusTcpProcess::calc2(void) ymframes[1].RegCount = option.modbus.ym2Count; } //按寄存器排序 - pItem->AddFrames(yxframes, ycframes, ymframes); + pItem->AddFrames(ycframes, ymframes, yxframes); continue; } } @@ -1661,7 +411,7 @@ void CHostModbusTcpProcess::calc2(void) } } //按寄存器排序 - pItem->AddFrames(yxframes, ycframes, ymframes); + pItem->AddFrames(ycframes, ymframes, yxframes); } } } @@ -1670,63 +420,9 @@ BOOLEAN CHostModbusTcpProcess::OnPreCreate(int id) { if (!CNetProcess::OnPreCreate(id)) return FALSE; - if (!GetOption(&m_nOptions, sizeof(m_nOptions))) - { - vLog(LOG_DEBUG, "润阳modbus读取配置错误。"); - return FALSE; - } - - m_bHaveFTP = m_nOptions.bHaveFTP; m_nTimeout = 200; calc2(); - - 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); - - vLog(LOG_DEBUG, "file size is: %d\n", sizeof(struRYDeviceData) * 250 / 1024); - //读取文件 - m_lastReadDirNo = 1; - m_lastReadFileNo = 1; - m_lastReadDirStartFileNo = 1; - m_bHaveUnReadFile = TRUE; - - char fileName[260]; - snprintf(fileName, sizeof(fileName), "hostmodbustcp_%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; } @@ -1787,8 +483,6 @@ BOOLEAN CHostModbusTcpProcess::Run(void) pItem->m_nNum++; m_nSendPoint = system32.ticks;//0; m_nNeedSend = FALSE; - - //fprintf(stderr, "tx<%d>: ", count+6); for (int a = 0; a < count+6; a++) fprintf(stderr, "%02X ", buffer[a]); fprintf(stderr, "\n"); FeedDog(); } } @@ -1829,19 +523,6 @@ BOOLEAN CHostModbusTcpProcess::OnTimer(void) pItem = (CHostModbusTcpProcessItem *)GetNextItem(); if (pItem == NULL) return TRUE; m_nNeedSend = TRUE; - - if (m_bHaveFTP) - { //启动时读取一次,后面自己维护序号 - if ((m_currentDirNo == -1) && (m_currentFileNo == -1)) - { //当前文件和目录都为-1,程序第一次启动。需要获取ftp目录及文件ID - m_nFrameType = MODBUSP_READ_ID; - m_nCurFuncCode = MODBUSP_READ_ID_FUNCCODE; - m_nCurBeginReg = MODBUSP_READ_ID_REGISTER_ADDRESS; - m_nCurRegCount = MODBUSP_READ_ID_REGISTER_LENGTH; - pItem->m_nFramePoll |= MODBUSP_GET_DATA_FRAME; - return TRUE; - } - } struModbusExtFrame* frame = pItem->GetNextFrame(); if (frame != NULL) { @@ -2251,10 +932,6 @@ BOOLEAN CHostModbusTcpProcess::OnReceiveData(CHostModbusTcpProcessItem *pItem, B { return OnReceiveYMData(pItem, &pData[3], count); } - else if (m_nCurFrame == MODBUSP_READ_ID) - { - return OnReceiveIDData(pItem, &pData[3], count); - } else if (m_nCurFrame == MODBUSP_YK_EXECUTE) { SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_EXEED, YKR_SUCC); @@ -2296,61 +973,6 @@ BOOLEAN CHostModbusTcpProcess::OnReceiveData(CHostModbusTcpProcessItem *pItem, B return FALSE; } -BOOLEAN CHostModbusTcpProcess::OnReceiveIDData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count) -{ - int uid; - BYTE* pBuf; - - if (pItem == NULL) return FALSE; - uid = pItem->GetUnitID(); - if (uid < 0) return FALSE; - - pBuf = pData; - -/* - 1)、路径信息是否有效 byte; - 2)、当前文件夹路径名的后缀 dint,按照顺序增加1(转字符串时在前补0); - 3)、当前文件夹下最后新文件的编号 dint; - 4)、当前文件夹下第一个文件的编号 dint; - 5)、当前文件夹下文件个数 dint; -*/ - //路径有效性判断 - int iv = ((pBuf[0] << 8) | pBuf[1]); pBuf += 2; - - m_iv = iv; - if (iv) { - vLog(LOG_DEBUG, "路径信息无效\n"); - return FALSE; - } - //当前文件夹路径名 - m_currentDirNo = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); pBuf += 4; - //当前文件夹下最后新文件 - m_currentFileNo = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); pBuf += 4; - //当前目录文件开始编号 - m_currentDirStartFileNo = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); pBuf += 4; - - - 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, "总共有%d个目录的%d个文件未读取。\n", dir_count, file_count); - } - /*文件从保存的最后读取的文件目录的文件一直督导当前开始目录*/ - vLog(LOG_DEBUG, "最新文件夹编号: %ld, 最新文件名编号: %ld: 最新文件夹中第一个文件的编号: %ld\n", m_currentDirNo, m_currentFileNo, m_currentDirStartFileNo); - - return TRUE; -} - BOOLEAN CHostModbusTcpProcess::OnReceiveYXData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count) { int uid; @@ -2461,7 +1083,6 @@ BOOLEAN CHostModbusTcpProcess::OnReceiveYCData(CHostModbusTcpProcessItem *pItem, reg_count = pParam[3]; value_type = pParam[4]; sign_mark = pParam[5]; - //vLog(LOG_DEBUG, "here count is: %d, value type is: %d, and ", reg_count, value_type); if ((1 == reg_count) && (2 == value_type)) { //16位归一化值 if (2 == value_type) @@ -2469,7 +1090,6 @@ BOOLEAN CHostModbusTcpProcess::OnReceiveYCData(CHostModbusTcpProcessItem *pItem, if (sign_mark == 0) nValue = (DWORD)(WORD)((pBuf[0] << 8) | pBuf[1]); else nValue = (DWORD)(short)((pBuf[0] << 8) | pBuf[1]); SetUnitYC(uid, point, (LONG)nValue); - //vLog(LOG_DEBUG, "value is: %ld.\n", nValue); } else if (8 == value_type) { @@ -2500,7 +1120,6 @@ BOOLEAN CHostModbusTcpProcess::OnReceiveYCData(CHostModbusTcpProcessItem *pItem, { //归一化值,高位在第一个寄存器 nValue = (DWORD)(pBuf[0] << 24 | pBuf[1] << 16 | pBuf[2] << 8 | pBuf[3]); SetUnitYC(uid, point, (LONG)nValue); - //vLog(LOG_DEBUG, "value is: %ld.\n", nValue); } else if (4 == value_type) { //归一化值,高位在第二个寄存器 diff --git a/das-dn/hostmodbustcp/host_modbus_tcp.h b/das-dn/hostmodbustcp/host_modbus_tcp.h index 622abedc..3e5698c0 100644 --- a/das-dn/hostmodbustcp/host_modbus_tcp.h +++ b/das-dn/hostmodbustcp/host_modbus_tcp.h @@ -4,172 +4,6 @@ #include "netproc.h" #include "modbus_def.h" -#include -#include -#include - -#pragma pack(1) -typedef struct { - QLONG localtime;// PLC本地时间 8 none 0.0001 毫秒 little endian 系统 - WORD iGenSpeed;// 发电机转速 2 200 0.1 转/分 40ms 控制系统 - WORD iGenPower;// 机组有功功率 2 201 0.1 千瓦 40ms 控制系统 - WORD iWindSpeed;// 风速 2 202 0.01 米/秒 40ms 气象 - WORD iVibrationY;// 机舱振动前后方向 2 203 0.001 米/秒^2 40ms 机舱 - WORD iVibrationZ;// 机舱振动左右方向 2 204 0.001 米/秒^2 40ms 机舱 - WORD iTurbineOperationMode;// 运行模式 2 205 1 需要解析 1s 控制系统 - WORD iBPLevel;// 刹车等级 2 206 1 需要解析 1s 控制系统 - WORD iYPLevel;// 偏航运行模式 2 207 1 需要解析 1s 控制系统 - WORD iWindSpeed_1sec;// 风速1秒均值 2 208 0.01 米/秒 1s 控制系统 - WORD iGenSpeed_1sec;// 发电机转速1秒均值 2 209 0.1 转/分 1s 控制系统 - WORD iGenPower_1sec;// 机组有功1秒均值 2 210 0.1 千瓦 1s 控制系统 - WORD iGenToruqe_1sec;// 发电机扭矩1秒均值 2 211 0.1 牛米 1s 控制系统 - WORD iRotorSpeed;// 风轮转速 2 212 0.1 转/分 1s 控制系统 - WORD iTheoreticalPower;// 理论有功功率 2 213 0.1 千瓦 1s 控制系统 - WORD iReactivePower;// 无功功率 2 214 0.1 千乏 1s 控制系统 - WORD iActivePowerSetPointValue;// 有功设定值 2 215 0.1 千瓦 1s 控制系统 - WORD iCosPhiSetValue;// 功率因数设定值 2 216 0.001 . 1s 控制系统 - WORD iSetValueGenSpeed;// 发电机转速设定值 2 217 0.1 转/分 1s 控制系统 - WORD iSetValuePitchAngle;// 桨叶角度设定值 2 218 0.01 度 1s 控制系统 - WORD iPitchAngle1RefValue;// 桨叶1角度给定 2 219 0.01 度 1s 控制系统 - WORD iPitchAngle2RefValue;// 桨叶2角度给定 2 220 0.01 度 1s 控制系统 - WORD iPitchAngle3RefValue;// 桨叶3角度给定 2 221 0.01 度 1s 控制系统 - WORD iPitchAngle1;// 桨叶1角度 2 222 0.01 度 1s 变桨系统 - WORD iPitchAngle2;// 桨叶2角度 2 223 0.01 度 1s 变桨系统 - WORD iPitchAngle3;// 桨叶3角度 2 224 0.01 度 1s 变桨系统 - WORD iVaneDirection;// 机舱方向 2 225 0.1 度 1s 气象 - WORD iWindDirection;// 风向(与机舱夹角) 2 226 0.1 度 1s 气象 - WORD StateWord01;// 状态字01 2 227 1 需要解析 1s 控制系统 详细解析见 状态字解析 - WORD StateWord02;// 状态字02 2 228 1 需要解析 1s 控制系统 - WORD StateWord03;// 状态字03 2 229 1 需要解析 1s 控制系统 - WORD StateWord04;// 状态字04 2 230 1 需要解析 1s 控制系统 - WORD StateWord05;// 状态字05 2 231 1 需要解析 1s 控制系统 - WORD StateWord06;// 状态字06 2 232 1 需要解析 1s 控制系统 - WORD StateWord07;// 状态字07 2 233 1 需要解析 1s 控制系统 - WORD StateWord08;// 状态字08 2 234 1 需要解析 1s 控制系统 - DWORD ActiveStatusCode01;// 故障代码01 4 235 1 需要解析 1s 控制系统 代表目前已经触发的故障代码类似:02(HH)04(HL)005(L) - DWORD ActiveStatusCode02;// 故障代码02 4 237 1 需要解析 1s 控制系统 详细解析见故障代码字解析 - DWORD ActiveStatusCode03;// 故障代码03 4 239 1 需要解析 1s 控制系统 - DWORD ActiveStatusCode04;// 故障代码04 4 241 1 需要解析 1s 控制系统 - DWORD ActiveStatusCode05;// 故障代码05 4 243 1 需要解析 1s 控制系统 - DWORD ActiveStatusCode06;// 故障代码06 4 245 1 需要解析 1s 控制系统 - DWORD ActiveStatusCode07;// 故障代码07 4 247 1 需要解析 1s 控制系统 - DWORD ActiveStatusCode08;// 故障代码08 4 249 1 需要解析 1s 控制系统 - WORD iFrequency;// 电网频率 2 251 0.01 赫兹 1s 电网 - WORD iUL1_690V;// 电网L1相电压 2 252 0.1 伏 1s 电网 - WORD iUL2_690V;// 电网L2相电压 2 253 0.1 伏 1s 电网 - WORD iUL3_690V;// 电网L3相电压 2 254 0.1 伏 1s 电网 - WORD iIL1_690V;// 电网L1相电流 2 255 0.1 安 1s 电网 - WORD iIL2_690V;// 电网L2相电流 2 256 0.1 安 1s 电网 - WORD iIL3_690V;// 电网L3相电流 2 257 0.1 安 1s 电网 - WORD iBlade1MotorCurrent;// 变桨电机1电流 2 258 0.1 安 1s 变桨系统 - WORD iBlade2MotorCurrent;// 变桨电机2电流 2 259 0.1 安 1s 变桨系统 - WORD iBlade3MotorCurrent;// 变桨电机3电流 2 260 0.1 安 1s 变桨系统 - WORD iPitchAngleBk1;// 备用桨叶角度1 2 261 0.01 度 1s 变桨系统 - WORD iPitchAngleBk2;// 备用桨叶角度2 2 262 0.01 度 1s 变桨系统 - WORD iPitchAngleBk3;// 备用桨叶角度3 2 263 0.01 度 1s 变桨系统 - WORD iCosPhi;// 并网点功率因数 2 264 0.001 . 1s 电网 - WORD iGearPressA;// 齿轮箱油压A 2 265 0.1 巴 1s 齿轮箱 - WORD iGearPressB;// 齿轮箱油压B 2 266 0.1 巴 1s 齿轮箱 - WORD iHydrPress;// 液压系统压力 2 267 0.1 巴 1s 液压系统 - WORD iNacellePositionLtd;// 机舱绝对方向 2 268 0.1 度 1s 机舱 - WORD iCableTwistTotal;// 总扭缆角度 2 269 0.1 度 1s 机舱 - WORD iNacellePositionTotal;// 机舱方向 2 270 0.1 度 1s 机舱 - WORD iTempOutdoor_1sec;// 环境温度 2 271 0.1 摄氏度 1s 环境 - WORD iTempHub_1sec;// 轮毂内温度 2 272 0.1 摄氏度 1s 轮毂 - WORD iTempNacelle_1sec;// 机舱内温度 2 273 0.1 摄氏度 1s 机舱 - WORD iTempTowerBase_1sec;// 塔基内温度 2 274 0.1 摄氏度 1s 塔基 - WORD iTempCabinetNacelle_1sec;// 机舱柜内温度 2 275 0.1 摄氏度 1s 机舱 - WORD iTempCabinetTowerBase_1sec;// 塔基柜内温度 2 276 0.1 摄氏度 1s 塔基 - WORD iTempTransformer690_400V_1sec;// 400伏变压器温度 2 277 0.1 摄氏度 1s 塔基 - WORD iTempMV_1sec;// 箱变温度 2 278 0.1 摄氏度 1s 箱变 - WORD iBlade1TempMotor_1sec;// 变桨电机1温度 2 279 0.1 摄氏度 1s 变桨系统 - WORD iBlade2TempMotor_1sec;// 变桨电机2温度 2 280 0.1 摄氏度 1s 变桨系统 - WORD iBlade3TempMotor_1sec;// 变桨电机3温度 2 281 0.1 摄氏度 1s 变桨系统 - WORD iBlade1TempBattBox_1sec;// 变桨电池柜1温度 2 282 0.1 摄氏度 1s 变桨系统 - WORD iBlade2TempBattBox_1sec;// 变桨电池柜2温度 2 283 0.1 摄氏度 1s 变桨系统 - WORD iBlade3TempBattBox_1sec;// 变桨电池柜3温度 2 284 0.1 摄氏度 1s 变桨系统 - WORD iTempCntr_1sec;// 变桨中控箱温度 2 285 0.1 摄氏度 1s 变桨系统 - WORD iBlade1TempInvBox_1sec;// 变桨逆变器1温度 2 286 0.1 摄氏度 1s 变桨系统 - WORD iBlade2TempInvBox_1sec;// 变桨逆变器2温度 2 287 0.1 摄氏度 1s 变桨系统 - WORD iBlade3TempInvBox_1sec;// 变桨逆变器3温度 2 288 0.1 摄氏度 1s 变桨系统 - WORD iBlade1TempPMMHeatsink_1sec;// 变桨PMM1散热器温度 2 289 0.1 摄氏度 1s 变桨系统 - WORD iBlade2TempPMMHeatsink_1sec;// 变桨PMM2散热器温度 2 290 0.1 摄氏度 1s 变桨系统 - WORD iBlade3TempPMMHeatsink_1sec;// 变桨PMM3散热器温度 2 291 0.1 摄氏度 1s 变桨系统 - WORD iBlade1TempPMCHeatsink_1sec;// 变桨PMC1散热器温度 2 292 0.1 摄氏度 1s 变桨系统 - WORD iBlade2TempPMCHeatsink_1sec;// 变桨PMC2散热器温度 2 293 0.1 摄氏度 1s 变桨系统 - WORD iBlade3TempPMCHeatsink_1sec;// 变桨PMC3散热器温度 2 294 0.1 摄氏度 1s 变桨系统 - WORD iTempRotorBearA_1sec;// 主轴承A温度 2 295 0.1 摄氏度 1s 传动链 - WORD iTempRotorBearB_1sec;// 主轴承B温度 2 296 0.1 摄氏度 1s 传动链 - WORD iTemp1GearOil_1sec;// 齿轮箱油温 2 297 0.1 摄氏度 1s 齿轮箱 - WORD iTempGearBearDE_1sec;// 齿轮箱驱动齿轴承温度 2 298 0.1 摄氏度 1s 齿轮箱 - WORD iTempGearBearNDE_1sec;// 齿轮箱非驱动侧轴承温度 2 299 0.1 摄氏度 1s 发电机 - WORD iTempGenBearDE_1sec;// 发电机驱动侧轴承温度 2 300 0.1 摄氏度 1s 发电机 - WORD iTempGenBearNDE_1sec;// 发电机非驱动侧轴承温度 2 301 0.1 摄氏度 1s 发电机 - WORD iTempGenStatorU_1sec;// 发电机绕组U温度 2 302 0.1 摄氏度 1s 发电机 - WORD iTempGenStatorV_1sec;// 发电机绕组V温度 2 303 0.1 摄氏度 1s 发电机 - WORD iTempGenStatorW_1sec;// 发电机绕组W温度 2 304 0.1 摄氏度 1s 发电机 - WORD iTempGenCoolingAir_1sec;// 发电机冷却风温度 2 305 0.1 摄氏度 1s 发电机 - WORD iAvailabillityToday;// 当天可利用率 2 306 0.001 . 1s 控制系统 - WORD iAvailabillityTotal;// 总可利用率 2 307 0.001 . 1s 控制系统 - DWORD iKWhThisDay;// 当天发电量 2 308 千瓦时 1s 控制系统 - DWORD iKWhOverall;// 总发电量 2 310 千瓦时 1s 控制系统 - WORD iOperationHoursDay;// 当天发电小时数 2 312 小时 1s 控制系统 - DWORD iOperationHoursOverall;// 总发电小时数 2 313 小时 1s 控制系统 - WORD iLostKWhThisDay;// 当天损失发电量 2 315 千瓦时 1s 控制系统 - DWORD iLostKWhOverall;// 总损失发电量 2 316 千瓦时 1s 控制系统 - DWORD FirstTriggeredCode;// 首触故障代码高 4 318 1 1s 控制系统 详细解析见故障代码字解析 - WORD SCW001;// 故障代码字01 2 320 1 1s 控制系统 - WORD SCW002;// 故障代码字02 2 321 1 1s 控制系统 - WORD SCW003;// 故障代码字03 2 322 1 1s 控制系统 - WORD SCW004;// 故障代码字04 2 323 1 1s 控制系统 - WORD SCW005;// 故障代码字05 2 324 1 1s 控制系统 - WORD SCW006;// 故障代码字06 2 325 1 1s 控制系统 - WORD SCW007;// 故障代码字07 2 326 1 1s 控制系统 - WORD SCW008;// 故障代码字08 2 327 1 1s 控制系统 - WORD SCW009;// 故障代码字09 2 328 1 1s 控制系统 - WORD SCW010;// 故障代码字10 2 329 1 1s 控制系统 - WORD SCW011;// 故障代码字11 2 330 1 1s 控制系统 - WORD SCW012;// 故障代码字12 2 331 1 1s 控制系统 - WORD SCW013;// 故障代码字13 2 332 1 1s 控制系统 - WORD SCW014;// 故障代码字14 2 333 1 1s 控制系统 - WORD SCW015;// 故障代码字15 2 334 1 1s 控制系统 - WORD SCW016;// 故障代码字16 2 335 1 1s 控制系统 - WORD SCW017;// 故障代码字17 2 336 1 1s 控制系统 - WORD SCW018;// 故障代码字18 2 337 1 1s 控制系统 - WORD SCW019;// 故障代码字19 2 338 1 1s 控制系统 - WORD SCW020;// 故障代码字20 2 339 1 1s 控制系统 - WORD SCW021;// 故障代码字21 2 340 1 1s 控制系统 - WORD SCW022;// 故障代码字22 2 341 1 1s 控制系统 - WORD SCW023;// 故障代码字23 2 342 1 1s 控制系统 - WORD SCW024;// 故障代码字24 2 343 1 1s 控制系统 - WORD SCW025;// 故障代码字25 2 344 1 1s 控制系统 - WORD SCW026;// 故障代码字26 2 345 1 1s 控制系统 - WORD SCW027;// 故障代码字27 2 346 1 1s 控制系统 - WORD SCW028;// 故障代码字28 2 347 1 1s 控制系统 - WORD SCW029;// 故障代码字29 2 348 1 1s 控制系统 - WORD SCW030;// 故障代码字30 2 349 1 1s 控制系统 - WORD SCW031;// 故障代码字31 2 350 1 1s 控制系统 - WORD SCW032;// 故障代码字32 2 351 1 1s 控制系统 - WORD SCW033;// 故障代码字33 2 352 1 1s 控制系统 - WORD SCW034;// 故障代码字34 2 353 1 1s 控制系统 - WORD SCW035;// 故障代码字35 2 354 1 1s 控制系统 - WORD SCW036;// 故障代码字36 2 355 1 1s 控制系统 - WORD SCW037;// 故障代码字37 2 356 1 1s 控制系统 - WORD SCW038;// 故障代码字38 2 357 1 1s 控制系统 - WORD SCW039;// 故障代码字39 2 358 1 1s 控制系统 - WORD SCW040;// 故障代码字40 2 359 1 1s 控制系统 - WORD SCW041;// 故障代码字41 2 360 1 1s 控制系统 - WORD SCW042;// 故障代码字42 2 361 1 1s 控制系统 - WORD iGenSpeed_10sec;// 发电机转速10秒均值 2 362 - WORD iGenSpeed_30sec;// 发电机转速30秒均值 2 363 - WORD iGenPower_10sec;// 机组有功10秒均值 2 364 - WORD iGenPower_30sec;// 机组有功30秒均值 2 365 - WORD iWindSpeed_10sec;// 风速10秒均值 2 366 - WORD iWindSpeed_30sec;// 风速30秒均值 2 367 - WORD iAvailablePower;// 可用有功功率 2 368 -} struRYDeviceData; -#pragma pack() - class CHostModbusTcpProcessItem : public CNetProcessItem { public: @@ -217,48 +51,6 @@ private: void calc2(void); void sort1(STRUCT_PARAM*, int); //功能码排序 void sort2(STRUCT_PARAM*, int); //寄存地址排序 - - struRYModbusOption m_nOptions; - //增加websocket连接 - pthread_t m_pid; - short m_uid; - -public: - BOOLEAN m_bHaveFTP; //存在FTP协议 - - //ftp参数信息 - char m_user[64]; - char m_password[64]; - char m_remotePath[128]; - char m_localPath[128]; - - //文件信息 - int m_iv; - LONG m_currentDirNo; //当前目录编号 - LONG m_currentFileNo; //当前文件编号 - LONG m_lastDirNo; //上一目录编号 - LONG m_lastFileNo; //上一文件编号 - LONG m_currentDirStartFileNo; //当前目录文件开始编号 - - LONG m_lastReadDirNo; //最后获取的目录编号 - LONG m_lastReadFileNo; //最后获取的文件编号 - LONG m_lastReadDirStartFileNo; //最后获取的目录文件开始编号 - LONG m_curStartDirNo; //当前获取的目录编号 - LONG m_curStartFileNo; //当前获取的文件编号 - BOOLEAN m_bHaveUnReadFile; //存在未读的文件 - BOOLEAN m_bFtpRun; - - - int _mkdir(const char* pathName) { - if (access(pathName, F_OK) == 0) return 0; - // 创建目录 - if (mkdir(pathName, 0777) == -1) { - vLog(LOG_ERROR, "创建文件夹 %s失败<%d,%s>\r\n", pathName, errno, strerror(errno)); - return -1; - } - return 1; - } - public: CHostModbusTcpProcess(); virtual ~CHostModbusTcpProcess(); @@ -278,9 +70,6 @@ public: BOOLEAN OnReceiveData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count); int OnPackageReceived(BYTE* pBuf, int count, int ord /* = -1 */); - - virtual BOOLEAN OnReceiveIDData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count); - virtual BOOLEAN OnReceiveYXData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count); virtual BOOLEAN OnReceiveYCData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count); virtual BOOLEAN OnReceiveYMData(CHostModbusTcpProcessItem *pItem, BYTE* pData, int count); diff --git a/das-dn/hostmodbustcpbf/host_modbus_tcp_bf.cpp b/das-dn/hostmodbustcpbf/host_modbus_tcp_bf.cpp new file mode 100644 index 00000000..bddcfac7 --- /dev/null +++ b/das-dn/hostmodbustcpbf/host_modbus_tcp_bf.cpp @@ -0,0 +1,2662 @@ +#include "host_modbus_tcp_bf.h" +#include +#include +#include +#include +#include + +#define MODBUSP_READ_ID 100 //读取文件及文件夹ID +#define MODBUSP_READ_ID_FUNCCODE 0x03 //读取文件及文件夹ID功能码。 +#define MODBUSP_READ_ID_REGISTER_ADDRESS 150 //读取文件及文件夹ID寄存器地址。 +#define MODBUSP_READ_ID_REGISTER_LENGTH 9 //读取文件及文件夹ID寄存器长度。 + +typedef std::unordered_map datalen2mbaddrmap; +datalen2mbaddrmap m_datalen2mbaddr_map; + +typedef struct { + short point; + short pos; +} struDataPos; +typedef std::unordered_map datatypeposmap; +typedef std::unordered_map datatypemap; + +typedef struct +{ + int start; + int length; +} FIELDDES; + +struct { + int length; + int address; +} 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 }, + { 2, 312 }, + { 4, 313 }, + { 2, 315 }, + { 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 } +}; + +static int websocket_write(const noPollConn* conn, const char * buffer, int buffer_len) +{ + int result; + result = nopoll_conn_send_text((noPollConn *)conn, (const char *)buffer, buffer_len); + /* ensure we have written all bytes but limit operation to 2 seconds */ + result = nopoll_conn_flush_writes((noPollConn *)conn, 2000000, result); + return (result == buffer_len) ? 0 : -1; +} + +static bool publish_sensor_data(const noPollConn* conn, const char* command, const Json::Value payload) +{ + Json::StreamWriterBuilder builder; + builder["indentation"] = ""; + builder["emitUTF8"] = true; + + Json::Value jsonRoot; + jsonRoot["cmd"] = command; + + char str[128]; + snprintf(str, sizeof(str), "%lld", snowflake_next_id()); + + 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); + int rc = websocket_write(conn, outputConfig.c_str(), outputConfig.length()); + //vLog(LOG_DEBUG, "send cmd: %s, payload: %d\n", command, outputConfig.length()/*, outputConfig.c_str()*/); + if (rc != 0) { + vLog(LOG_DEBUG, "websocket write is error<%d>,insert into database.\n", rc); + //插入数据库 + return false; + } + + return true; +} + +static float GetUnitYCRealFromValue(int uid, int order, DWORD value) +{ + int udb; + float coef; + float base; + struUnit* pUnit; + struUnitYC* pYC; + + if (uid < 0 || uid >= UNIT_NUM) return 0; + pUnit = &config.units[uid]; + if ((pUnit->state & 0x01) != TRUE) return 0; + if (order < 0 || order >= pUnit->yccount) return 0; + pYC = &pUnit->ycs[order]; + udb = pYC->order; + if (udb < 0 || udb >= DATABASE_YC_NUM) { + coef = 1.0f; + base = 0.0f; + } else { + coef = pYC->coef; + base = pYC->base; + } + return (float)(value * coef + base); +} + +BOOLEAN GetUnitYCIsFloat(int uid, int order) +{ + int udb; + float coef = 1.0f; + struUnit* pUnit; + struUnitYC* pYC; + if (uid < 0 || uid >= UNIT_NUM) return 0; + pUnit = &config.units[uid]; + if ((pUnit->state & 0x01) != TRUE) return 0; + if (order < 0 || order >= pUnit->yccount) return 0; + pYC = &pUnit->ycs[order]; + udb = pYC->order; + if (udb < 0 || udb >= DATABASE_YC_NUM) + { + coef = 1.0f; + } + else + { + coef = pYC->coef; + } + + if (fabsf(coef) <= 1E-8) coef = 1.0f; + if (fabsf(coef - 1.0f) <= 1E-8) return FALSE; + return TRUE; +} + +static int GetUnitYXCount(int uid) +{ + if (uid < 0 || uid >= UNIT_NUM) return 0; + return config.units[uid].yxcount; +} + +static int GetUnitYCCount(int uid) +{ + if (uid < 0 || uid >= UNIT_NUM) return 0; + return config.units[uid].yccount; +} + +static BOOLEAN GetUnitYCType(int uid, int order) +{ + struUnit* pUnit; + struUnitYC* pYC; + + if (uid < 0 || uid >= UNIT_NUM) return 0; + pUnit = &config.units[uid]; + if ((pUnit->state & 0x01) != TRUE) return 0; + if (order < 0 || order >= pUnit->yccount) return 0; + pYC = &pUnit->ycs[order]; + return pYC->highSpeed; +} + +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[1], pYC->m_param[2])); +} + +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[1], pYX->m_param[2])); +} + +static BYTE GetUnitYXDataPos(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 (pYX->m_param[3]); +} + +static BOOLEAN GetYCValue(const int order, const FIELDDES* fields, const char* pData, DWORD& value) +{ + if (pData == NULL) return FALSE; + if (fields == NULL) return FALSE; + if (order < 0 || order >= sizeof(m_datalen_mbaddr) / sizeof(m_datalen_mbaddr[0])) return FALSE; + int start = fields[order].start; + if (fields[order].length == sizeof(DWORD)) + { //4字节 + value = *(DWORD *)(pData + start); + return TRUE; + } + else if (fields[order].length == sizeof(WORD)) + { + WORD tmp = *(WORD *)(pData + start); + value = 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 >= 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; + value = FALSE; + return TRUE; + } + + return FALSE; +} + +static bool publishhistoryHighSpeedData(const noPollConn* conn, 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(conn, "historyHighSpeedData", root); + } + return false; +} + +static bool publishhistoryLowSpeedData(const noPollConn* conn, 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 / 1000 * 1000); //取整 + root["deviceId"] = static_units[uid].deviceId; + root["values"] = values; + return publish_sensor_data(conn, "historyLowSpeedData", root); + } + return false; +} + + +#define USE_MEMORY + +#ifdef USE_MEMORY + +struct memory { + char *response; + size_t size; +}; + +static size_t write_callback(void *ptr, size_t size, size_t nmemb, struct memory *mem) { + size_t new_size = mem->size + size * nmemb; + //fprintf(stderr, "mem is: %u", mem->response); + mem->response = (char *)realloc(mem->response, new_size + 1); + if (mem->response == NULL) { + fprintf(stderr, "Failed to allocate memory.\n"); + return 0; // Out of memory + } + memcpy(&(mem->response[mem->size]), ptr, size * nmemb); + mem->size = new_size; + mem->response[new_size] = '\0'; + return size * nmemb; +} + +#else +struct CustomProgress +{ + curl_off_t lastruntime; + CURL *curl; +}; + +static int progressCallback(void* p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) +{ + struct CustomProgress *progress = (struct CustomProgress *)p; + CURL *curl = progress->curl; + curl_off_t curtime = 0; + + curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &curtime); + if ((curtime - progress->lastruntime) >= 3000000) { + progress->lastruntime = curtime; + fprintf(stderr, "Total time: %f\n", curtime); + } + fprintf(stderr, "UP: %ld bytes of %ld bytes, DOWN: %ld bytes of %ld bytes.\n", ulnow, ultotal, dlnow, dltotal); + if (ultotal) fprintf(stderr, "UP progress: %0.2f\n", float(ulnow /ultotal)); + if (dltotal) fprintf(stderr, "DOWN progress: %0.2f\n", float(dlnow /dltotal)); + return 0; +} + +static size_t getContentLengthFunc(void *ptr, size_t size, size_t nmemb, void *stream) +{ + int r; + long len = 0; + + r = sscanf((const char*)ptr, "Content-Length: %ld\n", &len); + if (r) *((long *)stream) = len; + return size * nmemb; +} + +static size_t discardFunc(void *ptr, size_t size, size_t nmemb, void *stream) +{ + return size * nmemb; +} + +static size_t writefunc(void* ptr, size_t size, size_t nmemb, FILE* stream) +{ + return fwrite(ptr, size, nmemb, stream); +} +#endif + +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; +#ifndef USE_MEMORY + FILE *file; + curl_off_t local_file_len = -1; + long filesize = 0; + struct stat file_info; + int use_resume = 0; + + if (stat(local, &file_info) == 0) { + local_file_len = file_info.st_size; + use_resume = 1; + } +#if 0 + file = fopen(local, "ab+"); + if (file == NULL) { + vLog(LOG_ERROR, "open file error(%d,%s)\n", errno, strerror(errno)); + return 0; + } +#endif + 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_HEADERFUNCTION, getContentLengthFunc); + curl_easy_setopt(curl, CURLOPT_HEADERDATA, &filesize); + curl_easy_setopt(curl, CURLOPT_RESUME_FROM_LARGE, use_resume ? local_file_len : 0); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, file); + ret = curl_easy_perform(curl); + fclose(file); +#else + 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); +#endif + curl_easy_cleanup(curl); + curl_global_cleanup(); + + return ret; +} + +static void* ryftp_process(void* param) +{ + if (param == NULL) return ((void*)0); + + CHostModbusTcpBFProcess* mbt = (CHostModbusTcpBFProcess *)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* 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地址 + DWORD target_addr = mbt->target_addr; + memset(ipaddress, '\0', sizeof(ipaddress)); + inet_ntop(AF_INET, &target_addr, ipaddress, 16); + + for (int i = 0; i < 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]; + fields[len].start = reinterpret_cast(&t_data.localtime) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.localtime); + len++; + fields[len].start = reinterpret_cast(&t_data.iGenSpeed) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iGenSpeed); + len++; + fields[len].start = reinterpret_cast(&t_data.iGenPower) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iGenPower); + len++; + // + fields[len].start = reinterpret_cast(&t_data.iWindSpeed) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iWindSpeed); + len++; + fields[len].start = reinterpret_cast(&t_data.iVibrationY) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iVibrationY); + len++; + fields[len].start = reinterpret_cast(&t_data.iVibrationZ) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iVibrationZ); + len++; + fields[len].start = reinterpret_cast(&t_data.iTurbineOperationMode) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTurbineOperationMode); + len++; + fields[len].start = reinterpret_cast(&t_data.iBPLevel) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBPLevel); + len++; + fields[len].start = reinterpret_cast(&t_data.iYPLevel) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iYPLevel); + len++; + fields[len].start = reinterpret_cast(&t_data.iWindSpeed_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iWindSpeed_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iGenSpeed_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iGenSpeed_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iGenPower_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iGenPower_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iGenToruqe_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iGenToruqe_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iRotorSpeed) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iRotorSpeed); + len++; + fields[len].start = reinterpret_cast(&t_data.iTheoreticalPower) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTheoreticalPower); + len++; + fields[len].start = reinterpret_cast(&t_data.iReactivePower) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iReactivePower); + len++; + fields[len].start = reinterpret_cast(&t_data.iActivePowerSetPointValue) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iActivePowerSetPointValue); + len++; + fields[len].start = reinterpret_cast(&t_data.iCosPhiSetValue) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iCosPhiSetValue); + len++; + fields[len].start = reinterpret_cast(&t_data.iSetValueGenSpeed) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iSetValueGenSpeed); + len++; + fields[len].start = reinterpret_cast(&t_data.iSetValuePitchAngle) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iSetValuePitchAngle); + len++; + fields[len].start = reinterpret_cast(&t_data.iPitchAngle1RefValue) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iPitchAngle1RefValue); + len++; + fields[len].start = reinterpret_cast(&t_data.iPitchAngle2RefValue) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iPitchAngle2RefValue); + len++; + fields[len].start = reinterpret_cast(&t_data.iPitchAngle3RefValue) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iPitchAngle3RefValue); + len++; + fields[len].start = reinterpret_cast(&t_data.iPitchAngle1) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iPitchAngle1); + len++; + fields[len].start = reinterpret_cast(&t_data.iPitchAngle2) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iPitchAngle2); + len++; + fields[len].start = reinterpret_cast(&t_data.iPitchAngle3) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iPitchAngle3); + len++; + fields[len].start = reinterpret_cast(&t_data.iVaneDirection) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iVaneDirection); + len++; + fields[len].start = reinterpret_cast(&t_data.iWindDirection) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iWindDirection); + len++; + fields[len].start = reinterpret_cast(&t_data.StateWord01) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.StateWord01); + len++; + fields[len].start = reinterpret_cast(&t_data.StateWord02) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.StateWord02); + len++; + fields[len].start = reinterpret_cast(&t_data.StateWord03) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.StateWord03); + len++; + fields[len].start = reinterpret_cast(&t_data.StateWord04) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.StateWord04); + len++; + fields[len].start = reinterpret_cast(&t_data.StateWord05) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.StateWord05); + len++; + fields[len].start = reinterpret_cast(&t_data.StateWord06) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.StateWord06); + len++; + fields[len].start = reinterpret_cast(&t_data.StateWord07) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.StateWord07); + len++; + fields[len].start = reinterpret_cast(&t_data.StateWord08) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.StateWord08); + len++; + fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode01) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.ActiveStatusCode01); + len++; + fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode02) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.ActiveStatusCode02); + len++; + fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode03) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.ActiveStatusCode03); + len++; + fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode04) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.ActiveStatusCode04); + len++; + fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode05) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.ActiveStatusCode05); + len++; + fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode06) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.ActiveStatusCode06); + len++; + fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode07) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.ActiveStatusCode07); + len++; + fields[len].start = reinterpret_cast(&t_data.ActiveStatusCode08) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.ActiveStatusCode08); + len++; + fields[len].start = reinterpret_cast(&t_data.iFrequency) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iFrequency); + len++; + fields[len].start = reinterpret_cast(&t_data.iUL1_690V) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iUL1_690V); + len++; + fields[len].start = reinterpret_cast(&t_data.iUL2_690V) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iUL2_690V); + len++; + fields[len].start = reinterpret_cast(&t_data.iUL3_690V) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iUL3_690V); + len++; + fields[len].start = reinterpret_cast(&t_data.iIL1_690V) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iIL1_690V); + len++; + fields[len].start = reinterpret_cast(&t_data.iIL2_690V) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iIL2_690V); + len++; + fields[len].start = reinterpret_cast(&t_data.iIL3_690V) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iIL3_690V); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade1MotorCurrent) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade1MotorCurrent); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade2MotorCurrent) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade2MotorCurrent); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade3MotorCurrent) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade3MotorCurrent); + len++; + fields[len].start = reinterpret_cast(&t_data.iPitchAngleBk1) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iPitchAngleBk1); + len++; + fields[len].start = reinterpret_cast(&t_data.iPitchAngleBk2) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iPitchAngleBk2); + len++; + fields[len].start = reinterpret_cast(&t_data.iPitchAngleBk3) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iPitchAngleBk3); + len++; + fields[len].start = reinterpret_cast(&t_data.iCosPhi) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iCosPhi); + len++; + fields[len].start = reinterpret_cast(&t_data.iGearPressA) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iGearPressA); + len++; + fields[len].start = reinterpret_cast(&t_data.iGearPressB) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iGearPressB); + len++; + fields[len].start = reinterpret_cast(&t_data.iHydrPress) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iHydrPress); + len++; + fields[len].start = reinterpret_cast(&t_data.iNacellePositionLtd) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iNacellePositionLtd); + len++; + fields[len].start = reinterpret_cast(&t_data.iCableTwistTotal) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iCableTwistTotal); + len++; + fields[len].start = reinterpret_cast(&t_data.iNacellePositionTotal) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iNacellePositionTotal); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempOutdoor_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempOutdoor_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempHub_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempHub_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempNacelle_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempNacelle_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempTowerBase_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempTowerBase_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempCabinetNacelle_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempCabinetNacelle_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempCabinetTowerBase_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempCabinetTowerBase_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempTransformer690_400V_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempTransformer690_400V_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempMV_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempMV_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade1TempMotor_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade1TempMotor_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade2TempMotor_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade2TempMotor_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade3TempMotor_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade3TempMotor_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade1TempBattBox_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade1TempBattBox_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade2TempBattBox_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade2TempBattBox_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade3TempBattBox_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade3TempBattBox_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempCntr_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempCntr_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade1TempInvBox_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade1TempInvBox_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade2TempInvBox_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade2TempInvBox_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade3TempInvBox_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade3TempInvBox_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade1TempPMMHeatsink_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade1TempPMMHeatsink_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade2TempPMMHeatsink_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade2TempPMMHeatsink_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade3TempPMMHeatsink_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade3TempPMMHeatsink_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade1TempPMCHeatsink_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade1TempPMCHeatsink_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade2TempPMCHeatsink_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade2TempPMCHeatsink_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iBlade3TempPMCHeatsink_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iBlade3TempPMCHeatsink_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempRotorBearA_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempRotorBearA_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempRotorBearB_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempRotorBearB_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTemp1GearOil_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTemp1GearOil_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempGearBearDE_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempGearBearDE_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempGearBearNDE_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempGearBearNDE_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempGenBearDE_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempGenBearDE_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempGenBearNDE_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempGenBearNDE_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempGenStatorU_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempGenStatorU_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempGenStatorV_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempGenStatorV_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempGenStatorW_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempGenStatorW_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iTempGenCoolingAir_1sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iTempGenCoolingAir_1sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iAvailabillityToday) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iAvailabillityToday); + len++; + fields[len].start = reinterpret_cast(&t_data.iAvailabillityTotal) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iAvailabillityTotal); + len++; + fields[len].start = reinterpret_cast(&t_data.iKWhThisDay) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iKWhThisDay); + len++; + fields[len].start = reinterpret_cast(&t_data.iKWhOverall) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iKWhOverall); + len++; + fields[len].start = reinterpret_cast(&t_data.iOperationHoursDay) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iOperationHoursDay); + len++; + fields[len].start = reinterpret_cast(&t_data.iOperationHoursOverall) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iOperationHoursOverall); + len++; + fields[len].start = reinterpret_cast(&t_data.iLostKWhThisDay) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iLostKWhThisDay); + len++; + fields[len].start = reinterpret_cast(&t_data.iLostKWhOverall) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iLostKWhOverall); + len++; + fields[len].start = reinterpret_cast(&t_data.FirstTriggeredCode) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.FirstTriggeredCode); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW001) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW001); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW002) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW002); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW003) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW003); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW004) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW004); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW005) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW005); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW006) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW006); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW007) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW007); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW008) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW008); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW009) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW009); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW010) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW010); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW011) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW011); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW012) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW012); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW013) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW013); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW014) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW014); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW015) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW015); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW016) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW016); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW017) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW017); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW018) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW018); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW019) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW019); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW020) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW020); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW021) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW021); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW022) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW022); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW023) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW023); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW024) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW024); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW025) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW025); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW026) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW026); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW027) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW027); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW028) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW028); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW029) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW029); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW030) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW030); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW031) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW031); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW032) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW032); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW033) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW033); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW034) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW034); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW035) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW035); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW036) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW036); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW037) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW037); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW038) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW038); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW039) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW039); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW040) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW040); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW041) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW041); + len++; + fields[len].start = reinterpret_cast(&t_data.SCW042) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.SCW042); + len++; + fields[len].start = reinterpret_cast(&t_data.iGenSpeed_10sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iGenSpeed_10sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iGenSpeed_30sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iGenSpeed_30sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iGenPower_10sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iGenPower_10sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iGenPower_30sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iGenPower_30sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iWindSpeed_10sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iWindSpeed_10sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iWindSpeed_30sec) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iWindSpeed_30sec); + len++; + fields[len].start = reinterpret_cast(&t_data.iAvailablePower) - reinterpret_cast(&t_data); + fields[len].length = sizeof(t_data.iAvailablePower); + len++; + + + //判断是否链接单元 + 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-数据文件序号 + } + } 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-数据文件序号 + } + } + } + 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-数据文件序号 + } + } + + //根据实际配置表将 + 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) + { //读取当前文件 + 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 + { //读取未读的文件 + 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 + int result = ftpget(remote, name, user, password, 3, &chunk); + + if (result == CURLE_OK) { + //成功,处理文件 + vLog(LOG_DEBUG, "get %s to local %s, with name: %s, and password: %s okay.\n", remote, name, user, password); + ftpget_retry_count = 0; + + struRYDeviceData *data = (struRYDeviceData *)chunk.response; + unionCP56Time st; + 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; + st = Time_ttounionCP56Time(localtime); + + //如何将结构化数据传入,且快速获取 + Json::Value highspeedvalues; + for (datatypemap::iterator it = highspeedmap.begin(); it != highspeedmap.end(); it++) { + //获取数据 + DWORD 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; + } + } + publishhistoryHighSpeedData(g_conn, uid, unix_time, highspeedvalues); + + if (i % 25 == 0) { //40ms一个值,每25次位1s + Json::Value lowspeedvalues; + for (datatypemap::iterator it = lowspeedmap.begin(); it != lowspeedmap.end(); it++) { + //获取数据 + DWORD 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; + 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; + } + } + publishhistoryLowSpeedData(g_conn, uid, unix_time, lowspeedvalues); + } + } + + 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, "已读取完成所有未读的文件。\n"); + mbt->m_bHaveUnReadFile = FALSE; + } + } + bReadCurrentFile = TRUE; + } else if (result == CURLE_REMOTE_FILE_NOT_FOUND) { + //文件不存在,尝试60次(1分钟,正常情况下PLC10s生成一个文件) + 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; + } + } + } + + pthread_exit(0); + + return ((void*)0); +} + +CHostModbusTcpBFProcessItem::CHostModbusTcpBFProcessItem() +{ + m_nNum = 0; + m_nFramePoll = 0; + apdu_t0_begin = 1; + m_nCurFrame = 0; + + memset(m_nModbusFrames, 0, sizeof(m_nModbusFrames)); +} + +CHostModbusTcpBFProcessItem::~CHostModbusTcpBFProcessItem() +{ + m_nNum = 0; + m_nFramePoll = 0; + apdu_t0_begin = 1; + m_nCurFrame = 0; + + memset(m_nModbusFrames, 0, sizeof(m_nModbusFrames)); +} + +void CHostModbusTcpBFProcessItem::AddFrames(struModbusExtFrame* yxs, struModbusExtFrame* ycs, struModbusExtFrame* yms) +{ + int i = 0, j = 0; + memset(m_nModbusFrames, 0, sizeof(m_nModbusFrames)); + for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++) + { + if (yxs[j].FrameType == 0 || yxs[j].FuncCode == 0 || yxs[j].RegCount == 0) continue; + memcpy(&m_nModbusFrames[i], &yxs[j], sizeof(struModbusExtFrame)); + i++; + if (i >= MODBUS_RTU_AUTOMATIC_FRAME_MAX) break; + } + for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++) + { + if (ycs[j].FrameType == 0 || ycs[j].FuncCode == 0 || ycs[j].RegCount == 0) continue; + memcpy(&m_nModbusFrames[i], &ycs[j], sizeof(struModbusExtFrame)); + i++; + if (i >= MODBUS_RTU_AUTOMATIC_FRAME_MAX) break; + } + for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++) + { + if (yms[j].FrameType == 0 || yms[j].FuncCode == 0 || yms[j].RegCount == 0) continue; + memcpy(&m_nModbusFrames[i], &yms[j], sizeof(struModbusExtFrame)); + i++; + if (i >= MODBUS_RTU_AUTOMATIC_FRAME_MAX) break; + } +} + +struModbusExtFrame* CHostModbusTcpBFProcessItem::GetNextFrame(void) +{ + int last; + + if (m_nCurFrame >= MODBUS_RTU_AUTOMATIC_FRAME_MAX) return NULL; + if (m_nCurFrame < 0) m_nCurFrame = -1; + + last = m_nCurFrame; + for (m_nCurFrame++; m_nCurFrame < MODBUS_RTU_AUTOMATIC_FRAME_MAX; m_nCurFrame++) + { + if (m_nModbusFrames[m_nCurFrame].FuncCode == 0 || m_nModbusFrames[m_nCurFrame].FrameType == 0) break; + return &m_nModbusFrames[m_nCurFrame]; + } + for (m_nCurFrame = 0; m_nCurFrame <= last; m_nCurFrame++) + { + if (m_nModbusFrames[m_nCurFrame].FuncCode == 0 || m_nModbusFrames[m_nCurFrame].FrameType == 0) break; + return &m_nModbusFrames[m_nCurFrame]; + } + return NULL; +} + +void CHostModbusTcpBFProcessItem::Attach(int uid, int sock, DWORD peer_addr, WORD peer_port) +{ + CNetProcessItem::Attach(uid, sock, peer_addr, peer_port); + apdu_t0_begin = 1; + m_nNum = 0; + m_nFramePoll = 0; + m_nCurFrame = 0; +} + +void CHostModbusTcpBFProcessItem::Release(void) +{ + apdu_t0_begin = 1; + m_nNum = 0; + m_nFramePoll = 0; + m_nCurFrame = 0; + + CNetProcessItem::Release(); +} + +CHostModbusTcpBFProcess::CHostModbusTcpBFProcess() +{ + m_nCount = 0; + m_nFrameCount = 0; + m_nCurFrame = 0; + m_nSendPoint = 0; + m_nCurBeginReg = 0; + m_nNeedSend = FALSE; + + //websocket接口 + m_pid = 0; + //目录无效 + m_iv = 1; + m_currentDirNo = -1; //当前目录编号 + m_currentFileNo = -1; //当前文件编号 + m_lastDirNo = -1; //上一目录编号 + m_lastFileNo = -1; //上一文件编号 + m_bFtpRun = FALSE; +} + +CHostModbusTcpBFProcess::~CHostModbusTcpBFProcess() +{ + if (m_bHaveFTP) + { + m_bFtpRun = FALSE; + vLog(LOG_DEBUG, "保存本协议读取到的那个目录和文件\n"); + char fileName[260]; + snprintf(fileName, sizeof(fileName), "hostmodbustcp_%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); + } + } +} + +CNetProcessItem *CHostModbusTcpBFProcess::CreateItem(int ord) +{ + return dynamic_cast(new CHostModbusTcpBFProcessItem); +} + +void CHostModbusTcpBFProcess::DestroyItem(int ord, BOOLEAN bDeleted /* = FALSE */) +{ + CHostModbusTcpBFProcessItem *pItem = (CHostModbusTcpBFProcessItem *)GetItem(ord); + if (pItem != NULL && !bDeleted) + { + delete pItem; + return CNetProcess::DestroyItem(ord, TRUE); + } + + return CNetProcess::DestroyItem(ord, bDeleted); +} + +void CHostModbusTcpBFProcess::sort1(STRUCT_PARAM *params, int count) +{ + int i, j, n; + STRUCT_PARAM temp; + n = count; + for (i = 0; i < n - 1; ++i) //比较n-1轮 + { + for (j = 0; j < n - 1 - i; ++j) //每轮比较n-1-i次, + { + if (params[j].param[0] > params[j + 1].param[0]) + { + memcpy(&temp, ¶ms[j], sizeof(STRUCT_PARAM)); + memcpy(¶ms[j], ¶ms[j + 1], sizeof(STRUCT_PARAM)); + memcpy(¶ms[j + 1], &temp, sizeof(STRUCT_PARAM)); + } + } + } +} + +void CHostModbusTcpBFProcess::sort2(STRUCT_PARAM *params, int count) +{ + int i, j, n; + STRUCT_PARAM temp; + n = count; + for (i = 0; i < n - 1; ++i) //比较n-1轮 + { + for (j = 0; j < n - 1 - i; ++j) //每轮比较n-1-i次, + { + int addr1 = (int)MAKEWORD(params[j].param[1], params[j].param[2]); + int addr2 = (int)MAKEWORD(params[j+1].param[1], params[j+1].param[2]); + if (addr1 > addr2) + { + memcpy(&temp, ¶ms[j], sizeof(STRUCT_PARAM)); + memcpy(¶ms[j], ¶ms[j + 1], sizeof(STRUCT_PARAM)); + memcpy(¶ms[j + 1], &temp, sizeof(STRUCT_PARAM)); + } + } + } +} + +void CHostModbusTcpBFProcess::calc2(void) +{ + int i, j, n, uid; + BYTE addr; + CHostModbusTcpBFProcessItem *pItem; + + for (i = 0; i < PROCESS_UNIT_NUM; i++) + { + pItem = (CHostModbusTcpBFProcessItem *)GetItem(i); + if (NULL == pItem) continue; + uid = pItem->GetUnitID(); + if (uid < 0 || uid >= UNIT_NUM) continue; + + if (GetUnitAddr(uid, &addr, 1)) + { //获取单元地址成功,则该段原地址采用配置地址,否则该单元为无效地址。 + pItem->m_addr = addr; + } + struModbusExtFrame ycframes[MODBUS_RTU_AUTOMATIC_FRAME]; + struModbusExtFrame ymframes[MODBUS_RTU_AUTOMATIC_FRAME]; + struModbusExtFrame yxframes[MODBUS_RTU_AUTOMATIC_FRAME]; + memset(ycframes, 0, sizeof(ycframes)); + memset(ymframes, 0, sizeof(ymframes)); + memset(yxframes, 0, sizeof(yxframes)); + struUnitModbusOption option; + if (GetUnitOption(uid, &option, sizeof(option))) + { + if (option.use_owner_config) + { //采用协议配置 + if (option.modbus.yx1Enable) + { + yxframes[0].FrameType = MODBUSP_READ_YX1; + yxframes[0].FuncCode = option.modbus.yx1FuncCode; + yxframes[0].RegBegin = option.modbus.yx1Begin; + yxframes[0].RegCount = option.modbus.yx1Count; + } + if (option.modbus.yx2Enable) + { + yxframes[1].FrameType = MODBUSP_READ_YX1; + yxframes[1].FuncCode = option.modbus.yx2FuncCode; + yxframes[1].RegBegin = option.modbus.yx2Begin; + yxframes[1].RegCount = option.modbus.yx2Count; + } + if (option.modbus.yc1Enable) + { + ycframes[0].FrameType = MODBUSP_READ_YC1; + ycframes[0].FuncCode = option.modbus.yc1FuncCode; + ycframes[0].RegBegin = option.modbus.yc1Begin; + ycframes[0].RegCount = option.modbus.yc1Count; + } + if (option.modbus.yc2Enable) + { + ycframes[1].FrameType = MODBUSP_READ_YC1; + ycframes[1].FuncCode = option.modbus.yc2FuncCode; + ycframes[1].RegBegin = option.modbus.yc2Begin; + ycframes[1].RegCount = option.modbus.yc2Count; + } + if (option.modbus.yc3Enable) + { + ycframes[2].FrameType = MODBUSP_READ_YC1; + ycframes[2].FuncCode = option.modbus.yc3FuncCode; + ycframes[2].RegBegin = option.modbus.yc3Begin; + ycframes[2].RegCount = option.modbus.yc3Count; + } + if (option.modbus.yc4Enable) + { + ycframes[3].FrameType = MODBUSP_READ_YC1; + ycframes[3].FuncCode = option.modbus.yc4FuncCode; + ycframes[3].RegBegin = option.modbus.yc4Begin; + ycframes[3].RegCount = option.modbus.yc4Count; + } + if (option.modbus.ym1Enable) + { + ymframes[0].FrameType = MODBUSP_READ_YM1; + ymframes[0].FuncCode = option.modbus.ym1FuncCode; + ymframes[0].RegBegin = option.modbus.ym1Begin; + ymframes[0].RegCount = option.modbus.ym1Count; + } + if (option.modbus.ym2Enable) + { + ymframes[1].FrameType = MODBUSP_READ_YM1; + ymframes[1].FuncCode = option.modbus.ym2FuncCode; + ymframes[1].RegBegin = option.modbus.ym2Begin; + ymframes[1].RegCount = option.modbus.ym2Count; + } + //按寄存器排序 + pItem->AddFrames(yxframes, ycframes, ymframes); + continue; + } + } + { + int yccount, ymcount, yxcount; + yccount = GetUnitYCCount(uid); + ymcount = GetUnitYMCount(uid); + yxcount = GetUnitYXCount(uid); + + STRUCT_PARAM *ycparam = NULL, *ymparam = NULL, *yxparam = NULL; + if (yccount) ycparam = new STRUCT_PARAM[yccount]; + if (ymcount) ymparam = new STRUCT_PARAM[ymcount]; + if (yxcount) yxparam = new STRUCT_PARAM[yxcount]; + + if (ycparam) + { + memset(ycparam, 0, sizeof(STRUCT_PARAM) * yccount); + for (n = 0; n < yccount; n++) + { + memcpy(ycparam[n].param, GetUnitYCParamByPoint(uid, n), sizeof(STRUCT_PARAM)); + } + //按功能码排序 + sort1(ycparam, yccount); + //按寄存器地址排序 + sort2(ycparam, yccount); + //组帧 + for (n = 0; n < yccount; n++) + { + WORD addr = MAKEWORD(ycparam[n].param[1], ycparam[n].param[2]); + if (addr >= 65535) continue; + for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++) + { + if (ycframes[j].FuncCode == 0) + { + ycframes[j].FrameType = MODBUSP_READ_YC1; + ycframes[j].FuncCode = ycparam[n].param[0]; + ycframes[j].RegBegin = addr; + ycframes[j].RegCount = ycparam[n].param[3]; + break; + } + if (ycframes[j].FuncCode == ycparam[n].param[0]) + { + if (addr <= MODBUS_MAX_WORD_REGISTER_NUM + ycframes[j].RegBegin) + { + int len = addr - ycframes[j].RegBegin; + if (len) + { + ycframes[j].RegCount = len + ycparam[n].param[3]; + } + else + { + vLog(LOG_DEBUG, "遥测测点配置了相同的功能码和寄存器地址\n"); + } + break; + } + } + } + } + } + if (ymparam) + { + memset(ymparam, 0, sizeof(STRUCT_PARAM) * ymcount); + for (n = 0; n < ymcount; n++) + { + memcpy(ymparam[n].param, GetUnitYMParamByPoint(uid, n), sizeof(STRUCT_PARAM)); + } + sort1(ymparam, ymcount); + sort2(ymparam, ymcount); + //组帧 + for (n = 0; n < ymcount; n++) + { + WORD addr = MAKEWORD(ymparam[n].param[1], ymparam[n].param[2]); + if (addr >= 65535) continue; + for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++) + { + if (ymframes[j].FuncCode == 0) + { + ymframes[j].FrameType = MODBUSP_READ_YM1; + ymframes[j].FuncCode = ymparam[n].param[0]; + ymframes[j].RegBegin = addr; + ymframes[j].RegCount = ymparam[n].param[3]; + break; + } + if (ymframes[j].FuncCode == ymparam[n].param[0]) + { + if (addr <= MODBUS_MAX_WORD_REGISTER_NUM + ymframes[j].RegBegin) + { + int len = addr - ymframes[j].RegBegin; + if (len) + { + ymframes[j].RegCount = len + ymparam[n].param[3]; + } + else + { + vLog(LOG_DEBUG, "遥脉测点配置了相同的功能码和寄存器地址\n"); + } + break; + } + } + } + } + } + if (yxparam) + { + memset(yxparam, 0, sizeof(STRUCT_PARAM) * yxcount); + for (n = 0; n < yxcount; n++) + { + memcpy(yxparam[n].param, GetUnitYXParamByPoint(uid, n), sizeof(STRUCT_PARAM)); + } + sort1(yxparam, yxcount); + sort2(yxparam, yxcount); + //组帧 + for (n = 0; n < yxcount; n++) + { + WORD addr = MAKEWORD(yxparam[n].param[1], yxparam[n].param[2]); + if (addr >= 65535) continue; + for (j = 0; j < MODBUS_RTU_AUTOMATIC_FRAME; j++) + { + if (yxframes[j].FuncCode == 0) + { + yxframes[j].FrameType = MODBUSP_READ_YX1; + yxframes[j].FuncCode = yxparam[n].param[0]; + yxframes[j].RegBegin = addr; + yxframes[j].RegCount = 1; + break; + } + if (yxframes[j].FuncCode == yxparam[n].param[0]) + { + int len = addr - yxframes[j].RegBegin; + if (len) + { + if (yxframes[j].FuncCode == MODBUSC_F01 || yxframes[j].FuncCode == MODBUSC_F02) + { + if (addr <= MODBUS_MAX_BITMAP_REGISTER_NUM + yxframes[j].RegBegin) + { + yxframes[j].RegCount = len + 1; + break; + } + } + else if (yxframes[j].FuncCode == MODBUSC_F03 || yxframes[j].FuncCode == MODBUSC_F04) + { + if (addr <= MODBUS_MAX_WORD_REGISTER_NUM + yxframes[j].RegBegin) + { + yxframes[j].RegCount = len + 1; + break; + } + } + } + else + { + if (yxframes[j].FuncCode == MODBUSC_F01 || yxframes[j].FuncCode == MODBUSC_F02) + { + vLog(LOG_DEBUG, "遥信测点配置了相同的功能码和寄存器地址\n"); + } + break; + } + } + } + } + } + //按寄存器排序 + pItem->AddFrames(yxframes, ycframes, ymframes); + } + } +} + +BOOLEAN CHostModbusTcpBFProcess::OnPreCreate(int id) +{ + if (!CNetProcess::OnPreCreate(id)) return FALSE; + + if (!GetOption(&m_nOptions, sizeof(m_nOptions))) + { + vLog(LOG_DEBUG, "润阳modbus读取配置错误。"); + return FALSE; + } + + m_bHaveFTP = m_nOptions.bHaveFTP; + m_nTimeout = 200; + calc2(); + + 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); + + vLog(LOG_DEBUG, "file size is: %d\n", sizeof(struRYDeviceData) * 250 / 1024); + //读取文件 + m_lastReadDirNo = 1; + m_lastReadFileNo = 1; + m_lastReadDirStartFileNo = 1; + m_bHaveUnReadFile = TRUE; + + char fileName[260]; + snprintf(fileName, sizeof(fileName), "hostmodbustcp_%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 CHostModbusTcpBFProcess::Run(void) +{ + int count; + BYTE buffer[512]; + + if (!CNetProcess::Run()) return FALSE; + FeedDog(); + + //process polling command + CHostModbusTcpBFProcessItem *pItem = (CHostModbusTcpBFProcessItem *)GetItem(0); + if (NULL == pItem) return TRUE; + if (pItem->GetSock() < 0) { + usleep(20000); + return TRUE; + } + + pItem = (CHostModbusTcpBFProcessItem *)GetCurItem(); + if (NULL == pItem) return TRUE; + + buffer[0] = HIBYTE(pItem->m_nNum); buffer[1] = LOBYTE(pItem->m_nNum); + buffer[2] = 0; buffer[3] = MB_TCP_PROTOCOL_ID; + if ((m_nCurFrame == 0 && m_nNeedSend)) + { + count = 0; + if (GetYKFrame(pItem, &buffer[6], count, m_nCurFrame, m_nCurFuncCode)) + { //insert yk command + } + else if (GetYTFrame(pItem, &buffer[6], count, m_nCurFrame, m_nCurFuncCode)) + { //insert yt command + } + else if (pItem->m_nFramePoll & MODBUSP_SET_TIME_FRAME) + { + pItem->m_nFramePoll &= ~MODBUSP_SET_TIME_FRAME; + if (GetSetTimeFrame(pItem, &buffer[6], count)) + { + m_nCurFrame = 0; + } + } + else if (pItem->m_nFramePoll & MODBUSP_GET_DATA_FRAME) + { + pItem->m_nFramePoll &= ~MODBUSP_GET_DATA_FRAME; + if (GetReadDataFrame(pItem, &buffer[6], count)) + { + m_nCurFrame = m_nFrameType; + } + } + if (count >= 2) + { //发送前清除接收缓冲区所有数据 + buffer[4] = HIBYTE(count); + buffer[5] = LOBYTE(count); + if (WriteData(buffer, count + 6, 0)) + { + DisplayTxData(buffer, count + 6, TRUE); + } + pItem->m_nNum++; + m_nSendPoint = system32.ticks;//0; + m_nNeedSend = FALSE; + + //fprintf(stderr, "tx<%d>: ", count+6); for (int a = 0; a < count+6; a++) fprintf(stderr, "%02X ", buffer[a]); fprintf(stderr, "\n"); + FeedDog(); + } + } + + return TRUE; +} + +BOOLEAN CHostModbusTcpBFProcess::OnTimer(void) +{ + CHostModbusTcpBFProcessItem *pItem; + + if (!CNetProcess::OnTimer()) return FALSE; + + m_nCount++; + pItem = (CHostModbusTcpBFProcessItem *)GetItem(0); + if (NULL == pItem) return FALSE; + if (pItem->GetSock() < 0) + { + if ((pItem->apdu_t0_begin + 30) < system32.timers) + { + pItem->apdu_t0_begin = system32.timers; + Connect(pItem, 0, TRUE); + } + return TRUE; + } + + if (m_nCurFrame != 0) + { + if (m_nSendPoint && (m_nSendPoint + m_nTimeout) <= system32.ticks) + { //0.5 second command time out + m_nSendPoint = 0; + m_nCurFrame = 0; + } + } + + if (m_nCurFrame == 0 && (m_nCount % PollGap()) == 0) + { + pItem = (CHostModbusTcpBFProcessItem *)GetNextItem(); + if (pItem == NULL) return TRUE; + m_nNeedSend = TRUE; + + if (m_bHaveFTP) + { //启动时读取一次,后面自己维护序号 + if ((m_currentDirNo == -1) && (m_currentFileNo == -1)) + { //当前文件和目录都为-1,程序第一次启动。需要获取ftp目录及文件ID + m_nFrameType = MODBUSP_READ_ID; + m_nCurFuncCode = MODBUSP_READ_ID_FUNCCODE; + m_nCurBeginReg = MODBUSP_READ_ID_REGISTER_ADDRESS; + m_nCurRegCount = MODBUSP_READ_ID_REGISTER_LENGTH; + pItem->m_nFramePoll |= MODBUSP_GET_DATA_FRAME; + return TRUE; + } + } + struModbusExtFrame* frame = pItem->GetNextFrame(); + if (frame != NULL) + { + m_nFrameType = frame->FrameType; + m_nCurFuncCode = frame->FuncCode; + m_nCurBeginReg = frame->RegBegin; + m_nCurRegCount = frame->RegCount; + pItem->m_nFramePoll |= MODBUSP_GET_DATA_FRAME; + return TRUE; + } + } + + return TRUE; +} + +BOOLEAN CHostModbusTcpBFProcess::GetYKFrame(CHostModbusTcpBFProcessItem *pItem, BYTE* pBuf, int& count, DWORD& frame, BYTE& FuncCode) +{ + int uid; + BYTE result; + BYTE* pData; + + if (NULL == pItem) return FALSE; + uid = pItem->GetUnitID(); + if (uid < 0 || uid >= UNIT_NUM) return FALSE; + if (NULL == pBuf) return FALSE; + + pData = pBuf; + if (!GetUnitYK(uid, m_nYKOrder, m_bYKValue, m_nYKState, result)) + { + return FALSE; + } + + vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is %s result is %s.\n", uid, m_nYKOrder, (m_bYKValue ? "ClOSE" : "TRIP"), val_to_str(m_nYKState, yk_state, "STATE = %d"), val_to_str(result, yk_result, "RESULT = %d")); + + BYTE* m_param; + BYTE nFun; //功能码 + BOOLEAN nNeedSelect; //遥控需要选择 + WORD nReg, nVal; + WORD nCloseSelReg, nCloseExecReg, nCloseEscReg, nCloseValue; //合闸命令参数 + WORD nOpenSelReg, nOpenExecReg, nOpenEscReg, nOpenValue; //分闸命令参数 + + m_param = GetUnitYKParamByPoint(uid, m_nYKOrder); + if (NULL == m_param) return FALSE; + nFun = m_param[0]; //功能码占一个字节 + nNeedSelect = m_param[1]; //遥控是否需要选择 + nCloseSelReg = MAKEWORD(m_param[4], m_param[5]); //选择合寄存器 + nCloseExecReg = MAKEWORD(m_param[6], m_param[7]); //执行合寄存器 + nCloseEscReg = MAKEWORD(m_param[8], m_param[9]); //撤销合寄存器 + nCloseValue = MAKEWORD(m_param[10], m_param[11]); //合 + nOpenSelReg = MAKEWORD(m_param[12], m_param[13]); //选择分寄存器 + nOpenExecReg = MAKEWORD(m_param[14], m_param[15]); //执行分寄存器 + nOpenEscReg = MAKEWORD(m_param[16], m_param[17]); //撤销分寄存器 + nOpenValue = MAKEWORD(m_param[18], m_param[19]); //分 + if (m_nYKState == YKS_SELREQ) + { //遥控选择 + if (m_bYKValue) + { + nReg = nCloseSelReg; + nVal = nCloseValue; + } + else + { + nReg = nOpenSelReg; + nVal = nOpenValue; + } + if (0xffff == nReg || !nNeedSelect) + { //寄存器无效,遥控无须选择 + SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_SELED, YKR_SUCC); + vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_SELED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP")); + return FALSE; + } + else + { + pData[0] = pItem->m_addr; + pData[1] = nFun; + pData[2] = (nReg >> 8) & 0x00ff; + pData[3] = nReg & 0x00ff; + pData[4] = (nVal >> 8) & 0x00ff; + pData[5] = nVal & 0x00ff; + count = 6; + FuncCode = nFun; + frame = MODBUSP_YK_SELECT; + return TRUE; + } + } + else if (m_nYKState == YKS_EXEREQ) + { //遥控执行 + if (m_bYKValue) + { + nReg = nCloseExecReg; + nVal = nCloseValue; + } + else + { + nReg = nOpenExecReg; + nVal = nOpenValue; + } + if (0xffff == nReg) return FALSE; + pData[0] = pItem->m_addr; + pData[1] = nFun; + pData[2] = (nReg >> 8) & 0x00ff; + pData[3] = nReg & 0x00ff; + pData[4] = (nVal >> 8) & 0x00ff; + pData[5] = nVal & 0x00ff; + count = 6; + FuncCode = nFun; + frame = MODBUSP_YK_EXECUTE; + return TRUE; + } + else if (m_nYKState == YKS_ABRREQ) + { //遥控撤销 + if (m_bYKValue) + { + nReg = nCloseEscReg; + nVal = nCloseValue; + } + else + { + nReg = nOpenEscReg; + nVal = nOpenValue; + } + if (0xffff == nReg || !nNeedSelect) + { //寄存器无效 + SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_ABRED, YKR_SUCC); + vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP")); + return FALSE; + } + pData[0] = pItem->m_addr; + pData[1] = nFun; + pData[2] = (nReg >> 8) & 0x00ff; + pData[3] = nReg & 0x00ff; + pData[4] = (nVal >> 8) & 0x00ff; + pData[5] = nVal & 0x00ff; + count = 6; + FuncCode = nFun; + frame = MODBUSP_YK_CANCEL; + return TRUE; + } + else if ((m_nYKState == YKS_SELING || m_nYKState == YKS_SELED) && result == YKR_OVER) + { //遥控撤销 + if (m_bYKValue) + { + nReg = nCloseEscReg; + nVal = nCloseValue; + } + else + { + nReg = nOpenEscReg; + nVal = nOpenValue; + } + if (0xffff == nReg || !nNeedSelect) + { //寄存器无效 + SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_ABRED, YKR_SUCC); + vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP")); + return FALSE; + } + pData[0] = pItem->m_addr; + pData[1] = nFun; + pData[2] = (nReg >> 8) & 0x00ff; + pData[3] = nReg & 0x00ff; + pData[4] = (nVal >> 8) & 0x00ff; + pData[5] = nVal & 0x00ff; + count = 6; + FuncCode = nFun; + frame = MODBUSP_YK_CANCEL; + return TRUE; + } + return FALSE; +} + + +////////////////////////////////////////////////////////////////////////// +// yt start // +////////////////////////////////////////////////////////////////////////// +BOOLEAN CHostModbusTcpBFProcess::GetYTFrame(CHostModbusTcpBFProcessItem *pItem, BYTE* pBuf, int& count, DWORD& frame, BYTE& FuncCode) +{ + int uid; + BYTE result; + BYTE* pData; + + if (NULL == pItem) return FALSE; + uid = pItem->GetUnitID(); + if (uid < 0 || uid >= UNIT_NUM) return FALSE; + if (NULL == pBuf) return FALSE; + + pData = pBuf; + if (!GetUnitYT(uid, m_nYTOrder, m_dwYTValue, m_nYTState, result)) + { + return FALSE; + } + vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is %s result is %s.\n", uid, m_nYTOrder, m_dwYTValue, val_to_str(m_nYTState, yt_state, "STATE = %d"), val_to_str(result, yt_result, "RESULT = %d")); + BYTE* m_param; + BYTE nFun; //功能码 + BYTE nSetType; //设置方式 0单寄存器,1双寄存器 + BOOLEAN nNeedSelect; //遥设需要选择 + WORD nReg = 0xffff; + WORD nSelReg, nExecReg, nEscReg; //合闸命令参数 + + m_param = GetUnitYTParamByPoint(uid, m_nYTOrder); + if (NULL == m_param) return FALSE; + nSetType = m_param[0]; //0 16位整型值;1 32位整型值;2 32位浮点数值; + nFun = m_param[1]; //功能码占一个字节 + nNeedSelect = m_param[2]; //遥控是否需要选择 + nSelReg = MAKEWORD(m_param[4], m_param[5]); //选择寄存器 + nExecReg = MAKEWORD(m_param[6], m_param[7]); //执行寄存器 + nEscReg = MAKEWORD(m_param[8], m_param[9]); //撤销寄存器 + if (m_nYTState == YTS_SELREQ) + { //遥设选择 + nReg = nSelReg; + if (0xffff == nReg || !nNeedSelect) + { //寄存器无效,遥设无须选择 + SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_SELED, YTR_SUCC); + vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_SELED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue); + return FALSE; + } + else + { + FuncCode = nFun; + frame = MODBUSP_YT_SELECT; + } + } + else if (m_nYTState == YTS_EXEREQ) + { //遥设执行 + nReg = nExecReg; + if (0xffff == nReg) return FALSE; + FuncCode = nFun; + frame = MODBUSP_YT_EXECUTE; + } + else if (m_nYTState == YTS_ABRREQ) + { //遥设撤销 + nReg = nEscReg; + if (0xffff == nReg || !nNeedSelect) + { //寄存器无效 + SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_ABRED, YTR_SUCC); + vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue); + return FALSE; + } + FuncCode = nFun; + frame = MODBUSP_YT_CANCEL; + } + else if ((m_nYTState == YTS_SELING || m_nYTState == YTS_SELED) && result == YTR_OVER) + { //遥设撤销 + nReg = nEscReg; + if (0xffff == nReg || !nNeedSelect) + { //寄存器无效 + SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_ABRED, YTR_SUCC); + vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue); + return FALSE; + } + FuncCode = nFun; + frame = MODBUSP_YT_CANCEL; + } + //modify by assouan for clean; + pData[0] = pItem->m_addr; + pData[1] = nFun; + pData[2] = (nReg >> 8) & 0x00ff; + pData[3] = nReg & 0x00ff; + if (nFun == MODBUSC_F06) + { + pData[4] = (m_dwYTValue >> 8) & 0x00ff; + pData[5] = m_dwYTValue & 0x00ff; + count = 6; + } + else if (nFun == MODBUSC_F16) + { + if (nSetType == 0) + { + pData[4] = 0x00; + pData[5] = 0x01; + pData[6] = 0x02; + pData[7] = (m_dwYTValue >> 8) & 0x00ff; + pData[8] = m_dwYTValue & 0x00ff; + count = 9; + } + else if (nSetType == 1) + { + pData[4] = 0x00; + pData[5] = 0x02; + pData[6] = 0x04; + pData[7] = (m_dwYTValue >> 24) & 0x00ff; + pData[8] = (m_dwYTValue >> 16) & 0x00ff; + pData[9] = (m_dwYTValue >> 8) & 0x00ff; + pData[10] = m_dwYTValue & 0x00ff; + count = 11; + } + else if (nSetType == 2) + { + pData[4] = 0x00; + pData[5] = 0x02; + pData[6] = 0x04; + pData[7] = (m_dwYTValue >> 8) & 0x00ff; + pData[8] = m_dwYTValue & 0x00ff; + pData[9] = (m_dwYTValue >> 24) & 0x00ff; + pData[10] = (m_dwYTValue >> 16) & 0x00ff; + + count = 11; + } + } + else return FALSE; + return TRUE; +} +////////////////////////////////////////////////////////////////////////// +// yt end // +////////////////////////////////////////////////////////////////////////// + +BOOLEAN CHostModbusTcpBFProcess::GetSetTimeFrame(CHostModbusTcpBFProcessItem *pItem, BYTE* /*pData*/, int& /*count*/) +{ + return TRUE; +} + +BOOLEAN CHostModbusTcpBFProcess::GetReadDataFrame(CHostModbusTcpBFProcessItem *pItem, BYTE* pData, int& count) +{ + if (NULL == pItem) return FALSE; + + if (m_nFrameType == 0) return FALSE; + if (m_nCurFuncCode == 0) return FALSE; + + pData[0] = pItem->m_addr; + pData[1] = (BYTE)m_nCurFuncCode; + pData[2] = (m_nCurBeginReg >> 8) & 0x00ff; + pData[3] = m_nCurBeginReg & 0x00ff; + pData[4] = (m_nCurRegCount >> 8) & 0x00ff; + pData[5] = m_nCurRegCount & 0x00ff; + + count = 6; + return TRUE; +} + +int CHostModbusTcpBFProcess::OnPackageReceived(BYTE* pBuf, int count, int ord) +{ + int uid; + if (count < 6) + { //数据长度不足 + return 0; + } + CHostModbusTcpBFProcessItem* pItem; + pItem = (CHostModbusTcpBFProcessItem *)GetItem(ord); + if (NULL == pItem) return -1; + //头尾判断。 + WORD protocol, len; + protocol = MAKEWORD(pBuf[3], pBuf[2]); + len = MAKEWORD(pBuf[5], pBuf[4]); + if (count < len + 6) + { //数据接收未完 + return 0; + } + + if (protocol != MB_TCP_PROTOCOL_ID) + { //未知协议 + return -1; + } + BYTE* buffer = &pBuf[6]; + if (((buffer[1] & 0x7f) != MODBUSC_F01) && ((buffer[1] & 0x7f) != MODBUSC_F02) && + ((buffer[1] & 0x7f) != MODBUSC_F03) && ((buffer[1] & 0x7f) != MODBUSC_F04) && + ((buffer[1] & 0x7f) != MODBUSC_F05) && ((buffer[1] & 0x7f) != MODBUSC_F06) && + ((buffer[1] & 0x7f) != MODBUSC_F07) && ((buffer[1] & 0x7f) != MODBUSC_F08) && + ((buffer[1] & 0x7f) != MODBUSC_F11) && ((buffer[1] & 0x7f) != MODBUSC_F12) && + ((buffer[1] & 0x7f) != MODBUSC_F15) && ((buffer[1] & 0x7f) != MODBUSC_F16) && + ((buffer[1] & 0x7f) != MODBUSC_F17) && ((buffer[1] & 0x7f) != MODBUSC_F20) && + ((buffer[1] & 0x7f) != MODBUSC_F21) && ((buffer[1] & 0x7f) != MODBUSC_F22) && + ((buffer[1] & 0x7f) != MODBUSC_F23) && ((buffer[1] & 0x7f) != MODBUSC_F24) && + ((buffer[1] & 0x7f) != MODBUSC_F43) && ((buffer[1] & 0x7f) != MODBUSC_F26)) + { //不支持的功能码 + return -1; + } + if ((buffer[1] & 0x80) == 0x80) + { //错误代码 + m_nCurFrame = 0; + } + //根据地址查找单元id + uid = GetUnitByAddr(buffer, 1); + if (uid < 0 || uid >= UNIT_NUM) return (len + 6); + int order = GetOrderByUnitID(uid); + if (order < 0 || order >= PROCESS_UNIT_NUM) return (len + 6); + pItem = (CHostModbusTcpBFProcessItem *)GetItem(order); + if (NULL == pItem) return (len + 6); + if (OnReceiveData(pItem, buffer, (len - 3))) + { + m_nCurFrame = 0; + } + DisplayRxData(pBuf, (len + 6), TRUE, uid); + UnitFeedDog(uid); + return (len + 6); +} + +BOOLEAN CHostModbusTcpBFProcess::OnReceiveData(CHostModbusTcpBFProcessItem *pItem, BYTE* pData, int count) +{ + int uid; + if (NULL == pItem) return FALSE; + + uid = pItem->GetUnitID(); + if (uid < 0) return FALSE; + + UnitFeedDog(uid); + + if (pData[1] == m_nCurFuncCode) + { + if (m_nCurFrame == MODBUSP_READ_YX1) + { + return OnReceiveYXData(pItem, &pData[3], count); + } + else if (m_nCurFrame == MODBUSP_READ_YC1) + { + return OnReceiveYCData(pItem, &pData[3], count); + } + else if (m_nCurFrame == MODBUSP_READ_YM1) + { + return OnReceiveYMData(pItem, &pData[3], count); + } + else if (m_nCurFrame == MODBUSP_READ_ID) + { + return OnReceiveIDData(pItem, &pData[3], count); + } + else if (m_nCurFrame == MODBUSP_YK_EXECUTE) + { + SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_EXEED, YKR_SUCC); + vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_EXEED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP")); + return TRUE; + } + else if (MODBUSP_YK_SELECT == m_nCurFrame) + { + SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_SELED, YKR_SUCC); + vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_SELED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP")); + return TRUE; + } + else if (MODBUSP_YK_CANCEL == m_nCurFrame) + { + SetUnitYK(uid, m_nYKOrder, m_bYKValue, YKS_ABRED, YKR_SUCC); + vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRED result is YKR_SUCC.\n", uid, m_nYKOrder, (m_bYKValue ? "CLOSE" : "TRIP")); + return TRUE; + } + else if (MODBUSP_YT_EXECUTE == m_nCurFrame) + { + SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_EXEED, YTR_SUCC); + vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_EXEED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue); + return TRUE; + } + else if (MODBUSP_YT_SELECT == m_nCurFrame) + { + SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_SELED, YTR_SUCC); + vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_SELED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue); + return TRUE; + } + else if (MODBUSP_YT_CANCEL == m_nCurFrame) + { + SetUnitYT(uid, m_nYTOrder, m_dwYTValue, YTS_ABRED, YTR_SUCC); + vLog(LOG_WARN, "Unit(%d) set point(%d) %d state is YTS_ABRED result is YTR_SUCC.\n", uid, m_nYTOrder, m_dwYTValue); + return TRUE; + } + } + + return FALSE; +} + +BOOLEAN CHostModbusTcpBFProcess::OnReceiveIDData(CHostModbusTcpBFProcessItem *pItem, BYTE* pData, int count) +{ + int uid; + BYTE* pBuf; + + if (pItem == NULL) return FALSE; + uid = pItem->GetUnitID(); + if (uid < 0) return FALSE; + + pBuf = pData; + +/* + 1)、路径信息是否有效 byte; + 2)、当前文件夹路径名的后缀 dint,按照顺序增加1(转字符串时在前补0); + 3)、当前文件夹下最后新文件的编号 dint; + 4)、当前文件夹下第一个文件的编号 dint; + 5)、当前文件夹下文件个数 dint; +*/ + //路径有效性判断 + int iv = ((pBuf[0] << 8) | pBuf[1]); pBuf += 2; + + m_iv = iv; + if (iv) { + vLog(LOG_DEBUG, "路径信息无效\n"); + return FALSE; + } + //当前文件夹路径名 + m_currentDirNo = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); pBuf += 4; + //当前文件夹下最后新文件 + m_currentFileNo = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); pBuf += 4; + //当前目录文件开始编号 + m_currentDirStartFileNo = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); pBuf += 4; + + + 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, "总共有%d个目录的%d个文件未读取。\n", dir_count, file_count); + } + /*文件从保存的最后读取的文件目录的文件一直督导当前开始目录*/ + vLog(LOG_DEBUG, "最新文件夹编号: %ld, 最新文件名编号: %ld: 最新文件夹中第一个文件的编号: %ld\n", m_currentDirNo, m_currentFileNo, m_currentDirStartFileNo); + + return TRUE; +} + +BOOLEAN CHostModbusTcpBFProcess::OnReceiveYXData(CHostModbusTcpBFProcessItem *pItem, BYTE* pData, int count) +{ + int uid; + int i, j; + int point; + BYTE param[4]; + WORD reg; + + BOOLEAN yxVal; + + if (pItem == NULL) return FALSE; + uid = pItem->GetUnitID(); + if (uid < 0) return FALSE; + + reg = m_nCurBeginReg; + param[0] = m_nCurFuncCode; + if (MODBUSC_F03 == m_nCurFuncCode || MODBUSC_F04 == m_nCurFuncCode) + { //03功能码读取Holdings + WORD nValue; + WORD nTemp = 0x0001; + for (i = 0; i < count; i += 2) + { + nValue = (pData[i] << 8) | pData[i+1]; + nTemp = 0x0001; + param[1] = LOBYTE(reg); + param[2] = HIBYTE(reg); + reg++; + for (j = 0; j < 16; j++) + { + param[3] = j; + point = GetUnitYXPointByParam(uid, param, 4); + if (point >= 0) + { + yxVal = SPI_OFF; + if ((nValue) & nTemp) + { + yxVal = SPI_ON; + } + SetUnitYX(uid, point, yxVal); + } + nTemp <<= 1; + } + } + } + else if (MODBUSC_F01 == m_nCurFuncCode || MODBUSC_F02 == m_nCurFuncCode) + { //01 02功能码读取Coils和Status + BYTE *nValue = pData; + BYTE nTemp = 0x01; + for (i = 0; i < count; i++) + { + nTemp = 0x01; + for (j = 0; j < 8; j++) + { + param[1] = LOBYTE(reg); + param[2] = HIBYTE(reg); + reg++; + point = GetUnitYXPointByParam(uid, param, 3); + if (point >= 0) + { + yxVal = SPI_OFF; + if ((*nValue) & nTemp) + { + yxVal = SPI_ON; + } + SetUnitYX(uid, point, yxVal); + } + nTemp <<= 1; + } + nValue++; + } + } + + return TRUE; +} + +BOOLEAN CHostModbusTcpBFProcess::OnReceiveYCData(CHostModbusTcpBFProcessItem *pItem, BYTE* pData, int count) +{ + int uid; + int i; + BYTE* pBuf; + BYTE* pParam; + BYTE param[8]; + DWORD nValue = 0; + LONG bin_value; + float f_val; + int point; + WORD reg; + BYTE reg_count, value_type, sign_mark; + + if (pItem == NULL) return FALSE; + uid = pItem->GetUnitID(); + if (uid < 0) return FALSE; + + pBuf = pData; + reg = m_nCurBeginReg; + param[0] = m_nCurFuncCode; + for (i = 0; i < count;) + { + param[1] = LOBYTE(reg); + param[2] = HIBYTE(reg); + point = GetUnitYCPointByParam(uid, param, 3); + + if (point >= 0) + { //获得合法点号 + pParam = GetUnitYCParamByPoint(uid, point); + if (pParam != NULL) + { + reg_count = pParam[3]; + value_type = pParam[4]; + sign_mark = pParam[5]; + //vLog(LOG_DEBUG, "here count is: %d, value type is: %d, and ", reg_count, value_type); + if ((1 == reg_count) && (2 == value_type)) + { //16位归一化值 + if (2 == value_type) + { + if (sign_mark == 0) nValue = (DWORD)(WORD)((pBuf[0] << 8) | pBuf[1]); + else nValue = (DWORD)(short)((pBuf[0] << 8) | pBuf[1]); + SetUnitYC(uid, point, (LONG)nValue); + //vLog(LOG_DEBUG, "value is: %ld.\n", nValue); + } + else if (8 == value_type) + { + if (sign_mark == 0) nValue = (DWORD)(WORD)((pBuf[0] << 8) | pBuf[1]); + else nValue = (DWORD)(short)((pBuf[0] << 8) | pBuf[1]); + nValue = bcd_to_int((const BYTE*)&nValue, sizeof(WORD)); + SetUnitYC(uid, point, (LONG)nValue); + } + pBuf += 2; i += 2; reg++; + } + else if (2 == reg_count) + { //32位测量值 + if (0 == value_type) + { //浮点数,高位在第一个寄存器 + nValue = (DWORD)(pBuf[0] << 24 | pBuf[1] << 16 | pBuf[2] << 8 | pBuf[3]); + memcpy(&f_val, &nValue, 4); + SetUnitYC(uid, point, f_val); + //nValue = (DWORD)(f_val * 1000); + } + else if (1 == value_type) + { + nValue = (DWORD)(pBuf[2] << 24 | pBuf[3] << 16 | pBuf[0] << 8 | pBuf[1]); + memcpy(&f_val, &nValue, 4); + SetUnitYC(uid, point, f_val); + //nValue = (DWORD)(f_val * 1000); + } + else if (3 == value_type) + { //归一化值,高位在第一个寄存器 + nValue = (DWORD)(pBuf[0] << 24 | pBuf[1] << 16 | pBuf[2] << 8 | pBuf[3]); + SetUnitYC(uid, point, (LONG)nValue); + //vLog(LOG_DEBUG, "value is: %ld.\n", nValue); + } + else if (4 == value_type) + { //归一化值,高位在第二个寄存器 + nValue = (DWORD)(pBuf[2] << 24 | pBuf[3] << 16 | pBuf[0] << 8 | pBuf[1]); + SetUnitYC(uid, point, (LONG)nValue); + } + else if (5 == value_type) + { + nValue = (DWORD)(pBuf[3] << 24 | pBuf[2] << 16 | pBuf[1] << 8 | pBuf[0]); + memcpy(&f_val, &nValue, 4); + SetUnitYC(uid, point, f_val); + } + else if (6 == value_type) + { //32位bcd数据高位在第一个寄存器 + nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]); + bin_value = (LONG)bcd_to_int((const BYTE*)&nValue, sizeof(DWORD)); + SetUnitYC(uid, point, bin_value); + } + else if (7 == value_type) + { //32位bcd数据高位在第二个寄存器 + nValue = (DWORD)(pBuf[2] << 24 | pBuf[3] << 16 | pBuf[0] << 8 | pBuf[1]); + bin_value = (LONG)bcd_to_int((const BYTE*)&nValue, sizeof(DWORD)); + SetUnitYC(uid, point, bin_value); + } + pBuf += 4; i += 4; reg += 2; + } + } + } + else + { + pBuf += 2; i += 2; reg++; + } + } + return TRUE; +} + +BOOLEAN CHostModbusTcpBFProcess::OnReceiveYMData(CHostModbusTcpBFProcessItem *pItem, BYTE* pData, int count) +{ + int i; + int point; + int uid; + BYTE* pBuf; + BYTE* pParam; + BYTE nParam[4]; + BYTE value_type; + WORD reg; + DWORD nValue = 0; + float f_val; + DWORD dw[2]; //双精度转换中间变量 + double d_val; + DWORD bin_value; + + if (pItem == NULL) return FALSE; + uid = pItem->GetUnitID(); + if (uid < 0) return FALSE; + + pBuf = pData; + reg = m_nCurBeginReg; + + nParam[0] = m_nCurFuncCode; + for (i = 0; i < count; ) + { + nParam[1] = LOBYTE(reg); + nParam[2] = HIBYTE(reg); + point = GetUnitYMPointByParam(uid, nParam, 3); + if (point >= 0) + { //获得有效点号 + pParam = GetUnitYMParamByPoint(uid, point); + if (NULL != pParam) + { //获得有效参数 + value_type = pParam[4]; + if (0 == value_type) + { //16位无符号整型 + nValue = (pBuf[0] << 8) | pBuf[1]; + SetUnitYM(uid, point, nValue); + pBuf += 2; i += 2; reg++; + } + else if (1 == value_type) + { //32位无符号整型高位在第一个寄存器 + nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]); + SetUnitYM(uid, point, nValue); + pBuf += 4; reg += 2; i += 4; + } + else if (2 == value_type) + { //32位整型高位在第一个寄存器 + nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]); + SetUnitYM(uid, point, nValue); + pBuf += 4; reg += 2; i += 4; + } + else if (3 == value_type) + { //32位无符号整型高位在第二个寄存器 + nValue = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); + SetUnitYM(uid, point, nValue); + pBuf += 4; reg += 2; i += 4; + } + else if (4 == value_type) + { //32位整型高位在第二个寄存器 + nValue = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); + SetUnitYM(uid, point, nValue); + pBuf += 4; reg += 2; i += 4; + } + else if (5 == value_type) + { //32位浮点数高位在第一个寄存器 + nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]); + memcpy(&f_val, &nValue, 4); + SetUnitYM(uid, point, (DWORD)f_val); + pBuf += 4; reg += 2; i += 4; + } + else if (6 == value_type) + { //32位浮点数高位在第二个寄存器 + nValue = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); + memcpy(&f_val, &nValue, 4); + SetUnitYM(uid, point, (DWORD)f_val); + pBuf += 4; reg += 2; i += 4; + } + else if (7 == value_type) + { //64位浮点数高位在第一个寄存器 + dw[1] = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); + dw[0] = (DWORD)((pBuf[6] << 24) | (pBuf[7] << 16) | (pBuf[4] << 8) | pBuf[5]); + memcpy(&d_val, dw, 8); + SetUnitYM(uid, point, (DWORD)(d_val)); + pBuf += 8; reg += 4; i += 8; + } + else if (8 == value_type) + { + dw[0] = (DWORD)((pBuf[2] << 24) | (pBuf[3] << 16) | (pBuf[0] << 8) | pBuf[1]); + dw[1] = (DWORD)((pBuf[6] << 24) | (pBuf[7] << 16) | (pBuf[4] << 8) | pBuf[5]); + memcpy(&d_val, dw, 8); + SetUnitYM(uid, point, (DWORD)(d_val)); + pBuf += 8; reg += 4; i += 8; + } + else if (9 == value_type) + { + nValue = (DWORD)((pBuf[3] << 24) | (pBuf[2] << 16) | (pBuf[1] << 8) | pBuf[0]); + memcpy(&f_val, &nValue, 4); + SetUnitYM(uid, point, (DWORD)(f_val * 10)); + pBuf += 4; reg += 2; i += 4; + } + else if (10 == value_type) + { //32位bcd数据 + nValue = (DWORD)((pBuf[0] << 24) | (pBuf[1] << 16) | (pBuf[2] << 8) | pBuf[3]); + bin_value = bcd_to_int((const BYTE*)&nValue, sizeof(DWORD)); + SetUnitYM(uid, point, bin_value); + pBuf += 4; reg += 2; i += 4; + } + else + { //无配置 + pBuf += 2; reg++; i += 2; + } + } + } + else + { + pBuf += 2; i += 2; reg++; + } + } + + return TRUE; +} diff --git a/das-dn/hostmodbustcpbf/host_modbus_tcp_bf.h b/das-dn/hostmodbustcpbf/host_modbus_tcp_bf.h new file mode 100644 index 00000000..8e4f2918 --- /dev/null +++ b/das-dn/hostmodbustcpbf/host_modbus_tcp_bf.h @@ -0,0 +1,289 @@ +#ifndef _ZJD_HOST_MODBUS_TCP_BF_PROCESS_H_ +#define _ZJD_HOST_MODBUS_TCP_BF_PROCESS_H_ + +#include "netproc.h" +#include "modbus_def.h" + +#include +#include +#include + +#pragma pack(1) +typedef struct { + QLONG localtime;// PLC本地时间 8 none 0.0001 毫秒 little endian 系统 + WORD iGenSpeed;// 发电机转速 2 200 0.1 转/分 40ms 控制系统 + WORD iGenPower;// 机组有功功率 2 201 0.1 千瓦 40ms 控制系统 + WORD iWindSpeed;// 风速 2 202 0.01 米/秒 40ms 气象 + WORD iVibrationY;// 机舱振动前后方向 2 203 0.001 米/秒^2 40ms 机舱 + WORD iVibrationZ;// 机舱振动左右方向 2 204 0.001 米/秒^2 40ms 机舱 + WORD iTurbineOperationMode;// 运行模式 2 205 1 需要解析 1s 控制系统 + WORD iBPLevel;// 刹车等级 2 206 1 需要解析 1s 控制系统 + WORD iYPLevel;// 偏航运行模式 2 207 1 需要解析 1s 控制系统 + WORD iWindSpeed_1sec;// 风速1秒均值 2 208 0.01 米/秒 1s 控制系统 + WORD iGenSpeed_1sec;// 发电机转速1秒均值 2 209 0.1 转/分 1s 控制系统 + WORD iGenPower_1sec;// 机组有功1秒均值 2 210 0.1 千瓦 1s 控制系统 + WORD iGenToruqe_1sec;// 发电机扭矩1秒均值 2 211 0.1 牛米 1s 控制系统 + WORD iRotorSpeed;// 风轮转速 2 212 0.1 转/分 1s 控制系统 + WORD iTheoreticalPower;// 理论有功功率 2 213 0.1 千瓦 1s 控制系统 + WORD iReactivePower;// 无功功率 2 214 0.1 千乏 1s 控制系统 + WORD iActivePowerSetPointValue;// 有功设定值 2 215 0.1 千瓦 1s 控制系统 + WORD iCosPhiSetValue;// 功率因数设定值 2 216 0.001 . 1s 控制系统 + WORD iSetValueGenSpeed;// 发电机转速设定值 2 217 0.1 转/分 1s 控制系统 + WORD iSetValuePitchAngle;// 桨叶角度设定值 2 218 0.01 度 1s 控制系统 + WORD iPitchAngle1RefValue;// 桨叶1角度给定 2 219 0.01 度 1s 控制系统 + WORD iPitchAngle2RefValue;// 桨叶2角度给定 2 220 0.01 度 1s 控制系统 + WORD iPitchAngle3RefValue;// 桨叶3角度给定 2 221 0.01 度 1s 控制系统 + WORD iPitchAngle1;// 桨叶1角度 2 222 0.01 度 1s 变桨系统 + WORD iPitchAngle2;// 桨叶2角度 2 223 0.01 度 1s 变桨系统 + WORD iPitchAngle3;// 桨叶3角度 2 224 0.01 度 1s 变桨系统 + WORD iVaneDirection;// 机舱方向 2 225 0.1 度 1s 气象 + WORD iWindDirection;// 风向(与机舱夹角) 2 226 0.1 度 1s 气象 + WORD StateWord01;// 状态字01 2 227 1 需要解析 1s 控制系统 详细解析见 状态字解析 + WORD StateWord02;// 状态字02 2 228 1 需要解析 1s 控制系统 + WORD StateWord03;// 状态字03 2 229 1 需要解析 1s 控制系统 + WORD StateWord04;// 状态字04 2 230 1 需要解析 1s 控制系统 + WORD StateWord05;// 状态字05 2 231 1 需要解析 1s 控制系统 + WORD StateWord06;// 状态字06 2 232 1 需要解析 1s 控制系统 + WORD StateWord07;// 状态字07 2 233 1 需要解析 1s 控制系统 + WORD StateWord08;// 状态字08 2 234 1 需要解析 1s 控制系统 + DWORD ActiveStatusCode01;// 故障代码01 4 235 1 需要解析 1s 控制系统 代表目前已经触发的故障代码类似:02(HH)04(HL)005(L) + DWORD ActiveStatusCode02;// 故障代码02 4 237 1 需要解析 1s 控制系统 详细解析见故障代码字解析 + DWORD ActiveStatusCode03;// 故障代码03 4 239 1 需要解析 1s 控制系统 + DWORD ActiveStatusCode04;// 故障代码04 4 241 1 需要解析 1s 控制系统 + DWORD ActiveStatusCode05;// 故障代码05 4 243 1 需要解析 1s 控制系统 + DWORD ActiveStatusCode06;// 故障代码06 4 245 1 需要解析 1s 控制系统 + DWORD ActiveStatusCode07;// 故障代码07 4 247 1 需要解析 1s 控制系统 + DWORD ActiveStatusCode08;// 故障代码08 4 249 1 需要解析 1s 控制系统 + WORD iFrequency;// 电网频率 2 251 0.01 赫兹 1s 电网 + WORD iUL1_690V;// 电网L1相电压 2 252 0.1 伏 1s 电网 + WORD iUL2_690V;// 电网L2相电压 2 253 0.1 伏 1s 电网 + WORD iUL3_690V;// 电网L3相电压 2 254 0.1 伏 1s 电网 + WORD iIL1_690V;// 电网L1相电流 2 255 0.1 安 1s 电网 + WORD iIL2_690V;// 电网L2相电流 2 256 0.1 安 1s 电网 + WORD iIL3_690V;// 电网L3相电流 2 257 0.1 安 1s 电网 + WORD iBlade1MotorCurrent;// 变桨电机1电流 2 258 0.1 安 1s 变桨系统 + WORD iBlade2MotorCurrent;// 变桨电机2电流 2 259 0.1 安 1s 变桨系统 + WORD iBlade3MotorCurrent;// 变桨电机3电流 2 260 0.1 安 1s 变桨系统 + WORD iPitchAngleBk1;// 备用桨叶角度1 2 261 0.01 度 1s 变桨系统 + WORD iPitchAngleBk2;// 备用桨叶角度2 2 262 0.01 度 1s 变桨系统 + WORD iPitchAngleBk3;// 备用桨叶角度3 2 263 0.01 度 1s 变桨系统 + WORD iCosPhi;// 并网点功率因数 2 264 0.001 . 1s 电网 + WORD iGearPressA;// 齿轮箱油压A 2 265 0.1 巴 1s 齿轮箱 + WORD iGearPressB;// 齿轮箱油压B 2 266 0.1 巴 1s 齿轮箱 + WORD iHydrPress;// 液压系统压力 2 267 0.1 巴 1s 液压系统 + WORD iNacellePositionLtd;// 机舱绝对方向 2 268 0.1 度 1s 机舱 + WORD iCableTwistTotal;// 总扭缆角度 2 269 0.1 度 1s 机舱 + WORD iNacellePositionTotal;// 机舱方向 2 270 0.1 度 1s 机舱 + WORD iTempOutdoor_1sec;// 环境温度 2 271 0.1 摄氏度 1s 环境 + WORD iTempHub_1sec;// 轮毂内温度 2 272 0.1 摄氏度 1s 轮毂 + WORD iTempNacelle_1sec;// 机舱内温度 2 273 0.1 摄氏度 1s 机舱 + WORD iTempTowerBase_1sec;// 塔基内温度 2 274 0.1 摄氏度 1s 塔基 + WORD iTempCabinetNacelle_1sec;// 机舱柜内温度 2 275 0.1 摄氏度 1s 机舱 + WORD iTempCabinetTowerBase_1sec;// 塔基柜内温度 2 276 0.1 摄氏度 1s 塔基 + WORD iTempTransformer690_400V_1sec;// 400伏变压器温度 2 277 0.1 摄氏度 1s 塔基 + WORD iTempMV_1sec;// 箱变温度 2 278 0.1 摄氏度 1s 箱变 + WORD iBlade1TempMotor_1sec;// 变桨电机1温度 2 279 0.1 摄氏度 1s 变桨系统 + WORD iBlade2TempMotor_1sec;// 变桨电机2温度 2 280 0.1 摄氏度 1s 变桨系统 + WORD iBlade3TempMotor_1sec;// 变桨电机3温度 2 281 0.1 摄氏度 1s 变桨系统 + WORD iBlade1TempBattBox_1sec;// 变桨电池柜1温度 2 282 0.1 摄氏度 1s 变桨系统 + WORD iBlade2TempBattBox_1sec;// 变桨电池柜2温度 2 283 0.1 摄氏度 1s 变桨系统 + WORD iBlade3TempBattBox_1sec;// 变桨电池柜3温度 2 284 0.1 摄氏度 1s 变桨系统 + WORD iTempCntr_1sec;// 变桨中控箱温度 2 285 0.1 摄氏度 1s 变桨系统 + WORD iBlade1TempInvBox_1sec;// 变桨逆变器1温度 2 286 0.1 摄氏度 1s 变桨系统 + WORD iBlade2TempInvBox_1sec;// 变桨逆变器2温度 2 287 0.1 摄氏度 1s 变桨系统 + WORD iBlade3TempInvBox_1sec;// 变桨逆变器3温度 2 288 0.1 摄氏度 1s 变桨系统 + WORD iBlade1TempPMMHeatsink_1sec;// 变桨PMM1散热器温度 2 289 0.1 摄氏度 1s 变桨系统 + WORD iBlade2TempPMMHeatsink_1sec;// 变桨PMM2散热器温度 2 290 0.1 摄氏度 1s 变桨系统 + WORD iBlade3TempPMMHeatsink_1sec;// 变桨PMM3散热器温度 2 291 0.1 摄氏度 1s 变桨系统 + WORD iBlade1TempPMCHeatsink_1sec;// 变桨PMC1散热器温度 2 292 0.1 摄氏度 1s 变桨系统 + WORD iBlade2TempPMCHeatsink_1sec;// 变桨PMC2散热器温度 2 293 0.1 摄氏度 1s 变桨系统 + WORD iBlade3TempPMCHeatsink_1sec;// 变桨PMC3散热器温度 2 294 0.1 摄氏度 1s 变桨系统 + WORD iTempRotorBearA_1sec;// 主轴承A温度 2 295 0.1 摄氏度 1s 传动链 + WORD iTempRotorBearB_1sec;// 主轴承B温度 2 296 0.1 摄氏度 1s 传动链 + WORD iTemp1GearOil_1sec;// 齿轮箱油温 2 297 0.1 摄氏度 1s 齿轮箱 + WORD iTempGearBearDE_1sec;// 齿轮箱驱动齿轴承温度 2 298 0.1 摄氏度 1s 齿轮箱 + WORD iTempGearBearNDE_1sec;// 齿轮箱非驱动侧轴承温度 2 299 0.1 摄氏度 1s 发电机 + WORD iTempGenBearDE_1sec;// 发电机驱动侧轴承温度 2 300 0.1 摄氏度 1s 发电机 + WORD iTempGenBearNDE_1sec;// 发电机非驱动侧轴承温度 2 301 0.1 摄氏度 1s 发电机 + WORD iTempGenStatorU_1sec;// 发电机绕组U温度 2 302 0.1 摄氏度 1s 发电机 + WORD iTempGenStatorV_1sec;// 发电机绕组V温度 2 303 0.1 摄氏度 1s 发电机 + WORD iTempGenStatorW_1sec;// 发电机绕组W温度 2 304 0.1 摄氏度 1s 发电机 + WORD iTempGenCoolingAir_1sec;// 发电机冷却风温度 2 305 0.1 摄氏度 1s 发电机 + WORD iAvailabillityToday;// 当天可利用率 2 306 0.001 . 1s 控制系统 + WORD iAvailabillityTotal;// 总可利用率 2 307 0.001 . 1s 控制系统 + DWORD iKWhThisDay;// 当天发电量 2 308 千瓦时 1s 控制系统 + DWORD iKWhOverall;// 总发电量 2 310 千瓦时 1s 控制系统 + WORD iOperationHoursDay;// 当天发电小时数 2 312 小时 1s 控制系统 + DWORD iOperationHoursOverall;// 总发电小时数 2 313 小时 1s 控制系统 + WORD iLostKWhThisDay;// 当天损失发电量 2 315 千瓦时 1s 控制系统 + DWORD iLostKWhOverall;// 总损失发电量 2 316 千瓦时 1s 控制系统 + DWORD FirstTriggeredCode;// 首触故障代码高 4 318 1 1s 控制系统 详细解析见故障代码字解析 + WORD SCW001;// 故障代码字01 2 320 1 1s 控制系统 + WORD SCW002;// 故障代码字02 2 321 1 1s 控制系统 + WORD SCW003;// 故障代码字03 2 322 1 1s 控制系统 + WORD SCW004;// 故障代码字04 2 323 1 1s 控制系统 + WORD SCW005;// 故障代码字05 2 324 1 1s 控制系统 + WORD SCW006;// 故障代码字06 2 325 1 1s 控制系统 + WORD SCW007;// 故障代码字07 2 326 1 1s 控制系统 + WORD SCW008;// 故障代码字08 2 327 1 1s 控制系统 + WORD SCW009;// 故障代码字09 2 328 1 1s 控制系统 + WORD SCW010;// 故障代码字10 2 329 1 1s 控制系统 + WORD SCW011;// 故障代码字11 2 330 1 1s 控制系统 + WORD SCW012;// 故障代码字12 2 331 1 1s 控制系统 + WORD SCW013;// 故障代码字13 2 332 1 1s 控制系统 + WORD SCW014;// 故障代码字14 2 333 1 1s 控制系统 + WORD SCW015;// 故障代码字15 2 334 1 1s 控制系统 + WORD SCW016;// 故障代码字16 2 335 1 1s 控制系统 + WORD SCW017;// 故障代码字17 2 336 1 1s 控制系统 + WORD SCW018;// 故障代码字18 2 337 1 1s 控制系统 + WORD SCW019;// 故障代码字19 2 338 1 1s 控制系统 + WORD SCW020;// 故障代码字20 2 339 1 1s 控制系统 + WORD SCW021;// 故障代码字21 2 340 1 1s 控制系统 + WORD SCW022;// 故障代码字22 2 341 1 1s 控制系统 + WORD SCW023;// 故障代码字23 2 342 1 1s 控制系统 + WORD SCW024;// 故障代码字24 2 343 1 1s 控制系统 + WORD SCW025;// 故障代码字25 2 344 1 1s 控制系统 + WORD SCW026;// 故障代码字26 2 345 1 1s 控制系统 + WORD SCW027;// 故障代码字27 2 346 1 1s 控制系统 + WORD SCW028;// 故障代码字28 2 347 1 1s 控制系统 + WORD SCW029;// 故障代码字29 2 348 1 1s 控制系统 + WORD SCW030;// 故障代码字30 2 349 1 1s 控制系统 + WORD SCW031;// 故障代码字31 2 350 1 1s 控制系统 + WORD SCW032;// 故障代码字32 2 351 1 1s 控制系统 + WORD SCW033;// 故障代码字33 2 352 1 1s 控制系统 + WORD SCW034;// 故障代码字34 2 353 1 1s 控制系统 + WORD SCW035;// 故障代码字35 2 354 1 1s 控制系统 + WORD SCW036;// 故障代码字36 2 355 1 1s 控制系统 + WORD SCW037;// 故障代码字37 2 356 1 1s 控制系统 + WORD SCW038;// 故障代码字38 2 357 1 1s 控制系统 + WORD SCW039;// 故障代码字39 2 358 1 1s 控制系统 + WORD SCW040;// 故障代码字40 2 359 1 1s 控制系统 + WORD SCW041;// 故障代码字41 2 360 1 1s 控制系统 + WORD SCW042;// 故障代码字42 2 361 1 1s 控制系统 + WORD iGenSpeed_10sec;// 发电机转速10秒均值 2 362 + WORD iGenSpeed_30sec;// 发电机转速30秒均值 2 363 + WORD iGenPower_10sec;// 机组有功10秒均值 2 364 + WORD iGenPower_30sec;// 机组有功30秒均值 2 365 + WORD iWindSpeed_10sec;// 风速10秒均值 2 366 + WORD iWindSpeed_30sec;// 风速30秒均值 2 367 + WORD iAvailablePower;// 可用有功功率 2 368 +} struRYDeviceData; +#pragma pack() + +class CHostModbusTcpBFProcessItem : public CNetProcessItem +{ +public: + BYTE m_addr; + WORD m_nNum; + DWORD m_nFramePoll; +private: + int m_nCurFrame; + struModbusExtFrame m_nModbusFrames[MODBUS_RTU_AUTOMATIC_FRAME_MAX]; +public: + CHostModbusTcpBFProcessItem(); + virtual ~CHostModbusTcpBFProcessItem(); + + DWORD apdu_t0_begin; + void Attach(int uid, int sock, DWORD peer_addr, WORD peer_port); + void Release(void); + + struModbusExtFrame* GetNextFrame(void); + void AddFrames(struModbusExtFrame*, struModbusExtFrame*, struModbusExtFrame*); +}; + +class CHostModbusTcpBFProcess : public CNetProcess +{ +public: + BYTE m_nFrameType; + DWORD m_nCount; //loops passed + DWORD m_nFrameCount; + + WORD m_nCurBeginReg; + WORD m_nCurRegCount; + BYTE m_nCurFuncCode; + BOOLEAN m_nNeedSend; + DWORD m_nCurFrame; + DWORD m_nSendPoint; //send out loop + short m_nTimeout; + + int m_nYKOrder; + BYTE m_bYKValue; + BYTE m_nYKState; + + int m_nYTOrder; + DWORD m_dwYTValue; + BYTE m_nYTState; +private: + void calc2(void); + void sort1(STRUCT_PARAM*, int); //功能码排序 + void sort2(STRUCT_PARAM*, int); //寄存地址排序 + + struRYModbusOption m_nOptions; + //增加websocket连接 + pthread_t m_pid; + short m_uid; + +public: + BOOLEAN m_bHaveFTP; //存在FTP协议 + + //ftp参数信息 + char m_user[64]; + char m_password[64]; + char m_remotePath[128]; + char m_localPath[128]; + + //文件信息 + int m_iv; + LONG m_currentDirNo; //当前目录编号 + LONG m_currentFileNo; //当前文件编号 + LONG m_lastDirNo; //上一目录编号 + LONG m_lastFileNo; //上一文件编号 + LONG m_currentDirStartFileNo; //当前目录文件开始编号 + + LONG m_lastReadDirNo; //最后获取的目录编号 + LONG m_lastReadFileNo; //最后获取的文件编号 + LONG m_lastReadDirStartFileNo; //最后获取的目录文件开始编号 + LONG m_curStartDirNo; //当前获取的目录编号 + LONG m_curStartFileNo; //当前获取的文件编号 + BOOLEAN m_bHaveUnReadFile; //存在未读的文件 + BOOLEAN m_bFtpRun; + + + int _mkdir(const char* pathName) { + if (access(pathName, F_OK) == 0) return 0; + // 创建目录 + if (mkdir(pathName, 0777) == -1) { + vLog(LOG_ERROR, "创建文件夹 %s失败<%d,%s>\r\n", pathName, errno, strerror(errno)); + return -1; + } + return 1; + } + +public: + CHostModbusTcpBFProcess(); + virtual ~CHostModbusTcpBFProcess(); + + CNetProcessItem *CreateItem(int ord); + void DestroyItem(int ord, BOOLEAN bDeleted = FALSE); + + virtual BOOLEAN OnPreCreate(int id); + virtual BOOLEAN Run(void); + virtual BOOLEAN OnTimer(void); + + virtual BOOLEAN GetReadDataFrame(CHostModbusTcpBFProcessItem *pItem, BYTE* pData, int& count); + + virtual BOOLEAN GetYKFrame(CHostModbusTcpBFProcessItem *pItem, BYTE* pBuf, int& count, DWORD& frame, BYTE& FuncCode); + virtual BOOLEAN GetYTFrame(CHostModbusTcpBFProcessItem *pItem, BYTE* pBuf, int& count, DWORD& frame, BYTE& FuncCode); + virtual BOOLEAN GetSetTimeFrame(CHostModbusTcpBFProcessItem *pItem, BYTE* pData, int& count); + + BOOLEAN OnReceiveData(CHostModbusTcpBFProcessItem *pItem, BYTE* pData, int count); + int OnPackageReceived(BYTE* pBuf, int count, int ord /* = -1 */); + + virtual BOOLEAN OnReceiveIDData(CHostModbusTcpBFProcessItem *pItem, BYTE* pData, int count); + + virtual BOOLEAN OnReceiveYXData(CHostModbusTcpBFProcessItem *pItem, BYTE* pData, int count); + virtual BOOLEAN OnReceiveYCData(CHostModbusTcpBFProcessItem *pItem, BYTE* pData, int count); + virtual BOOLEAN OnReceiveYMData(CHostModbusTcpBFProcessItem *pItem, BYTE* pData, int count); +}; + +#endif //_ZJD_HOST_MODBUS_RTU_TCP_BF_PROCESS_H_ diff --git a/das-dn/inc/public.h b/das-dn/inc/public.h index 1e0b7bdd..f5acc4f7 100644 --- a/das-dn/inc/public.h +++ b/das-dn/inc/public.h @@ -198,7 +198,9 @@ typedef int SOCKET; #define PROTOCOL_SUB_GDW104 47 //国网104从 #define PROTOCOL_HW_MQTT 72 //华为物联平台ROMA #define PROTOCOL_OPCUA 78 //opcua协议 -#define PROTOCOL_FTP2MINIO 79 //opcua协议 +#define PROTOCOL_FTP2MINIO 79 //FTP转minio协议 +#define PROTOCOL_HOST_BF_MODBUSTCP 80 //倍福MODBUSTCP主 +#define PROTOCOL_HOST_BF_ADS 81 //倍福ADS协议 #define ADDR_TYPE_NORMAL 0 #define ADDR_TYPE_HEX 1 diff --git a/das-dn/submodbustcp/sub_modbus_tcp.cpp b/das-dn/submodbustcp/sub_modbus_tcp.cpp new file mode 100644 index 00000000..86d9a3db --- /dev/null +++ b/das-dn/submodbustcp/sub_modbus_tcp.cpp @@ -0,0 +1,1030 @@ +#include "sub_modbus_tcp.h" + +#define MB_TCP_TID 0 +#define MB_TCP_PID 2 +#define MB_TCP_LEN 4 +#define MB_TCP_UID 6 +#define MB_TCP_FUNC 7 + +#define MB_TCP_BUF_SIZE ( 256 + 7 ) /* Must hold a complete Modbus TCP frame. */ + +/////////////////////////////////////////////////////////////////////////////////// +CSubModbusTcpProcessItem::CSubModbusTcpProcessItem() +{ + ied_addr = 255; + m_nNum = 0; + + m_CoilRegCount; + m_DiscreteRegCount = 0; + m_HoldingRegCount = 0; + m_InputregCount = 0; + + m_pCoilRegTable = NULL; + m_pDiscreteRegTable = NULL; + m_pHoldingRegTable = NULL; + m_pInputRegTable = NULL; +} + +CSubModbusTcpProcessItem::~CSubModbusTcpProcessItem() +{ + ied_addr = 255; + m_nNum = 0; + + if (m_pCoilRegTable) + { + delete[] m_pCoilRegTable; + m_pCoilRegTable = NULL; + } + + if (m_pDiscreteRegTable) + { + delete[] m_pDiscreteRegTable; + m_pDiscreteRegTable = NULL; + } + + if (m_pHoldingRegTable) + { + delete[] m_pHoldingRegTable; + m_pHoldingRegTable = NULL; + } + + if (m_pInputRegTable) + { + delete[] m_pInputRegTable; + m_pInputRegTable = NULL; + } +} + +void CSubModbusTcpProcessItem::Attach(int uid, int sock, DWORD peer_addr, WORD peer_port) +{ + CNetProcessItem::Attach(uid, sock, peer_addr, peer_port); + + m_nNum = 0; +} + +void CSubModbusTcpProcessItem::Release(void) +{ + m_nNum = 0; + + CNetProcessItem::Release(); +} + +CSubModbusTcpProcess::CSubModbusTcpProcess() +{ + +} + +CSubModbusTcpProcess::~CSubModbusTcpProcess() +{ +} + +CNetProcessItem *CSubModbusTcpProcess::CreateItem(int ord) +{ + return dynamic_cast(new CSubModbusTcpProcessItem); +} + +void CSubModbusTcpProcess::DestroyItem(int ord, BOOLEAN bDeleted /* = FALSE */) +{ + CSubModbusTcpProcessItem *pItem = (CSubModbusTcpProcessItem *)GetItem(ord); + if (pItem != NULL && !bDeleted) + { + delete pItem; + return CNetProcess::DestroyItem(ord, TRUE); + } + + return CNetProcess::DestroyItem(ord, bDeleted); +} + +BOOLEAN CSubModbusTcpProcess::OnPreCreate(int id) +{ + int i, j; + int uid; + BYTE addr[6]; + CSubModbusTcpProcessItem *pItem; + if (!CNetProcess::OnPreCreate(id)) return FALSE; + + struSubModbusTCPOption m_option; + if (!GetOption(&m_option, sizeof(m_option))) return FALSE; + + m_YC_Type = m_option.defaultYCType; + for (i = 0; i < PROCESS_UNIT_NUM; i++) + { + pItem = (CSubModbusTcpProcessItem *)GetItem(i); + if (NULL == pItem) continue; + uid = GetUnitID(i); + + if (uid < 0 || uid >= UNIT_NUM) continue; + if (GetUnitAddr(uid, addr, 6)) + { //获取单元地址成功,则该段原地址采用配置地址,否则该单元为无效地址。 + pItem->ied_addr = addr[4]; //配置地址 + } + //此处增加判断 + m_CoilRegTable.clear(); + m_DiscreteTable.clear(); + m_HoldingRegTable.clear(); + m_InputRegTable.clear(); + //获取遥信数量 + int yxcount = GetUnitYXCount(uid); + //获取coil和discrete寄存器 + for (j = 0; j < yxcount; j++) { + BYTE* param = GetUnitYXParamByPoint(uid, j); + if (param) { + if (param[0] == 0 || param[0] == 1) { + m_DiscreteTable.push_back(j); + } else { + m_CoilRegTable.push_back(j); + } + } + } + + int yccount = GetUnitYCCount(uid); + for (j = 0; j < yccount; j++) { + BYTE* param = GetUnitYCParamByPoint(uid, j); + if (param) { + if (param[0] == 0 || param[0] == 1) { + m_InputRegTable.push_back(j); + } else { + m_HoldingRegTable.push_back(j); + } + } + } + + if (m_CoilRegTable.size() > 0) + { + pItem->m_CoilRegCount = m_CoilRegTable.size(); + pItem->m_pCoilRegTable = new BYTE[pItem->m_CoilRegCount]; + memset(pItem->m_pCoilRegTable, 0, sizeof(BYTE) * pItem->m_CoilRegCount); + } + if (m_DiscreteTable.size() > 0) + { + pItem->m_DiscreteRegCount = m_DiscreteTable.size(); + pItem->m_pDiscreteRegTable = new BYTE[pItem->m_DiscreteRegCount]; + memset(pItem->m_pDiscreteRegTable, 0, sizeof(BYTE) * pItem->m_DiscreteRegCount); + } + if (m_InputRegTable.size() > 0) + { + int count = 0; + if (m_YC_Type == M_ME_NC) count = (m_InputRegTable.size() << 1); + else count = m_InputRegTable.size(); + pItem->m_InputregCount = count; + pItem->m_pInputRegTable = new WORD[count]; + memset(pItem->m_pInputRegTable, 0, sizeof(WORD) * count); + } + int ymcount = GetUnitYMCount(uid); + if (m_HoldingRegTable.size() > 0 || ymcount > 0) + { + int count = m_HoldingRegTable.size(); + if (m_YC_Type == M_ME_NC) count = (count << 1); + count += (ymcount << 1); + pItem->m_HoldingRegCount = count; + pItem->m_pHoldingRegTable = new WORD[count]; + memset(pItem->m_pHoldingRegTable, 0, sizeof(WORD) * count); + } + } + return TRUE; +} + +BOOLEAN CSubModbusTcpProcess::Run(void) +{ + if (!CNetProcess::Run()) return FALSE; + + int i, j, uid; + + FeedDog(); + for (i = 0; i < PROCESS_UNIT_NUM; i++) + { + CSubModbusTcpProcessItem *pItem = (CSubModbusTcpProcessItem *)GetItem(i); + if (NULL == pItem) continue; + uid = pItem->GetUnitID(); + if (uid < 0) continue; + //刷新寄存器 + WORD *wd_input = NULL; + WORD *wd_hold = NULL; + BYTE *bt_coil = NULL; + BYTE *bt_discrete = NULL; + + if (pItem->m_pInputRegTable) { + wd_input = (WORD *)pItem->m_pInputRegTable; + } + if (pItem->m_pHoldingRegTable) { + wd_hold = (WORD *)pItem->m_pHoldingRegTable; + } + for (j = 0; j < m_InputRegTable.size(); j++) + { + if (m_YC_Type == M_ME_NC) + { + union + { + float fv; + DWORD dv; + } val; + + val.fv = GetUnitYCReal(uid, m_InputRegTable[j]); + *wd_input = ((val.dv >> 16) & 0xffff); wd_input++; + *wd_input = (val.dv & 0xffff); wd_input++; + } + else + { + *wd_input = (WORD)GetUnitYC(uid, m_InputRegTable[j]); wd_input++; + } + } + for (j = 0; j < m_HoldingRegTable.size(); j++) + { + if (m_YC_Type == M_ME_NC) + { + union + { + float fv; + DWORD dv; + } val; + + val.fv = GetUnitYCReal(uid, m_HoldingRegTable[j]); + *wd_hold = ((val.dv >> 16) & 0xffff); wd_hold++; + *wd_hold = (val.dv & 0xffff); wd_hold++; + } + else + { + *wd_hold = (WORD)GetUnitYC(uid, m_HoldingRegTable[j]); wd_hold++; + } + } + for (j = 0; j < GetUnitYMCount(uid); j++) + { + DWORD val = (DWORD)GetUnitYM(uid, j); + *wd_hold = ((val >> 16) & 0xffff); wd_hold++; + *wd_hold = (val & 0xffff); wd_hold++; + } + + if (pItem->m_pCoilRegTable) { + bt_coil = (BYTE *)pItem->m_pCoilRegTable; + for (j = 0; j < m_CoilRegTable.size(); j++) + { + *bt_coil = (BYTE)GetUnitYX(uid, m_CoilRegTable[j]); bt_coil++; + } + } + if (pItem->m_pDiscreteRegTable) { + bt_discrete = (BYTE *)pItem->m_pDiscreteRegTable; + for (j = 0; j < m_DiscreteTable.size(); j++) + { + *bt_discrete = (BYTE)GetUnitYX(uid, m_DiscreteTable[j]); bt_discrete++; + } + } + } + return TRUE; +} + +BOOLEAN CSubModbusTcpProcess::OnTimer(void) +{ + if (!CNetProcess::OnTimer()) return FALSE; + + int i, uid; + for (i = 0; i < PROCESS_UNIT_NUM; i++) + { + CSubModbusTcpProcessItem *pItem = (CSubModbusTcpProcessItem *)GetItem(i); + if (NULL == pItem) continue; + uid = pItem->GetUnitID(); + if (uid < 0) continue; + + int order; + BYTE action, result; + DWORD value; + BYTE by_value; + if (GetUnitYT(uid, order, value, action, result)) + { + vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is %s result is %s\n", uid, order, value, val_to_str(action, yt_state, "STATE=%d"), val_to_str(result, yt_result, "RESULT=%d")); + if (YTS_SELED == action && YTR_FAIL == result) + { + action = YTS_ABRED; + } + else if (YTS_SELREQ == action && YTR_OVER == result) + { + action = YTS_ABRED; + } + else if (YTS_SELING == action && YTR_OVER == result) + { + action = YTS_ABRED; + } + + if (YTS_SELED == action) + { + SetUnitYT(uid, order, value, YTS_EXEREQ, YTR_IDLE); + vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_EXEREQ result is YTR_IDLE.\n", uid, order, value); + } + else if (YTS_ABRED == action) + { + SetUnitYT(uid, order, value, YTS_ABRREQ, YTR_IDLE); + vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_ABRREQ result is YTR_IDLE.\n", uid, order, value); + } + } + if (GetUnitYK(uid, order, by_value, action, result)) + { + vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is %s result is %s\n", uid, order, (by_value ? "CLOSE" : "TRIP"), val_to_str(action, yk_state, "STATE=%d"), val_to_str(result, yk_result, "RESULT=%d")); + if (YKS_SELED == action && YKR_FAIL == result) + { + action = YKS_ABRED; + } + else if (YKS_SELREQ == action && YKR_OVER == result) + { + action = YKS_ABRED; + } + else if (YKS_SELING == action && YKR_OVER == result) + { + action = YKS_ABRED; + } + if (YKS_ABRED == action) + { + SetUnitYK(uid, order, by_value, YKS_ABRREQ, YKR_IDLE); + vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_ABRREQ result is YKR_IDLE.\n", uid, order, (by_value ? "CLOSE" : "TRIP")); + } + else if (YKS_SELED == action) + { + SetUnitYK(uid, order, by_value, YKS_EXEREQ, YKR_IDLE); + vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_EXEREQ result is YKR_IDLE.\n", uid, order, (by_value ? "CLOSE" : "TRIP")); + } + } + } + return TRUE; +} + +int CSubModbusTcpProcess::OnPackageReceived(BYTE* pBuf, int count, int ord) +{ + int uid; + CSubModbusTcpProcessItem* pItem; + pItem = (CSubModbusTcpProcessItem *)GetItem(ord); + if (NULL == pItem) return -1; + uid = pItem->GetUnitID(); + if (uid < 0 || uid >= UNIT_NUM) return -1; + //头尾判断。 + WORD usLength; + WORD usTID; + WORD usPID; + + if (count < MB_TCP_FUNC) + { //数据长度不足 + return 0; + } + usLength = pBuf[MB_TCP_LEN] << 8U; + usLength |= pBuf[MB_TCP_LEN + 1]; + if (count < (MB_TCP_UID + usLength)) + { //数据接收未完 + vLog(LOG_WARN, "数据没有接收完成.\n"); + return 0; + } + usPID = pBuf[MB_TCP_PID] << 8U; + usPID |= pBuf[MB_TCP_PID + 1]; + if (usPID != MB_TCP_PROTOCOL_ID) + { //未知协议 + vLog(LOG_ERROR, "未知协议\n"); + return -1; + } + usTID = pBuf[MB_TCP_TID] << 8U; + usTID |= pBuf[MB_TCP_TID + 1]; + usLength = count - MB_TCP_FUNC; + + BYTE *ppucFrame = &pBuf[MB_TCP_FUNC]; + BYTE ucRcvAddress = pBuf[MB_TCP_UID]; + if (ucRcvAddress != pItem->ied_addr && ucRcvAddress != MB_ADDRESS_BROADCAST) + { + vLog(LOG_DEBUG, "数据不是发送给我的.\n"); + return count; + } + BYTE ucFunctionCode = ppucFrame[MB_PDU_FUNC_OFF]; + eMBException eException; + eMBErrorCode eStatus = MB_ENOERR; + + DisplayRxData(pBuf, (MB_TCP_UID + usLength + 1), TRUE, uid); + UnitFeedDog(uid); + eException = MB_EX_ILLEGAL_FUNCTION; + switch (ucFunctionCode) + { + case MB_FUNC_READ_INPUT_REGISTER: + eException = eMBFuncReadInputRegister(pItem, ppucFrame, &usLength); + break; + case MB_FUNC_READ_HOLDING_REGISTER: + eException = eMBFuncReadHoldingRegister(pItem, ppucFrame, &usLength); + break; + case MB_FUNC_WRITE_MULTIPLE_REGISTERS: + eException = eMBFuncWriteMultipleHoldingRegister(pItem, ppucFrame, &usLength); + break; + case MB_FUNC_WRITE_REGISTER: + eException = eMBFuncWriteHoldingRegister(pItem, ppucFrame, &usLength); + break; + case MB_FUNC_READ_COILS: + eException = eMBFuncReadCoils(pItem, ppucFrame, &usLength); + break; + case MB_FUNC_WRITE_SINGLE_COIL: + eException = eMBFuncWriteCoil(pItem, ppucFrame, &usLength); + break; + case MB_FUNC_WRITE_MULTIPLE_COILS: + eException = eMBFuncWriteMultipleCoils(pItem, ppucFrame, &usLength); + break; + case MB_FUNC_READ_DISCRETE_INPUTS: + eException = eMBFuncReadDiscreteInputs(pItem, ppucFrame, &usLength); + break; + default: + break; + + } + if (ucRcvAddress != MB_ADDRESS_BROADCAST) + { + if (eException != MB_EX_NONE) + { + usLength = 0; + ppucFrame[usLength++] = (BYTE)(ucFunctionCode | MB_FUNC_ERROR); + ppucFrame[usLength++] = eException; + } + + eStatus = eMBTCPSend(ucRcvAddress, ppucFrame, usLength); + if (eStatus != MB_ENOERR) + { + vLog(LOG_ERROR, "modbus tcp send error(%d)\n", eStatus); + return -1; + } + } + return (count); +} + +eMBErrorCode CSubModbusTcpProcess::eMBTCPSend(BYTE ucSlaveAddress, const BYTE *pucFrame, WORD usLength) +{ + eMBErrorCode eStatus = MB_ENOERR; + BYTE *pucMBTCPFrame = (BYTE *) pucFrame - MB_TCP_FUNC; + WORD usTCPLength = usLength + MB_TCP_FUNC; + + pucMBTCPFrame[MB_TCP_LEN] = (usLength + 1) >> 8U; + pucMBTCPFrame[MB_TCP_LEN + 1] = (usLength + 1) & 0xFF; + if (WriteData(pucMBTCPFrame, usTCPLength, GetCurOrder())) + { + DisplayTxData(pucMBTCPFrame, usTCPLength, TRUE); + } + else + { + eStatus = MB_EIO; + } + return eStatus; +} + +eMBException CSubModbusTcpProcess::prveMBError2Exception(eMBErrorCode eErrorCode) +{ + eMBException eStatus; + + switch (eErrorCode) + { + case MB_ENOERR: + eStatus = MB_EX_NONE; + break; + case MB_ENOREG: + eStatus = MB_EX_ILLEGAL_DATA_ADDRESS; + break; + case MB_ETIMEDOUT: + eStatus = MB_EX_SLAVE_BUSY; + break; + default: + eStatus = MB_EX_SLAVE_DEVICE_FAILURE; + break; + } + return eStatus; +} + +eMBException CSubModbusTcpProcess::eMBFuncReadInputRegister(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen) +{ + WORD usRegAddress; + WORD usRegCount; + BYTE *pucFrameCur; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if (*usLen == (MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN)) + { + usRegAddress = (WORD)(pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8); + usRegAddress |= (WORD)(pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1]); + + usRegCount = (WORD)(pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8); + usRegCount |= (WORD)(pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1]); + + if ((usRegCount >= 1) && (usRegCount < MB_PDU_FUNC_READ_REGCNT_MAX)) + { + pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; + *usLen = MB_PDU_FUNC_OFF; + + *pucFrameCur++ = MB_FUNC_READ_INPUT_REGISTER; + *usLen += 1; + + *pucFrameCur++ = (BYTE)(usRegCount << 1); + *usLen += 1; + eRegStatus = eMBRegInputCB(pItem, pucFrameCur, usRegAddress, usRegCount); + + if (eRegStatus != MB_ENOERR) + { + eStatus = prveMBError2Exception(eRegStatus); + } + else + { + *usLen += usRegCount << 1; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +eMBException CSubModbusTcpProcess::eMBFuncWriteHoldingRegister(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen) +{ + WORD usRegAddress; + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if (*usLen == (MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN)) + { + usRegAddress = (WORD)(pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8); + usRegAddress |= (WORD)(pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1]); + + eRegStatus = eMBRegHoldingCB(pItem, &pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF], usRegAddress, 1, MB_REG_WRITE); + + if (eRegStatus != MB_ENOERR) + { + eStatus = prveMBError2Exception(eRegStatus); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +eMBException CSubModbusTcpProcess::eMBFuncWriteMultipleHoldingRegister(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen) +{ + WORD usRegAddress; + WORD usRegCount; + BYTE ucRegByteCount; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if (*usLen >= (MB_PDU_FUNC_WRITE_MUL_SIZE_MIN + MB_PDU_SIZE_MIN)) + { + usRegAddress = (WORD)(pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8); + usRegAddress |= (WORD)(pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1]); + + usRegCount = (WORD)(pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF] << 8); + usRegCount |= (WORD)(pucFrame[MB_PDU_FUNC_WRITE_MUL_REGCNT_OFF + 1]); + + ucRegByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF]; + + if ((usRegCount >= 1) && (usRegCount <= MB_PDU_FUNC_WRITE_MUL_REGCNT_MAX) && (ucRegByteCount == (BYTE) (usRegCount << 1))) + { + eRegStatus = eMBRegHoldingCB(pItem, &pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF], usRegAddress, usRegCount, MB_REG_WRITE); + + if (eRegStatus != MB_ENOERR) + { + eStatus = prveMBError2Exception(eRegStatus); + } + else + { + *usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +eMBException CSubModbusTcpProcess::eMBFuncReadHoldingRegister(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen) +{ + WORD usRegAddress; + WORD usRegCount; + BYTE *pucFrameCur; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if (*usLen == (MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN)) + { + usRegAddress = (WORD)(pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8); + usRegAddress |= (WORD)(pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1]); + + usRegCount = (WORD)(pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF] << 8); + usRegCount = (WORD)(pucFrame[MB_PDU_FUNC_READ_REGCNT_OFF + 1]); + + if ((usRegCount >= 1) && (usRegCount <= MB_PDU_FUNC_READ_REGCNT_MAX)) + { + pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; + *usLen = MB_PDU_FUNC_OFF; + + *pucFrameCur++ = MB_FUNC_READ_HOLDING_REGISTER; + *usLen += 1; + + *pucFrameCur++ = (BYTE) (usRegCount << 1); + *usLen += 1; + + eRegStatus = eMBRegHoldingCB(pItem, pucFrameCur, usRegAddress, usRegCount, MB_REG_READ); + + if (eRegStatus != MB_ENOERR) + { + eStatus = prveMBError2Exception(eRegStatus); + } + else + { + *usLen += usRegCount << 1; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +eMBException CSubModbusTcpProcess::eMBFuncReadCoils(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen) +{ + WORD usRegAddress; + WORD usCoilCount; + BYTE ucNBytes; + BYTE *pucFrameCur; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if (*usLen == (MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN)) + { + usRegAddress = (WORD)(pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8); + usRegAddress |= (WORD)(pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1]); + + usCoilCount = (WORD)(pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF] << 8); + usCoilCount |= (WORD)(pucFrame[MB_PDU_FUNC_READ_COILCNT_OFF + 1]); + + if ((usCoilCount >= 1) && (usCoilCount < MB_PDU_FUNC_READ_COILCNT_MAX)) + { + pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; + *usLen = MB_PDU_FUNC_OFF; + + *pucFrameCur++ = MB_FUNC_READ_COILS; + *usLen += 1; + + if ((usCoilCount & 0x0007) != 0) + { + ucNBytes = (BYTE)((usCoilCount >> 3) + 1); + } + else + { + ucNBytes = (BYTE)(usCoilCount >> 3); + } + *pucFrameCur++ = ucNBytes; + *usLen += 1; + + eRegStatus = eMBRegCoilsCB(pItem, pucFrameCur, usRegAddress, usCoilCount, MB_REG_READ); + + if (eRegStatus != MB_ENOERR) + { + eStatus = prveMBError2Exception(eRegStatus); + } + else + { + + *usLen += ucNBytes;; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +eMBException CSubModbusTcpProcess::eMBFuncWriteCoil(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen) +{ + WORD usRegAddress; + BYTE ucBuf[2]; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if (*usLen == (MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN)) + { + usRegAddress = (WORD)(pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF] << 8); + usRegAddress |= (WORD)(pucFrame[MB_PDU_FUNC_WRITE_ADDR_OFF + 1]); + + if ((pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF + 1] == 0x00) && ((pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF) || (pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0x00))) + { + ucBuf[1] = 0; + if (pucFrame[MB_PDU_FUNC_WRITE_VALUE_OFF] == 0xFF) + { + ucBuf[0] = 1; + } + else + { + ucBuf[0] = 0; + } + eRegStatus = eMBRegCoilsCB(pItem, &ucBuf[0], usRegAddress, 1, MB_REG_WRITE); + + if (eRegStatus != MB_ENOERR) + { + eStatus = prveMBError2Exception(eRegStatus); + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +eMBException CSubModbusTcpProcess::eMBFuncWriteMultipleCoils(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen) +{ + WORD usRegAddress; + WORD usCoilCnt; + BYTE ucByteCount; + BYTE ucByteCountVerify; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if (*usLen > (MB_PDU_FUNC_WRITE_SIZE + MB_PDU_SIZE_MIN)) + { + usRegAddress = (WORD)(pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF] << 8); + usRegAddress |= (WORD)(pucFrame[MB_PDU_FUNC_WRITE_MUL_ADDR_OFF + 1]); + + usCoilCnt = (WORD)(pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF] << 8); + usCoilCnt |= (WORD)(pucFrame[MB_PDU_FUNC_WRITE_MUL_COILCNT_OFF + 1]); + + ucByteCount = pucFrame[MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF]; + + if ((usCoilCnt & 0x0007) != 0) + { + ucByteCountVerify = (BYTE)(usCoilCnt / 8 + 1); + } + else + { + ucByteCountVerify = (BYTE)(usCoilCnt / 8); + } + + if ((usCoilCnt >= 1) && + (usCoilCnt <= MB_PDU_FUNC_WRITE_MUL_COILCNT_MAX) && + (ucByteCountVerify == ucByteCount)) + { + eRegStatus = eMBRegCoilsCB(pItem, &pucFrame[MB_PDU_FUNC_WRITE_MUL_VALUES_OFF], usRegAddress, usCoilCnt, MB_REG_WRITE); + + if (eRegStatus != MB_ENOERR) + { + eStatus = prveMBError2Exception(eRegStatus); + } + else + { + *usLen = MB_PDU_FUNC_WRITE_MUL_BYTECNT_OFF; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +eMBException CSubModbusTcpProcess::eMBFuncReadDiscreteInputs(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen) +{ + WORD usRegAddress; + WORD usDiscreteCnt; + BYTE ucNBytes; + BYTE *pucFrameCur; + + eMBException eStatus = MB_EX_NONE; + eMBErrorCode eRegStatus; + + if (*usLen == (MB_PDU_FUNC_READ_SIZE + MB_PDU_SIZE_MIN)) + { + usRegAddress = (WORD)(pucFrame[MB_PDU_FUNC_READ_ADDR_OFF] << 8); + usRegAddress |= (WORD)(pucFrame[MB_PDU_FUNC_READ_ADDR_OFF + 1]); + + usDiscreteCnt = (WORD)(pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF] << 8); + usDiscreteCnt |= (WORD)(pucFrame[MB_PDU_FUNC_READ_DISCCNT_OFF + 1]); + + if ((usDiscreteCnt >= 1) && (usDiscreteCnt < MB_PDU_FUNC_READ_DISCCNT_MAX)) + { + pucFrameCur = &pucFrame[MB_PDU_FUNC_OFF]; + *usLen = MB_PDU_FUNC_OFF; + + *pucFrameCur++ = MB_FUNC_READ_DISCRETE_INPUTS; + *usLen += 1; + + if ((usDiscreteCnt & 0x0007) != 0) + { + ucNBytes = (BYTE) ((usDiscreteCnt >> 3) + 1); + } + else + { + ucNBytes = (BYTE) (usDiscreteCnt >> 3); + } + *pucFrameCur++ = ucNBytes; + *usLen += 1; + + eRegStatus = eMBRegDiscreteCB(pItem, pucFrameCur, usRegAddress, usDiscreteCnt); + + if (eRegStatus != MB_ENOERR) + { + eStatus = prveMBError2Exception(eRegStatus); + } + else + { + *usLen += ucNBytes;; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + } + else + { + eStatus = MB_EX_ILLEGAL_DATA_VALUE; + } + return eStatus; +} + +eMBErrorCode CSubModbusTcpProcess::eMBRegInputCB(CSubModbusTcpProcessItem *pItem, BYTE* pucRegBuffer, WORD usAddress, WORD usNRegs) +{ + eMBErrorCode eStatus = MB_ENOERR; + int iRegIndex; + + if ((usAddress >= 0) && (usAddress + usNRegs <= 0 + pItem->m_InputregCount)) + { + iRegIndex = (int)(usAddress - 0); + while (usNRegs > 0) + { + *pucRegBuffer++ = (BYTE)(pItem->m_pInputRegTable[iRegIndex] >> 8); + *pucRegBuffer++ = (BYTE)(pItem->m_pInputRegTable[iRegIndex] & 0xFF); + iRegIndex++; + usNRegs--; + } + } + else + { + eStatus = MB_ENOREG; + } + + return eStatus; +} + +eMBErrorCode CSubModbusTcpProcess::eMBRegHoldingCB(CSubModbusTcpProcessItem *pItem, BYTE* pucRegBuffer, WORD usAddress, WORD usNRegs, eMBRegisterMode eMode) +{ + eMBErrorCode eStatus = MB_ENOERR; + WORD usRegHoldingValue; + int iRegIndex; + int uid; + + uid = pItem->GetUnitID(); + + if ((usAddress >= 0) && (usAddress + usNRegs <= 0 + pItem->m_HoldingRegCount)) + { + iRegIndex = (int)(usAddress - 0); + switch (eMode) + { + case MB_REG_READ: + while (usNRegs > 0) + { + *pucRegBuffer++ = (BYTE)(pItem->m_pHoldingRegTable[iRegIndex] >> 8); + *pucRegBuffer++ = (BYTE)(pItem->m_pHoldingRegTable[iRegIndex] & 0xFF); + iRegIndex++; + usNRegs--; + } + break; + case MB_REG_WRITE: + while (usNRegs > 0) + { + usRegHoldingValue = *pucRegBuffer++ << 8; + usRegHoldingValue |= *pucRegBuffer++; + //写寄存器 + SetUnitYT(uid, iRegIndex, usRegHoldingValue, YTS_EXEREQ, YTR_IDLE); + vLog(LOG_DEBUG, "Unit(%d) set point(%d) %d state is YTS_EXEREQ result is YTR_IDLE.\n", uid, iRegIndex, usRegHoldingValue); + iRegIndex++; + usNRegs--; + } + } + } + else + { + eStatus = MB_ENOREG; + } + return eStatus; +} + + +eMBErrorCode CSubModbusTcpProcess::eMBRegCoilsCB(CSubModbusTcpProcessItem *pItem, BYTE* pucRegBuffer, WORD usAddress, WORD usNCoils, eMBRegisterMode eMode) +{ + eMBErrorCode eStatus = MB_ENOERR; + WORD usCoilGroups = ((usNCoils - 1) / 8 + 1); + BYTE ucStatus = 0; + BYTE usRegCoilsValue; + BYTE ucBits = 0; + BYTE ucDisp = 0; + int iRegIndex = usAddress - 0; + int uid; + + uid = pItem->GetUnitID(); + if ((usAddress >= 0) && (usAddress + usNCoils <= 0 + pItem->m_CoilRegCount)) + { + iRegIndex = (int)(usAddress - 0); + switch (eMode) + { /* Pass current register values to the protocol stack. */ + case MB_REG_READ: + while (usCoilGroups--) + { + ucDisp = 0; + ucBits = 8; + ucStatus = 0; + while((usNCoils--) != 0 && (ucBits--) != 0) + { + ucStatus |= (pItem->m_pCoilRegTable[iRegIndex++] << (ucDisp++)); + } + *pucRegBuffer++ = ucStatus; + } + break; + case MB_REG_WRITE: + while (usCoilGroups--) + { + ucStatus = *pucRegBuffer++; + ucBits = 8; + while ((usNCoils--) != 0 && (ucBits--) != 0) + { + usRegCoilsValue = ucStatus & 0X01; + //写线圈 + SetUnitYK(uid, iRegIndex, usRegCoilsValue, YKS_SELREQ, YKR_IDLE); + vLog(LOG_WARN, "Unit(%d) yk(%d) %s state is YKS_EXEREQ result is YKR_IDLE.\n", uid, iRegIndex, (usRegCoilsValue ? "CLOSE" : "TRIP")); + iRegIndex++; + ucStatus >>= 1; + } + } + } + } + else + { + eStatus = MB_ENOREG; + } + return eStatus; +} + +eMBErrorCode CSubModbusTcpProcess::eMBRegDiscreteCB(CSubModbusTcpProcessItem *pItem, BYTE* pucRegBuffer, WORD usAddress, WORD usNDiscrete) +{ + eMBErrorCode eStatus = MB_ENOERR; + WORD usDiscreteGroups = ((usNDiscrete - 1) / 8 + 1); + BYTE ucStatus = 0; + BYTE ucBits = 0; + BYTE ucDisp = 0; + int iRegIndex = usAddress - 0; + + if ((usAddress >= 0) && (usAddress + usNDiscrete <= 0 + pItem->m_DiscreteRegCount)) + { + iRegIndex = (int)(usAddress - 0); + while (usDiscreteGroups--) + { + ucDisp = 0; + ucBits = 8; + ucStatus = 0; + while((usNDiscrete--) != 0 && (ucBits--) != 0) + { + ucStatus |= (pItem->m_pDiscreteRegTable[iRegIndex++] << (ucDisp++)); + } + *pucRegBuffer++ = ucStatus; + } + } + else + { + eStatus = MB_ENOREG; + } + return eStatus; +} diff --git a/das-dn/submodbustcp/sub_modbus_tcp.h b/das-dn/submodbustcp/sub_modbus_tcp.h new file mode 100644 index 00000000..294c8cf6 --- /dev/null +++ b/das-dn/submodbustcp/sub_modbus_tcp.h @@ -0,0 +1,92 @@ +#ifndef _ZJD_SUB_MODBUS_TCP_PROCESS_H_ +#define _ZJD_SUB_MODBUS_TCP_PROCESS_H_ + +#include "netproc.h" +#include "modbus_def.h" +#include + +#pragma pack(1) +typedef struct +{ + struNetWorkOption net; + BYTE defaultYCType; +} struSubModbusTCPOption; +#pragma pack() + +typedef std::vector vecInt; + +class CSubModbusTcpProcessItem : public CNetProcessItem +{ +public: + BYTE ied_addr; + WORD m_nNum; + + short m_CoilRegCount; + short m_DiscreteRegCount; + short m_HoldingRegCount; + short m_InputregCount; + + BYTE *m_pCoilRegTable; + BYTE *m_pDiscreteRegTable; + WORD *m_pHoldingRegTable; + WORD *m_pInputRegTable; + +public: + CSubModbusTcpProcessItem(); + virtual ~CSubModbusTcpProcessItem(); + + void Attach(int uid, int sock, DWORD peer_addr, WORD peer_port); + void Release(void); + +}; + +class CSubModbusTcpProcess : public CNetProcess +{ +public: + CSubModbusTcpProcess(); + virtual ~CSubModbusTcpProcess(); + + CNetProcessItem *CreateItem(int ord); + void DestroyItem(int ord, BOOLEAN bDeleted = FALSE); + + virtual BOOLEAN OnPreCreate(int id); + virtual BOOLEAN Run(void); + virtual BOOLEAN OnTimer(void); +private: + struSubModbusTCPOption m_option; + BYTE m_YC_Type; + enum + { + M_ME_NA, + M_ME_NC + }; + + vecInt m_CoilRegTable; + vecInt m_DiscreteTable; + vecInt m_HoldingRegTable; + vecInt m_InputRegTable; + +private: + int OnPackageReceived(BYTE* pBuf, int count, int ord /* = -1 */); + BOOLEAN OnReceiveData(CSubModbusTcpProcessItem *pItem, BYTE* pData, int count, int uid); + + eMBErrorCode eMBTCPSend(BYTE ucSlaveAddress, const BYTE *pucFrame, WORD usLength); + + eMBException prveMBError2Exception(eMBErrorCode eErrorCode); + eMBException eMBFuncReadInputRegister(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen); + eMBException eMBFuncReadHoldingRegister(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen); + eMBException eMBFuncWriteHoldingRegister(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen); + eMBException eMBFuncWriteMultipleHoldingRegister(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen); + eMBException eMBFuncReadCoils(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen); + eMBException eMBFuncWriteCoil(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen); + eMBException eMBFuncWriteMultipleCoils(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen); + eMBException eMBFuncReadDiscreteInputs(CSubModbusTcpProcessItem *pItem, BYTE* pucFrame, WORD* usLen); + + + eMBErrorCode eMBRegInputCB(CSubModbusTcpProcessItem *pItem, BYTE* pucRegBuffer, WORD usAddress, WORD usNRegs); + eMBErrorCode eMBRegHoldingCB(CSubModbusTcpProcessItem *pItem, BYTE* pucRegBuffer, WORD usAddress, WORD usNRegs, eMBRegisterMode eMode); + eMBErrorCode eMBRegCoilsCB(CSubModbusTcpProcessItem *pItem, BYTE* pucRegBuffer, WORD usAddress, WORD usNCoils, eMBRegisterMode eMode); + eMBErrorCode eMBRegDiscreteCB(CSubModbusTcpProcessItem *pItem, BYTE* pucRegBuffer, WORD usAddress, WORD usNDiscrete); +}; + +#endif //_ZJD_SUB_MODBUS_TCP_PROCESS_H_