0

I am trying to make an Intranet of Things (IoT) page. I am using Flask for the python backend. I am trying to update the state of my light in real time. I believe the route to go is the AJAX/XMLHttpRequest on the front end. I am struggling to figure out how to send the JSON to the front end from the back end. Every example online seems to be a POST request instead of Get.

I believe I have the object created correctly as well as open and sending it correctly. I think my error is on the python side and not doing request right. I tried copying this example https://gist.github.com/KentaYamada/2eed4af1f6b2adac5cc7c9063acf8720. All the other stack overflow examples seem to do different methods like return or add an if statement for the return. I am not sure example how to setup to return the 'get' argument in request.args.get[]. The suggested potential duplicates only show one end, are in express js with the $ syntax which I'm not familiar with, or something similar

I am currently getting 500 errors. Below is my code.

HTML:

<html> <head>
    <meta name = "Viewport" context = "width=device-width. initial-scale=1.0">
    <title>Chang's IoT Controls</title>
    <link href="{{url_for('static',filename='Styles/Controls.css')}}" rel="stylesheet" type="text/css"/>
    </head>

    <body>
        <h1>Controls</h1>
        <p> Controls to control Chang's IoT Hub</p>

    <figure class="item">
    <img src="{{light}}" id="light" onclick="Power(this)" />
    <figcaption id = light1 class="caption">Light</figcaption>
    </figure>


    <figure class="item">
    <img src="{{url_for('static',filename='Images/OffLight.jpg')}}" id="temp" onclick="Power(this)" />
    <figcaption class="Temperature" id="state" <span style="border:2px solid black">Here</span></figcaption>
        <button type = "button" id="toggle" onclick ="Power(this)" > Change Lights </button>
    </figure>

    <figure class="item">
    <img src="{{temp}}" id="temp" onclick="Power(this)" />
    <figcaption id = temperature class="caption">{{degree}}</figcaption>
    </figure>


    <script>
    document.getElementById("state").innerHTML = "reached";

    const xhttp = new XMLHttpRequest();
    xhttp.onload = function () {
        const xmlDoc = JSON.parse(this.responseText);
        const status = xmlDoc.Status;
        document.getElementById("state").innerHTML = status;

        if(status == "On")
        {
            document.getElementById("temp").src = "{{url_for('static',filename='Images/OnLight.jpg')}}";
        }
        if(status == "Off")
        {
            document.getElementById("temp").src = "{{url_for('static',filename='Images/OffLight.jpg')}}";
        }
    }
    xhttp.open("GET",'/get_json');
    xhttp.send();
    console.log(xhttp.response);
    </script>

    <p>
        <a href="/">Homepage</a>
    </p>

    </body>

</html>


Python:

from flask import Flask, redirect, url_for, render_template, request

app = Flask(__name__)

@app.route("/", methods=["POST", "GET"])
def home():
    imgname = url_for('static', filename='Images/OnLight.jpg')
    thermo = url_for('static', filename='Images/Thermometer.png')
    heat = 50

#    if request.method == "GET":
#        file = request.form(url_for('static',filename='test.json'))
#        return file

    return render_template("Controls.html", light=imgname, temp=thermo, degree=heat)

@app.route('/get_json')
def get_json():
    return jsonify(Status= "On")

if __name__=="__main__":
    app.run(host="0.0.0.0", port=80)

JSON:

{
  "Light":
  [{"Status": "On"}]


}

I tried looking at examples including git repos like https://gist.github.com/KentaYamada/2eed4af1f6b2adac5cc7c9063acf8720 as well as stack overflow pages like Getting data from xhr request using python and how to properly get data from javascript to my python flask backend using XMLHttpRequest? as well as looked at the APIs

zealotben
  • 13
  • 2
  • _I am currently getting 500 errors_ Look in the webserver error log. – John Gordon Jan 26 '23 at 02:33
  • @JohnGordon I'm getting a bad request error now assuming I'm doing that right (I'm using firefox and click inspect and looking at the network tab. I'm getting 400 and 404 so it seems I'm requesting the GET wrong? – zealotben Jan 26 '23 at 03:03

1 Answers1

0

You can create different routes for html and for json.

For your Json try something like below

@app.route(“/get_json“, methods = [“GET”])
def get_json_to_frontend():
    // logic
    return jsonify( your response) 

for html you can use your home() function that you’ve already created

Assume your response is : { "state" : "Ok" }

This is what you're Javascript should look like:

let xhttp = new XMLHttpRequest();
        xhttp.onload = () => {
            let t = JSON.parse(xhttp.response);
            console.log(t.state);
        }
        xhttp.open("GET", URL);
        xhttp.send();

This should work. It's pretty straight forward.

  • I am not allowed to return it from my home page? So would my html change from xhttp.open("GET",'/'); to xhttp.open("GET",'/'get_json));? If I then want to change the state of the light from the front end (via a onclick), would I create another page to toggle the back end global variables? – zealotben Jan 26 '23 at 02:43
  • I tried redirecting it to that with "return jsonify({"Status": "On"}), but its still not working and I am getting 404 and 400 errors. I changed the get request to xhttp.open("GET",'/get_json'); – zealotben Jan 26 '23 at 03:06
  • I think you were missing some basics, no worries we are all new at some point to a tech stack. For returning json responses refer this https://stackoverflow.com/questions/13081532/return-json-response-from-flask-view. – Ram Sai Meghnadh Jan 26 '23 at 03:15
  • And for your home page html it’ll stay the same. And you’ll make another request from your home page html for fetching json – Ram Sai Meghnadh Jan 26 '23 at 03:18
  • I updated the code above to reflect the changes (and removed the if==GET section in my py since that was causing errors) , but it doesn't seem to be updating the image. homepage/get_json shows the right json dictionary, but my image is still the off light. It appears my status variable is undefined? – zealotben Jan 26 '23 at 03:40
  • Javascript functions are case-sensitive, so make sure you're using document.getElementById instead of document.GetElementById. And for parsing Json response using XMLHttpRequest() you can refer this https://stackoverflow.com/questions/1973140/parsing-json-from-xmlhttprequest-responsejson. You can use fetch API for HTTP requests. Remember fetching your home_page is first step, after that you can make any no of requests using Javascript. For each request you can create a view function in flask. – Ram Sai Meghnadh Jan 26 '23 at 04:00
  • I got it working, thanks for all your help! It appears the last error was that I was calling the JSON wrong. It was xmlDoc.Status and not xmlDoc.State – zealotben Jan 26 '23 at 04:19
  • Just to summarize my learnings (if you can confirm): The way to send data or toggle events from the front end to the back end is essentially calling another url (i.e. the /get_json call) without a return .html. Is it possible to send a variable to the backend? Looks like it may be the second arg in xmlhttp.open? Additionally, since the image is based on load, will it update if I change the JSON or should I have everything outside the on_load? – zealotben Jan 26 '23 at 04:49