inav-configurator icon indicating copy to clipboard operation
inav-configurator copied to clipboard

Replace Bing Maps with Esri World Imagery

Open Scavanger opened this issue 6 months ago • 9 comments

Bing Maps is out of service.

Esri World Imagery (+ World Boundaries and Transportation) is not quite as detailed but can be used free of charge and does not require an API key.

Scavanger avatar Jun 11 '25 02:06 Scavanger

Thank you so much, Scavanger!

Linux zip available for testing here: https://github.com/iNavFlight/inav-configurator/actions/runs/15574766724/artifacts/3301919165

Windows here: https://github.com/iNavFlight/inav-configurator/actions/runs/15574766724/artifacts/3301938929

sensei-hacker avatar Jun 11 '25 02:06 sensei-hacker

We should make a 8.0.2 configurator for that soon don't you think?

b14ckyy avatar Jun 11 '25 06:06 b14ckyy

I'm thinking 8.1 and add the change Breadoven has recently made a PR through, to allow the old altitude estimator use. But, it should be well tested.

MrD-RC avatar Jun 11 '25 06:06 MrD-RC

The only thing I could mention. Is that it shows Map data not yet available, when zoomed beyond what the imagery provides. Not a deal breaker by any means. But it may be raised by some after the release, as being a problem.

I'm thinking 8.1 and add the change Breadoven has recently made a PR through, to allow the old altitude estimator use. But, it should be well tested.

@MrD-RC I have yesterdays build loaded and ready. And intend to test and tune it on a couple of the planes I had troubles with. But the weather down here is miserable. So I'm looking for a day that I can spend a good amount of time trying different adjustments.

Jetrell avatar Jun 12 '25 04:06 Jetrell

@Jetrell

The only thing I could mention. Is that it shows Map data not yet available, when zoomed beyond what the imagery provides. Not a deal breaker by any means. But it may be raised by some after the release, as being a problem. stments.

Can you show me how you did it? I had actually set the max zoom so that this doesn't happen, it works for me too.

Scavanger avatar Jun 12 '25 12:06 Scavanger

@Scavanger This is using the WIndows version.

This is max resolution.

less zoom

Then once it's zoomed in more.

zoomed

Jetrell avatar Jun 13 '25 08:06 Jetrell

It may be the maximum available depends on the location, and may change over time. Avoiding the possibility may mean detecting it live. Or just allow it - let people zoom until they see that particular location can't be zoomed any further at the moment.

sensei-hacker avatar Jun 13 '25 14:06 sensei-hacker

This is an issue with the data set. If you live in Western Europe or the USA, the data is available at all advertised scales. If you live the the Australian outback or other less populated area, the data is not available.

INAV cannot fix this. However, we might mention it in the release note.

If this bothers you, you can add a more comprehensive source via the "Map Proxy" option.

You may know this place ....

MapBox

image

Google

image

Bing (RIP)

image

Esri (alas)

image

stronnag avatar Jun 13 '25 19:06 stronnag

yeah that makes sense. In my area where the max level is available, I can zoom in to a full screen single pixel as the map drawer just does not load more and zooms what it has. But when I go into some outback or desert, then the server delivers a "no map data" tile instead. Configurator cannot know that this is no actual map.

But overall looks good to me and I think we can merge.

b14ckyy avatar Jun 13 '25 20:06 b14ckyy

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
DoS via large requests

Description: The code concatenates many coordinate pairs into a single OpenTopoData query without input
validation or request size limits, which could allow denial-of-service via excessive URL
length or request volume when user-controlled mission points are large.
waypointCollection.js [459-471]

Referred Code
const response = await fetch('https://api.opentopodata.org/v1/aster30m?locations='+coordList+'&samples='+String(samples+1));
const myJson = await response.json();

if (myJson.status == "OK") {
    elevation = [];
    for (var i = 0; i < myJson.results.length; i++){
        if (myJson.results[i].elevation == null) {
            elevation[i] = 0;
        } else {
            elevation[i] = myJson.results[i].elevation;
        }
    }
}        
Missing network timeouts

Description: External API calls to OpenTopoData are performed without timeout, retry, or error
handling, risking UI hangs or unhandled promise rejections during network failures.
fwApproach.js [88-93]

Referred Code
const response = await fetch('https://api.opentopodata.org/v1/aster30m?locations='+lat+','+lon);
const myJson = await response.json();
if (myJson.status == "OK" && myJson.results[0].elevation != null) {
    elevation = myJson.results[0].elevation;
}    
return elevation;
Third-party service usage

Description: Esri XYZ tile layers are used without API key or referrer restrictions; if Esri usage
requires attribution and potential access constraints, this could violate provider terms
or be blocked, leading to service disruption.
groundstation.js [71-89]

Referred Code
privateScope.mapLayers.push(new ol.layer.Tile({
    source: new ol.source.XYZ({
        url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
        attributions: 'Source: Esri, Maxar, Earthstar Geographics, and the GIS User Community',
        maxZoom: 19
    })
}));
privateScope.mapLayers.push(new ol.layer.Tile({
    source: new ol.source.XYZ({
        url: 'https://services.arcgisonline.com/arcgis/rest/services/Reference/World_Transportation/MapServer/tile/{z}/{y}/{x}',
        maxZoom: 19
    })
}));
privateScope.mapLayers.push(new ol.layer.Tile({
    source: new ol.source.XYZ({
        url: 'https://services.arcgisonline.com/arcgis/rest/services/Reference/World_Boundaries_and_Places/MapServer/tile/{z}/{y}/{x}',
        maxZoom: 19
    })
}));
Ticket Compliance
🎫 No ticket provided
  • [ ] Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

🔴
Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Missing error handling: New fetch to OpenTopoData lacks try/catch, response status checks, and fallback handling,
causing potential silent failures and unhandled promise rejections.

Referred Code
const response = await fetch('https://api.opentopodata.org/v1/aster30m?locations='+lat+','+lon);
const myJson = await response.json();
if (myJson.status == "OK" && myJson.results[0].elevation != null) {
    elevation = myJson.results[0].elevation;
}    
return elevation;
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
No auditing: Newly added logic for selecting and initializing map layers (e.g., Esri/MapProxy/OSM)
performs critical external requests without any audit logging of actions or outcomes.

Referred Code
    privateScope.mapLayers.push(new ol.layer.Tile({
        source: new ol.source.XYZ({
            url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
            attributions: 'Source: Esri, Maxar, Earthstar Geographics, and the GIS User Community',
            maxZoom: 19
        })
    }));
    privateScope.mapLayers.push(new ol.layer.Tile({
        source: new ol.source.XYZ({
            url: 'https://services.arcgisonline.com/arcgis/rest/services/Reference/World_Transportation/MapServer/tile/{z}/{y}/{x}',
            maxZoom: 19
        })
    }));
    privateScope.mapLayers.push(new ol.layer.Tile({
        source: new ol.source.XYZ({
            url: 'https://services.arcgisonline.com/arcgis/rest/services/Reference/World_Boundaries_and_Places/MapServer/tile/{z}/{y}/{x}',
            maxZoom: 19
        })
    }));
} else if ( globalSettings.mapProviderType == 'mapproxy' ) {
    privateScope.mapLayers.push(new ol.layer.Tile({


 ... (clipped 10 lines)
Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
External input use: New code builds query strings for external API calls using coordinates without validating
or bounding input values, which may cause unexpected behavior or denial-of-service if
malformed.

Referred Code
point2measure.forEach(function (item) {
    coordList += item + '|';
});
const response = await fetch('https://api.opentopodata.org/v1/aster30m?locations='+coordList+'&samples='+String(samples+1));
const myJson = await response.json();

if (myJson.status == "OK") {
    elevation = [];
    for (var i = 0; i < myJson.results.length; i++){
        if (myJson.results[i].elevation == null) {
            elevation[i] = 0;
        } else {
            elevation[i] = myJson.results[i].elevation;
        }
    }
}        
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

qodo-code-review[bot] avatar Oct 31 '25 05:10 qodo-code-review[bot]