packet_forwarder icon indicating copy to clipboard operation
packet_forwarder copied to clipboard

Time information not sent when faking GPS module

Open frazar opened this issue 6 years ago • 4 comments

When the gateway is not equipped with a GPS module and is configured with fake_gps: true, the time information is not added to the "DeviceTimeAns" MAC command specified in LoRaWAN 1.0.3.

Browsing the code I found a couple of TODOs that mention the possibility of using an alternative time source from the GPS module:

A solution could use the clock_gettime() function with CLOCK_REALTIME to get the seconds since the Unix epoch, and then convert to seconds since the GPS epoch (taking into consideration leap seconds..).

I see two way of enabling the behaviour of using the local time:

  • by adding a new option, e.g. "fake_gps_time", or
  • by enabling reading the local time whenever gps_ref_valid is false.

I'm willing to propose a PR, but I'm not an expert in C or the codebase, so I might need a little guidance.

frazar avatar Oct 04 '18 07:10 frazar

MAC commands are processed by the back-end, not the gateway (also not the packet forwarder on the gateway) so I assume your statement is based on back-end code? What code?

kersing avatar Oct 04 '18 19:10 kersing

Maybe you're right, and the problem lies in the Network Server software. As I mentioned before, I'm not an expert, and I'm still trying to figure stuff out.

I thought it was due to packet_forwarder because of the TODOs I found skimming the code and the # Invalid gps time reference messages I was seeing in the logs.

I'll investigate more thoroughly and report back.

frazar avatar Oct 07 '18 11:10 frazar

I'll report here the results of my research.

Loraserver

First, I tried to understand why the Loraserver was sending a zero payload for the DeviceTimeAns.

Basically, when the loraserver software receives a request of the DeviceTimeReq MAC command, it will answer copying the timestamp of the received packet.

You can see this behaviour in the handleDeviceTimeReq() function:

  • here the function reads the TimeSinceGpsEpoch field of the rxInfo structure into the timeSinceGPSEpoch variable, as follows:

    timeSinceGPSEpoch, err = ptypes.Duration(rxInfo.TimeSinceGpsEpoch)
    
  • here the timeSinceGPSEpoch variable is used to populate the payload of the DeviceTimeAns MAC command.

    MACCommands: storage.MACCommands{
        {
            CID: lorawan.DeviceTimeAns,
            Payload: &lorawan.DeviceTimeAnsPayload{
                TimeSinceGPSEpoch: timeSinceGPSEpoch,
            },
        },
    },
    

So if the DeviceTimeAns payload is zero, it's because the rxInfo.TimeSinceGpsEpoch field is zero. This field is read from..

Lora-gateway-bridge

The next layer of the network is the Lora-gateway-bridge. Turns out the TimeSinceGpsEpoch field is populated using the "tmms" field of the JSON object received by the packet_forwarder, as seen here

// Time since GPS epoch
if rxpk.Tmms != nil {
    d := time.Duration(*rxpk.Tmms) * time.Millisecond
    frame.RxInfo.TimeSinceGpsEpoch = ptypes.DurationProto(d)
}

So how is the "tmms" field set?

packet_forwarder

The lora-gateway-bridge reads the JSON sent by packet_forwarder. It turns out the "tmms" field is always missing from this JSON.

I could only find it mentioned in the PROTOCOL.TXT of the packet_forwarder from Lora-Net

Conclusions

Probably the easiest solution is patching the lora-gateway-bridge so that it uses the "time" field rather then "tmms" to set RxInfo.TimeSinceGpsEpoch.

frazar avatar Oct 16 '18 22:10 frazar

A little update. I forked the packet_forwader from Lora-net to add the "tmms" field in the uplink JSON. With that modification, the DeviceTimeAns and DeviceTimeReq comands work correctly.

frazar avatar Nov 14 '18 15:11 frazar