Pepper robot: How to use tablet to send text input for further processing in Choregraphe? - pepper

I need to send a user text input to the robot through the integrated tablet, and catch it somehow, for further processing in Choregraphe.
After reading the Aldebaran documentation about ALTabletService API, I found few methods which might be a solution to all this. The methods are ALTabletService::showInputTextDialog and ALTabletService::onInputText, but somehow I can't get them to work: they return absolutely nothing when I input some text through the tablet.
I need access to the string created when the user inputs a piece of text. Any advice how to do it?

i realized this without ALTabletService methods showInputTextDialog or onInputText
My Approach:
I made an html page with an input field and a button to send the input.
On button press I use the forceInput method from ALDialog doc via QiMessaging Javascript library. doc
I can't test it right now but this should help as a inspiration
function forceInput(input) {
QiSession(function(session) {
session.service('ALDialog').then(function(ALDialog) {
ALDialog.forceInput(input);
});
}
}
Now you can send the input to the topic.
This could be sth like "imput_from_tablet blablabla".
And in the Dialog you catch
u:(imput_from_tablet _*) $1
Where $1 should be blablabla.
Hope that helps
best regards

You can create a webpage for the tablet and package it in your application - see the documentation here; then on that webpage you can create a text input field (be careful that the bottom half of the screen will be hidden by the keyboard when the field is selected), and then use the javascript SDK to (for example) raise an ALMemory event with the inputted text value, that you can then get from Choregraphe.

I had exactly the same problem and I found this ALTabletService::onInputText method in the signal list. You can find examples how to use signals on the same page. Based on these examples I created the following script that can get a value from the input field:
import qi
import sys
def main(app):
try:
session = app.session
tabletService = session.service("ALTabletService")
tabletService.showInputTextDialog("Example dialog", "OK", "Cancel")
signal_id = 0
def callback(button_id, input_text):
if button_id == 1:
print "'OK' button is pressed."
print "Input text: " + input_text
if button_id == 0:
print "'Cancel' button is pressed"
tabletService.onInputText.disconnect(signal_id)
app.stop()
# attach the callback function to onJSEvent signal
signal_id = tabletService.onInputText.connect(callback)
print "Signal ID: {}".format(signal_id)
app.run()
except Exception, e:
print "Error was: ", e
if __name__ == "__main__":
ip = "10.0.10.254" # the IP of the robot
port = 9559
try:
connection_url = "tcp://{}:{}".format(ip, port)
app = qi.Application(url=connection_url)
app.start()
except RuntimeError:
print("Can't connect to Naoqi.")
sys.exit(1)
main(app)

Related

How to tell if the user already rated my UWP app?

Windows 10 Store UWP apps can use StoreContext.RequestRateAndReviewAppAsync function, or simply a URL like this ms-windows-store://review/?ProductId=9WZDNCRFHVJL, to display a user rating window for the app:
I prefer the URL method since I can simply invoke it via ShellExecute method.
But my question is how do I find out if the user had already rated my app, so that I don't display that rating window again?
This is unfortunately not possible, but there is probably a good reason for it - if developers were able to check this programmatically, they could "cheat the system" by giving users who rated some bonuses/perks for reviewing the app.
Currently there is no such api can directly tell if the user already rated the UWP app, but you could use roaming data in your app which keeps your app's app data in sync across multiple devices.
If the user has rated your app, you can set "Yes" in the RoamingSettings, if the value from RoamingSettings is "No", you can display that rating window again. You could determine whether the rating is successful, e.g. in StoreContext.RequestRateAndReviewAppAsync method, the ExtendedJsonData property of the StoreRateAndReviewResult class contains a JSON-formatted string that indicates whether the rating request was successful. By ExtendedJsonData property, you can know if the rating is successful and then set the value to "Yes" in the RoamingSettings.
private async void Button_Click(object sender, RoutedEventArgs e)
{
ApplicationDataContainer RatingSettings = ApplicationData.Current.RoamingSettings;
//initialization
if (RatingSettings.Values["isRated"] == null)
{
RatingSettings.Values["isRated"] = "No";
}
var isRatedStr = RatingSettings.Values["isRated"].ToString();
if (isRatedStr == "No")
{
//display the rate windows
if (//if rated successfully)
{
RatingSettings.Values["isRated"] = "Yes";
}
}
}
Or you can use the Get app ratings and Get app reviews methods in the Store analytics API to programmatically retrieve the ratings and reviews from your customers in JSON format. For more details, you can refer to this document.

Send Image or Document with Inline Menu

I am coding an Python Telegram Bot with python-telegram-bot. I created a custom inline menu.
I want that the User could press a button and will get an picture. The send_photo function needs an instance of bot an update.
But I don't know how to pass that on to the CallBackQuery handler.
Does anyone have an idea how to solve it?
The send photo function:
def gvu(bot, update):
bot.send_photo(update.message.chat_id, photo=open('botpic/gvu.jpg', 'rb'))
The Handler in Main Routine:
updater.dispatcher.add_handler(CallbackQueryHandler(pattern="1", callback=gvu))
return self.callback(dispatcher.bot, update, **optional_args)
The error:
TypeError: callback_handler() got an unexpected keyword argument 'chat_data'
This works for me:
buttonsMenu = [
[telegram.InlineKeyboardButton("UP", callback_data="UpVote")],
[telegram.InlineKeyboardButton("DOWN", callback_data="DownVote")],
]
keyboard_markup = telegram.InlineKeyboardMarkup(buttonsMenu)
context.bot.sendPhoto(chat_id=update.message.chat.id, photo=open('./imgpath.jpg'), 'rb'),caption='messageText', reply_markup=keyboard_markup)
This will send an image, with text and 2 butttons below the text msg.
Now for the callback query, i did this in main():
# Callbacks for the msg buttons
dp.add_handler(CallbackQueryHandler(vote, pattern="UpVote"))
dp.add_handler(CallbackQueryHandler(vote, pattern="DownVote"))
Where vote , is a def that runs the code i want for that callback.
hope it makes sense.
Read into documentation here:
https://core.telegram.org/bots/api#inlinequery
https://github.com/python-telegram-bot/python-telegram-bot/blob/master/examples/inlinekeyboard.py

Python 2 and AppleScript. Dialogue prompts and default answers

Here is just a small snippet of the Python code I use to read the XML data of Mac System Profiler files for the purpose of adding the data to a database without having to copy/paste the details manually.
Specifically this snippet of code prompts the user to enter an "Article Number" to save the given ".spx" (System Profiler Report) under.
import subprocess
exampleString = "12345"
theText = subprocess.check_output(['osascript', '-e',
r'''set theText to text returned of (display dialog "Enter new Article Number here:
\n\nElse just press OK" default answer "" with title "Hardware Paster v1.0" with icon 2)'''
])
"theText" will go to on dictate the name of the spx file.
I would like to set the value of the "default answer" inside of the AppleScript prompt with the value of another variable inside the main python script ("exampleString" in this case). The "12345" is just placeholder text here.
The ultimate aim is to minimise data-entry by the end user.
Thanks for your help.
Just string format and you're good!
>>> exampleString = "world"
>>> 'hello there "{}"!'.format(exampleString)
'hello there "world"!'
And applied to your program:
exampleString = "12345"
template = r'''set theText to text returned of (display dialog "Enter new Article Number here:
\n\nElse just press OK" default answer "{}" with title "Hardware Paster v1.0" with icon 2)'''
theText = subprocess.check_output(
['osascript', '-e', template.format(exampleString)])

implicitly_wait VS. time_sleep() in Selenium 3.0.2 Python 2.7

I'm trying to implement a simple sub dowloader with Selenium on Python 2.7 going on the http://www.yifysubtitles.com website.
I have run into serious troubles with implementing waits either implicit or explicit in Selenium - surely caused by ignorance rather than code.
I eventually opted for the destroy-all time.sleep() solution. The program works but I would like a more programatic solution and a prettier code.
Here is the code with the both implicit and explicit waits:
user_input = raw_input("Enter the movie of interest: ")
profile = SetProfile()
browser = webdriver.Firefox(profile)
# browser.implicitly_wait(30)
WindowSize(400, 400)
browser.get(url)
print "Searching..."
search_bar = browser.find_element_by_id("qSearch")
click_button = browser.find_element_by_class_name("glyphicon")
#wait_1 = WebDriverWait(browser, 50)
#cookie_element = wait_1.until(EC.element_to_be_clickable((By.CLASS_NAME,"cc_btn.cc_btn_accept_all")))
time.sleep(5)
accept_cookies_btn = browser.find_element_by_class_name("cc_btn.cc_btn_accept_all")
search_bar.clear()
accept_cookies_btn.click()
search_bar.send_keys(user_input)
search_bar.send_keys(Keys.RETURN)
time.sleep(10)
#wait_2 = WebDriverWait(browser, 50)
#result_element = wait_2.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "h3.media-heading")))
result = browser.find_element_by_class_name("media-heading")
result.click()
print "Movie found!"
time.sleep(10)
req = requests.get(browser.current_url)
soup = BeautifulSoup(req.text)
link_to_sub = ResultParser(soup)
print "Choosing the best eng. subtitle..."
browser.get(url+link_to_sub[1])
download_button = browser.find_element_by_class_name("btn-icon")
download_button.click()
time.sleep(10)
browser.quit()
print "Enjoy!"
I have commented out the waits (explicit or implicit) I tried to use. Indeed, If I use waits instead time.sleep, Selenium will throw at me an ElementNotVisibleException.
Thus, am I doing something wrong with the waits?
Regarding the implicit waits, Selenium always throws at me ElementNotVisibleException: Message: (With message empty) when I run the program, whatever the wait length (tried 5, 30 and 100!).
When I use explicit waits, similarly, Selenium either throw ElementNotVisibleException or seems to use the DOM from the preceding page. Indeed, in the last case the wait is after clicking on the result, but I get the heading of the previous page...
As I said, when I use time.sleep(), Selenium finds the elements without any trouble.
A long message for a simple question: why my waits seem to not work?

kibana 5 scripted field for regex match

I want to add scritpted field in Kibana 5 to get stored proc name from message. To be able to visualize number of errors per each SP.
I have field "message" where I can see error text:
"[2017-02-03 05:04:51,087] # MyApp.Common.Server.Logging.ExceptionLogger [ERROR]: XmlWebServices Exception
User:
Name: XXXXXXXXXXXXXXXXXXXXXXX
Email: 926715#test.com
User ID: 926715 (PAID)
Web Server: PERFTESTSRV
Exception:
Type: MyApp.Common.Server.DatabaseException
Message: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
Source: MyApp.Common.Server
Database: MyDB
Cmd Type: StoredProcedure
Cmd Text: spGetData
Trans: YES
Trans Lvl: Unspecified"
Guide: https://www.elastic.co/blog/using-painless-kibana-scripted-fields
My plan is to add something like as a Painless script:
def m = /(?:Cmd\sText:\s*)[a-zA-Z]{1,}/.matcher(doc['message'].value);
if ( m.matches() ) {
return m.group(1)
} else {
return "no match"
}
And also I've tried
def tst = doc['message'].value;
if (tst != null)
{
def m = /(?:User\sID:\s*)[0-9]{1,}/.matcher(tst);
if ( m.matches() ) {
return m.group(1)
}
} else {
return "no match"
}
How I can address doc['message'].value?
When I try to do so I got error "Courier Fetch: 5 of 5 shards failed."
When I try doc['message.keyword'].value, I do not have full message inside. I do not understand where I can learn the structure of what message have inside and how I can refer it?
I assume that problem with lenght of message. It is too long to be type "keyword". It should be type "text" which is not supported by painless.
https://www.elastic.co/blog/using-painless-kibana-scripted-fields
Both Painless and Lucene expressions operate on fields stored in doc_values. So >for string data, you will need to have the string to be stored in data type >keyword. Scripted fields based on Painless also cannot operate directly on >_source.
https://www.elastic.co/guide/en/elasticsearch/reference/master/keyword.html_italic_
A field to index structured content such as email addresses, hostnames, status >codes, zip codes or tags.
If you need to index full text content such as email bodies or product >descriptions, it is likely that you should rather use a text field.