mirror of
https://github.com/meshtastic/firmware.git
synced 2026-10-10 15:43:36 -04:00
* logging: strip redundant punctuation, level prefixes, and 'successfully' from log strings The logger already appends a newline and prints the level tag, so trailing '.', '!', '...', literal \n, and 'Error:'/'Warning:' prefixes inside format strings are wasted flash bytes. Same for 'successfully' (the affirmative form already implies it). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 * logging: tighten verbose log strings in modules, radio, platform, and system code Rewrite wordy log messages to terser equivalents - drop filler words (articles, 'attempting', 'due to', 'please'), use 'Can't X'/'X failed' phrasing, and abbreviate where the codebase already does (config, init, msg, BT). Format specifiers and argument lists are unchanged; distinctive greppable tokens are preserved. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 * logging: tighten verbose log strings in telemetry sensors and GPS Same terseness pass: drop filler, 'Can't X'/'X failed' phrasing, common abbreviations (temp, msg). Specifiers, arguments, and sensor-name prefixes unchanged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 * logging: tighten verbose log strings in mesh core Same terseness pass over NodeDB, Router, MeshService, PhoneAPI, RadioInterface, NextHopRouter, and PacketHistory: 'X failed'/'Can't X' phrasing, imperative verbs, dropped filler. Specifiers and arguments unchanged; duplicate literals kept identical to preserve linker string dedup. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 * logging: 'Unable to/Could not/Cannot' -> "Can't" in log strings Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 * logging: clang-format rewrap after string shortening Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 * logging: restore boot-logo trailing newline and progress-dot strings The terseness pass over-trimmed: the Meshtastic ASCII boot logo kept its blank line via a trailing \n, and three bare "." progress ticks were reduced to empty strings. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LBiZc9sfPrH1MZ2L3Fxgt1 * Update src/mesh/wifi/WiFiAPClient.cpp Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * logging: address review feedback on the terseness audit - Node/packet IDs use the repo's 0x%08x convention in NextHopRouter, NodeDB, AdminModule and CannedMessageModule. The sibling log in each if/else pair is converted too, so a pair isn't split across two formats. next_hop stays 0x%x - it's the last-byte relay hint, not a NodeNum. - RTC: the read-path and set-path "not found" warnings were byte-identical, so the linker deduped them and the log couldn't say which one fired. Split into "RTC read:" / "RTC set:". (The four sites live in mutually exclusive #ifdef branches, so the RTC family was never ambiguous.) - SCD4X getAmbientPressure()/setAmbientPressure() logged "altitude", and SCD30 getASC() logged "Can't send command" for a read. Both now name the operation they actually perform. - LOG_ERROR already carries the level: ". Error: %u" -> ", rc=%u" (matching the existing rc=%d house style) and "Error executing X()" -> "X() failed". - Typos and wording: "OTA partiton. (Reason" -> "OTA partition (reason", "CST3530 not response ~" -> "CST3530 no response", "Packet received with to: of 0" -> "to=0", HostMetrics "Error decoding" -> "Can't decode", and the dangling ": " on the NextHopRouter retransmission line. Printf specifier sequences are byte-identical on all 37 touched lines apart from the 6 deliberate %x/%u -> %08x node-ID widenings, all on uint32_t args. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
231 lines
5.4 KiB
C++
231 lines
5.4 KiB
C++
#ifdef ARCH_PORTDUINO
|
|
|
|
#include "GpsdSerial.h"
|
|
#include "configuration.h"
|
|
|
|
#include <cerrno>
|
|
|
|
#ifdef _WIN32
|
|
#include <mutex>
|
|
#include <winsock2.h>
|
|
#include <ws2tcpip.h>
|
|
#else
|
|
#include <arpa/inet.h>
|
|
#include <fcntl.h>
|
|
#include <netdb.h>
|
|
#include <netinet/in.h>
|
|
#include <sys/socket.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
|
|
namespace
|
|
{
|
|
// Winsock needs explicit init, closesocket(), ioctlsocket() and WSAGetLastError().
|
|
// SOCKET fits the header's `int` on Win64, and INVALID_SOCKET narrows to -1.
|
|
#ifdef _WIN32
|
|
// Done lazily to keep the dependency local to the one file that needs it.
|
|
void initSocketsOnce()
|
|
{
|
|
static std::once_flag flag;
|
|
std::call_once(flag, [] {
|
|
WSADATA wsaData;
|
|
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
|
});
|
|
}
|
|
|
|
void closeSocket(int fd)
|
|
{
|
|
::closesocket(static_cast<SOCKET>(fd));
|
|
}
|
|
|
|
void setNonBlocking(int fd)
|
|
{
|
|
u_long mode = 1;
|
|
::ioctlsocket(static_cast<SOCKET>(fd), FIONBIO, &mode);
|
|
}
|
|
|
|
// Winsock has no MSG_DONTWAIT, but the socket is already non-blocking so a plain
|
|
// recv() has the same semantics.
|
|
int recvNonBlocking(int fd, void *buf, size_t len)
|
|
{
|
|
return ::recv(static_cast<SOCKET>(fd), static_cast<char *>(buf), static_cast<int>(len), 0);
|
|
}
|
|
|
|
int sendAll(int fd, const void *buf, size_t len)
|
|
{
|
|
return ::send(static_cast<SOCKET>(fd), static_cast<const char *>(buf), static_cast<int>(len), 0);
|
|
}
|
|
|
|
bool lastErrorWasWouldBlock()
|
|
{
|
|
return WSAGetLastError() == WSAEWOULDBLOCK;
|
|
}
|
|
#else
|
|
void initSocketsOnce() {}
|
|
|
|
void closeSocket(int fd)
|
|
{
|
|
::close(fd);
|
|
}
|
|
|
|
void setNonBlocking(int fd)
|
|
{
|
|
::fcntl(fd, F_SETFL, O_NONBLOCK);
|
|
}
|
|
|
|
int recvNonBlocking(int fd, void *buf, size_t len)
|
|
{
|
|
return static_cast<int>(::recv(fd, buf, len, MSG_DONTWAIT));
|
|
}
|
|
|
|
int sendAll(int fd, const void *buf, size_t len)
|
|
{
|
|
return static_cast<int>(::write(fd, buf, len));
|
|
}
|
|
|
|
bool lastErrorWasWouldBlock()
|
|
{
|
|
return errno == EAGAIN || errno == EWOULDBLOCK;
|
|
}
|
|
#endif
|
|
} // namespace
|
|
|
|
namespace arduino
|
|
{
|
|
|
|
// The single global instance used by PortduinoGlue and GPS::createGps().
|
|
GpsdSerial gpsdSerial;
|
|
|
|
void GpsdSerial::setAddress(const std::string &host, int port)
|
|
{
|
|
_host = host;
|
|
_port = port;
|
|
}
|
|
|
|
bool GpsdSerial::connectToGpsd()
|
|
{
|
|
if (_host.empty())
|
|
return false;
|
|
|
|
initSocketsOnce();
|
|
|
|
struct addrinfo hints = {}, *res = nullptr;
|
|
hints.ai_family = AF_UNSPEC;
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
std::string portStr = std::to_string(_port);
|
|
|
|
if (getaddrinfo(_host.c_str(), portStr.c_str(), &hints, &res) != 0 || !res) {
|
|
LOG_WARN("gpsdSerial: can't resolve %s", _host.c_str());
|
|
return false;
|
|
}
|
|
|
|
// Try every address returned by getaddrinfo (e.g. ::1 before 127.0.0.1).
|
|
int fd = -1;
|
|
for (struct addrinfo *rp = res; rp != nullptr; rp = rp->ai_next) {
|
|
fd = static_cast<int>(socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol));
|
|
if (fd < 0)
|
|
continue;
|
|
if (connect(fd, rp->ai_addr, static_cast<int>(rp->ai_addrlen)) == 0)
|
|
break; // connected
|
|
closeSocket(fd);
|
|
fd = -1;
|
|
}
|
|
freeaddrinfo(res);
|
|
|
|
if (fd < 0) {
|
|
LOG_WARN("gpsdSerial: connect to %s:%d failed", _host.c_str(), _port);
|
|
return false;
|
|
}
|
|
|
|
// Switch to non-blocking so available()/read() never stall the GPS thread.
|
|
setNonBlocking(fd);
|
|
|
|
// Ask gpsd to stream raw NMEA sentences.
|
|
const char watchCmd[] = "?WATCH={\"enable\":true,\"nmea\":true}\n";
|
|
sendAll(fd, watchCmd, sizeof(watchCmd) - 1);
|
|
|
|
_sockfd = fd;
|
|
_rxBuf.clear();
|
|
LOG_INFO("gpsdSerial: connected to %s:%d", _host.c_str(), _port);
|
|
return true;
|
|
}
|
|
|
|
void GpsdSerial::begin(unsigned long /*baud*/, uint16_t /*config*/)
|
|
{
|
|
if (_sockfd >= 0)
|
|
end();
|
|
_lastConnectAttemptMs = 0; // force immediate connect on begin()
|
|
connectToGpsd();
|
|
}
|
|
|
|
void GpsdSerial::end()
|
|
{
|
|
if (_sockfd >= 0) {
|
|
closeSocket(_sockfd);
|
|
_sockfd = -1;
|
|
}
|
|
_rxBuf.clear();
|
|
}
|
|
|
|
void GpsdSerial::fillBuffer()
|
|
{
|
|
if (_sockfd < 0)
|
|
return;
|
|
// Guard: if the buffer is already full, skip recv entirely so n is always
|
|
// assigned before the post-loop disconnect check below.
|
|
if (_rxBuf.size() >= RX_BUF_MAX)
|
|
return;
|
|
|
|
uint8_t tmp[256];
|
|
int n;
|
|
while (_rxBuf.size() < RX_BUF_MAX && (n = recvNonBlocking(_sockfd, tmp, sizeof(tmp))) > 0) {
|
|
size_t space = RX_BUF_MAX - _rxBuf.size();
|
|
size_t toCopy = (static_cast<size_t>(n) < space) ? static_cast<size_t>(n) : space;
|
|
for (size_t i = 0; i < toCopy; i++)
|
|
_rxBuf.push_back(tmp[i]);
|
|
}
|
|
|
|
if (n == 0 || (n < 0 && !lastErrorWasWouldBlock())) {
|
|
// gpsd closed the connection or a real error occurred.
|
|
LOG_WARN("gpsdSerial: disconnected, will retry");
|
|
closeSocket(_sockfd);
|
|
_sockfd = -1;
|
|
_rxBuf.clear();
|
|
}
|
|
}
|
|
|
|
int GpsdSerial::available()
|
|
{
|
|
if (_sockfd < 0) {
|
|
// Throttle reconnect attempts to avoid log spam and repeated DNS lookups
|
|
// when gpsd is unreachable.
|
|
uint32_t now = millis();
|
|
if (now - _lastConnectAttemptMs >= RECONNECT_INTERVAL_MS) {
|
|
_lastConnectAttemptMs = now;
|
|
connectToGpsd();
|
|
}
|
|
}
|
|
fillBuffer();
|
|
return static_cast<int>(_rxBuf.size());
|
|
}
|
|
|
|
int GpsdSerial::peek()
|
|
{
|
|
if (_rxBuf.empty())
|
|
return -1;
|
|
return static_cast<int>(_rxBuf.front());
|
|
}
|
|
|
|
int GpsdSerial::read()
|
|
{
|
|
if (_rxBuf.empty())
|
|
return -1;
|
|
uint8_t c = _rxBuf.front();
|
|
_rxBuf.pop_front();
|
|
return static_cast<int>(c);
|
|
}
|
|
|
|
} // namespace arduino
|
|
|
|
#endif // ARCH_PORTDUINO
|