Take out JSON elements out of Socket MQTT in Flask - python

I'm currently using MQTT-Flask to accomplish sending a payload over MQTT and sockets to my Flask webserver. So far it works well, and I've been attempting to build on what I have and transition the payload into JSON to pack more data into it, so that I can use the variables on different parts of the site.
That said, I'm not able to save have it been recognized as JSON so that I can save the variables from it, and I was hoping someone could point me in the right direction.
So the snippet of data I use in Flask looks as follows:
#mqtt.on_message()
def handle_mqtt_message(client, userdata, message):
data = dict(
topic=message.topic,
payload=message.payload.decode(),
)
socketio.emit('mqtt_message', data=data)
as came standard with the github, and I saw no fault with this, so I kept it.
On the template/index.html it looks as follows:
<script type="text/javascript" src="{{ url_for('static', filename='jquery-3.3.1.min.js') }}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='socket.io.min.js') }}"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
var socket = io.connect('http://' + document.domain + ':' + location.port);
socket.on('mqtt_message', function(data) {
console.log(data);
$('#mqtt_msg').text(data.payload);
})
});
</script>
<div id="mqtt_msg"></div>
I've tried parsing it into JSON.stringify and just trying to take it out as data.timestamp but all of that doesn't seem to work. It feels like it is very straightforward.
The payload I'm pushing looks as follows:
{
"timestamp": 1614708210,
"payload": "432",
"agent": "web_admin"
}
Any help or input would be greatly appreciated.

Create JSON string while sending data
socketio.emit('mqtt_message', data=json.dumps(data))
parse the JSON string on the client-side
socket.on('mqtt_message', (data) => {
console.log(JSON.parse(data));
});
Don't forget to import json package in python
import json

Related

Flask Get Request for JSON

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>
Homepage
</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
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.

How to upload a file in html page, using http trigger in azure functions using python?

I would like to have a some way, how to upload a file (could be html without php, or some interactive azure upload page, whatever), and through my URL params I would like to send parameters, which will run the rest of code using this uploaded file (ofc I need to save it to blob at least).
I need a rest api, so i chose azure functions.
Is there any way how to do it in python? I saw lots of examples in C#, but docs for python are limited.
Thx a lot!
Regarding the issue, you can use Html Form to implement it.
For example
Html page
<!DOCTYPE html>
<html>
<script type="text/javascript"
src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.js">
</script>
<body>
<form enctype="multipart/form-data">
<input name="file" type="file" />
<input type="button" value="Upload" />
</form>
<progress></progress>
<script language="javascript" type="text/javascript">
$(document).ready(function(){
$(':file').on('change', function () {
var file = this.files[0];
console.log(file)
$(':button').on('click', function () {
var form = new FormData()
form.append('file',file)
$.ajax({
// Your server script to process the upload
url: '<your azure function app url>',
type: 'POST',
crossDomain: true,
enctype: 'multipart/form-data',
// Form data
data:form,
// Tell jQuery not to process data or worry about content-type
// You *must* include these options!
cache: false,
contentType: false,
processData: false,
success : function(data){console.log(data);},
// Custom XMLHttpRequest
xhr: function () {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) {
// For handling the progress of the upload
myXhr.upload.addEventListener('progress', function (e) {
if (e.lengthComputable) {
$('progress').attr({
value: e.loaded,
max: e.total,
});
}
}, false);
}
return myXhr;
}
});
});
});
});
</script>
</body>
</html>
Function code (upload file to Azure blob )
import logging
import os
import azure.functions as func
from azure.storage.blob import BlobServiceClient, BlobClient
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
try:
file= req.files.get('file')
logging.info(file.filename)
connect_str="your storage account connection string"
container="your container name"
blob_service_client = BlobServiceClient.from_connection_string(connect_str)
blob_client =blob_service_client.get_blob_client(container=container,blob=file.filename)
blob_client.upload_blob(file)
except Exception as ex:
logging.info(ex.args)
return func.HttpResponse(f"the file {file.filename} upload successfully")
Configure CORS for you function
Test

