Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Submitting a new plugin
#11
(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:
Code:
        function refreshPage() {
            window.location = "/";
            }
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:
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();

            }
        });
Reply
#12
I hope I am not being a pest for you, if so, let me know.

I found another oddity. If you turn the system off, then turn on manual mode, the system is automatically turned on.
Also, in manual mode, if you turn the system off, when you turn manual mode off, the system is turned back on.
IS that the desired behavior?
The following code is the cause:

def change_values(self):
qdict = web.input()
print("cv qdict: ", qdict) # - test
if "rsn" in qdict and qdict["rsn"] == "1":
stop_stations()
raise web.seeother("/")
if "en" in qdict and qdict["en"] == "":
qdict["en"] = "1" # default
elif "en" in qdict and qdict["en"] == "0":
gv.srvals = [0] * (gv.sd["nst"]) # turn off all stations
set_output()

This "if" in is curious and causes the behaviou:

if "en" in qdict and qdict["en"] == "":
qdict["en"] = "1" # default

By the way, I have the control buttons updating when changed by the keypad plugin. The api/status GET was reporting the change, so it was pretty easy to update the gui.
Reply
#13
(2023 Jan 29, 05:06 PM)RandyBryant Wrote: I hope I am not being a pest for you, if so, let me know.

I found another oddity.  If you turn the system off, then turn on manual mode, the system is automatically turned on.
Also, in manual mode, if you turn the system off, when you turn manual mode off, the system is turned back on.
IS that the desired behavior?
The following code  is the cause:

def change_values(self):   
        qdict = web.input()
        print("cv qdict: ", qdict)  # - test
        if "rsn" in qdict and qdict["rsn"] == "1":
            stop_stations()
            raise web.seeother("/")
        if "en" in qdict and qdict["en"] == "":
            qdict["en"] = "1"  # default
        elif "en" in qdict and qdict["en"] == "0":
            gv.srvals = [0] * (gv.sd["nst"])  # turn off all stations
            set_output()

This "if" in is curious and causes the behaviou:

        if "en" in qdict and qdict["en"] == "":
            qdict["en"] = "1"  # default

By the way, I have the control buttons updating when changed by the keypad plugin.  The api/status GET was reporting the change, so it was pretty easy to update the gui.

You are not being a pest. I appreciate your input.
Regarding the system turning on when switching manual mode I would say it is a bug. Ill work on fixing it.
<p><br></p>
Reply
#14
I think I have fixed it:

in webpages.py around line 137:


def change_values(self):
qdict = web.input()
if "rsn" in qdict and qdict["rsn"] == "1":
stop_stations()
raise web.seeother("/")
if "en" in qdict and qdict["en"] == "":
print(" change values qdict =", qdict)
print(" setting en to 1 why?")
#qdict["en"] = "1" # default

Dan, would you prefer we discuss my questions and changes through the Forum or with private emails?

Also, in home.html, there are a couple of calls to "displayProgram()".  I cannot find a function named that nor a JavaScript function.
Where is displayProgram and what does it do?

Randy
Reply
#15
Randy,

The displayProgram() JavaScript function is defined in SIP/static/scripts/schedule.js line 239.
Those scripts are loaded when base.html is opened.
base.html acts as a container for the other SIP pages and holds the basic HTML structure and provides the header, clock panel and footer that appear on each page.
<p><br></p>
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)