Compare commits
3 Commits
5bd75b9d5d
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| e6c9099c80 | |||
| 05adb18909 | |||
| 0a7db042f6 |
51
air/main.cpp
51
air/main.cpp
@@ -12,18 +12,18 @@
|
||||
#include <cstring>
|
||||
#include <atomic>
|
||||
#include <span>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
/**
|
||||
* Вспомогательная функция для получения текущего времени в миллисекундах
|
||||
*/
|
||||
inline int64_t milliseconds() {
|
||||
timeval tv{};
|
||||
gettimeofday(&tv,nullptr);
|
||||
return ((tv.tv_sec * 1000000l) + tv.tv_usec) / 1000;
|
||||
timespec ts{};
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return static_cast<int64_t>(ts.tv_sec) * 1000 + static_cast<int64_t>(ts.tv_nsec) / 1000000;
|
||||
}
|
||||
|
||||
constexpr int64_t SBUS_SEND_FRAME_INTERVAL = 15;
|
||||
constexpr int64_t SBUS_SEND_FRAME_INTERVAL = 50;
|
||||
constexpr int64_t SBUS_RXLOSS_INTERVAL = 500;
|
||||
|
||||
class UDPServer {
|
||||
@@ -177,7 +177,6 @@ struct SbusData {
|
||||
};
|
||||
|
||||
class SerialPort {
|
||||
private:
|
||||
int fd;
|
||||
|
||||
public:
|
||||
@@ -187,7 +186,7 @@ public:
|
||||
// Открытие последовательного порта
|
||||
fd = ::open(port_path.c_str(), O_RDWR | O_NOCTTY | O_SYNC);
|
||||
if (fd < 0) {
|
||||
std::cerr << "Failed to open serial port " << port_path << ": " << std::strerror(errno) << std::endl;
|
||||
std::cout << "Failed to open serial port " << port_path << ": " << std::strerror(errno) << std::endl;
|
||||
return false;
|
||||
}
|
||||
struct termios2 tio{};
|
||||
@@ -209,7 +208,7 @@ public:
|
||||
tio.c_cflag |= (BOTHER|CREAD|CLOCAL);
|
||||
|
||||
if (ioctl(fd, TCSETS2, &tio) != 0) {
|
||||
std::cerr << "Failed to set termios2 attributes: " << std::strerror(errno) << std::endl;
|
||||
std::cout << "Failed to set termios2 attributes: " << std::strerror(errno) << std::endl;
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
@@ -244,18 +243,18 @@ public:
|
||||
}
|
||||
|
||||
// Метод для записи данных в порт
|
||||
bool write(std::span<const uint8_t> data) {
|
||||
bool writeBuffer(std::span<const uint8_t> data) {
|
||||
if (fd < 0) return false;
|
||||
|
||||
ssize_t written = ::write(fd, data.data(), data.size());
|
||||
ssize_t written = write(fd, data.data(), data.size());
|
||||
if (written < 0) {
|
||||
std::cerr << "Failed to write to serial port" << std::endl;
|
||||
std::cout << "Failed to write to serial port " << strerror(errno) << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Принудительная отправка данных
|
||||
if (drain() < 0) {
|
||||
std::cerr << "Failed to flush data to serial port" << std::endl;
|
||||
std::cout << "Failed to flush data to serial port" << strerror(errno) << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -264,7 +263,7 @@ public:
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
// Парсим аргументы командной строки
|
||||
std::string serial_port = "/dev/ttyUSB0";
|
||||
std::string serial_port = "/dev/ttyPS0";
|
||||
if (argc > 1) {
|
||||
serial_port = argv[1];
|
||||
}
|
||||
@@ -288,15 +287,25 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
int packetCount = 0;
|
||||
int totalPacketCount = 0;
|
||||
int serialErrors = 0;
|
||||
int64_t lastStatisticsShow = milliseconds();
|
||||
int64_t _lastLoopNow = lastStatisticsShow;
|
||||
while (true) {
|
||||
pollfd udpFd{.fd = udp_server.sockfd, .events = POLLIN, .revents = 0};
|
||||
poll(&udpFd, 1, SBUS_SEND_FRAME_INTERVAL / 4);
|
||||
auto now = milliseconds();
|
||||
if (std::abs(now - _lastLoopNow) > SBUS_SEND_FRAME_INTERVAL) {
|
||||
std::cout << "Warning: Loop freeze, reset timers. now time:" << now << std::endl;
|
||||
lastSbusWrite = 0;
|
||||
lastSbusRecv = 0;
|
||||
lastStatisticsShow = 0;
|
||||
}
|
||||
_lastLoopNow = now;
|
||||
|
||||
if (udpFd.revents & POLLIN) {
|
||||
// Прием UDP пакета
|
||||
std::vector<uint16_t> data = udp_server.receive();
|
||||
lastSbusRecv = milliseconds();
|
||||
lastSbusRecv = now;
|
||||
|
||||
if (!data.empty()) {
|
||||
packetCount++;
|
||||
@@ -320,10 +329,18 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
const auto now = milliseconds();
|
||||
// std::cout << "from loop: current time " << now << std::endl;
|
||||
if (now - lastSbusWrite >= SBUS_SEND_FRAME_INTERVAL && now - lastSbusRecv <= SBUS_RXLOSS_INTERVAL) {
|
||||
lastSbusWrite = now;
|
||||
if (!serial.write(sb.binaryBuffer)) {
|
||||
if (!serial.writeBuffer(sb.binaryBuffer)) {
|
||||
serialErrors++;
|
||||
} else {
|
||||
serialErrors = 0;
|
||||
}
|
||||
|
||||
// после 50 ошибок дальше не будем пытаться что-то писать, ибо это бесполезно
|
||||
if (serialErrors >= 50) {
|
||||
std::cout << "FATAL: 50 errors on serial port write operation, exit" << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -337,7 +354,7 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Error: " << e.what() << std::endl;
|
||||
std::cout << "Error: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user