kersing / packet_forwarder

Multi protocol packet forwarder supporting the TTN gateway-connector protocol.
Other
85 stars 56 forks source link

Time information not sent when faking GPS module #25

Open frazar opened 5 years ago

frazar commented 5 years ago

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:

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.

kersing commented 5 years ago

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?

frazar commented 5 years ago

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 commented 5 years ago

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:

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 commented 5 years ago

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.