Pepper: pass variable from Python to web JS - pepper

I'm programming an App for the Aldebaran's Pepper robot. I'm using Choregraphe and I made an html for displaying in robots tablet. I have made the boxes for displaying the web and I need to pass a variable from Python to the web Javascript.
Is there any way to do it?
The Python code is the same as the default of a Raise Event box, it receives a string "IMAGE" on his onStart input:
class MyClass(GeneratedClass):
def __init__(self):
GeneratedClass.__init__(self)
pass
def onLoad(self):
self.memory = ALProxy("ALMemory")
def onUnload(self):
self.memory = None
def onInput_onStart(self, p):
self.memory.raiseEvent(self.getParameter("key"), p)
self.onStopped(p)
def onInput_onStop(self):
self.onUnload() #~ it is recommended to call onUnload of this box in a onStop method, as the code written in onUnload is used to stop the box as well
pass
And the Javascript code is this:
$('document').ready(function(){
var session = new QiSession();
session.service("ALMemory").done(function (ALMemory) {
ALMemory.subscriber("PepperQiMessaging/totablet").done(function(subscriber) {
$("#log").text("AAA");
subscriber.signal.connect(toTabletHandler);
});
});
function toTabletHandler(value) {
$("#log").text("-> ");
}
});
It enters the first #log but not the second of JS.

yes, I think the webpage is loading too late to catch your event. One quick solution would be to send an event from Javascript when the page is ready, and wait for this event in your Python script. Once this event is received, then you know that the webpage is ready and you can send the "sendImage" event.

