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

#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;
}