Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically fetch WMS images and disable caching #101

Closed
talldude69 opened this issue May 6, 2017 · 13 comments
Closed

Automatically fetch WMS images and disable caching #101

talldude69 opened this issue May 6, 2017 · 13 comments

Comments

@talldude69
Copy link

I was wondering if anything in the TimeDimension API will allow an automatic refresh of WMS images. I have a radar loop using the NOAA nowCOAST WMS reflectivity images. The loop loads in an hour's worth of images great. The problem is that they do not update as new images are available from the WMS service. I was hoping the "cache" or "cacheForward" options would help. Will either of these do the trick or there another API option that would work? If not, what would you suggest? Thanks in advance.

Mike

@bielfrontera
Copy link
Contributor

Hi @talldude69 ,
there is no option in the API to refresh the available times of a WMS layer (they are set when the layer is added to the map).

But you can extend the WMS Class and manage this option with a custom method.
I haven't tested, but I think this should work:

L.TimeDimension.Layer.WMS.AutoRefresh = L.TimeDimension.Layer.WMS.extend({

    initialize: function(layer, options) {
        L.TimeDimension.Layer.WMS.prototype.initialize.call(this, layer, options);
        this._updateTimeDimension = true;
        this._refreshTime = this.options.refreshTime || 60000 * 5; // refresh every 5 minutes by default
        this._intervalID = null;
    },

    onAdd: function(map) {
        L.TimeDimension.Layer.WMS.prototype.onAdd.call(this, map);
        this._intervalID = window.setInterval(
            L.bind(this._refreshAvailableTimes, this),
            this._refreshTime
        );
    },

    onRemove: function(map) {
        L.TimeDimension.Layer.WMS.prototype.onRemove.call(this, map);
        if (!this._intervalID) return;
        clearInterval(this._intervalID);
        this._intervalID = null;
    },

    _refreshAvailableTimes: function() {        
        this._capabilitiesRequested = false;
        this._requestTimeDimensionFromCapabilities();
    },

});

L.timeDimension.layer.wms.autoRefresh = function(layer, options) {
    return new L.TimeDimension.Layer.WMS.AutoRefresh(layer, options);
};

If it's useful, I could add this option to the library.

@talldude69
Copy link
Author

Hi bielfrontera,

I created another js file (leaflet.timedimension.layer.wms.autorefresh.js) from your code and modified my layer to:

var testTimeLayer = L.timeDimension.layer.wms.autoRefresh(radarWMS, {
refreshTime: 300000
//cache: 0,
//cacheForward: 10,
//setDefaultTime: true,
//requestTimeFromCapabilities: true,
//updateTimeDimension: true,
//updateTimeDimensionMode: "extremes"
});
testTimeLayer.addTo(radarmap);

The WMS images load as before but still no refresh of WMS images after 5 minutes. Am I doing something wrong?

Mike

@bielfrontera
Copy link
Contributor

I think your code is correct. Have you debugged it?
Put some breakpoints. For example at _refreshAvailableTimes and also at setAvailableTimes (L.TimeDimension.Layer.WMS and L.TimeDimension). Change the refreshTime option, so you won't need to wait too long.

@talldude69
Copy link
Author

I am unable to get the images to refresh.

@bielfrontera
Copy link
Contributor

@talldude69,
updateTimeDimensionMode option should be 'replace' (you can place it inside initialize).

I have debugged the code in this example, and realised that _requestTimeDimensionFromCapabilities was been called, and after setAvailableTimes... but with the mode 'intersect'. Therefore, there were no new times added to the list of available times.

@talldude69
Copy link
Author

bielfrontera,

I made the changes you recommended but the images are still not refreshing automatically.

@bielfrontera
Copy link
Contributor

Is the player on a continuous loop?

Or the player is stopped and you expect that the viewer automatically changes to the last available time when a new time is detected from the server?? In that case, you should subscribe the layer to the event availabletimeschanged and set the time to the last available time.

And you should check in the console the list of available times after requesting the server.

@talldude69
Copy link
Author

The player is on a continuous loop. Here is the relevant html portion:

var endDate = new Date();
endDate.setUTCSeconds(0, 0);
//$j("#satloop").attr('src', srcsat + '?timestamp=' + Math.random());

//var endDate = new Date();
//endDate.setUTCSeconds(0, 0);

var radarmap = L.map('radargis', {
zoom: zoom,
fullscreenControl: false,
timeDimension: true,
timeDimensionControl: true,
timeDimensionControlOptions: {
    autoPlay: true,
    displayDate: true,
    playerOptions: {
        buffer: 5,
        transitionTime: 1000,
        loop: true
    },
    speedSlider: true
},
timeDimensionOptions: {
    timeInterval: "PT60M/" + endDate.toISOString(),
    period: "PT5M"

},

center: [latitude, longitude]

});

L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(radarmap);

//var wmsURL = "https://idpgis.ncep.noaa.gov/arcgis/services/NWS_Observations/radar_base_reflectivity/MapServer/WMSServer";
//var wmsUrl = "https://idpgis.ncep.noaa.gov/arcgis/services/radar/radar_base_reflectivity_time/ImageServer/WMSServer";
var wmsUrl = "http://new.nowcoast.noaa.gov/arcgis/services/nowcoast/radar_meteo_imagery_nexrad_time/MapServer/WMSServer";
var radarWMS = L.nonTiledLayer.wms(wmsUrl, {
layers: '1',
format: 'image/png',
transparent: true,
opacity: 0.7,
attribution: 'nowCOAST'
});
// var cachewms = "&"+ Math.random();
//var proxy = '../Leaflet.Timedimension-master/examples/server/proxy.php';
var testTimeLayer = L.timeDimension.layer.wms.autoRefresh(radarWMS, {
refreshTime: 60000,
//cache: 0,
//cacheForward: 10,
//setDefaultTime: true,
//requestTimeFromCapabilities: true,
updateTimeDimension: true,
//updateTimeDimensionMode: "replace"
});
testTimeLayer.addTo(radarmap);