I solved the problem. I put a delay box of 2 seconds between the show HTML box and the sendImage box like in the image below:
I think the problem was that the string that is send to tabled was sent before the web was prepared to receive it, and the delay of 2 seconds (with 1 it doesn't work) the page have time to prepare for receiving data.

Related

Flask POST request and javascript

Is it possible to POST data with flask_sqlalchemy and prevent a page reload?
I have a webpage with a form. The form only appears after a function, activated by an onclick event, is run. I want my user to be able to submit information using the form, and see the form only empty and the rest of the page remain unchanged.
I have already tried return '', 204 but this does not fix the issue.
Use Javascript or jQuery:
Javascript example:
function resetFormPause() {
myVar = setTimeout(resetForm, 250);
}
function resetForm() {
document.getElementById('form').reset();
}
Add onclick='resetFormPause()' to your submit button and use <form id='form'>.
We use setTimeout() to allow the data to be sent. If we merely add the resetForm() function, we will delete the data that we want to send. If we have small text to send, 250ms is plenty of time. If we have larger data, then we use the same idea, but we have to (a) allow more time, or (b) use an event to trigger the execution of resetForm().

browser.click() & browser.send_keys() conflict - Selenium 3.0 Python 2.7

I am currently trying to implement a subtitle downloader with the help of the http://www.yifysubtitles.com website.
The first part of my code is to click on the accept cookies button and then send keys to search the movie of interest.
url = "http://www.yifysubtitles.com"
profile = SetProfile() # A function returning my favorite profile for Firefox
browser = webdriver.Firefox(profile)
WindowSize(400, 400)
browser.get(url)
accept_cookies = WebDriverWait(browser, 100).until(
EC.element_to_be_clickable((By.CLASS_NAME, "cc_btn.cc_btn_accept_all")))
accept_cookies_btn = browser.find_element_by_class_name("cc_btn.cc_btn_accept_all")
accept_cookies_btn.click()
search_bar = browser.find_element_by_id("qSearch")
search_bar.send_keys("Harry Potter and the Chamber of Secrets")
search_bar.send_keys(Keys.RETURN)
print "Succesfully clicked!"
But it only works once - if not randomly. If I turn on my computer and run the code, it does click, make the search and print the last statement. The second time, it doesn't click but still make the search and print the final statement.
After each try, I close the session with the browser.quit() method.
Any idea on what might be the issue here?
Specify wait for button and search bar it should solve your problem.
Thanks,D

strange behavior in the order of execution of a function in kivy

The following method is binded to a send button that should send an email using Python's SMTP library. What I want is that a label in my screen displays a "sending..." Text before sending the mail then after sending the mail a popup will show a text that the mail was sent. The problem that I am facing is that after pressing the button nothing happens (the label text does not show) and after a moment( normal time for mail to be sent) the popup show and the text in the label shows... It is very strange to me that all output is displaying at the same time in stead of the normal order:
display text in label > send mail > show the popup after mail was sent.
My code is as follows:
def send_email(self):
self.the_mail_feedback.text = "Sending..."#this is not showing at first but after execution!
gmail_user = str(self.txt_from_mail.text)
gmail_pwd = str(self.txt_password.text)
FROM = str(self.txt_from_mail.text)
TO = []
TO.append(str(self.txt_to_mail.text))
SUBJECT = "subject 1"
TEXT = "some text..."
message = """\From: %s\nTo: %s\nSubject:
%s\n\n%s""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
try:
server = smtplib.SMTP("smtp.gmail.com", 587)
server.ehlo()
server.starttls()
server.login(gmail_user, gmail_pwd)
server.sendmail(FROM, TO, message)
server.close()
self.pop.open()#a popup that says that the mail is sent...
#self.the_mail_feedback.text="" #will uncomment when it works to reset feedback
except:
self.the_mail_feedback.text="Failed To Send Mail... Check Credentials
"
The problem is that all these operations take place in the same thread, the main program loop. So for instance your second line does change the label text, but the ui doesn't update until your function finishes and releases control to the normal kivy eventloop. The eventloop then updates the graphical representation of the label.
So actually everything does take place in order, it's just the graphics aren't free to update until the function finishes, at which point everything happens at once. For the same reason, you'll find you can't do any touch input while the mail is sending.
To avoid this, you need to work with the eventloop and allow places for the normal kivy control flow to continue. Here's a quick example that I think should work:
def begin_send_email(self):
self.the_mail_feedback.text = "Sending..."#this is not showing at first but after execution!
Clock.schedule_once(self.finish_send_email, 0)
def finish_send_email(self, *args):
gmail_user = str(self.txt_from_mail.text)
gmail_pwd = str(self.txt_password.text)
FROM = str(self.txt_from_mail.text)
TO = []
TO.append(str(self.txt_to_mail.text))
SUBJECT = "subject 1"
TEXT = "some text..."
message = """\From: %s\nTo: %s\nSubject:
%s\n\n%s""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
try:
server = smtplib.SMTP("smtp.gmail.com", 587)
server.ehlo()
server.starttls()
server.login(gmail_user, gmail_pwd)
server.sendmail(FROM, TO, message)
server.close()
self.pop.open()#a popup that says that the mail is sent...
#self.the_mail_feedback.text="" #will uncomment when it works to reset feedback
except:
self.the_mail_feedback.text="Failed To Send Mail... Check Credentials
Of course there are other ways to structure it, but the general idea is that instead of locking the event loop the function updates the label text then schedules some more tasks before handing control back to the eventloop. The eventloop then does its normal tasks including setting the graphical label to 'Sending...' like you want, before performing the scheduled function to finish sending.
You may also find it necessary or useful to look at sending the email from a separate thread, to avoid locking the ui, though it might be fast enough to be okay. You can do this quite easily, though you have to be careful to only perform graphics operations in the main thread.

In Django, how to find out if a request has been canceled?

I have a view in Django which streams a response. (Think of a web-based chat circa 1999, or the comet technique.)
def events(request):
def generate_events():
for i in range(10):
time.sleep(2)
yield " " * 1024
yield "This is some text.\n"
return HttpResponse(generate_events())
Now, I'd like to detect when the user cancels the loading of the page, since there is no point in sending more data. Ideally, there would be something like:
if not request.is_alive():
return
Is there a way to achieve this in Django?
I really don't think you can do that from the server-side. But I'm sure you could use JavaScript to get some decent results. The "stream" will die when the JS stops asking for stuff from the server like in the case of a cancelled request.

Django - show loading message during long processing

How can I show a please wait loading message from a django view?
I have a Django view that takes significant time to perform calculations on a large dataset.
While the process loads, I would like to present the user with a feedback message e.g.: spinning loading animated gif or similar.
After trying the two different approaches suggested by Brandon and Murat, Brandon's suggestion proved the most successful.
Create a wrapper template that includes the javascript from http://djangosnippets.org/snippets/679/. The javascript has been modified: (i) to work without a form (ii) to hide the progress bar / display results when a 'done' flag is returned (iii) with the JSON update url pointing to the view described below
Move the slow loading function to a thread. This thread will be passed a cache key and will be responsible for updating the cache with progress status and then its results. The thread renders the original template as a string and saves it to the cache.
Create a view based on upload_progress from http://djangosnippets.org/snippets/678/ modified to (i) instead render the original wrapper template if progress_id='' (ii) generate the cache_key, check if a cache already exists and if not start a new thread (iii) monitor the progress of the thread and when done, pass the results to the wrapper template
The wrapper template displays the results via document.getElementById('main').innerHTML=data.result
(* looking at whether step 4 might be better implemented via a redirect as the rendered template contains javascript that is not currently run by document.getElementById('main').innerHTML=data.result)
Another thing you could do is add a javascript function that displays a loading image before it actually calls the Django View.
function showLoaderOnClick(url) {
showLoader();
window.location=url;
}
function showLoader(){
$('body').append('<div style="" id="loadingDiv"><div class="loader">Loading...</div></div>');
}
And then in your template you can do:
This will take some time...
Here's a quick default loadingDiv : https://stackoverflow.com/a/41730965/13476073
Note that this requires jQuery.
a more straightforward approach is to generate a wait page with your gif etc. and then use the javascript
window.location.href = 'insert results view here';
to switch to the results view which starts your lengthy calculation. The page wont change until the calculation is finished. When it finishes, then the results page will be rendered.
Here's an oldie, but might get you going in the right direction: http://djangosnippets.org/snippets/679/
A workaround that I chose was to use beforunload and unload events to show the loading image. This can be used with or without window.load. In my case, it's the view that is taking a great amount of time and not the page loading, hence I am not using window.load (because it's already a lot of time by the time window.load comes into picture, and at that point of time, I do not need the loading icon to be shown anymore).
The downside is that there is a false message that goes out to the user that the page is loading even when when the request has not even reached the server or it's taking much time. Also, it doesn't work for requests coming from outside my website. But I'm living with this for now.
Update: Sorry for not adding code snippet earlier, thanks #blockhead. The following is a quick and dirty mix of normal JS and JQuery that I have in the master template.
Update 2: I later moved to making my view(s) lightweight which send the crucial part of the page quickly, and then using ajax to get the remaining content while showing the loading icon. It needed quite some work, but the end result is worth it.
window.onload=function(){
$("#load-icon").hide(); // I needed the loading icon to hide once the page loads
}
var onBeforeUnLoadEvent = false;
window.onunload = window.onbeforeunload= function(){
if(!onBeforeUnLoadEvent){ // for avoiding dual calls in browsers that support both events
onBeforeUnLoadEvent = true;
$("#load-icon").show();
setTimeout(function(){
$("#load-icon").hide();},5000); // hiding the loading icon in any case after
// 5 seconds (remove if you do not want it)
}
};
P.S. I cannot comment yet hence posted this as an answer.
Iterating HttpResponse
https://stackoverflow.com/a/1371061/198062
Edit:
I found an example to sending big files with django: http://djangosnippets.org/snippets/365/ Then I look at FileWrapper class(django.core.servers.basehttp):
class FileWrapper(object):
"""Wrapper to convert file-like objects to iterables"""
def __init__(self, filelike, blksize=8192):
self.filelike = filelike
self.blksize = blksize
if hasattr(filelike,'close'):
self.close = filelike.close
def __getitem__(self,key):
data = self.filelike.read(self.blksize)
if data:
return data
raise IndexError
def __iter__(self):
return self
def next(self):
data = self.filelike.read(self.blksize)
if data:
return data
raise StopIteration
I think we can make a iterable class like this
class FlushContent(object):
def __init__(self):
# some initialization code
def __getitem__(self,key):
# send a part of html
def __iter__(self):
return self
def next(self):
# do some work
# return some html code
if finished:
raise StopIteration
then in views.py
def long_work(request):
flushcontent = FlushContent()
return HttpResponse(flushcontent)
Edit:
Example code, still not working:
class FlushContent(object):
def __init__(self):
self.stop_index=2
self.index=0
def __getitem__(self,key):
pass
def __iter__(self):
return self
def next(self):
if self.index==0:
html="loading"
elif self.index==1:
import time
time.sleep(5)
html="finished loading"
self.index+=1
if self.index>self.stop_index:
raise StopIteration
return html
Here is another explanation on how to get a loading message for long loading Django views
Views that do a lot of processing (e.g. complex queries with many objects, accessing 3rd party APIs) can take quite some time before the page is loaded and shown to the user in the browser. What happens is that all that processing is done on the server and Django is not able to serve the page before it is completed.
The only way to show a show a loading message (e.g. a spinner gif) during the processing is to break up the current view into two views:
First view renders the page with no processing and with the loading message
The page includes a AJAX call to the 2nd view that does the actual processing. The result of the processing is displayed on the page once its done with AJAX / JavaScript