Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic Station backend: FineTimeSinceGpsEpoch missing from uplink event? #228

Open
1 task done
LouneCode opened this issue Apr 20, 2023 · 2 comments
Open
1 task done

Comments

@LouneCode
Copy link

LouneCode commented Apr 20, 2023

  • I have searched the issues of this repository and believe that this is not a duplicate.

Summary

Hi all,

It looks like the ChirpStack Gateway Bridge with Basic Station backend don't support fine timestamps? Actually the websocket message of the Basic Station backend has a “fts” tag for fine timestamps, but this feature is missing from the ChirpStack Gateway bridge?

 

Basic Station backend websocket message (SX1303, SX1302):

2022-12-19 17:20:14.797 [AIO:XDEB] [3|WS] > {"msgtype":"updf","MHdr":64, ---> "fts":-1 <--- ,"rssi":-45,"snr":13.75,"rxtime":1671470414.687880516}}

What is the use-case?

A Fine timestamp is used to get the TDoA geolocation of the transmitter (sensor).

Implementation description

ChirpStack Gateway Bridge

The RadioMetaDataUpInfo structure in radio_meta_data.go implements which elements of a websocket message to parse.

// RadioMetaDataUpInfo contains the radio meta-data uplink info.
type RadioMetaDataUpInfo struct {
	RxTime  float64 `json:"rxtime"`
	RCtx    uint64  `json:"rctx"`
	XTime   uint64  `json:"xtime"`
	GPSTime int64   `json:"gpstime"`
	RSSI    float32 `json:"rssi"`
	SNR     float32 `json:"snr"`
}

A fine timestamp (Fts element) could be added quite simply to the RadioMetaDataUpInfo structure as follows:

// RadioMetaDataUpInfo contains the radio meta-data uplink info.
type RadioMetaDataUpInfo struct {
	RxTime  float64 `json:"rxtime"`
	RCtx    uint64  `json:"rctx"`
	XTime   uint64  `json:"xtime"`
	GPSTime int64   `json:"gpstime"`
	Fts     *int64  `json:"fts,omitempty"`
	RSSI    float32 `json:"rssi"`
	SNR     float32 `json:"snr"`
}

Func SetRadioMetaDataToProto() in the same file needs a little refactoring:

// SetRadioMetaDataToProto sets the given parameters to the given protobuf struct.
func SetRadioMetaDataToProto(loraBand band.Band, gatewayID lorawan.EUI64, rmd RadioMetaData, pb *gw.UplinkFrame) error {
	//
	// TxInfo
	//
	dr, err := loraBand.GetDataRate(rmd.DR)
	if err != nil {
		return errors.Wrap(err, "get data-rate error")
	}

	pb.TxInfo = &gw.UplinkTxInfo{
		Frequency: rmd.Frequency,
	}

	switch dr.Modulation {
	case band.LoRaModulation:
		pb.TxInfo.Modulation = &gw.Modulation{
			Parameters: &gw.Modulation_Lora{
				Lora: &gw.LoraModulationInfo{
					Bandwidth:             uint32(dr.Bandwidth) * 1000,
					SpreadingFactor:       uint32(dr.SpreadFactor),
					CodeRate:              gw.CodeRate_CR_4_5,
					PolarizationInversion: false,
				},
			},
		}
	case band.FSKModulation:
		pb.TxInfo.Modulation = &gw.Modulation{
			Parameters: &gw.Modulation_Fsk{
				Fsk: &gw.FskModulationInfo{
					Datarate: uint32(dr.BitRate),
				},
			},
		}
	}

	//
	// RxInfo
	//
	pb.RxInfo = &gw.UplinkRxInfo{
		GatewayId: gatewayID.String(),
		Rssi:      int32(rmd.UpInfo.RSSI),
		Snr:       float32(rmd.UpInfo.SNR),
	}

	if rxTime := rmd.UpInfo.RxTime; rxTime != 0 {
		sec, nsec := math.Modf(rmd.UpInfo.RxTime)
		if sec != 0 {
			val := time.Unix(int64(sec), int64(nsec))
			pb.RxInfo.Time = timestamppb.New(val)
		}
	}

	if gpsTime := rmd.UpInfo.GPSTime; gpsTime != 0 {
		gpsTimeDur := time.Duration(gpsTime) * time.Microsecond
		gpsTimeTime := time.Time(gps.NewTimeFromTimeSinceGPSEpoch(gpsTimeDur))

		pb.RxInfo.TimeSinceGpsEpoch = durationpb.New(gpsTimeDur)
		pb.RxInfo.Time = timestamppb.New(gpsTimeTime)
	}

	if fts := rmd.UpInfo.Fts; fts != nil {
		if *fts > -1 {

			ftsTimeDur := time.Duration(*fts) * time.Nanosecond

			if gpsTime := rmd.UpInfo.GPSTime; gpsTime != 0 {
				gpsTimeDur := time.Duration(gpsTime) * time.Microsecond
				// take the seconds from the gps time
				gpsTimeDur = gpsTimeDur - (gpsTimeDur % time.Second)
				// add the nanos from the fine-timestamp
				ftsTimeDur = gpsTimeDur + ftsTimeDur
			}

			pb.RxInfo.FineTimeSinceGpsEpoch = durationpb.New(ftsTimeDur)
		}
	}

After these small changes, the fine timestamp information exist in the uplink event as follows (if you are using the GLS Basic Station instead of Basic Station backend):

"rxInfo": [
    {
        "gatewayId": "0016c001ffxxxxxx",
        "uplinkId": 3232276575,
        "time": "2022-12-26T12:01:47.709920+00:00",
        "timeSinceGpsEpoch": "1356091325.709920s",
        "fineTimeSinceGpsEpoch": "1356091325.263021396s",
        "rssi": -45,
        "snr": 14.25,
        "location": {
            "latitude": 62.1979847889177,
            "longitude": 21.123254060745244
        },
        "context": "AAAAAAAAAAAAMgABVWHvOA==",
        "metadata": {
            "region_common_name": "EU868",
            "region_name": "eu868"
        }
    },

This feature can be patched with the following commands:

$ git clone https://github.com/chirpstack/chirpstack-gateway-bridge.git chirpstack-gateway-bridge
$ cd chirpstack-gateway-bridge
$ curl https://raw.githubusercontent.com/LouneCode/GLS-chripstack-gateway-bridge/main/builder/GLS_CSGB_v4.0.8.1.patch | git apply

# Sanity check:
$ cat ./internal/backend/basicstation/structs/radio_meta_data.go

 

More information about this idea can be found at:

 

Can you implement this by yourself and make a pull request?

See the implementation proposal above.

@LouneCode LouneCode changed the title Basic Station back end: FineTimeSinceGpsEpoch missing from uplink event? Basic Station backend: FineTimeSinceGpsEpoch missing from uplink event? Apr 20, 2023
@brocaar
Copy link
Collaborator

brocaar commented May 18, 2023

I'm happy to add support for the fine-timestamp, but I'm hesitant to implement features which are not part of the "official" documented protocol and implementation. I would rather wait until lorabasics/basicstation#177 has been integrated in the "official" Basics Station implementation.

@LouneCode
Copy link
Author

I agree that. Sounds like a good plan. Looking forward "official" support of the fine-timestamp in the Basic station implementation.

I have run about five months that "unofficial" version of the fine-timestamp patch and it works like a charm ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants