emilhe / dash-leaflet

MIT License
204 stars 33 forks source link

Force reload of WMS tiles? #238

Closed guidocioni closed 1 month ago

guidocioni commented 1 month ago

I want to force a refresh of WMS tiles every minute. For this reason I added a Interval component in my application and created a callback which tries to append a cache parameter to the WMS request url so that the tiles are forced to reload.

# Map Container for layout
dl.Map(
dl.WMSTileLayer(url="https://maps.dwd.de/geoserver/ows?", id='wms-layer-point',),
)

# callback to update the URL
@callback(
    Output("wms-layer-point", "url"),
    Input("interval-wms-refresh", "n_intervals"),
    prevent_initial_call=True,
)
def refresh_wms(n_intervals):
    if n_intervals > 0:
        return f"https://maps.dwd.de/geoserver/ows?cache={int(time.time())}"

However it seems this doesn't have any impact on the URL of the WMS Tiles (although the callback is correctly executed). Is this due to the fact that in the new leaflet everything inside the Map container is immutable? Is there any other way to force a refresh of the WMS tiles?

prl900 commented 1 month ago

Hi Guido,

Haven't tested this idea but I wonder if you could use the params prop to pass a random value on a fake WMS argument to force the update.

The params prop admits custom arguments that are directly passed to the WMS calls -- this is to deal with different non standard WMS implementations. You could use this to pass a new random value on a parameter "aux" each time the callback is triggered so the WMS requests are in fact different. The WMS will normally ignore the "aux" field and return the new tiles.

Hope this helps.

guidocioni commented 1 month ago

Hi Guido,

Haven't tested this idea but I wonder if you could use the params prop to pass a random value on a fake WMS argument to force the update.

The params prop admits custom arguments that are directly passed to the WMS calls -- this is to deal with different non standard WMS implementations. You could use this to pass a new random value on a parameter "aux" each time the callback is triggered so the WMS requests are in fact different. The WMS will normally ignore the "aux" field and return the new tiles.

Hope this helps.

Thanks, that makes complete sense...and it works! :)

I ended up using something like this

@callback(
    Output("wms-layer", "params"),
    Input("interval-wms-refresh", "n_intervals"),
    prevent_initial_call=True,
)
def refresh_wms(n_intervals):
    '''
    Refresh WMS tiles with interval
    '''
    if n_intervals > 0:
        return dict(cache=int(time.time()))