(ctx context.Context, dev *ttnpb.EndDevice, down *ttnpb.ApplicationDownlink)
| 222 | } |
| 223 | |
| 224 | func deviceHasPathForDownlink(ctx context.Context, dev *ttnpb.EndDevice, down *ttnpb.ApplicationDownlink) bool { |
| 225 | if dev.GetMulticast() || dev.GetMacState() == nil { |
| 226 | return len(down.GetClassBC().GetGateways()) > 0 |
| 227 | } |
| 228 | switch dev.MacState.DeviceClass { |
| 229 | case ttnpb.Class_CLASS_A: |
| 230 | return down.GetClassBC() == nil && |
| 231 | len(downlinkPathsFromRecentUplinks(dev.GetMacState().GetRecentUplinks()...)) > 0 |
| 232 | case ttnpb.Class_CLASS_B, ttnpb.Class_CLASS_C: |
| 233 | return len(downlinkPathsFromRecentUplinks(dev.GetMacState().GetRecentUplinks()...)) > 0 || |
| 234 | len(down.GetClassBC().GetGateways()) > 0 |
| 235 | default: |
| 236 | panic(fmt.Errorf("unmatched class: %v", dev.MacState.DeviceClass)) |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | // nextDataDownlinkSlot returns the next downlinkSlot before or at earliestAt when next data downlink can be transmitted to the device |
| 241 | // given the data known by Network Server and true, if such downlinkSlot and downlink exist, otherwise it returns nil and false. |
no test coverage detected