Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3bef5ea660 | |||
| 25486b5c8f |
@@ -62,3 +62,11 @@ with `curl` when fields change; never hand-edit `testdata/` payloads.
|
|||||||
- `alt_baro` may be the string `"ground"` instead of a number → `readsb.AltBaro`.
|
- `alt_baro` may be the string `"ground"` instead of a number → `readsb.AltBaro`.
|
||||||
- readsb timestamps are fractional-second Unix floats → `readsb.UnixTime`.
|
- readsb timestamps are fractional-second Unix floats → `readsb.UnixTime`.
|
||||||
- `outline.json` points are `[lat, lon, altFeet]` tuples → `readsb.RangePoint`.
|
- `outline.json` points are `[lat, lon, altFeet]` tuples → `readsb.RangePoint`.
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
`CHANGELOG.md` follows [Keep a Changelog](https://keepachangelog.com/) and
|
||||||
|
SemVer. Record every user-facing change under `## [Unreleased]` as part of the
|
||||||
|
change itself — don't defer it to release time. When tagging a release, rename
|
||||||
|
`[Unreleased]` to the new version with the date and add a fresh empty
|
||||||
|
`[Unreleased]` section plus its compare link at the bottom.
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project are documented here.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.2.1] - 2026-06-23
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- `MinSpeed`/`MaxSpeed` aircraft filters in `pkg/types/readsb`, selectable
|
||||||
|
between ground speed and true airspeed via the `SpeedSource` type. `MaxSpeed`
|
||||||
|
drops aircraft with no speed reading.
|
||||||
|
|
||||||
|
## [0.2.0] - 2026-06-23
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Client retry configuration with exponential backoff (`RetryConfig`,
|
||||||
|
`WithRetry`). Retries transport errors and 5xx responses; never retries 4xx or
|
||||||
|
context cancellation.
|
||||||
|
- String-typed enums for readsb message type and emitter category.
|
||||||
|
|
||||||
|
## [0.1.1] - 2026-06-22
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- License.
|
||||||
|
|
||||||
|
## [0.1.0] - 2026-06-22
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Initial release: `pkg/types/readsb` and `pkg/types/wingbits` decode types,
|
||||||
|
the `pkg/client` HTTP client with one-shot queries and channel/iterator
|
||||||
|
polling for every endpoint, the `cmd/wingbits` CLI, and a README.
|
||||||
|
|
||||||
|
[Unreleased]: https://gitea.libretechconsulting.com/rmcguire/wingbits/compare/v0.2.1...HEAD
|
||||||
|
[0.2.1]: https://gitea.libretechconsulting.com/rmcguire/wingbits/compare/v0.2.0...v0.2.1
|
||||||
|
[0.2.0]: https://gitea.libretechconsulting.com/rmcguire/wingbits/compare/v0.1.1...v0.2.0
|
||||||
|
[0.1.1]: https://gitea.libretechconsulting.com/rmcguire/wingbits/compare/v0.1.0...v0.1.1
|
||||||
|
[0.1.0]: https://gitea.libretechconsulting.com/rmcguire/wingbits/releases/tag/v0.1.0
|
||||||
@@ -104,6 +104,38 @@ func OnGround() AircraftFilter {
|
|||||||
return func(a *Aircraft) bool { return a.AltBaro.OnGround }
|
return func(a *Aircraft) bool { return a.AltBaro.OnGround }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SpeedSource selects which speed reading a speed filter compares against. Its
|
||||||
|
// zero value is GroundSpeed.
|
||||||
|
type SpeedSource int
|
||||||
|
|
||||||
|
const (
|
||||||
|
// GroundSpeed measures against GS (ground speed, knots).
|
||||||
|
GroundSpeed SpeedSource = iota
|
||||||
|
// TrueAirspeed measures against TAS (true airspeed, knots).
|
||||||
|
TrueAirspeed
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s SpeedSource) of(a *Aircraft) float64 {
|
||||||
|
if s == TrueAirspeed {
|
||||||
|
return float64(a.TAS)
|
||||||
|
}
|
||||||
|
return a.GS
|
||||||
|
}
|
||||||
|
|
||||||
|
// MinSpeed keeps aircraft at or above knots, measured by src.
|
||||||
|
func MinSpeed(knots float64, src SpeedSource) AircraftFilter {
|
||||||
|
return func(a *Aircraft) bool { return src.of(a) >= knots }
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxSpeed keeps aircraft with a positive reading at or below knots, measured by
|
||||||
|
// src; aircraft with no reading are dropped.
|
||||||
|
func MaxSpeed(knots float64, src SpeedSource) AircraftFilter {
|
||||||
|
return func(a *Aircraft) bool {
|
||||||
|
v := src.of(a)
|
||||||
|
return v > 0 && v <= knots
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithinNM keeps aircraft within the given range (nautical miles) of the receiver.
|
// WithinNM keeps aircraft within the given range (nautical miles) of the receiver.
|
||||||
func WithinNM(nm float64) AircraftFilter {
|
func WithinNM(nm float64) AircraftFilter {
|
||||||
return func(a *Aircraft) bool { return a.RDst > 0 && a.RDst <= nm }
|
return func(a *Aircraft) bool { return a.RDst > 0 && a.RDst <= nm }
|
||||||
|
|||||||
@@ -68,6 +68,19 @@ func TestAircraftFilters(t *testing.T) {
|
|||||||
t.Errorf("WithinNM kept %s at %.1f nm", a.Hex, a.RDst)
|
t.Errorf("WithinNM kept %s at %.1f nm", a.Hex, a.RDst)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fast := r.Filter(MinSpeed(250, GroundSpeed))
|
||||||
|
for _, a := range fast {
|
||||||
|
if a.GS < 250 {
|
||||||
|
t.Errorf("MinSpeed kept %s at %.0f kt", a.Hex, a.GS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// MaxSpeed drops aircraft with no reading, so every kept aircraft is positive.
|
||||||
|
slow := r.Filter(MaxSpeed(250, GroundSpeed))
|
||||||
|
for _, a := range slow {
|
||||||
|
if a.GS <= 0 || a.GS > 250 {
|
||||||
|
t.Errorf("MaxSpeed kept %s at %.0f kt", a.Hex, a.GS)
|
||||||
|
}
|
||||||
|
}
|
||||||
// Composition is AND: position AND high altitude is a subset of each.
|
// Composition is AND: position AND high altitude is a subset of each.
|
||||||
both := r.Filter(WithPosition(), MinAltitude(30000))
|
both := r.Filter(WithPosition(), MinAltitude(30000))
|
||||||
if len(both) > len(pos) || len(both) > len(high) {
|
if len(both) > len(pos) || len(both) > len(high) {
|
||||||
|
|||||||
Reference in New Issue
Block a user