diff --git a/include/serial.h b/include/serial.h index 5dd424a..44a257f 100644 --- a/include/serial.h +++ b/include/serial.h @@ -22,267 +22,297 @@ namespace ranges = std::ranges; namespace views = std::views; namespace serial { -template struct _StrongType {}; + template struct _StrongType {}; -template struct _StrongType { - using Type = T; -}; + template struct _StrongType { + using Type = T; + }; -template struct _StrongType { - using Type = decltype(true ? std::declval() : std::declval()); -}; + template struct _StrongType { + using Type = decltype(true ? std::declval() : std::declval()); + }; -template struct _StrongType { - using Type = - typename _StrongType::Type>::Type; -}; + template struct _StrongType { + using Type = + typename _StrongType::Type>::Type; + }; -template -using _strongType_t = typename _StrongType::Type; + template + using _strongType_t = typename _StrongType::Type; -template struct _IsCastable {}; + template struct _IsCastable {}; -template struct _IsCastable { - static constexpr bool value = true; - using Type = T; -}; + template struct _IsCastable { + static constexpr bool value = true; + using Type = T; + }; -template struct _IsCastable { - using __TRUE = char; - using __FALSE = struct { - char _[2]; - }; - static consteval __TRUE __TEST(U); - static consteval __FALSE __TEST(...); - static constexpr bool value = - sizeof(__TEST(std::declval())) == sizeof(__TRUE); - using Type = std::conditional_t; -}; + template struct _IsCastable { + using __TRUE = char; + using __FALSE = struct { + char _[2]; + }; + static consteval __TRUE __TEST(U); + static consteval __FALSE __TEST(...); + static constexpr bool value = + sizeof(__TEST(std::declval())) == sizeof(__TRUE); + using Type = std::conditional_t; + }; -template struct _IsCastable { - static constexpr bool value = - _IsCastable::Type>::value; - using Type = - std::conditional_t::Type, void>; -}; + template struct _IsCastable { + static constexpr bool value = + _IsCastable::Type>::value; + using Type = + std::conditional_t::Type, void>; + }; -template -concept _SupportString = requires { - _IsCastable::value; -}; -template <_SupportString T> [[maybe_unused]] std::string _to_string(T &&str) { - if constexpr (std::is_same_v, std::string>) { - return str; - } else if constexpr (std::is_same_v, std::string_view>) { - return std::move(std::string(str.data())); - } else if constexpr (std::is_same_v, const char *>) { - return std::string(str); - } -} + template + concept _SupportString = requires { + _IsCastable::value; + }; + template <_SupportString T> [[maybe_unused]] std::string _to_string(T&& str) { + if constexpr (std::is_same_v, std::string>) { + return str; + } + else if constexpr (std::is_same_v, std::string_view>) { + return std::move(std::string(str.data())); + } + else if constexpr (std::is_same_v, const char*>) { + return std::string(str); + } + } -static std::vector GetUsbPorts() { + static std::vector GetUsbPorts() { #if defined(_WIN32) || defined(_WIN64) - std::vector portArray; - std::string comname; - std::string showname; - ranges::for_each(views::iota(1, 256), [&](int i) { - std::format_to(std::back_inserter(comname), "\\\\.\\COM{}", i); - std::format_to(std::back_inserter(showname), "COM{}", i); - const HANDLE m_handle = ::CreateFileA( - comname.c_str(), static_cast(GENERIC_WRITE) | GENERIC_READ, - 0U, nullptr, OPEN_EXISTING, 0U, nullptr); - if (m_handle != INVALID_HANDLE_VALUE) { - portArray.push_back(showname); - CloseHandle(m_handle); - } - comname.clear(); - showname.clear(); - }); - return portArray; + std::vector portArray; + std::string comname; + std::string showname; + ranges::for_each(views::iota(1, 256), [&](int i) { + std::format_to(std::back_inserter(comname), "\\\\.\\COM{}", i); + std::format_to(std::back_inserter(showname), "COM{}", i); + const HANDLE m_handle = ::CreateFileA( + comname.c_str(), static_cast(GENERIC_WRITE) | GENERIC_READ, + 0U, nullptr, OPEN_EXISTING, 0U, nullptr); + if (m_handle != INVALID_HANDLE_VALUE) { + portArray.push_back(showname); + CloseHandle(m_handle); + } + comname.clear(); + showname.clear(); + }); + return portArray; #elif defined(__linux__) #endif -} + } -enum class [[maybe_unused]] SerialErrorCode { - SUCCESS, - TIMEOUT, - SETTIMEOUTERROR, - WRITEINGERROR, - READINGERROR, -}; + enum class [[maybe_unused]] SerialErrorCode { + SUCCESS, + TIMEOUT, + SETTIMEOUTERROR, + WRITEINGERROR, + READINGERROR, + }; -enum SerialDataBits { - DATABIT_5 = 0, - DATABIT_6, - DATABIT_7, - DATABIT_8, - DATABIT_16, -}; -enum SerialStopBits { - STOPBIT_1 = 0, - STOPBIT_1_5, - STOPBIT_2, -}; -enum SerialParity { - SERIAL_PARITY_NONE = 0, - SERIAL_PARITY_EVEN, - SERIAL_PARITY_ODD, - SERIAL_PARITY_MARK, - SERIAL_PARITY_SPACE, -}; + enum SerialDataBits { + DATABIT_5 = 0, + DATABIT_6, + DATABIT_7, + DATABIT_8, + DATABIT_16, + }; + enum SerialStopBits { + STOPBIT_1 = 0, + STOPBIT_1_5, + STOPBIT_2, + }; + enum SerialParity { + SERIAL_PARITY_NONE = 0, + SERIAL_PARITY_EVEN, + SERIAL_PARITY_ODD, + SERIAL_PARITY_MARK, + SERIAL_PARITY_SPACE, + }; -class Serial { - private: - serialib ser; - const char *endChar = "\r\n"; - std::function logCallBack; - bool removeEcho = true; // 剔除回显 + class Serial { + private: + serialib ser; + const char* endChar = "\r\n"; + std::function logCallBack; + bool removeEcho = true; // 剔除回显 - public: - Serial() = default; - ~Serial() { CloseDevice(); } - Serial(const Serial &other) = delete; - Serial(Serial &&other) = delete; - Serial &operator=(const Serial &other) = delete; - Serial &operator=(Serial &&other) = delete; + public: + Serial() = default; + ~Serial() { CloseDevice(); } + Serial(const Serial& other) = delete; + Serial(Serial&& other) = delete; + Serial& operator=(const Serial& other) = delete; + Serial& operator=(Serial&& other) = delete; - auto SetRemoveEcho(bool remove) { removeEcho = remove; } - auto SetDtr(bool flag) { return flag ? ser.setDTR() : ser.clearDTR(); } - auto SetRts(bool flag) { return flag ? ser.setRTS() : ser.clearRTS(); } + auto SetRemoveEcho(bool remove) { removeEcho = remove; } + auto SetDtr(bool flag) { return flag ? ser.setDTR() : ser.clearDTR(); } + auto SetRts(bool flag) { return flag ? ser.setRTS() : ser.clearRTS(); } - static std::string GetTimeNow() { - auto now = std::chrono::system_clock::now(); - auto now_c = std::chrono::system_clock::to_time_t(now); - char buffer[32]; - auto _ = ctime_s(buffer, 32, &now_c); - return buffer; - } + static std::string GetTimeNow() { + auto now = std::chrono::system_clock::now(); + auto now_c = std::chrono::system_clock::to_time_t(now); + char buffer[32]; + auto _ = ctime_s(buffer, 32, &now_c); + return buffer; + } - bool IsOpen() { return ser.isDeviceOpen(); } + bool IsOpen() { return ser.isDeviceOpen(); } - template <_SupportString T> - bool OpenDevice(T portName, unsigned int bauds = 115200, int delayTime = 0, - SerialDataBits dataBits = SerialDataBits::DATABIT_8, - SerialStopBits stopBits = SerialStopBits::STOPBIT_1, - SerialParity parity = SerialParity::SERIAL_PARITY_NONE) { + template <_SupportString T> + bool OpenDevice(T portName, unsigned int bauds = 115200, int delayTime = 0, + SerialDataBits dataBits = SerialDataBits::DATABIT_8, + SerialStopBits stopBits = SerialStopBits::STOPBIT_1, + SerialParity parity = SerialParity::SERIAL_PARITY_NONE) { #if defined(_WIN32) || defined(__WIN64) - std::string reallyPortName; - std::format_to(std::back_inserter(reallyPortName), "\\\\.\\{}", - portName); + std::string reallyPortName; + std::format_to(std::back_inserter(reallyPortName), "\\\\.\\{}", + portName); #elif defined(__linux__) - std::string reallyPortName = std::string(portName); + std::string reallyPortName = std::string(portName); #endif - std::this_thread::sleep_for(std::chrono::milliseconds(delayTime)); - if (ser.isDeviceOpen()) - ser.closeDevice(); + std::this_thread::sleep_for(std::chrono::milliseconds(delayTime)); + if (ser.isDeviceOpen()) + ser.closeDevice(); - int code = ser.openDevice(reallyPortName.c_str(), bauds, - static_cast<::SerialDataBits>(dataBits), - static_cast<::SerialParity>(parity), - static_cast<::SerialStopBits>(stopBits)); - if (code == 1) { - return true; - } else { - return false; - } - } + int code = ser.openDevice(reallyPortName.c_str(), bauds, + static_cast<::SerialDataBits>(dataBits), + static_cast<::SerialParity>(parity), + static_cast<::SerialStopBits>(stopBits)); + if (code == 1) { + return true; + } + else { + return false; + } + } - void Log(const std::string &log) const { - if (logCallBack) { - auto msg = GetTimeNow() + " " + log; - logCallBack(msg); - } - } + void Log(const std::string& log) const { + if (logCallBack) { + auto msg = GetTimeNow() + " " + log; + logCallBack(msg); + } + } - void - SetLogCallBack(const std::function &callBack) { - logCallBack = callBack; - } - void CloseDevice() { - if (!ser.isDeviceOpen()) - return; - ser.closeDevice(); - } + void + SetLogCallBack(const std::function& callBack) { + logCallBack = callBack; + } + void CloseDevice() { + if (!ser.isDeviceOpen()) + return; + ser.closeDevice(); + } - template <_SupportString T> - std::expected - DelayGetResponse(int delayTime, T command, int timeout = 50) { - std::this_thread::sleep_for(std::chrono::milliseconds(delayTime)); - return GetAtResponse(command, timeout); - } + template <_SupportString T> + std::expected + DelayGetResponse(int delayTime, T command, int timeout = 50) { + std::this_thread::sleep_for(std::chrono::milliseconds(delayTime)); + return GetAtResponse(command, timeout); + } - template - bool GetAtUntilRepeat(T command, Args... args) { - std::stringstream ss; - int i = 0; - while (i++ < repeatTime) { - ss.str(""); - ss << "Count: " << i << "\n"; - Log(ss.str()); - std::this_thread::sleep_for(std::chrono::milliseconds(delayTime)); - if (GetAtUntil(command, args...)) - return true; - } - return false; - } + template + bool GetAtUntilRepeat(T command, Args... args) { + std::stringstream ss; + int i = 0; + while (i++ < repeatTime) { + ss.str(""); + ss << "Count: " << i << "\n"; + Log(ss.str()); + std::this_thread::sleep_for(std::chrono::milliseconds(delayTime)); + if (GetAtUntil(command, args...)) + return true; + } + return false; + } - template <_SupportString T> - std::expected - GetAtResponse(T command, int timeout = 50) { - ser.flushReceiver(); - std::string reallyCommand = std::string(command) + endChar; - ser.writeString(reallyCommand.c_str()); - Log("Send: " + reallyCommand); - std::this_thread::sleep_for(10ms); - auto availableSize = ser.available(); - auto buffer = std::make_unique(availableSize + 1); - std::memset(buffer.get(), 0, availableSize); - auto size = ser.readBytes(buffer.get(), availableSize, timeout); + template <_SupportString T> + std::expected + GetAtResponse(T command, int timeout = 50) { + ser.flushReceiver(); + std::string reallyCommand = std::string(command) + endChar; + ser.writeString(reallyCommand.c_str()); + Log("Send: " + reallyCommand); + std::this_thread::sleep_for(10ms); + auto availableSize = ser.available(); + auto buffer = std::make_unique(availableSize + 1); + std::memset(buffer.get(), 0, availableSize); + auto size = ser.readBytes(buffer.get(), availableSize, timeout); - if (size > 0) { - buffer[size] = '\0'; - std::string response = std::string(buffer.get()); - Log("Receive: " + response); - if (removeEcho) - response.replace(0, reallyCommand.length(), ""); - return response; - } - return std::unexpected(SerialErrorCode::TIMEOUT); - } + if (size > 0) { + buffer[size] = '\0'; + std::string response = std::string(buffer.get()); + Log("Receive: " + response); + if (removeEcho) + response.replace(0, reallyCommand.length(), ""); + return response; + } + return std::unexpected(SerialErrorCode::TIMEOUT); + } - template <_SupportString T> - auto GetAtResponseRepeat(T command, int timeout = 200, int repeatTime = 1) - -> void { - for (int i = 0; i <= repeatTime; i++) { - auto _ = GetAtResponse(command, timeout); - } - } + template <_SupportString T> + auto GetAtResponseRepeat(T command, int timeout = 200, int repeatTime = 1) + -> void { + for (int i = 0; i <= repeatTime; i++) { + auto _ = GetAtResponse(command, timeout); + } + } - template - bool GetAtUntil(T command, Args... expect) { - auto endTime = std::chrono::system_clock::now() + - std::chrono::milliseconds(timeout); - ser.flushReceiver(); - std::string reallyCommand = std::string(command) + endChar; - ser.writeString(reallyCommand.c_str()); - Log("Send : " + reallyCommand); - while (std::chrono::system_clock::now() < endTime) { - std::this_thread::sleep_for(10ms); - auto availableSize = ser.available(); - auto buffer = std::make_unique(availableSize + 1); - auto size = ser.readBytes(buffer.get(), availableSize, timeout); - buffer[size] = '\0'; - auto str = std::string(buffer.get()); - if (size > 0) - Log("Receive: " + str); - if (((str.find(expect) != std::string::npos) && ...)) { - return true; - } - } - return false; - } -}; + template + bool GetAtUntil(T command, Args... expect) { + auto endTime = std::chrono::system_clock::now() + + std::chrono::milliseconds(timeout); + ser.flushReceiver(); + std::string reallyCommand = std::string(command) + endChar; + ser.writeString(reallyCommand.c_str()); + Log("Send : " + reallyCommand); + while (std::chrono::system_clock::now() < endTime) { + std::this_thread::sleep_for(10ms); + auto availableSize = ser.available(); + auto buffer = std::make_unique(availableSize + 1); + auto size = ser.readBytes(buffer.get(), availableSize, timeout); + buffer[size] = '\0'; + auto str = std::string(buffer.get()); + if (size > 0) + Log("Receive: " + str); + if (((str.find(expect) != std::string::npos) && ...)) { + return true; + } + } + return false; + } + + template + std::string GetAtUntilAndReturn(T command, Args... expect) + { + auto endTime = std::chrono::system_clock::now() + + std::chrono::milliseconds(timeout); + ser.flushReceiver(); + std::string resp = ""; + std::string reallyCommand = std::string(command) + endChar; + ser.writeString(reallyCommand.c_str()); + Log("Send : " + reallyCommand); + while (std::chrono::system_clock::now() < endTime) { + std::this_thread::sleep_for(10ms); + auto availableSize = ser.available(); + auto buffer = std::make_unique(availableSize + 1); + auto size = ser.readBytes(buffer.get(), availableSize, timeout); + buffer[size] = '\0'; + auto str = std::string(buffer.get()); + resp += str; + if (size > 0) + Log("Receive: " + str); + if (((str.find(expect) != std::string::npos) && ...)) { + return resp; + } + } + return resp; + } + }; } // namespace serial #endif // SERIAL_H