// // Created by pengx on 2025/3/18. // #include "methane_serial_port.hpp" #include "tcp_service.hpp" #include "constant_config.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> namespace beast = boost::beast; namespace http = beast::http; namespace net = boost::asio; using tcp = net::ip::tcp; void upload_to_server(const int value) { net::io_context ioc; tcp::resolver resolver{ioc}; auto const results = resolver.resolve(ConstantConfig::SERVICE_ADDRESS, ConstantConfig::HTTP_PORT); tcp::socket socket{ioc}; try { net::connect(socket, results.begin(), results.end()); // 构建HTTP请求 http::request<http::string_body> req{http::verb::post, ConstantConfig::API_RECEIVE_DATA, 11}; req.set(http::field::host, ConstantConfig::SERVICE_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"}} std::ostringstream oss; oss << R"({"type":6,"devcode":")" << ConstantConfig::DOG_CODE << R"(","data":{"gas":")" << value << R"("}})"; std::string body = oss.str(); 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(); } }); }