diff --git a/include/serial.h b/include/serial.h index 3e34f07..f558802 100644 --- a/include/serial.h +++ b/include/serial.h @@ -22,6 +22,64 @@ namespace ranges = std::ranges; namespace views = std::views; namespace serial { +template struct _StrongType {}; + +template struct _StrongType { + using Type = T; +}; + +template struct _StrongType { + using Type = decltype(true ? std::declval() : std::declval()); +}; + +template struct _StrongType { + using Type = + typename _StrongType::Type>::Type; +}; + +template +using _strongType_t = typename _StrongType::Type; + +template struct _IsCastable {}; + +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 { + static constexpr bool value = + _IsCastable::Type>::value; + using Type = + std::conditional_t::Type, void>; +}; + +template +concept _SupportString = requires { + _IsCastable::value; +}; + +template <_SupportString T> 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() { std::vector portArray; @@ -43,12 +101,6 @@ static std::vector GetUsbPorts() { return portArray; } -template -concept SupportString = requires { - std::is_same_v; - std::is_same_v; -}; - enum class [[maybe_unused]] SerialErrorCode { SUCCESS, TIMEOUT, @@ -73,6 +125,8 @@ class Serial { 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(); } static std::string GetTimeNow() { auto now = std::chrono::system_clock::now(); @@ -84,7 +138,7 @@ class Serial { bool IsOpen() { return ser.isDeviceOpen(); } - template + template <_SupportString T> bool OpenDevice(T portName, unsigned int bauds = 115200, int delayTime = 0) { std::string reallyPortName; @@ -118,7 +172,7 @@ class Serial { ser.closeDevice(); } - template + template <_SupportString T> std::expected DelayGetResponse(int delayTime, T command, int timeout = 50) { std::this_thread::sleep_for(std::chrono::milliseconds(delayTime)); @@ -126,7 +180,7 @@ class Serial { } template + _SupportString T, _SupportString... Args> bool GetAtUntilRepeat(T command, Args... args) { std::stringstream ss; int i = 0; @@ -141,16 +195,11 @@ class Serial { return false; } - template + template <_SupportString T> std::expected GetAtResponse(T command, int timeout = 50) { ser.flushReceiver(); - std::string reallyCommand; - if constexpr (std::is_same_v) { - reallyCommand = command + endChar; - } else { - reallyCommand = std::string(command) + endChar; - } + std::string reallyCommand = std::string(command) + endChar; ser.writeString(reallyCommand.c_str()); Log("Send: " + reallyCommand); std::this_thread::sleep_for(10ms); @@ -161,7 +210,7 @@ class Serial { if (size > 0) { buffer[size] = '\0'; - std::string response = std::string(buffer); + std::string response = std::string(buffer.get()); Log("Receive: " + response); if (removeEcho) response.replace(0, reallyCommand.length(), ""); @@ -170,7 +219,7 @@ class Serial { return std::unexpected(SerialErrorCode::TIMEOUT); } - template + template <_SupportString T> auto GetAtResponseRepeat(T command, int timeout = 200, int repeatTime = 1) -> void { for (int i = 0; i <= repeatTime; i++) { @@ -178,17 +227,12 @@ class Serial { } } - template + template bool GetAtUntil(T command, Args... expect) { auto endTime = std::chrono::system_clock::now() + std::chrono::milliseconds(timeout); ser.flushReceiver(); - std::string reallyCommand; - if constexpr (std::is_same_v) { - reallyCommand = command + endChar; - } else { - reallyCommand = std::string(command) + endChar; - } + std::string reallyCommand = std::string(command) + endChar; ser.writeString(reallyCommand.c_str()); Log("Send : " + reallyCommand); while (std::chrono::system_clock::now() < endTime) { diff --git a/main.cc b/main.cc index c4d967b..1e3babb 100644 --- a/main.cc +++ b/main.cc @@ -1,19 +1,40 @@ +#include "include/serial.h" #include #include +#include #include -#include #include +#include #include - -#include "include/serial.h" #undef max using namespace std::literals::chrono_literals; +using namespace std::literals::string_view_literals; +using namespace std::literals::string_literals; using namespace serial; namespace ranges = std::ranges; namespace views = std::views; void PrintLog(const std::string &msg) { std::cout << msg << std::endl; } +template + requires std::is_same_v || + std::is_same_v +std::vector split(T str, T d) { + auto v = views::split(str, d) | views::transform([](auto word) { + return T(word.begin(), word.end()); + }); + return std::vector(v.begin(), v.end()); +} + +int main() { + Serial ser; + ser.OpenDevice("COM11", 115200); + ser.SetLogCallBack(PrintLog); + ser.GetAtUntilRepeat<5>("AT", "OK"); + return 0; +} + +/* int main(int argc, char **const argv) { Serial serial; auto ports = serial::GetUsbPorts(); @@ -30,20 +51,20 @@ int main(int argc, char **const argv) { std::getline(std::cin, command); system("cls"); auto startTime = std::chrono::system_clock::now(); - if (command.find(":") != std::string::npos) { - command.erase(std::remove_if(command.begin(), command.end(), - [](char c) { return c == ':'; }), - command.end()); - auto reallyCommand = command.substr(0, command.find_first_of(' ')); - auto expect = command.substr(command.find_first_of(' ') + 1, - command.length()); - auto res = serial.GetAtUntil(reallyCommand, expect, 2000); + if (command.at(0) == ':') { + command = command.substr(1, command.length() - 1); + auto sp = split(command, " "s); + auto reallyCommand = sp[0]; + auto expect = sp[1]; + auto res = serial.GetAtUntil(reallyCommand, 2000, expect); auto endTime = std::chrono::system_clock::now(); - std::cout << "dura: " + res ? std::cout + << "dura: " << std::chrono::duration_cast( endTime - startTime) .count() - << std::endl; + << std::endl + : std::cout << "Recive Error"; } else { auto resp = serial.GetAtResponse(command); auto endTime = std::chrono::system_clock::now(); @@ -57,3 +78,4 @@ int main(int argc, char **const argv) { } return 0; } +*/ \ No newline at end of file