diff --git a/LFtid1056/LFtid1056.rc b/LFtid1056/LFtid1056.rc new file mode 100644 index 0000000..0fded0b --- /dev/null +++ b/LFtid1056/LFtid1056.rc @@ -0,0 +1,60 @@ +// Microsoft Visual C++ 生成的资源脚本。 +// + +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// 从 TEXTINCLUDE 2 资源生成。 +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// 中文(简体,中国) 资源 + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 4, 2 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // 中文(简体,中国) 资源 +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// 从 TEXTINCLUDE 3 资源生成。 +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // 不是 APSTUDIO_INVOKED diff --git a/LFtid1056/LFtid1056.vcxproj.filters b/LFtid1056/LFtid1056.vcxproj.filters new file mode 100644 index 0000000..fedcb19 --- /dev/null +++ b/LFtid1056/LFtid1056.vcxproj.filters @@ -0,0 +1,666 @@ +锘 + + + + + + + + cloudfront\code + + + cloudfront\code + + + cloudfront\code + + + cloudfront\code + + + cloudfront\code + + + cloudfront\code + + + cloudfront\code + + + + + + + + cloudfront\code + + + cloudfront\code + + + cloudfront\code + + + cloudfront\code + + + cloudfront\code + + + cloudfront\code\curl + + + cloudfront\code\curl + + + cloudfront\code\curl + + + cloudfront\code\curl + + + cloudfront\code\curl + + + cloudfront\code\curl + + + cloudfront\code\curl + + + cloudfront\code\curl + + + cloudfront\code\curl + + + cloudfront\code\curl + + + cloudfront\code\curl + + + cloudfront\code\curl + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\rocketmq + + + cloudfront\code\nlohmann + + + cloudfront\code\nlohmann + + + cloudfront\code\nlohmann + + + cloudfront\code\nlohmann + + + cloudfront\code\nlohmann + + + cloudfront\code\nlohmann\detail + + + cloudfront\code\nlohmann\detail + + + cloudfront\code\nlohmann\detail + + + cloudfront\code\nlohmann\detail + + + cloudfront\code\nlohmann\detail + + + cloudfront\code\nlohmann\detail + + + cloudfront\code\nlohmann\detail + + + cloudfront\code\nlohmann\detail + + + cloudfront\code\nlohmann\detail + + + cloudfront\code\nlohmann\detail + + + cloudfront\code\nlohmann\detail + + + cloudfront\code\nlohmann\thirdparty\hedley + + + cloudfront\code\nlohmann\thirdparty\hedley + + + cloudfront\code\nlohmann\detail\conversions + + + cloudfront\code\nlohmann\detail\conversions + + + cloudfront\code\nlohmann\detail\conversions + + + cloudfront\code\nlohmann\detail\input + + + cloudfront\code\nlohmann\detail\input + + + cloudfront\code\nlohmann\detail\input + + + cloudfront\code\nlohmann\detail\input + + + cloudfront\code\nlohmann\detail\input + + + cloudfront\code\nlohmann\detail\input + + + cloudfront\code\nlohmann\detail\iterators + + + cloudfront\code\nlohmann\detail\iterators + + + cloudfront\code\nlohmann\detail\iterators + + + cloudfront\code\nlohmann\detail\iterators + + + cloudfront\code\nlohmann\detail\iterators + + + cloudfront\code\nlohmann\detail\iterators + + + cloudfront\code\nlohmann\detail\meta + + + cloudfront\code\nlohmann\detail\meta + + + cloudfront\code\nlohmann\detail\meta + + + cloudfront\code\nlohmann\detail\meta + + + cloudfront\code\nlohmann\detail\meta + + + cloudfront\code\nlohmann\detail\meta + + + cloudfront\code\nlohmann\detail\meta + + + cloudfront\code\nlohmann\detail\meta\call_std + + + cloudfront\code\nlohmann\detail\meta\call_std + + + cloudfront\code\nlohmann\detail\output + + + cloudfront\code\nlohmann\detail\output + + + cloudfront\code\nlohmann\detail\output + + + cloudfront\code\log4cplus\boost + + + cloudfront\code\log4cplus\config + + + cloudfront\code\log4cplus\config + + + cloudfront\code\log4cplus\config + + + cloudfront\code\log4cplus\config + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\helpers + + + cloudfront\code\log4cplus\internal + + + cloudfront\code\log4cplus\internal + + + cloudfront\code\log4cplus\internal + + + cloudfront\code\log4cplus\internal + + + cloudfront\code\log4cplus\internal + + + cloudfront\code\log4cplus\spi + + + cloudfront\code\log4cplus\spi + + + cloudfront\code\log4cplus\spi + + + cloudfront\code\log4cplus\spi + + + cloudfront\code\log4cplus\spi + + + cloudfront\code\log4cplus\spi + + + cloudfront\code\log4cplus\spi + + + cloudfront\code\log4cplus\spi + + + cloudfront\code\log4cplus\thread + + + cloudfront\code\log4cplus\thread + + + cloudfront\code\log4cplus\thread + + + cloudfront\code\log4cplus\thread\impl + + + cloudfront\code\log4cplus\thread\impl + + + cloudfront\code\log4cplus\thread\impl + + + cloudfront\code\log4cplus\thread\impl + + + cloudfront\code\log4cplus\thread\impl + + + + + {e569c345-343c-4c70-b52e-1188cb7eb2a0} + + + {3aa4794b-faf1-449a-b331-d701ebafc085} + + + {f67e6a10-2961-4892-8537-bd8ab15a5bd3} + + + {9d9e729c-19ee-46f3-97be-d46b4fc4bb9a} + + + {17a8acb0-648d-4bb8-82f1-74a3c132e1ef} + + + {b22c4f25-4b96-48dc-bb52-7f642bc742d0} + + + {2b9bfc19-7f39-4a2f-80ad-f39e96a96b40} + + + {a0f6b856-c407-420c-86ef-4c48a3c4df2e} + + + {0cb06b60-69a9-4dd4-a963-4aedd6b4d7e3} + + + {73b4c759-6aba-40d3-8773-72a196af5a77} + + + {cb07968a-09c4-45ca-a73c-20d328df3216} + + + {3a75fc98-7cc2-4003-a060-73147b374fed} + + + {100fee77-5ece-4d12-b55e-2183e5790d1b} + + + {c10e4535-fe1d-4a33-a38f-29805e4e9b92} + + + {a147fc02-f373-49a8-a11f-a8914da54a7d} + + + {422223c2-2cfe-4998-b31d-7b59532b6d1f} + + + {dc41a517-5a25-4d36-848d-8a21c9e35117} + + + {f8ee7436-8072-4ba7-b219-3d33e410de0d} + + + {a66dc9bc-1acc-4048-adb2-7326395c7568} + + + {6039e9c3-2685-4a49-a08e-842dfc4d80d1} + + + {2f9e665b-d0f0-4de0-9b4d-23d002ec9990} + + + {b40f40d0-492d-4fcf-8125-4db493497930} + + + {d64ce5f1-cb40-4da4-a7da-766e5a2d1656} + + + + + cloudfront\code\curl + + + cloudfront\code\curl + + + cloudfront\code\curl + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus + + + cloudfront\code\log4cplus\config + + + cloudfront\code\lib + + + + + + cloudfront\code\lib + + + cloudfront\code\lib + + + cloudfront\code\lib + + + cloudfront\code\lib + + + \ No newline at end of file diff --git a/LFtid1056/RCa04916 b/LFtid1056/RCa04916 new file mode 100644 index 0000000..b8493ab Binary files /dev/null and b/LFtid1056/RCa04916 differ diff --git a/LFtid1056/RCa17100 b/LFtid1056/RCa17100 new file mode 100644 index 0000000..b8493ab Binary files /dev/null and b/LFtid1056/RCa17100 differ diff --git a/LFtid1056/RCb04916 b/LFtid1056/RCb04916 new file mode 100644 index 0000000..b8493ab Binary files /dev/null and b/LFtid1056/RCb04916 differ diff --git a/LFtid1056/RCb17100 b/LFtid1056/RCb17100 new file mode 100644 index 0000000..b8493ab Binary files /dev/null and b/LFtid1056/RCb17100 differ diff --git a/LFtid1056/client2.cpp b/LFtid1056/client2.cpp index b8cd6c5..1729d9b 100644 --- a/LFtid1056/client2.cpp +++ b/LFtid1056/client2.cpp @@ -1,283 +1,307 @@ -#include -#include -#include -#include -#include -#include "PQSMsg.h" #include "client2.h" +#include "PQSMsg.h" #include "dealMsg.h" +#include +#include +#include +#include +#include +#include // 閰嶇疆鍙傛暟 -#define CONNECTIONS 10 // 鏀寔1000涓苟鍙戣繛鎺 -#define SERVER_IP "101.132.39.45" // 鐩爣鏈嶅姟鍣↖P "101.132.39.45" -#define SERVER_PORT 1056 // 鐩爣鏈嶅姟鍣ㄧ鍙 -#define BASE_RECONNECT_DELAY 5000 // 鍩虹閲嶈繛寤惰繜(ms) -#define MAX_RECONNECT_DELAY 60000 // 鏈澶ч噸杩炲欢杩(ms) +constexpr int BASE_RECONNECT_DELAY = 5000; // 鍩虹閲嶈繛寤惰繜(ms) +constexpr int MAX_RECONNECT_DELAY = 60000; // 鏈澶ч噸杩炲欢杩(ms) +constexpr const char* SERVER_IP = "101.132.39.45"; // 鐩爣鏈嶅姟鍣↖P +constexpr int SERVER_PORT = 1056; // 鐩爣鏈嶅姟鍣ㄧ鍙 -static uv_loop_t* global_loop; // 鍏ㄥ眬浜嬩欢寰幆 -static client_context_t client_contexts[CONNECTIONS]; // 瀹㈡埛绔笂涓嬫枃鏁扮粍 -static uv_timer_t monitor_timer; // 杩炴帴鐩戞帶瀹氭椂鍣 +static uv_loop_t* global_loop = nullptr; +static std::vector> client_contexts; +static uv_timer_t monitor_timer; extern SafeMessageQueue message_queue; + +// ClientContext 瀹炵幇 +ClientContext::ClientContext(uv_loop_t* loop, const DeviceInfo& device, int index) + : loop(loop), state(ConnectionState::DISCONNECTED), + reconnect_attempts(0), shutdown(false), device_info(device), index_(index) { + + // 鍒濆鍖 TCP 鍙ユ焺 + uv_tcp_init(loop, &client); + client.data = this; + + // 鍒濆鍖栧畾鏃跺櫒 + uv_timer_init(loop, &timer); + timer.data = this; + + // 鍒濆鍖栭噸杩炲畾鏃跺櫒 + uv_timer_init(loop, &reconnect_timer); + reconnect_timer.data = this; +} + +ClientContext::~ClientContext() { + stop_timers(); + close_handles(); +} + +void ClientContext::init_tcp() { + if (!uv_is_active((uv_handle_t*)&client)) { + uv_tcp_init(loop, &client); + client.data = this; + } +} + +void ClientContext::start_timer() { + if (!uv_is_active((uv_handle_t*)&timer)) { + uv_timer_start(&timer, on_timer, 6000, 6000); + } +} + +void ClientContext::start_reconnect_timer(int delay) { + if (!uv_is_active((uv_handle_t*)&reconnect_timer)) { + uv_timer_start(&reconnect_timer, try_reconnect, delay, 0); + } +} + +void ClientContext::stop_timers() { + if (uv_is_active((uv_handle_t*)&timer)) uv_timer_stop(&timer); + if (uv_is_active((uv_handle_t*)&reconnect_timer)) uv_timer_stop(&reconnect_timer); +} + +void ClientContext::close_handles() { + if (!uv_is_closing((uv_handle_t*)&client)) { + uv_close((uv_handle_t*)&client, nullptr); + } + if (!uv_is_closing((uv_handle_t*)&timer)) { + uv_close((uv_handle_t*)&timer, nullptr); + } + if (!uv_is_closing((uv_handle_t*)&reconnect_timer)) { + uv_close((uv_handle_t*)&reconnect_timer, nullptr); + } +} + /* 缂撳啿鍖哄垎閰嶅洖璋 */ void alloc_buffer(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf) { - void* buffer = malloc(suggested_size); - if (!buffer) { - *buf = uv_buf_init(NULL, 0); - return; - } - *buf = uv_buf_init((char*)buffer, suggested_size); + buf->base = new char[suggested_size]; + buf->len = suggested_size; } /* 鏁版嵁璇诲彇鍥炶皟 */ void on_read(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { - client_context_t* ctx = (client_context_t*)stream->data; + ClientContext* ctx = static_cast(stream->data); if (nread < 0) { if (nread != UV_EOF) { - fprintf(stdout, "[Client %d] RECV ERROR: %s\n", - ctx->index, uv_strerror(nread)); + std::cerr << "[Device " << ctx->device_info.device_id + << "] RECV ERROR: " << uv_strerror(nread) << std::endl; } uv_close((uv_handle_t*)stream, on_close); - free(buf->base); + delete[] buf->base; return; } if (nread > 0) { // 灏嗘帴鏀跺埌鐨勬暟鎹斁鍏ユ秷鎭槦鍒 deal_message_t msg; - msg.client_index = ctx->index; - msg.data = (char*)malloc(nread); + msg.device_id = ctx->device_info.device_id; // 鐩存帴璧嬪 + msg.mac = ctx->device_info.mac; // 鐩存帴璧嬪 + + // 澶嶅埗娴嬬偣淇℃伅 + msg.points = ctx->device_info.points; + + msg.data = new char[nread]; msg.length = nread; memcpy(msg.data, buf->base, nread); if (!message_queue.push(msg)) { - fprintf(stderr, "[Client %d] Message queue full, dropping message\n", ctx->index); - free(msg.data); + std::cerr << "[Device " << ctx->device_info.device_id + << "] Message queue full, dropping message" << std::endl; + delete[] msg.data; } } - free(buf->base); + + delete[] buf->base; } /* 鏁版嵁鍐欏叆鍥炶皟 */ void on_write(uv_write_t* req, int status) { - client_context_t* ctx = (client_context_t*)req->handle->data; + ClientContext* ctx = static_cast(req->handle->data); if (status < 0) { - fprintf(stdout, "[Client %d] SEND ERROR: %s\n", - ctx->index, uv_strerror(status)); + std::cerr << "[Device " << ctx->device_info.device_id + << "] SEND ERROR: " << uv_strerror(status) << std::endl; } - free(req->data); // 閲婃斁鍙戦佹暟鎹紦鍐插尯 - free(req); // 閲婃斁鍐欏叆璇锋眰 + delete[] static_cast(req->data); // 閲婃斁鍙戦佹暟鎹紦鍐插尯 + delete req; // 閲婃斁鍐欏叆璇锋眰 } /* 瀹氭椂鍙戦佸洖璋 */ void on_timer(uv_timer_t* handle) { - client_context_t* ctx = (client_context_t*)handle->data; + ClientContext* ctx = static_cast(handle->data); - if (ctx->state != STATE_CONNECTED) { + if (ctx->state != ConnectionState::CONNECTED) { return; } - //鍗曚釜瑁呯疆瀹氭椂娑堟伅鏀跺彂鏈哄埗 - // 鐢熸垚瀹屾暣鎶ユ枃 瑁呯疆浜戞湇鍔$櫥褰曟姤鏂 - auto binary_data = generate_frontlogin_message("00-B7-8D-A8-00-D6"); - // 杞崲涓烘暟缁勫舰寮 - unsigned char* binary_array = binary_data.data(); - size_t data_size = binary_data.size(); + // 浣跨敤瑁呯疆鑷繁鐨凪AC鍦板潃鐢熸垚鐧诲綍鎶ユ枃 + auto binary_data = generate_frontlogin_message(ctx->device_info.mac); - // 姝ゅ鍙皟鐢ㄥ彂閫佸嚱鏁 - send_binary_data(ctx, binary_array, data_size); + // 璋冪敤鍙戦佸嚱鏁 + send_binary_data(ctx, binary_data.data(), binary_data.size()); + + // 鏍规嵁瑁呯疆鐘舵佸彂閫佸叾浠栨暟鎹 + if (ctx->device_info.status == 1) { // 鍦ㄧ嚎鐘舵 + // 鍙互鍙戦佽缃厤缃俊鎭垨娴嬬偣鏁版嵁 + } } + /* 鍙戦佷簩杩涘埗鎶ユ枃鍑芥暟 */ -void send_binary_data(client_context_t* ctx, const unsigned char* data, size_t data_size) { - if (ctx->state != STATE_CONNECTED) { - fprintf(stderr, "[Client %d] Cannot send binary data: not connected\n", ctx->index); +void send_binary_data(ClientContext* ctx, const unsigned char* data, size_t data_size) { + if (ctx->state != ConnectionState::CONNECTED) { + std::cerr << "[Device " << ctx->device_info.device_id + << "] Cannot send: not connected" << std::endl; return; } - uv_buf_t buf = uv_buf_init((char*)data, data_size); - uv_write_t* write_req = (uv_write_t*)malloc(sizeof(uv_write_t)); - if (!write_req) { - fprintf(stderr, "[Client %d] Failed to allocate write request\n", ctx->index); - return; - } - write_req->data = NULL; // 涓嶉渶瑕侀澶栨暟鎹紝鍥犱负data宸茬粡浼犲叆 - //fprintf(stdout, "[Client %d] Sending initial %zu bytes data\n", ctx->index, data_size); + uv_buf_t buf = uv_buf_init(const_cast(reinterpret_cast(data)), data_size); + uv_write_t* write_req = new uv_write_t; + + // 澶嶅埗鏁版嵁浠ョ‘淇濆畨鍏 + char* data_copy = new char[data_size]; + memcpy(data_copy, data, data_size); + write_req->data = data_copy; int ret = uv_write(write_req, (uv_stream_t*)&ctx->client, &buf, 1, on_write); if (ret < 0) { - fprintf(stderr, "[Client %d] uv_write failed: %s\n", ctx->index, uv_strerror(ret)); - free(write_req); + std::cerr << "[Device " << ctx->device_info.device_id + << "] uv_write failed: " << uv_strerror(ret) << std::endl; + delete[] data_copy; + delete write_req; } - // 娉ㄦ剰锛氳繖閲屼笉闇瑕侀噴鏀綿ata锛屽洜涓篸ata鏄敱璋冪敤鑰呯鐞嗙殑 } + /* 杩炴帴鍏抽棴鍥炶皟 */ void on_close(uv_handle_t* handle) { - client_context_t* ctx = (client_context_t*)handle->data; - ctx->state = STATE_DISCONNECTED; - fprintf(stderr, "[Client %d] closed\n", ctx->index); - // 鍋滄瀹氭椂鍣 - uv_timer_stop(&ctx->timer); - uv_timer_stop(&ctx->reconnect_timer); + ClientContext* ctx = static_cast(handle->data); + ctx->state = ConnectionState::DISCONNECTED; + std::cerr << "[Device " << ctx->device_info.device_id << "] Connection closed" << std::endl; + + ctx->stop_timers(); - // 鑷姩閲嶈繛閫昏緫 if (!ctx->shutdown) { int delay = BASE_RECONNECT_DELAY * pow(2, ctx->reconnect_attempts); delay = delay > MAX_RECONNECT_DELAY ? MAX_RECONNECT_DELAY : delay; - fprintf(stdout, "[Client %d] Reconnecting in %dms (attempt %d)\n", - ctx->index, delay, ctx->reconnect_attempts + 1); + std::cout << "[Device " << ctx->device_info.device_id + << "] Reconnecting in " << delay << "ms (attempt " + << ctx->reconnect_attempts + 1 << ")" << std::endl; ctx->reconnect_attempts++; - uv_timer_start(&ctx->reconnect_timer, try_reconnect, delay, 0); + ctx->start_reconnect_timer(delay); } } /* 灏濊瘯閲嶈繛 */ void try_reconnect(uv_timer_t* timer) { - client_context_t* ctx = (client_context_t*)timer->data; + ClientContext* ctx = static_cast(timer->data); - if (ctx->state != STATE_DISCONNECTED || ctx->shutdown) { + if (ctx->state != ConnectionState::DISCONNECTED || ctx->shutdown) { return; } - fprintf(stderr, "[Client %d] try_reconnect\n", ctx->index); - // 閲嶆柊鍒濆鍖朤CP鍙ユ焺 - uv_tcp_init(ctx->loop, &ctx->client); - ctx->client.data = ctx; - ctx->state = STATE_CONNECTING; + + std::cerr << "[Device " << ctx->device_info.device_id << "] Attempting reconnect" << std::endl; + + ctx->init_tcp(); + ctx->state = ConnectionState::CONNECTING; struct sockaddr_in addr; uv_ip4_addr(SERVER_IP, SERVER_PORT, &addr); - uv_connect_t* req = (uv_connect_t*)malloc(sizeof(uv_connect_t)); + uv_connect_t* req = new uv_connect_t; req->data = ctx; int ret = uv_tcp_connect(req, &ctx->client, (const struct sockaddr*)&addr, on_connect); if (ret < 0) { - fprintf(stderr, "[Client %d] Connect error: %s\n", ctx->index, uv_strerror(ret)); - free(req); + std::cerr << "[Device " << ctx->device_info.device_id + << "] Connect error: " << uv_strerror(ret) << std::endl; + delete req; uv_close((uv_handle_t*)&ctx->client, on_close); } } /* 杩炴帴寤虹珛鍥炶皟 */ void on_connect(uv_connect_t* req, int status) { - client_context_t* ctx = (client_context_t*)req->data; + ClientContext* ctx = static_cast(req->data); + delete req; if (status < 0) { - fprintf(stderr, "[Client %d] Connect failed: %s\n", ctx->index, uv_strerror(status)); - // 鐩存帴鍏抽棴鍙ユ焺锛岄伩鍏嶅悗缁噸澶嶅叧闂 + std::cerr << "[Device " << ctx->device_info.device_id + << "] Connect failed: " << uv_strerror(status) << std::endl; if (!uv_is_closing((uv_handle_t*)&ctx->client)) { - uv_close((uv_handle_t*)&ctx->client, NULL); + uv_close((uv_handle_t*)&ctx->client, on_close); } - free(req); return; } - fprintf(stderr, "[Client %d] on_connect\n", ctx->index); - ctx->state = STATE_CONNECTED; + + std::cerr << "[Device " << ctx->device_info.device_id << "] Connected to server" << std::endl; + + ctx->state = ConnectionState::CONNECTED; ctx->reconnect_attempts = 0; - // 鍚姩鏁版嵁鎺ユ敹 uv_read_start((uv_stream_t*)&ctx->client, alloc_buffer, on_read); - - // 鍚姩瀹氭椂鍙戦 - uv_timer_start(&ctx->timer, on_timer, 6000, 6000); - - free(req); + ctx->start_timer(); } /* 鍒濆鍖栨墍鏈夊鎴风杩炴帴 */ -void init_clients(uv_loop_t* loop) { - for (int i = 0; i < CONNECTIONS; i++) { - client_context_t* ctx = &client_contexts[i]; - memset(ctx, 0, sizeof(client_context_t)); - - ctx->loop = loop; - ctx->index = i; - ctx->state = STATE_DISCONNECTED; - - // 鍒濆鍖朤CP鍙ユ焺 - uv_tcp_init(loop, &ctx->client); - ctx->client.data = ctx; - - // 鍒濆鍖栧畾鏃跺櫒 - uv_timer_init(loop, &ctx->timer); - ctx->timer.data = ctx; - - // 鍒濆鍖栭噸杩炲畾鏃跺櫒 - uv_timer_init(loop, &ctx->reconnect_timer); - ctx->reconnect_timer.data = ctx; - - // 棣栨杩炴帴 - try_reconnect(&ctx->reconnect_timer); +void init_clients(uv_loop_t* loop, const std::vector& devices) { + client_contexts.clear(); + for (size_t i = 0; i < devices.size(); i++) { + // 淇敼涓篊++11鍏煎鐨剈nique_ptr鍒涘缓鏂瑰紡 + client_contexts.push_back( + std::unique_ptr( + new ClientContext(loop, devices[i], i) + ) + ); + try_reconnect(&client_contexts.back()->reconnect_timer); } } /* 鍋滄鎵鏈夊鎴风 */ void stop_all_clients() { - for (int i = 0; i < CONNECTIONS; i++) { - client_context_t* ctx = &client_contexts[i]; - ctx->shutdown = 1; - - // 鍏抽棴鎵鏈夊彞鏌 - if (!uv_is_closing((uv_handle_t*)&ctx->client)) { - uv_close((uv_handle_t*)&ctx->client, NULL); - } - if (!uv_is_closing((uv_handle_t*)&ctx->timer)) { - uv_close((uv_handle_t*)&ctx->timer, NULL); - } - if (!uv_is_closing((uv_handle_t*)&ctx->reconnect_timer)) { - uv_close((uv_handle_t*)&ctx->reconnect_timer, NULL); - } + for (auto& ctx : client_contexts) { + ctx->shutdown = true; + ctx->close_handles(); } + client_contexts.clear(); } + /* 杩炴帴鐩戞帶鍥炶皟 */ void monitor_connections(uv_timer_t* handle) { - // 鑷姩鎭㈠鏂紑鐨勮繛鎺 static int recovery_counter = 0; - if (++recovery_counter >= 5) { // 姣5娆$洃鎺ф墽琛屼竴娆℃仮澶 + if (++recovery_counter >= 5) { int active_count = 0; - for (int i = 0; i < CONNECTIONS; i++) { - if (client_contexts[i].state == STATE_CONNECTED) { + for (const auto& ctx : client_contexts) { + if (ctx->state == ConnectionState::CONNECTED) { active_count++; } } - printf("Active connections: %d/%d\n", active_count, CONNECTIONS); + std::cout << "Active connections: " << active_count << "/" << client_contexts.size() << std::endl; recovery_counter = 0; } - - //static int monitor_temp = 0; - //monitor_temp++; - //if (monitor_temp >= 30) { - // monitor_temp = 0; - // printf("30 second to stop all client\n"); - // // 鍋滄骞跺叧闂洃鎺у畾鏃跺櫒 - // uv_timer_stop(handle); - // uv_close((uv_handle_t*)handle, NULL); - // - // // 鍋滄鎵鏈夊鎴风 - // stop_all_clients(); - // - // // 鍋滄浜嬩欢寰幆 - // uv_stop(global_loop); - //} } static void close_walk_cb(uv_handle_t* handle, void* arg) { if (!uv_is_closing(handle)) { - fprintf(stderr, "Force closing leaked handle: %p (type=%d)\n", - handle, handle->type); - uv_close(handle, NULL); + uv_close(handle, nullptr); } } -void start_client_connect() { +/* 鍚姩瀹㈡埛绔繛鎺 */ +void start_client_connect(const std::vector& devices) { // 鍒涘缓鍏ㄥ眬浜嬩欢寰幆 global_loop = uv_default_loop(); // 鍒濆鍖栨墍鏈夊鎴风 - init_clients(global_loop); + init_clients(global_loop, devices); // 鍚姩杩炴帴鐩戞帶 uv_timer_init(global_loop, &monitor_timer); @@ -294,10 +318,13 @@ void start_client_connect() { // 瀹夊叏鍏抽棴浜嬩欢寰幆 int err = uv_loop_close(global_loop); if (err) { - fprintf(stderr, "uv_loop_close error: %s\n", uv_strerror(err)); + std::cerr << "uv_loop_close error: " << uv_strerror(err) << std::endl; // 寮哄埗娓呯悊娈嬬暀鍙ユ焺锛堣皟璇曠敤锛 - uv_walk(global_loop, close_walk_cb, NULL); + uv_walk(global_loop, close_walk_cb, nullptr); uv_run(global_loop, UV_RUN_NOWAIT); } - global_loop = NULL; -} + + // 娓呯悊鎵鏈夊鎴风 + stop_all_clients(); + global_loop = nullptr; +} \ No newline at end of file diff --git a/LFtid1056/client2.h b/LFtid1056/client2.h index 20d7fb2..8b7449b 100644 --- a/LFtid1056/client2.h +++ b/LFtid1056/client2.h @@ -1,33 +1,63 @@ -#include -#include -#include #include -#include -#include -#include +#include +#include +#include -/* 连接状态枚举 */ -typedef enum { - STATE_DISCONNECTED, // 未连接状态 - STATE_CONNECTING, // 连接中状态 - STATE_CONNECTED // 已连接状态 -} connection_state_t; +// 测点信息结构 +struct PointInfo { + std::string point_id; // 测点ID + std::string name; // 测点名称 + std::string device_id; // 所属装置ID + double PT1; // 电压变比1 + double PT2; // 电压变比2 + double CT1; // 电流变比1 + double CT2; // 电流变比2 +}; -/* 客户端上下文结构体 */ -typedef struct { - uv_loop_t* loop; // libuv事件循环 - uv_tcp_t client; // TCP客户端句柄 - int index; // 客户端索引 - uv_timer_t timer; // 数据发送定时器 - uv_timer_t reconnect_timer;// 重连定时器 - connection_state_t state; // 当前连接状态 - int reconnect_attempts; // 当前重连次数 - volatile int shutdown; // 关闭标志 (新增) -} client_context_t; -//函数声明 -void try_reconnect(uv_timer_t* timer);//客户端重连回调 -void on_connect(uv_connect_t* req, int status);//客户端连接回调 -void on_close(uv_handle_t* handle);//客户端断开回调 -void stop_all_clients(); // 新增函数 停止所有客户端连接 -void start_client_connect();//启动客户端连接 -void send_binary_data(client_context_t* ctx, const unsigned char* data, size_t data_size); \ No newline at end of file +// 装置信息结构 +struct DeviceInfo { + std::string device_id; // 装置ID + std::string name; // 装置名称 + std::string model; // 装置型号 + std::string mac; // 装置MAC地址 + int status; // 运行状态 (0: 离线, 1: 在线) + std::vector points; // 下属测点 +}; + +enum class ConnectionState { + DISCONNECTED, + CONNECTING, + CONNECTED +}; + +class ClientContext { +public: + uv_loop_t* loop; + uv_tcp_t client; + uv_timer_t timer; + uv_timer_t reconnect_timer; + ConnectionState state; + int reconnect_attempts; + volatile bool shutdown; + DeviceInfo device_info; // 装置信息 + + ClientContext(uv_loop_t* loop, const DeviceInfo& device, int index); + ~ClientContext(); + + void init_tcp(); + void start_timer(); + void start_reconnect_timer(int delay); + void stop_timers(); + void close_handles(); + +private: + int index_; +}; + +// 函数声明 +void start_client_connect(const std::vector& devices); +void send_binary_data(ClientContext* ctx, const unsigned char* data, size_t data_size); +void on_timer(uv_timer_t* handle);//装置定时回调 +void try_reconnect(uv_timer_t* timer);//装置重连回调 +void on_connect(uv_connect_t* req, int status);//装置连接回调 +void on_close(uv_handle_t* handle);//装置关闭回调 \ No newline at end of file diff --git a/LFtid1056/dealMsg.cpp b/LFtid1056/dealMsg.cpp index 7b47c24..5a83df4 100644 --- a/LFtid1056/dealMsg.cpp +++ b/LFtid1056/dealMsg.cpp @@ -10,14 +10,15 @@ #include "PQSMsg.h" #include "client2.h" #include "dealMsg.h" +#include +using namespace std; SafeMessageQueue message_queue; // 全局消息队列 -void process_received_message(int client_index, const char* data, size_t length) { +void process_received_message(string mac, const char* data, size_t length) { // 实际的消息处理逻辑 // 这里可以添加您的业务处理代码 - printf("Processing message from client %d, size: %zu\n", client_index, length); - + std::cout << "Active connections: " << mac << " size:" << length << std::endl; // 示例:解析消息并处理 // 注意:根据您的协议实现具体的解析逻辑 } diff --git a/LFtid1056/dealMsg.h b/LFtid1056/dealMsg.h index 8550547..56cbe82 100644 --- a/LFtid1056/dealMsg.h +++ b/LFtid1056/dealMsg.h @@ -7,16 +7,19 @@ #include #include #include - +#include +using namespace std; /* 常量定义 */ #define MESSAGE_QUEUE_SIZE 10000 // 消息队列容量 -/* 消息结构体 */ -typedef struct { - int client_index; // 客户端索引 - char* data; // 消息数据 - size_t length; // 消息长度 -} deal_message_t; +// 修改后的 deal_message_t 结构 +struct deal_message_t { + std::string device_id; // 使用 std::string 代替 char 数组 + std::string mac; // 使用 std::string 代替 char 数组 + char* data; // 接收到的数据 + size_t length; // 数据长度 + std::vector points; // 关联的测点信息 +}; /* 线程安全的消息队列 */ class SafeMessageQueue { @@ -57,4 +60,4 @@ public: } }; -void process_received_message(int client_index, const char* data, size_t length); \ No newline at end of file +void process_received_message(string mac, const char* data, size_t length); \ No newline at end of file diff --git a/LFtid1056/main_thread.cpp b/LFtid1056/main_thread.cpp index af393b0..19dc836 100644 --- a/LFtid1056/main_thread.cpp +++ b/LFtid1056/main_thread.cpp @@ -78,7 +78,29 @@ void* client_manager_thread(void* arg) { printf("Started client connections\n"); - start_client_connect(); + // 创建测点数据 + std::vector points1 = { + {"P001", "Main Voltage", "D001", 10.0, 0.0, 100.0, 0.0}, + {"P002", "Backup Voltage", "D001", 5.0, 0.0, 50.0, 0.0} + }; + + std::vector points2 = { + {"P101", "Generator Output", "D002", 20.0, 0.0, 200.0, 0.0} + }; + + // 创建装置列表 + std::vector devices = { + { + "D001", "Primary Device", "Model-X", "00-B7-8D-A8-00-D1", + 1, points1 + }, + { + "D002", "Backup Device", "Model-Y", "00-B7-8D-A8-00-D6", + 1, points2 + } + }; + + start_client_connect(devices); printf("Stopped all client connections\n"); @@ -108,11 +130,9 @@ void* message_processor_thread(void* arg) { // 实际消息处理逻辑 // 注意:这里需要根据msg.client_index区分客户端 // 处理完成后释放内存 - printf("Processing message from client %d, length: %zu\n", - msg.client_index, msg.length); // 调用实际的消息处理函数 - process_received_message(msg.client_index, msg.data, msg.length); + process_received_message(msg.mac, msg.data, msg.length); free(msg.data); } diff --git a/LFtid1056/resource.h b/LFtid1056/resource.h new file mode 100644 index 0000000..6a29061 --- /dev/null +++ b/LFtid1056/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by LFtid1056.rc + +// 新对象的下一组默认值 +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif