2023 Jan 28, 05:46 PM
(2023 Jan 28, 04:18 PM)dan Wrote:(2023 Jan 28, 12:31 AM)RandyBryant Wrote:(2023 Jan 27, 03:55 PM)dan Wrote:(2023 Jan 26, 03:56 PM)RandyBryant Wrote:(2023 Jan 26, 03:18 PM)dan Wrote: Hi Randy,
The problem of certain changes not showing up in the UI until a page refresh is due to the fact that the changes happen on the server (raspberry pi) side and are not pushed to the browser until a refresh is done.
I have been looking into a way for the server to cause a page refresh on the browser but I have not found a simple solution. If you have any ideas on how to accomplish this I would be very interested.
Dan
I have limited WEB programming experience, but I'll investigate.
What causes the station updates when the keypad starts a program run? The run times/status shows up with out doing a refresh.
Randy
The way the stations are updated when a program is running is that the home page requests a status update from the server once a second (templates/home.html line ~76). It gets an update from the api_status class in webpages.py (line ~645) which sends a JSON formatted list of status data. JavaScript on the home page updates the display.
You can see the status data at <SIP url>/api/status
I have been tinkering with HTML Server-Sent Events (SSE) to force a page refresh on the browser. One big problem is that if a plugin changes the value of a SIP variable there is no easy way to detect the change unless the plugin notifies the core program.
Dan
I have a little headway in try to understand the WEB interface and status updates.
Turns out the following code return not only the station running info, but a few system status items too:
class api_status(ProtectedPage):
"""Simple Status API"""
def GET(self):
#print("api_status GET")
statuslist = []
status = {
"systemName": gv.sd["name"],
"systemStatus": gv.sd["en"],
"waterLevel": gv.sd["wl"],
"rainDelay": gv.sd["rd"],
"mode": gv.sd["mm"]
}
.
.
.
status["status"] = "waiting"
status["reason"] = "program"
status["programName"] = pname
status["remaining"] = rem
else:
status["reason"] = "system_off"
statuslist.append(status)
web.header("Content-Type", "application/json")
#print(" returning '{}'".format(statuslist))
return json.dumps(statuslist)
When the keypad runs a station this status return to a /api/status request, returns the system info too. It just doesn't get updated by the Gui. I don't understand how the program data causes the home.html to repaint the program info:
function statusTimer() {
jQuery.getJSON("/api/status", updateStatus)
}
Is the request, and:
function updateStatus(status) {
let display, updateInterval = 5000;
console.debug("SIP home.html: status.length = " + status.length);
for (let s=0; s<status.length; s++) {
let station = status[s];
let classes = "noNewline stationStatus station_" + station.status;
if (s == 0) {
let system = status[s];
console.debug("SIP home.html: system status = " + system.systemStatus);
console.debug(" system name = " + system.systemName);
console.debug(" water level = " + system.waterLevel);
console.debug(" rain delay = " + system.rainDelay);
console.debug(" mode = " + system.mode);
}
else {
console.debug("SIP home.html: station " + s + "; status = " + station.status);
switch (station.reason) {
case "program" :
let minutes = Math.floor(station.remaining / 60);
let seconds = Math.floor(station.remaining - 60*minutes);
if (minutes < 10) {minutes = "0"+minutes;}
if (seconds < 10) {seconds = "0"+seconds;}
,.
.
.
jQuery("td#status" + station.station)
.text(display)
.removeClass()
.addClass(classes);
}
setTimeout(statusTimer,updateInterval);
if (updateInterval > 1000) {
displayProgram();
}
Updates the program/station part of the Gui.
So how do I get it to also repaint the other information?
Updating part of a page can be done with JavaScript but in some cases it is necessary to refresh the entire page.
In home.html line ~179 there is some code to do that:
I should point out that the "$" symbol is often used for jQuery but in SIP (web.py) templates that symbol is used for embedded Python code:Code:function refreshPage() {
window.location = "/";
}
https://webpy.readthedocs.io/en/latest/templating.html
I'll try that, but I have discovered that I can use jQuery to change the text of the System Status Button with out a refresh. So I am thinking there should be a way to execute a click function, like this code that is already in the code:
jQuery("button#cRainDelay").click(function(){
if (rd != 0) {
h = 0;
} else {
h = prompt($:{json.dumps(_(u'Enter hours to delay'), ensure_ascii=False)},"0");
}
if (h < 0) {
h = prompt("Delay must be a positive value","0");
}
if (h != null && h >= 0){
jQuery("form[name='hf'] input[name='rd']").val(h);
jQuery("form[name='hf']").submit();
}
});