var theLegend = L.control({
position: 'bottomright'
});

theLegend.onAdd = function(map) {
var src = "http://new.nowcoast.noaa.gov/images/legends/radar.png";
var div = L.DomUtil.create('div', 'info legend');
div.style.width = '270px';
div.style.height = '50px';
div.innerHTML += 'Legend
legend';
return div;
};
theLegend.addTo(radarmap);

@bielfrontera
Copy link
Contributor

Use src files of Leaflet.TimeDimension and check if the message "available times changed" appears in the console. And debug L.TimeDimension.setAvailableTimes method: check if mode is 'replace' and compare the length the previous and the new _availableTimes array.

And you might have problems with the browser cache. Check if the GetCapabilities requests are using the cache instead of refreshing the data from your server.

@talldude69
Copy link
Author

talldude69 commented May 10, 2017

It appeared that the main issue was not specifying a proxy variable. I used the proxy.php file and the radar loop is now updating. I have 2 questions. I placed the following code to keep my interval at 30 minutes:

`var current = new Date(Date.now());
var currenttime = current.toISOString();
var previous = new Date(Date.now() - (30 * 60000));
var previoustime = previous.toISOString();

var radarmap = L.map('radargis', {
zoom: zoom,
fullscreenControl: false,
timeDimension: true,
timeDimensionControl: true,
timeDimensionControlOptions: {
    autoPlay: true,
    displayDate: true,
    playerOptions: {
        buffer: 6,
        transitionTime: 1000,
        loop: true
    },
    speedSlider: true
},
timeDimensionOptions: {
    timeInterval: previoustime + "/" + currenttime,
    //timeInterval: "PT30M/" + endDate.toISOString(),
    //period: "PT5M"
    period: "PT4M"

},

center: [latitude, longitude]

});

L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(radarmap);

//var wmsURL = "https://idpgis.ncep.noaa.gov/arcgis/services/NWS_Observations/radar_base_reflectivity/MapServer/WMSServer";
//var wmsUrl = "https://idpgis.ncep.noaa.gov/arcgis/services/radar/radar_base_reflectivity_time/ImageServer/WMSServer";
var wmsUrl = "http://new.nowcoast.noaa.gov/arcgis/services/nowcoast/radar_meteo_imagery_nexrad_time/MapServer/WMSServer";
var radarWMS = L.nonTiledLayer.wms(wmsUrl, {
layers: '1',
format: 'image/png',
transparent: true,
opacity: 0.7
//attribution: 'nowCOAST'
});
// var cachewms = "&"+ Math.random();
var proxy = 'proxy.php';
var testTimeLayer = L.timeDimension.layer.wms.autoRefresh(radarWMS, {
refreshTime: 240000,
proxy: proxy,
//cache: 0,
//cacheForward: 0,
//setDefaultTime: true,
//requestTimeFromCapabilities: true,
updateTimeDimension: true,
updateTimeDimensionMode: "replace"
});
testTimeLayer.addTo(radarmap);

var theLegend = L.control({
position: 'bottomright'
});

theLegend.onAdd = function(map) {
var src = "http://new.nowcoast.noaa.gov/images/legends/radar.png";
var div = L.DomUtil.create('div', 'info legend');
div.style.width = '270px';
div.style.height = '50px';
div.innerHTML += 'Legend
legend';
return div;
};
theLegend.addTo(radarmap);`

I see that the initial load takes this but is quickly overridden with the full 5 hours worth of WMS png images available from the nowCOAST server. How can I just use a moving 30-minute loop of radar images with the same refresh that your code is employing?

Also, is there an alternative to using php as the proxy? My reason for asking is that the CMS I ultimately will place this code does not support php. I am currently using a commercial server which does support php.

@bielfrontera
Copy link
Contributor

@talldude69,
ok. About the problem you had with the GetCapabilities requests: you have to check console and network tabs when you have problems with javascript.

Proxy: you can use any language in your server to send the request to the WMS server and redirect the response to the client. Here you have an example in python.

Available times: you are right. You are initialising timedimension with a list of times (each 4 minutes from last half hour), but when you load the Radar Layer, the list of times is replaced by the times of the layer (and after that, when _refreshAvailableTimes is called). I think the easiest way is to override the method setAvailableTimes (at autorefresh.js). There, you can modify the times you get as argument (the list of times of the layer from GetCapabilities). You can use L.TimeDimension.Util.intersect_arrays to get the list of times that you really want on your viewer.

@talldude69
Copy link
Author

talldude69 commented May 10, 2017

I will not be allowed to use the CMS server to post python, php, etc. Only client-side js scripts. Not really sure if this is going to work without that proxy. I am still trying to wrap my arms around this proxy file. Why am I able to pull images right away but I need a proxy to continue the process of obtaining images?

@bielfrontera
Copy link
Contributor

You do not need a proxy to get the images. But you need a proxy to fetch the result of GetCapabilities from the WMS server. This is a problem of CORS (you are requesting a resource from another server: cross-origin). This depends on the server, and it seems that the WMS server that you are using does not accepts requests from other domains (so you need a proxy).

If you can't use GetCapabilities to get the list of available times of the layer, you would need another strategy to check if there are new times available. You could check the response code of the request of an image with the next time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants