serial/include/serial.h

206 lines
6.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef SERIAL_H
#define SERIAL_H
#include <cstring>
#include <type_traits>
#include <iostream>
#include <string>
#include <chrono>
#include <optional>
#include <thread>
#include <functional>
#include <vector>
#include <format>
#include "../third/serialib.h"
using namespace std::literals::chrono_literals;
namespace serial
{
static std::vector<std::string> GetUsbPorts()
{
std::vector<std::string> portArray;
std::string comname;
std::string showname;
for (int i = 0; i <= 256; i++)
{
std::format_to(std::back_inserter(comname), "\\\\.\\COM{}", i);
std::format_to(std::back_inserter(showname), "COM{}", i);
// 创建或者打开一个文件或者I/O设备如执行成功则返回文件句柄 INVALID_HANDLE_VALUE 表示出错
const HANDLE m_handle =
::CreateFileA(comname.c_str(),
static_cast<DWORD>(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;
}
template <typename T>
concept SupportString = requires {
std::is_same_v<T, const char *>;
std::is_same_v<T, std::string>;
};
enum class
[[maybe_unused]] ErrorCode
{
SUCCESS,
TIMEOUT,
SETTIMEOUTERROR,
WRITEINGERROR,
READINGERROR,
};
class Serial
{
private:
serialib ser;
const char *endChar = "\r\n";
std::function<void(const std::string &)> logCallBack;
public:
Serial() = default;
std::string GetTimeNow()
{
auto now = std::chrono::system_clock::now();
auto now_c = std::chrono::system_clock::to_time_t(now);
char buffer[32];
ctime_s(buffer, 32, &now_c);
return std::string(buffer);
}
bool IsOpen(){
return ser.isDeviceOpen();
}
template <SupportString T>
bool OpenDevice(T portName, unsigned int bauds = 115200)
{
std::string reallyPortName;
std::format_to(std::back_inserter(reallyPortName), "\\\\.\\{}", portName);
if(ser.isDeviceOpen()) return true;
int code;
code = ser.openDevice(reallyPortName.c_str(), bauds);
if (code == 1)
{
return true;
}
else
{
return false;
}
}
void Log(const std::string &log)
{
if (logCallBack)
{
auto msg = GetTimeNow() + " " + log + "\n";
logCallBack(msg);
}
}
void SetLogCallBack(std::function<void(const std::string &)> callBack)
{
logCallBack = callBack;
}
void CloseDevice()
{
if(!ser.isDeviceOpen()) return;
ser.closeDevice();
}
~Serial() = default;
template<SupportString T>
std::optional<std::string> 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::optional<std::string> GetAtResponse(T command, int timeout = 50)
{
ser.flushReceiver();
std::string reallyCommand;
std::string response;
if constexpr (std::is_same_v<T, std::string>)
{
reallyCommand = command + endChar;
}
else
{
reallyCommand = std::string(command) + endChar;
}
ser.writeString(reallyCommand.c_str());
Log("Send: " + reallyCommand);
std::this_thread::sleep_for(10ms);
auto availableSize = ser.available();
char *buffer = new char[availableSize + 1];
std::memset(buffer, 0, availableSize);
auto size = ser.readBytes(buffer, availableSize, timeout);
if (size > 0)
{
buffer[size] = '\0';
response = std::string(buffer);
Log("Receive: " + response);
delete[] buffer;
return response;
}
delete[] buffer;
return std::nullopt;
}
template <SupportString T>
bool GetAtUntil(T command, T expect = "OK", int timeout = 50)
{
auto endTime = std::chrono::system_clock::now() + std::chrono::milliseconds(timeout);
ser.flushReceiver();
std::string reallyCommand;
if constexpr (std::is_same_v<T, std::string>)
{
reallyCommand = command + endChar;
}
else
{
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 = new char[availableSize + 1];
auto size = ser.readBytes(buffer, availableSize, timeout);
buffer[size] = '\0';
auto str = std::string(buffer);
delete[] buffer;
if (size > 0)
Log("Receive: " + str);
if (str.find(expect) != std::string::npos)
{
return true;
}
}
return false;
}
};
}
#endif // SERIAL_H