Skip to content

[feature] BSSID Estimated Location #1373

@nemesifier

Description

@nemesifier

⚠️ Note: not suited for beginner contributors.

Continuation of: #201.

This issue is not a definitive plan carved in stone but I tried to add as much info as possible.


Is your feature request related to a problem? Please describe.

OpenWISP can already estimate a device location from the device last_ip using the existing Estimated Location flow, which is based on the WHOIS Lookup feature. This is useful but often imprecise, and it does not help devices whose last_ip is private or otherwise not suitable for GeoIP lookup.

Many OpenWrt devices can scan nearby WiFi access points. The BSSID scan results can be sent to an external geolocation service, such as the Google Geolocation API, to obtain a more accurate estimated location without requiring changes to the OpenWrt agent or firmware.

This feature continues the broader automatic positioning work from #201.

Describe the solution you'd like

Add an optional controller-side BSSID-assisted estimated location feature.

This should be a separate feature from the existing WHOIS Lookup / Estimated Location feature because BSSID geolocation can work independently from public IP geolocation.

The feature must be disabled by default and must require an external geolocation API key before it can run. It must be possible to enable or disable it at organization level, similarly to the existing Estimated Location feature.

The feature must not run for deactivated devices. It must also not overwrite manually set locations; it should only create or update locations managed by the estimated location system.

Initial implementation scope:

  • Implement support for OpenWrt only.
  • Use the existing connection/connector system to execute the scan command on the device.
  • Keep connector-specific command logic in the connector layer so other connector classes can add support later.
  • Scan all enabled radios, not just radio0.
  • Before scanning, check whether the device has any enabled radio that can be scanned.
  • Collect the strongest nearby BSSIDs and the useful metadata required by the external provider.
  • Send multiple BSSIDs to improve precision, ideally at least 3 and at most 10, choosing the strongest signals.
  • Use the Google Geolocation API for the first implementation.
  • Follow the Google Geolocation API documentation for the exact request payload rather than duplicating the full provider contract in this issue.
  • Use the returned coordinates to create or update the device estimated location.
  • Execute internal BSSID scans through connector/service code without creating visible user command history records, because these scans are system-initiated rather than user-initiated commands.

Example OpenWrt command:

ubus call iwinfo scan '{"device":"radio0"}'

The implementation should discover the available enabled radios and run the scan on all of them. radio0 is only an example.

Integration With Estimated Location

The BSSID feature should integrate with the existing Estimated Location flow while remaining independently configurable.

If only BSSID Estimated Location is enabled, run BSSID geolocation directly when the device becomes eligible.

If both BSSID Estimated Location and WHOIS/GeoIP Estimated Location are enabled, the implementation needs to take both signals into account. BSSID should improve the precision of the estimated location when it succeeds, but the existing GeoIP behavior remains useful and should not be discarded without investigation.

In particular, the current GeoIP Estimated Location flow can associate multiple devices with the same public last_ip to the same geographic location. This is useful because devices sharing a public IP are often in the same building or site. BSSID geolocation should improve the precision of that estimated location where possible, while preserving the ability to associate devices with the same public IP to the same location.

The exact order of operations needs investigation. Possible approaches include trying BSSID before GeoIP, using GeoIP as a fallback when BSSID fails, or letting GeoIP create/associate the estimated location first and then using BSSID to improve it. The final approach should be chosen based on reliability, notification behavior, and the smallest safe change to the current Estimated Location flow.

The implementation should preserve the existing behavior of notifying users that locations are estimated and should be manually improved. Users do not need to know whether the automatic estimate came from GeoIP or BSSID; they only need to know that the location is estimated and may need manual correction.

The feature should run only once for a device while the automatic estimated location remains valid. It can run again when there is evidence that the device may have physically moved, for example when the WHOIS data changes. As with the existing GeoIP estimated location flow, the scan should not run if the location has already been manually verified or changed by a user, because that location is no longer estimated.

The exact event that makes a device eligible for the first BSSID scan needs investigation. It may require a combination of events such as device creation, first successful connection, first config/status update, and/or a periodic task that scans eligible devices once.

If BSSID scanning or the external geolocation request fails, the system should keep the existing GeoIP-based estimated location when available.

Notification Behavior

The current GeoIP estimated location flow sends notifications when an estimated location is created or updated. With BSSID geolocation, the system may first create/update a GeoIP estimate and then improve it shortly after using BSSID data. The implementation should avoid notifying users twice for what is conceptually one automatic location update.

