2026-08-04 17:58:07 +02:00
|
|
|
#ifndef GEONET_H
|
|
|
|
|
#define GEONET_H
|
2026-09-10 14:47:30 +02:00
|
|
|
#include <stdbool.h>
|
2026-08-04 17:58:07 +02:00
|
|
|
#include <stdint.h>
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
2026-09-10 14:47:30 +02:00
|
|
|
// 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.
|
2026-08-04 17:58:07 +02:00
|
|
|
//
|
2026-09-10 14:47:30 +02:00
|
|
|
// 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`.
|
2026-08-04 17:58:07 +02:00
|
|
|
//
|
2026-09-10 14:47:30 +02:00
|
|
|
// 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.
|
2026-08-04 17:58:07 +02:00
|
|
|
//
|
2026-09-10 14:47:30 +02:00
|
|
|
// `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.
|
2026-08-04 17:58:07 +02:00
|
|
|
//
|
2026-09-10 14:47:30 +02:00
|
|
|
// `btp_dest_port` is the BTP-B destination port (ETSI TS 103 248): 2001 = CAM, 2002 = DENM,
|
|
|
|
|
// 2003 = MAPEM, 2004 = SPATEM.
|
2026-08-04 17:58:07 +02:00
|
|
|
//
|
2026-09-10 14:47:30 +02:00
|
|
|
// Returns bytes written, or -1 if the out buffer is too small.
|
2026-08-04 17:58:07 +02:00
|
|
|
int geonet_wrap_shb(const uint8_t *its_payload, int its_len,
|
2026-09-10 14:47:30 +02:00
|
|
|
const gn_lpv_t *lpv,
|
2026-08-04 17:58:07 +02:00
|
|
|
uint16_t btp_dest_port,
|
|
|
|
|
uint8_t *out, size_t out_len);
|
|
|
|
|
|
|
|
|
|
#endif
|