You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
5.9 KiB
200 lines
5.9 KiB
|
|
#include <fcntl.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
//
|
|
#include <arpa/inet.h>
|
|
#include <netinet/in.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
//
|
|
#include <map>
|
|
#include <set>
|
|
#include <string>
|
|
|
|
#include "uart_channel.hpp"
|
|
#include "utils/stringutils.hpp"
|
|
using namespace nlohmann;
|
|
using namespace iflytop;
|
|
|
|
static map<int, uint32_t> g_baundmap = {
|
|
{0, 0000000}, {50, 0000001}, {75, 0000002}, {110, 0000003}, //
|
|
{134, 0000004}, {150, 0000005}, {200, 0000006}, {300, 0000007}, //
|
|
{600, 0000010}, {1200, 0000011}, {1800, 0000012}, {2400, 0000013}, //
|
|
{4800, 0000014}, {9600, 0000015}, {19200, 0000016}, {38400, 0000017}, //
|
|
{57600, 0010001}, {115200, 0010002}, {230400, 0010003}, {460800, 0010004}, //
|
|
{500000, 0010005}, {576000, 0010006}, {921600, 0010007}, {1000000, 0010010}, //
|
|
{1152000, 0010011}, {1500000, 0010012}, {2000000, 0010013}, {2500000, 0010014}, //
|
|
{3000000, 0010015}, {3500000, 0010016}, {4000000, 0010017},
|
|
};
|
|
|
|
int findBaudrate(int baudrate) {
|
|
auto baundrate_find_result = g_baundmap.find(baudrate);
|
|
if (baundrate_find_result == g_baundmap.end()) {
|
|
return -1;
|
|
}
|
|
return baundrate_find_result->second;
|
|
}
|
|
|
|
UartChannel::UartChannel(string chname, string ifname, int baudrate, bool hexch, int rxovertime) {
|
|
logger = LoggerFactory.createRotatingFileLogger(chname);
|
|
|
|
m_chname = chname;
|
|
m_ifname = ifname;
|
|
m_baudrate = baudrate;
|
|
m_hexch = hexch;
|
|
m_rxovertime = rxovertime;
|
|
if (m_rxovertime == 0) {
|
|
m_rxovertime = 1;
|
|
}
|
|
}
|
|
|
|
void UartChannel::initialize() {
|
|
m_uartHandler.name = (char*)m_ifname.c_str();
|
|
m_uartHandler.rate = findBaudrate(m_baudrate);
|
|
if (m_uartHandler.rate == -1) {
|
|
logger->error("unsupport baudrate:{}", m_baudrate);
|
|
m_errorFlag = true;
|
|
m_errorMsg = "unsupport baudrate";
|
|
return;
|
|
}
|
|
|
|
int suc = uartStart(&m_uartHandler);
|
|
if (suc != 0) {
|
|
logger->error("uartStart fail");
|
|
m_errorFlag = true;
|
|
m_errorMsg = "uart open fail";
|
|
return;
|
|
}
|
|
|
|
m_rxthread.reset(new Thread(fmt::format("{}-rxthread", m_chname), [this]() {
|
|
logger->info("{} rxthread start", m_chname);
|
|
ThisThread thisThread;
|
|
char rxcache[4096] = {0};
|
|
int rxlen = 0;
|
|
while (!thisThread.getExitFlag()) {
|
|
int ret = uartReceive(&m_uartHandler, &rxcache[rxlen], 1024); // send the received text over UART
|
|
if (ret < 0) {
|
|
logger->error("uartReceive fail, ret:{}", ret);
|
|
thisThread.sleepForMs(1000);
|
|
continue;
|
|
}
|
|
|
|
if (ret > 0) {
|
|
rxlen += ret;
|
|
::usleep(m_rxovertime * 1000);
|
|
continue;
|
|
}
|
|
|
|
if (rxlen != 0 && ret == 0) {
|
|
if (m_hexch) { // hex channel
|
|
string rxhexstr = StringUtils().bytesToString((uint8_t*)rxcache, rxlen);
|
|
logger->info("{} RX:-> {}({})", m_chname, rxhexstr, rxlen);
|
|
if (m_ondata) m_ondata(this, true, rxcache, rxlen);
|
|
} else { // str channel
|
|
string rxstr(rxcache, rxlen);
|
|
logger->info("{} RX:-> {}({})", m_chname, rxstr, rxlen);
|
|
if (m_ondata) m_ondata(this, false, rxcache, rxlen);
|
|
}
|
|
rxlen = 0;
|
|
}
|
|
::usleep(m_rxovertime * 1000);
|
|
//
|
|
} // end while
|
|
}));
|
|
return;
|
|
}
|
|
|
|
void UartChannel::senddata(bool binary, const char* data, size_t len) {
|
|
string txdata(data, len);
|
|
if ((m_hexch ^ binary)) {
|
|
logger->warn("{} Skip Tx | data format error, channel is a {} channel", m_chname, m_hexch ? "hex" : "str");
|
|
return;
|
|
}
|
|
|
|
if (m_errorFlag) {
|
|
logger->warn("{} Skip Tx, due to errorflag", m_chname, txdata, len);
|
|
return;
|
|
}
|
|
|
|
string txdatastr;
|
|
if (binary) {
|
|
txdatastr = StringUtils().bytesToString((uint8_t*)data, len);
|
|
} else {
|
|
txdatastr = txdata;
|
|
}
|
|
|
|
logger->info("{} TX:-> {}({})", m_chname, txdatastr, len);
|
|
|
|
int txlen = 0;
|
|
if (binary) {
|
|
txlen = uartSend(&m_uartHandler, (char*)data, len);
|
|
if (txlen != (int)len) logger->warn("tx fail");
|
|
} else {
|
|
txlen = uartSend(&m_uartHandler, txdatastr.c_str(), txdatastr.size());
|
|
if (txlen != (int)txdatastr.size()) logger->warn("tx fail");
|
|
}
|
|
}
|
|
void UartChannel::registerOnDataCallback(OnData_t ondata) { m_ondata = ondata; }
|
|
void UartChannel::callcmd(string cmd, unordered_map<string, string> param, json& receipt) {
|
|
logger->info("{} callcmd {} {}", m_chname, cmd, paramToString(param));
|
|
if (cmd == "setBaudrate") {
|
|
int rate = atoi(param["baudrate"].c_str());
|
|
if (rate == 0) {
|
|
logger->error("rate is 0");
|
|
receipt["status"] = -1;
|
|
receipt["msg"] = "rate is not support";
|
|
return;
|
|
}
|
|
|
|
int setrate = findBaudrate(rate);
|
|
if (setrate == -1) {
|
|
logger->error("unsupport baudrate:{}", m_baudrate);
|
|
receipt["status"] = -1;
|
|
receipt["msg"] = "unsupport baudrate";
|
|
return;
|
|
}
|
|
|
|
int suc = uartSetRate(&m_uartHandler, setrate);
|
|
if (suc != 0) {
|
|
logger->error("uartSetRate fail ,ecode = {}", strerror(errno));
|
|
receipt["status"] = -1;
|
|
receipt["msg"] = fmt::format("uartSetRate fail ,ecode = {}", strerror(errno));
|
|
return;
|
|
}
|
|
m_baudrate = rate;
|
|
receipt["status"] = 0;
|
|
receipt["msg"] = "ok";
|
|
} else if (cmd == "getBaudrate") {
|
|
receipt["status"] = 0;
|
|
receipt["data"]["baudrate"] = m_baudrate;
|
|
} else {
|
|
logger->error("unsupport cmd:{}", cmd);
|
|
receipt["status"] = -1;
|
|
receipt["msg"] = "unsupport cmd";
|
|
}
|
|
}
|
|
|
|
list<string> UartChannel::getCmdList() {
|
|
list<string> cmdlist;
|
|
return cmdlist;
|
|
}
|
|
|
|
json UartChannel::getChannelInfo() {
|
|
json info;
|
|
info["name"] = m_chname;
|
|
info["alias"] = getAlias();
|
|
info["type"] = "uart";
|
|
|
|
info["ifname"] = m_ifname;
|
|
info["baudrate"] = m_baudrate;
|
|
info["hexch"] = m_hexch;
|
|
info["rxovertime"] = m_rxovertime;
|
|
info["error"]["status"] = m_errorFlag;
|
|
info["error"]["msg"] = m_errorMsg;
|
|
return info;
|
|
}
|