code: func GetNextPingSlotAfter(afterGPSEpochTS time.Duration, devAddr lorawan.DevAddr, pingNb int) (time.Duration, error) {
  	if pingNb == 0 {
  		return 0, errors.New("pingNb must be > 0")
  	}
  	beaconStart := afterGPSEpochTS - (afterGPSEpochTS % beaconPeriod)
  	pingPeriod := pingPeriodBase / pingNb
  
  	for {
  		pingOffset, err := GetPingOffset(beaconStart, devAddr, pingNb)
  		if err != nil {
  			return 0, err
  		}
  
  		for n := 0; n < pingNb; n++ {
  			gpsEpochTime := beaconStart + beaconReserved + (time.Duration(pingOffset+n*pingPeriod) * slotLen)
  
  			if gpsEpochTime > afterGPSEpochTS {
  				log.WithFields(log.Fields{
  					"dev_addr":                   devAddr,
  					"beacon_start_time_s":        int(beaconStart / beaconPeriod),
  					"after_beacon_start_time_ms": int((gpsEpochTime - beaconStart) / time.Millisecond),
  					"ping_offset_ms":             pingOffset,
  					"ping_slot_n":                n,
  					"ping_nb":                    pingNb,
  				}).Info("get next ping-slot timestamp")
  				return gpsEpochTime, nil
  			}
  		}
  
  		beaconStart += beaconPeriod
  	}
  }
docs: // GetNextPingSlotAfter returns the next pingslot occuring after the given gps epoch timestamp.