// // Created by pengx on 2025/3/18. // #include "methane_serial_port.hpp" #include <iomanip> #include <iostream> #include <boost/beast/core.hpp> #include <boost/beast/http.hpp> #include <boost/beast/version.hpp> #include <boost/asio/connect.hpp> #include <boost/asio/ip/tcp.hpp> #include "tcp_service.hpp" namespace beast = boost::beast; namespace http = beast::http; namespace net = boost::asio; using tcp = net::ip::tcp; void upload_to_server(const int value) { //TODO 根据实际情况修改为服务器TCP客户端HTTP和端口 const std::string server_address = "192.168.123.125"; const std::string server_port = "30028"; const std::string dog_code = "B42D4000OCAD3N82"; net::io_context ioc; tcp::resolver resolver{ioc}; auto const results = resolver.resolve(server_address, server_port); tcp::socket socket{ioc}; try { net::connect(socket, results.begin(), results.end()); // 构建HTTP请求 http::request<http::string_body> req{http::verb::post, "/device/receiveData", 11}; req.set(http::field::host, server_address); req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); req.set(http::field::content_type, "application/json"); req.set(http::field::connection, "keep-alive"); //{"type":6,"devcode":"1212","data":{"gas":"20"}} const std::string body = R"({"type":6,"devcode":")" + dog_code + R"(","data":{"gas":")" + std::to_string(value) + "\"}}"; req.body() = body; req.prepare_payload(); // 发送HTTP请求 http::write(socket, req); } catch (std::exception const &e) { std::cerr << "Error: " << e.what() << std::endl; if (socket.is_open()) { socket.shutdown(tcp::socket::shutdown_both); socket.close(); } } } void MethaneSerialPort::upload_to_server_async(const int value) { post(io_service_, [this, value] { upload_to_server(value); }); } void MethaneSerialPort::handle_response(const std::vector<uint8_t> &buffer) { const auto x = buffer[2]; const auto y = buffer[3]; const auto z = buffer[4]; const auto w = buffer[5]; const auto result = x * (1 << 24) + y * (1 << 16) + z * (1 << 8) + w; TcpService::getInstance().update_gas_value(result); //上传到服务器 upload_to_server_async(result); } MethaneSerialPort::MethaneSerialPort( boost::asio::io_service &io_service, const std::string &port_name, const int baud_rate ): io_service_(io_service), port_(io_service, port_name), timer_(io_service) { port_.set_option(serial_port_base::baud_rate(baud_rate)); port_.set_option(serial_port_base::character_size(8)); port_.set_option(serial_port_base::parity(serial_port_base::parity::none)); port_.set_option(serial_port_base::stop_bits(serial_port_base::stop_bits::one)); std::cout << "MethaneSerialPort init success" << std::endl; start_timer(); } void MethaneSerialPort::start_timer() { timer_.expires_from_now(boost::posix_time::seconds(3)); timer_.async_wait([this](const boost::system::error_code &error) { if (!error) { read_from_port(); } }); } //CC 05 00 00 00 00 0D 77 void MethaneSerialPort::read_from_port() { // 检查缓冲区中是否有足够的数据 if (buffer_.size() >= 8) { std::istream is(&buffer_); std::vector<uint8_t> response(8); is.read(reinterpret_cast<char *>(response.data()), 8); // 检查数据包的头和尾 if (response[0] == 0xCC && response[7] == 0x77) { // 数据包完整且正确 std::cout << "received 8 bytes: "; for (size_t i = 0; i < 8; ++i) { std::cout << std::hex << std::uppercase << std::setw(2) << std::setfill('0') << static_cast<int>(response[i]) << " "; } std::cout << std::endl; handle_response(response); // 清空 buffer_,确保不缓存数据 buffer_.consume(8); } else { // 数据包不完整或不正确,丢弃该数据包 buffer_.consume(1); // 丢弃第一个字节并重新开始 } // 重新启动定时器 start_timer(); return; } async_read( port_, buffer_, boost::asio::transfer_at_least(1), [this](const boost::system::error_code &error, const size_t) mutable { if (!error) { read_from_port(); // 递归调用以继续检查数据 } else { // 清空 buffer_,即使发生错误 buffer_.consume(buffer_.size()); start_timer(); } }); }