The rough desired behavior is:

  • If BSSID succeeds, send one notification about the estimated location.
  • If BSSID fails and GeoIP succeeds, send one notification about the GeoIP estimated location or same-public-IP association.
  • If GeoIP is disabled or skipped and BSSID succeeds, send one notification about the BSSID estimated location.
  • If both fail, do not create/update an estimated location; log the failure and use existing error notification patterns only where helpful.

This likely requires a small orchestration layer around the two estimation paths, or delaying/suppressing the GeoIP notification until the BSSID attempt has completed. The final approach should be chosen during implementation based on the smallest reliable change to the existing flow.

Error Handling And Retries

External API failures should be retried up to 10 times. Use existing retry HTTP utilities from openwisp-utils where possible, including exponential backoff.

Device connection failures and WiFi scanning failures should also be retried up to 10 times. This can be implemented as a Celery task using Celery retry mechanisms with increasing delays, for example 1 minute, 2 minutes, 4 minutes, 8 minutes, and so on.

The task should exit safely without creating or updating an estimated location when:

  • The feature is disabled globally or for the organization.
  • The external geolocation API key is missing or invalid.
  • The device is deactivated.
  • The device has no working connection.
  • The device has no enabled/scannable radios.
  • The scan returns too few useful BSSIDs.
  • The external provider does not return usable coordinates.
  • The device already has a manually set location.

Privacy And Data Sharing

The feature is disabled by default and requires explicit provider configuration. BSSID scan data is location-sensitive, so the implementation should send only the data needed by the configured external provider.

SSID names should not be sent unless they are required by the provider. For Google Geolocation API, contributors should prefer BSSID/macAddress and signal/channel metadata according to the provider documentation.

Suggested Implementation Areas

  • Existing Estimated Location flow: openwisp_controller/geo/estimated_location/.
  • Existing WHOIS trigger flow: openwisp_controller/config/whois/service.py and openwisp_controller/geo/estimated_location/handlers.py.
  • Existing command/connection flow: openwisp_controller/connection/base/models.py, openwisp_controller/connection/tasks.py, and OpenWrt connector code in openwisp_controller/connection/connectors/openwrt/ssh.py.

Expected Tests

  • Feature disabled globally or for the organization: no scan/geolocation task runs.
  • Missing external geolocation API key: feature cannot be enabled or task exits safely.
  • Deactivated device: no scan/geolocation task runs.
  • Device with manual location: manual location is not overwritten.
  • Device with only BSSID Estimated Location enabled: BSSID geolocation can run without WHOIS/GeoIP.
  • Device with both BSSID and GeoIP Estimated Location enabled: both signals are handled without breaking the existing GeoIP Estimated Location flow.
  • Device with public last_ip and BSSID failure: GeoIP estimated location and same-public-IP association still work.
  • Devices sharing the same public last_ip: existing behavior of associating them to the same estimated location is preserved, and BSSID can improve that estimated location when available.
  • OpenWrt device with multiple radios: all enabled radios are scanned.
  • No enabled/scannable radios: task exits safely.
  • Scan returns fewer than the minimum useful BSSIDs: task exits safely or falls back to GeoIP when available.
  • External geolocation success: estimated location is created or updated with returned coordinates.
  • External geolocation failure: existing GeoIP estimate remains available and notification behavior is sane.
  • Retry behavior: external API, device connection, and scan failures are retried up to 10 times.
  • Run frequency: BSSID scan does not repeat unnecessarily while the current estimated location remains valid.
  • Notification behavior: avoid duplicate notifications when BSSID and GeoIP are both involved.
  • System-driven BSSID scans do not create visible user command history records.

Describe alternatives you've considered

One alternative is modifying one of the OpenWrt agents to collect and send BSSID scan data to OpenWISP. This is less attractive because it risks introducing firmware-side bugs and would not be immediately available on already deployed networks.

Another alternative is implementing this in openwisp-monitoring. This is less attractive because Estimated Location already lives in openwisp-controller; splitting the feature further would make the code harder to maintain.

Open Investigation Points

  • Decide the exact event or combination of events that should trigger the first BSSID scan for eligible devices, especially when WHOIS/GeoIP is disabled or not applicable.
  • Decide how to orchestrate BSSID geolocation with the existing GeoIP/same-public-IP Estimated Location flow without duplicating notifications or losing the useful same-location association behavior.

Metadata

Metadata

Assignees

No one assigned
    No fields configured for Feature.

    Projects

    Status

    To do

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions