Send CAMs under the phone's position vector, not bench placeholders
Every field of the GeoNetworking Source Position Vector this firmware sent was a compile-time constant: the bench coordinates, speed 0, heading 0, TST 0, station type passengerCar and one fixed MAC. The CAM inside described a moving cyclist while the GN header around it described a car parked at the bench. SERIAL_MSG_CAM_TX_PV (0x05) puts a 24-byte prefix ahead of the CAM UPER: MAC, station type, PAI, TST, latitude, longitude, speed and heading, all values the phone already has when it builds the CAM and none of which this chip can know. geonet_wrap_shb now takes them as a gn_lpv_t, and tx_radio_task hands the same MAC to dot11p_build_frame, so the 802.11 source address and the GN_ADDR MID stay one address across a pseudonym change. Speed is clamped rather than masked, since an overflowing 15-bit value flips its sign bit and reads as travelling backwards. This reverses the Phase 03 decision that the firmware owns the pseudonym. A pseudonym only protects anyone if the MAC, the GN_ADDR and the CAM's stationID change together, and the phone owns the stationID. The heartbeat gains a capability byte (payload[7], bit0 = CAM_TX_PV), appended so an app reading the first 7 bytes is unaffected. The app sends 0x05 only once it sees that bit, so app and firmware can be updated in either order. CAM_TX (0x01) is still handled and falls back to the bench values, with the station type corrected to cyclist to match the CAM. Verified on air from the COM10 test board, decoded independently by the CiT One's gnHeader: 24 of 24 CAM_TX_PV frames matched the sent position vector field by field, and so did the CAM station ID. The legacy path delivered 23 of 24 frames with no field mismatches. Flashed on the COM3 OBU and its boot log is clean. Also corrects the SERIAL_LINK_MAX_PAYLOAD comment, which still named the 400-byte receive capture buffer as the ceiling on the RX path. That buffer is 800 bytes now, so the serial link is the ceiling, and larger payloads are dropped and counted there.
This commit is contained in:
+43
-29
@@ -1,43 +1,57 @@
|
||||
#ifndef GEONET_H
|
||||
#define GEONET_H
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// Wraps an ITS application payload (e.g. from denm_encode) with a minimal
|
||||
// GeoNetworking Basic Header + Common Header + Single-Hop-Broadcast
|
||||
// extended header (HeaderType=TSB(5), HeaderSubtype=SINGLE_HOP(0), per
|
||||
// ETSI EN 302 636-4-1 table 9), then prepends a BTP-B header addressed to
|
||||
// the DENM service port (2002).
|
||||
// The variable content of a GeoNetworking Long Position Vector (ETSI EN 302 636-4-1 clause
|
||||
// 9.5.2): who the sender is and where it was. This is the Source Position Vector every
|
||||
// GeoNetworking packet from this firmware carries.
|
||||
//
|
||||
// `mac` is the 6-byte pseudonym/link-layer address - pass the SAME address
|
||||
// you hand to dot11p_build_frame's src address, since GN_ADDR's MID field
|
||||
// (the last 6 bytes of the 8-byte GN_ADDR) is defined to BE that
|
||||
// link-layer address (EN 302 636-4-1 clause 9.5.1). `station_type` is the
|
||||
// 5-bit ITS-S type from the same clause (5 = passengerCar) and gets packed
|
||||
// into GN_ADDR alongside the address.
|
||||
// Every field here used to be a compile-time constant: the bench coordinates, speed 0, heading 0,
|
||||
// timestamp 0, passengerCar, and one fixed MAC. The phone never told the firmware where it was,
|
||||
// so the GN layer described a stationary car parked at the bench while the CAM inside it
|
||||
// described a moving cyclist somewhere else. The phone now supplies these values with each frame
|
||||
// (SERIAL_MSG_CAM_TX_PV in serial_link.h) and this firmware only lays them out on the wire.
|
||||
typedef struct {
|
||||
// Pseudonym. Written into GN_ADDR's MID field here AND, by dot11p_build_frame, into the
|
||||
// 802.11 source address. Clause 9.5.1 defines the MID as the link-layer address, so the two
|
||||
// must be the same six bytes; taking both from this one field is what keeps them identical
|
||||
// when the pseudonym rotates.
|
||||
uint8_t mac[6];
|
||||
// ITS-S type, TS 102 894-2 StationType (2 = cyclist). Only the low 5 bits fit in GN_ADDR.
|
||||
uint8_t station_type;
|
||||
// Position Accuracy Indicator.
|
||||
bool pai;
|
||||
// TST: the moment lat/lon were acquired, in ms, as TimestampIts modulo 2^32.
|
||||
uint32_t tst_ms;
|
||||
// 1/10 microdegree, signed.
|
||||
int32_t lat_tenmicrodeg;
|
||||
int32_t lon_tenmicrodeg;
|
||||
// 0.01 m/s. The wire field is 15-bit signed, so this is clamped to -16384..16383 on encode.
|
||||
int16_t speed_cms;
|
||||
// 0.1 degree from north, clockwise. Wrapped into 0..3599 on encode.
|
||||
uint16_t heading_decideg;
|
||||
} gn_lpv_t;
|
||||
|
||||
// Wraps an ITS application payload (the CAM UPER bytes the phone built) in a GeoNetworking Basic
|
||||
// Header + Common Header + Single-Hop-Broadcast extended header (HeaderType=TSB(5),
|
||||
// HeaderSubtype=SINGLE_HOP(0), EN 302 636-4-1 table 9), then a BTP-B header addressed to
|
||||
// `btp_dest_port`.
|
||||
//
|
||||
// `latitude_tenmicrodeg`/`longitude_tenmicrodeg` go into the Source Long
|
||||
// Position Vector (clause 9.5.2) as plain 32-bit signed big-endian fields -
|
||||
// NOT UPER bit-packed like the DENM payload's position fields, this is a
|
||||
// fixed-width binary protocol. Pass the SAME values you gave denm_encode's
|
||||
// eventPosition, so the GN-layer position and the DENM's own claimed
|
||||
// position agree.
|
||||
// Single-hop broadcast is the correct packet type for CAM, which ETSI defines as never forwarded,
|
||||
// so it has no destination area and no sequence number. A future DENM transmit path would need
|
||||
// GeoBroadcast (HeaderType=4) instead, which this function does not build.
|
||||
//
|
||||
// Deliberate simplification: real DENM dissemination normally uses
|
||||
// GeoBroadcast (GBC, HeaderType=4) so RSUs/OBUs can forward it across an
|
||||
// area - that needs a sequence number + geo-area fields this skeleton
|
||||
// doesn't build yet. Single-hop broadcast is simpler and is the
|
||||
// best-tested decode path in the receiver firmware you already have
|
||||
// working (same extended header shape as CAM). Fine for a single-vehicle
|
||||
// beacon; revisit if you need real multi-hop forwarding later.
|
||||
// `lpv` supplies the Source Position Vector. Hand the SAME lpv->mac to dot11p_build_frame as its
|
||||
// source address, or the GN and 802.11 layers will name two different senders.
|
||||
//
|
||||
// `btp_dest_port` is the BTP-B destination port for the service being carried
|
||||
// (ETSI TS 103 248): 2001 = CAM, 2002 = DENM, 2003 = MAPEM, 2004 = SPATEM, ...
|
||||
// `btp_dest_port` is the BTP-B destination port (ETSI TS 103 248): 2001 = CAM, 2002 = DENM,
|
||||
// 2003 = MAPEM, 2004 = SPATEM.
|
||||
//
|
||||
// Returns bytes written, or -1 if out buffer too small.
|
||||
// Returns bytes written, or -1 if the out buffer is too small.
|
||||
int geonet_wrap_shb(const uint8_t *its_payload, int its_len,
|
||||
const uint8_t mac[6], uint8_t station_type,
|
||||
int32_t latitude_tenmicrodeg, int32_t longitude_tenmicrodeg,
|
||||
const gn_lpv_t *lpv,
|
||||
uint16_t btp_dest_port,
|
||||
uint8_t *out, size_t out_len);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user