We want to send a boolean value from python to javascript so we can use it in our html website.
We tried using sockets but thats too complicated for us. Our next thought was to use an api and we know how to get information from an api using javascript. What we want to do is post a python boolean value to an api, and then get the boolean value from the api using javascript.
But we don't know how to do so.
We are using a raspberry pi for all our code and a hardware-button which returns true in python when pressed.
We are currently testing code we found from https://healeycodes.com/javascript/python/beginners/webdev/2019/04/11/talking-between-languages.html
But this code doesnt work for us.
We are also using pycharm as our workspace, is this a problem?
Our current code in javascript:
const request = new XMLHttpRequest();
request.open("GET", url, true);
request.onreadystatechange = function() {
if (request.readyState === 4 && request.status === 200) {
success(JSON.parse(request.responseText));
}
};
request.send();
setInterval(get("button-status.json", receiveStatus), 3000);
}
function receiveStatus(response) {
if (response.status !== status) { // only do something if status has changed
status = response.status;
console.log('button status is now', status);
}
}
let status;
// checks every 100ms
get()
Our python code we're using for testing:
import random
import json
import time
button_status = False
path = (r"C:\Users\Sam\Desktop\pythonProject\pythonflask\emplates") # replace with your actual path
def save_button_status():
with open(path + "/button-status.json", "w") as f:
json.dump({'status': button_status}, f)
while True :
value = random.randrange(1, 10)
if ( value <= 5) :
button_status = True
save_button_status()
time.sleep(3)
else :
button_status = False
save_button_status()
time.sleep(3)
print(button_status)
Javascript within a webpage cannot directly run a Python script on your computer or read information from a local terminal. What you could do is have your Python program output a small json file to your localhost folder which is overwritten when the button is pressed or released, like this:
import json
button_status = False # assuming it is initially off
path = "path/to/your/localhost/folder" # replace with your actual path
def save_button_status():
with open(path + "/button-status.json", "w") as f:
json.dump({'status': button_status}, f)
# Then call save_button_status() whenever the status changes
Then in your javascript, set an interval to periodically call a function that gets this json file and does something based on the value if it has changed:
function get(url, success) {
//--- Get JSON data at the given URL and call `success` if successful
const request = new XMLHttpRequest();
request.open("GET", url, true);
request.onreadystatechange = function() {
if (request.readyState === 4 && request.status === 200) {
success(JSON.parse(request.responseText));
}
};
request.send();
}
function receiveStatus(response) {
if (response.status !== status) { // only do something if status has changed
status = response.status;
console.log('button status is now', status);
}
}
let status;
let interval = setInterval(() => get("button-status.json", receiveStatus), 100); // checks every 100ms
There may be some lag as your local server updates the file.
You can try to set up a SQL Database. Write a SQL statement in Python to receive your boolean. After that make a PHP script on your Web server to receive the SQL data. Then sent a request to the URL of the PHP script using an XHTTP JavasScript request.
Related
I followed some guides on how to send json objects to the server(written using node.js) and it doesn't work, I have no idea what is wrong. I know that my server works fine since I tested it on postman so it's my js code that's the problem, all the tutorials I see follow a similar XMLHttpRequest format.
this is my code
var ing = new Ingredient(name, date, qty, rp);
var url = "http://localhost:8081/addIngredient";
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
//Send the proper header information along with the request
// application/json is sending json format data
xhr.setRequestHeader("Content-type", "application/json");
// Create a state change callback
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// Print received data from server
result.innerHTML = this.responseText;
}
};
// Converting JSON data to string
var data = JSON.stringify(ing);
document.write(data);
// Sending data with the request
xhr.send(data);
I used document.write to check where the code stops working but everything passes (since the document.write prints something), I suspect that there is something wrong/missing from xhr.send(data) but I can't tell what. Finally, nothing gets printed from the callback.
It's better to use onload instead of onreadystatechange
xhr.onload = function() {
if (xhr.status == 200) {
console.log(`Response length = ${xhr.response.length}`);
// store xhr.response here somewhere
}
};
I am a beginner in web development (self learner),and I am trying to connect my javascript .js file to java servlet through AJAX where I am stuck. It's not making the AJAX call, or not entering the java code, returning to the call back function. Is my url mapping or path specified correct? Or can you see some other error? Thanks!
JS code:
a = parseInt(document.getElementById("num"+ 0).value);
var xhr = new XMLHttpRequest();
xhr.open("GET", "/add?num1=" + a , true ); // true is for Asynchronous request
alert("here3 a=" + a);
xhr.send();
var ret = eval(xhr.responseText); //just trial
alert("eval" + ret);
xhr.onreadystatechange = () => {
if(xhr.readyState == 4 && xhr.status == 200){
document.getElementbyId('ajaxResponse').innerHTML = xhr.responseText;
var ret = eval(xhr.responseText);
alert("Callback1 = " + ret);
}
else(alert("Callback failed"))
};
Java servlet:
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
System.out.println("Add Servlet called");
int i = Integer.parseInt(req.getParameter("num1"));
// int j = Integer.parseInt(req.getParameter("num2"));
// int k = i+j;
PrintWriter out = res.getWriter();
out.println("Result is i=" + i);
res.setContentType("text/plain");
res.getWriter().write(i);
}
Web.xml
(servlet): callJava
com.AddServlet
(servlet-mapping):callJava
/add
It just goes in else condition of callback function ("Callback failed"). Also, does the location/folder structure of the servlet or js file matters, if mapping is done in .xml file? Thanks!
I can't really help you with the server side part as I'm not familiar with the framework that you are using. But the following are my recommendations for the client side code:
Use let instead of var;
true flag to make request async is not necessary because it is the default and will be soon deprecated.
It is preferable to use the new addEventListener API instead of directly adding the handler to the intended target.
Fully setup your request before calling open and send.
Use === operator instead of ==.
const a = parseInt(document.getElementById("num" + 0).value);
let xhr = new XMLHttpRequest();
xhr.addEventListener('readystatechange', (e) => {
if(e.target.readyState === 4){
document.getElementbyId('ajaxResponse').innerHTML = e.target.responseText;
}
});
xhr.open("GET", "/add?num1=" + a);
xhr.send();
Please let me know if it works. If it does, you may want to check if your server is correctly setting the "found" response code (200).
Ok I figured it out, the url should just be "add?num1=" instead of "/add?num1=". It does map through .xml file! Now I am reaching java file and status is 200 :D
Next I am trying to figure out how to return back value any ajax response value from java servlet to javascript file or html file. Should I do it somehow in xhr.onreadystatechange() function? It's still not satisfying both conditions [if(xhr.readyState == 4 && xhr.status == 200)]. Any suggestions?
I was going through the following article :
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data
Here , the concept of AJAX is being illustrated however , for simple illustration ,instead of connecting to the server ,the content is being fetched from the system which has the browser in it .
So in the following code lines from the above mentioned link :
var url = verse + '.txt';
var request = new XMLHttpRequest();
request.open('GET', url);
Here a GET verb is to fetch the contents of the file in the local system and no server is present there .
Similarly , by using javascript and in the absence of a server
can we add some parameters to GET or POST verb and run a code in the local system which processes these parameters and sends an output .
Like :
var url = 'verse + '.txt' + '?' 'name = ' + 'vim' ; //Adding parameters
and there will be some javascript file , which takes these parameter "name "
and returns it in uppercase , like "VIM " .
Can we do anything like that using Javascript only (not nodejs or anything that sets up a server " ) without server listening ?
To achieve the requirement you can use Chromium or Chrome browser launched with --allow-file-access-from-files flag set.
fetch() does not permit requesting local files having file: protocol, though XMLHttpRequest() does. fetch() does allow requesting data URL and Blob URL.
For
some javascript file , which takes these parameter "name " and returns
it in uppercase , like "VIM "
Worker can be used to get the contents of a local file, manipulate the content, then postMessage() can be called to communicate with main thread.
For example
worker.js
onmessage = e => {
// do stuff
let url = new URL(e.data);
let [[,param]] = [...url.searchParams]; // get query string parameter `'vim'`
let request = new XMLHttpRequest();
request.open('GET', 'file:///path/to/local/file' /* e.data */);
request.onload = e => {
console.log(request.responseText); // `setTimeout()` can be inside `load` handler
}
request.send();
// asynchronous response
setTimeout(() => {
// set `data URL` that `fetch()` will request
postMessage(`data:text/plain,${param.toUpperCase()}`);
}, Math.floor(Math.random() * 2000));
}
At console or within a script
const localRequest = async(url) => {
const request = await fetch(await new Promise(resolve => {
const worker = new Worker('worker.js');
worker.onmessage = e => {
resolve(e.data);
worker.terminate();
}
worker.postMessage(url);
}));
const response = await request.text();
console.log(response);
}
localRequest('file:///verse.txt?name=vim');
I am currently trying to write some Javascript to interact with an API that I deployed on GAE (using Python) using XMXMLHttpRequest(). I've had no issue getting a GET, however the PUT is giving me a lot of trouble.
Interestingly, I have no issue touching the PUT request from a test HTTP site (https://www.hurl.it/), however I receive a status value of 0 every time I try from my own Javascript code. Below are snippets of my GAE and Javascript code.
(NOTE - I must use a "put" for this call as a requirement.)
Any guidance would be appreciated!
GAE (Server):
def put(self):
# Save variables for update
cardkey = self.request.get('key', default_value=None)
ident = self.request.get('ident', default_value=None)
brand = self.request.get('brand', default_value=None)
year = self.request.get('year', default_value=None)
player = self.request.get('player', default_value=None)
# If card key is provided then update card
if cardkey:
# Get card
card_to_update = ndb.Key(db_models.Card, int(cardkey)).get()
if ident:
card_to_update.ident = ident
if brand:
card_to_update.brand = brand
if year:
card_to_update.year = year
if player:
card_to_update.player = player
# Save changes and print update to requester
card_to_update.put()
card_dict_format = card_to_update.to_dict()
self.response.write(json.dumps(card_dict_format))
return
# If card key is not provided send error
else:
self.response.write('key not provided. must provide key for update.')
return
And the Javascript from my webpage:
<script>
window.onload = function()
{
var myRequest = new XMLHttpRequest();
var url = 'http://cs496-assignment3-mastrokn.appspot.com/updatecard';
var param = 'key=5636318331666432';
myRequest.open('put', url);
myRequest.onreadystatechange = function()
{
if ((myRequest.readyState == 4) && (myRequest.status == 200))
{
// var myArr = JSON.parse(myRequst.responseText);
// myFunction(myArr);
document.getElementById("viewCards").innerHTML = myRequest.status;
}
else
{
document.getElementById("viewCards").innerHTML = myRequest.status;
}
}
myRequest.send(param);
}
</script>
First, your onreadystatechange() handler should look like this:
myRequest.onreadystatechange = function()
{
if (myRequest.readyState == 4) //Don't do anything until the readyState==4
{
if(myRequest.status == 200) //Check for status==200
{
document.getElementById("viewCards").innerHTML = myRequest.status;
}
else //All other status codes
{
document.getElementById("viewCards").innerHTML =
'readyState='
+ myRequest.readyState
+ ' status='
+ myRequest.status
+ ' status text='
+ myRequest.statusText;
}
}
}
Then, from the docs:
If you end up with an XMLHttpRequest having status=0 and
statusText=null, it means that the request was not allowed to be
performed. It was UNSENT.
To see what went wrong, check the javascript console in your browser for an error, e.g.:
[Error] XMLHttpRequest cannot load
http://cs496-assignment3-mastrokn.appspot.com/updatecard. Origin
http://localhost:4567 is not allowed by Access-Control-Allow-Origin.
(4.htm, line 0)
When I run the code above and send the XMLHttpRequest to my own local server, the PUT request succeeds with a status code of 200.
Lastly, I have doubts about the server code you posted because I don't know of any framework where you return None from a request handler--rather you return some string or a response object. Yet, using other means to make a PUT request to your url returns a 200 status code. Is that really your server code? What framework are you using?
I am relatively new to web development and am trying to get the client javascript to send GET requests to a python script running on the server and the server to return data based on that request. I have tried adapting the examples of the webpy library I found online to no avail. Whenever a GET request is sent, the responseText attribute of XMLHttpRequest() returns the text of the python file rather than the data. Any advise would be much appreciated!
The javascript function:
function sendSerialCommand(selection, command) {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
if (command !== 5) {
document.getElementById("output2").innerHTML = xmlhttp.responseText;
document.getElementById("output2").style.color = "green";
} else {
document.getElementById("output1").innerHTML = xmlhttp.responseText;
console.log(xmlhttp.responseText);
document.getElementById("output1").style.color = "green";
}
}
};
xmlhttp.open("GET", pythonFileName + "?sel=" + selection + "?cmd=" + command, true);
xmlhttp.send();
}
...and the test python script:
import web
urls = (
'/', 'Index'
)
app = web.application(urls,globals())
#MAIN LOOP
class Index:
def GET(self):
webInput = web.input()
return 'message: GET OK!'
if __name__ == "__main__":
app.run()
The trick was to use the CGI library for python as such:
#!/usr/bin/python
# Import modules for CGI handling
import cgi, cgitb
# Create instance of FieldStorage
form = cgi.FieldStorage()
# Get data from fields
first_name = form.getvalue('cmd')
last_name = form.getvalue('sel')
print "Content-type:text/html\r\n\r\n"
print "Hello %s %s" % (first_name, last_name)
This captures the keys and data from the GET request and the print command returns data to the xmlhttp.responseText attribute on the client-side.
The script has to be placed into a file the websever is able to execute the script from. That is usually the default /cgi-bin folder located in either /var/www or /etc.