How to reload an image from the same path without refreshing the page?

I'm trying to load an image file with flask, and then update the same file with a different image and display the newly updated image without having to refresh the page.
I've tried different combinations with ajax and jquery and none have worked so far but it is possible I'm just missing a really simple fix.
This is the index.html file I currently have
<script src ="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<body>
<div>
<img id="my_image" src = "{{img}}">
</div>
<script>
function getimg(){
$.ajax({
type: 'GET',
cache: false,
url: "{{url_for('get_img')}}",
success: function(resp){
dt = new Date();
$('my_image').attr('src', resp.img + "?" + dt.getTime());
}
});
}
$(document).ready(function(){
setInterval(getimg, 3000);
});
</script>
</body>
And this is the flask routes from getImage.py
import json
from flask import render_template
#app.route('/img')
def open_image():
img = 'static\\testing.jpg'
return render_template('index.html',**locals())
#app.route('/get_img', methods = ['GET'])
def get_img():
img = 'static\\testing.jpg'
return json.dumps({img:img})
I know the ajax is sending requests through to flask via cmd but it does not actually update the image.

Send variables from a python script run on a raspberry pi to webserver

I have a python script running on my raspberry pi that outputs data from sensors connected to the pi's GPIO input. I need a simple way to have this live data on a server accessible from anywhere. I've looked at django framework but it seems like overkill for what I need to do.
You mean something like this?
You can create a static webpage with some JS like so:
<html>
<head>
<title>My Pi</title>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
</head>
<body>
<div id="sensor1"></div>
Get data from sensor 1
<script type="text/javascript">
function getSensor1() {
$.ajax({
type: "POST",
url: "cgi-bin/cputemp.py",
dataType: "html",
success: function(msg) {
document.getElementById('sensor1').innerHTML = msg;
},
});
}
</script>
</body>
And something like this in a cgi-bin/cputemp.py directory relative to your html page.
#!/usr/bin/python
import cgi;
import cgitb;
import time
cgitb.enable()
import commands
import sys
import string
print "Content-type: text/html\n\n";
mytemp1 = commands.getoutput('/opt/vc/bin/vcgencmd measure_temp | cut -d "=" -f2 | cut -f1')
output = "Pi CPU Temp is: " + mytemp1
print output
You can run a script every x minutes with cron, the script will have to output the values instead of run in loops, and the cron task will be something like:
curl -X POST -d '$(python /path/to/script.py)' http://example.com/receive.php
You can use Flask instead of Django.
And if you don't want to create server you can use third party Application Like ThingSpeak where you can just post data and you can view your data from anywhere.

tornado can't load jquery.js?

here is my simple html, when I open the file directly, there is no issue
<html>
<head>
<meta charset="utf-8">a
<title>Demo</title>
</head>
<body>
jQuery
<script src="jquery.js"></script>
<script>
$( document ).ready(function() {
$( "a" ).click(function( event ) {
alert( "The link will no longer take you to jquery.com" );
event.preventDefault();
});
});
</script>
</body>
</html>
However, if i input the http://localhost:8000/ tornaod gives me the error that WARNING:tornado.access:404 GET /jquery.js (::1) 3.00ms
following is my simple tornado code...I am not sure what wrong with my code...
class IndexHandler(tornado.web.RequestHandler):
def get(self):
self.render("./pages/index.html")
app = tornado.web.Application([(r'/test1', Test1Handler),
(r'/test2', Test2Handler),
(r'/test3', Test3Handler),
(r'/', IndexHandler)],
debug=True)
app.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
From what I see, you have only 4 paths specified to be accessible via Tornado: /test1, /test2, test3 and /. There is no path specified to access /jquery.js.
Theck this question to see how to serve static files:
Using Tornado, how do I serve static files and serve a favicon.ico from a different directory than the static path?

Categories