From 5cc3b5f1d22aadf5ee87242e67c1e8f30c53ebad Mon Sep 17 00:00:00 2001 From: blazSmehov Date: Thu, 27 Nov 2025 14:20:50 +0100 Subject: [PATCH] chore: refactor distance related code for locations algorithm --- cmd/location/main.go | 24 ++------------ internal/pkg/common/utils/distance.go | 45 +++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 21 deletions(-) create mode 100644 internal/pkg/common/utils/distance.go diff --git a/cmd/location/main.go b/cmd/location/main.go index 13a9e68..8089abb 100644 --- a/cmd/location/main.go +++ b/cmd/location/main.go @@ -4,11 +4,10 @@ import ( "context" "encoding/json" "fmt" - "math" - "strconv" "time" "github.com/AFASystems/presence/internal/pkg/common/appcontext" + "github.com/AFASystems/presence/internal/pkg/common/utils" "github.com/AFASystems/presence/internal/pkg/config" "github.com/AFASystems/presence/internal/pkg/kafkaclient" "github.com/AFASystems/presence/internal/pkg/model" @@ -163,13 +162,12 @@ func assignBeaconToList(adv model.BeaconAdvertisement, appState *appcontext.AppS now := time.Now().Unix() if !ok { - appState.UpdateLatestBeacon(id, model.Beacon{ID: id, BeaconType: adv.BeaconType, LastSeen: now, IncomingJSON: adv, BeaconLocation: adv.Hostname, Distance: getBeaconDistance(adv)}) + appState.UpdateLatestBeacon(id, model.Beacon{ID: id, BeaconType: adv.BeaconType, LastSeen: now, IncomingJSON: adv, BeaconLocation: adv.Hostname, Distance: utils.CalculateDistance(adv)}) return } settings := appState.GetSettingsValue() - fmt.Println("RSSI: ", adv.RSSI) if settings.RSSIEnforceThreshold && (int64(adv.RSSI) < settings.RSSIMinThreshold) { return } @@ -189,7 +187,7 @@ func assignBeaconToList(adv model.BeaconAdvertisement, appState *appcontext.AppS } metric := model.BeaconMetric{ - Distance: getBeaconDistance(adv), + Distance: utils.CalculateDistance(adv), Timestamp: now, RSSI: int64(adv.RSSI), Location: adv.Hostname, @@ -204,19 +202,3 @@ func assignBeaconToList(adv model.BeaconAdvertisement, appState *appcontext.AppS appState.UpdateBeacon(id, beacon) } - -func getBeaconDistance(adv model.BeaconAdvertisement) float64 { - ratio := float64(adv.RSSI) * (1.0 / float64(twosComp(adv.TXPower))) - distance := 100.0 - if ratio < 1.0 { - distance = math.Pow(ratio, 10) - } else { - distance = (0.89976)*math.Pow(ratio, 7.7095) + 0.111 - } - return distance -} - -func twosComp(inp string) int64 { - i, _ := strconv.ParseInt("0x"+inp, 0, 64) - return i - 256 -} diff --git a/internal/pkg/common/utils/distance.go b/internal/pkg/common/utils/distance.go new file mode 100644 index 0000000..00755f7 --- /dev/null +++ b/internal/pkg/common/utils/distance.go @@ -0,0 +1,45 @@ +package utils + +import ( + "math" + "strconv" + + "github.com/AFASystems/presence/internal/pkg/model" +) + +// CalculateDistance calculates the approximate distance from RSSI and TX power +// Uses a hybrid approach combining logarithmic and polynomial models +func CalculateDistance(adv model.BeaconAdvertisement) float64 { + txPower := twosComp(adv.TXPower) + ratio := float64(adv.RSSI) / float64(txPower) + + if ratio < 1.0 { + return math.Pow(ratio, 10) + } else { + return (0.89976)*math.Pow(ratio, 7.7095) + 0.111 + } +} + +// TwosComp converts a two's complement hexadecimal string to int64 +func twosComp(inp string) int64 { + i, err := strconv.ParseInt("0x"+inp, 0, 64) + if err != nil { + return 0 + } + + if i >= 128 { + return i - 256 + } + return i +} + +// ValidateRSSI validates if RSSI value is within reasonable bounds +func ValidateRSSI(rssi int64) bool { + return rssi >= -120 && rssi <= 0 +} + +// ValidateTXPower validates if TX power is within reasonable bounds +func ValidateTXPower(txPower string) bool { + power := twosComp(txPower) + return power >= -128 && power <= 127 +}