Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/Mesh.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,10 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) {
if (is_ok) {
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): valid advertisement received!", getLogDateTime());
onAdvertRecv(pkt, id, timestamp, app_data, app_data_len);

// Collect timestamp for peer-based time synchronization
collectPeerTimestamp(timestamp, pkt);

action = routeRecvPacket(pkt);
} else {
MESH_DEBUG_PRINTLN("%s Mesh::onRecvPacket(): received advertisement with forged signature! (app_data_len=%d)", getLogDateTime(), app_data_len);
Expand Down Expand Up @@ -720,4 +724,16 @@ void Mesh::sendZeroHop(Packet* packet, uint16_t* transport_codes, uint32_t delay
sendPacket(packet, 0, delay_millis);
}

void Mesh::collectPeerTimestamp(uint32_t timestamp, const Packet* packet) {
// Calculate estimated airtime per hop based on packet size and radio settings
uint32_t airtime_per_hop_ms = _radio->getEstAirtimeFor(packet->getRawLength());
uint8_t hop_count = packet->path_len;

MESH_DEBUG_PRINTLN("Mesh::collectPeerTimestamp: timestamp=%u, hop_count=%d, airtime_per_hop=%ums",
timestamp, hop_count, airtime_per_hop_ms);

// Call addPeerTimestamp through virtual method (no-op in base RTCClock)
_rtc->addPeerTimestamp(timestamp, hop_count, airtime_per_hop_ms);
}

}
7 changes: 7 additions & 0 deletions src/Mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ class Mesh : public Dispatcher {
//void routeRecvAcks(Packet* packet, uint32_t delay_millis);
DispatcherAction forwardMultipartDirect(Packet* pkt);

/**
* \brief Collect timestamp from peer advertisement for time synchronization
* \param timestamp The timestamp from the advertisement packet
* \param packet The packet containing hop count and used for airtime calculation
*/
void collectPeerTimestamp(uint32_t timestamp, const Packet* packet);

protected:
DispatcherAction onRecvPacket(Packet* pkt) override;

Expand Down
16 changes: 16 additions & 0 deletions src/MeshCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,22 @@ class RTCClock {
}
return last_unique = t;
}

/**
* \brief Add a timestamp from a peer for time synchronization
* \param timestamp The timestamp from the peer's advertisement
* \param hop_count Number of hops the packet has traveled
* \param estimated_airtime_per_hop_ms Estimated airtime per hop in milliseconds (from radio settings)
* Override in classes that support peer-based time synchronization
*/
virtual void addPeerTimestamp(uint32_t timestamp, uint8_t hop_count, uint32_t estimated_airtime_per_hop_ms = 1000) { /* no op */ }

/**
* \brief Check if this clock uses hardware RTC
* \returns true if hardware RTC is present, false otherwise
* Override in classes that can detect hardware RTC
*/
virtual bool hasHardwareRTC() const { return false; }
};

}
6 changes: 5 additions & 1 deletion src/helpers/AutoDiscoverRTCClock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ uint32_t AutoDiscoverRTCClock::getCurrentTime() {
return _fallback->getCurrentTime();
}

void AutoDiscoverRTCClock::setCurrentTime(uint32_t time) {
void AutoDiscoverRTCClock::setCurrentTime(uint32_t time) {
if (ds3231_success) {
rtc_3231.adjust(DateTime(time));
} else if (rv3028_success) {
Expand All @@ -70,3 +70,7 @@ void AutoDiscoverRTCClock::setCurrentTime(uint32_t time) {
_fallback->setCurrentTime(time);
}
}

bool AutoDiscoverRTCClock::hasHardwareRTC() const {
return ds3231_success || rv3028_success || rtc_8563_success;
}
6 changes: 6 additions & 0 deletions src/helpers/AutoDiscoverRTCClock.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,10 @@ class AutoDiscoverRTCClock : public mesh::RTCClock {
void tick() override {
_fallback->tick(); // is typically VolatileRTCClock, which now needs tick()
}

/**
* \brief Check if a hardware RTC was detected
* \returns true if hardware RTC is available, false otherwise
*/
bool hasHardwareRTC() const override;
};
Loading