I 'm trying to write a code which will send a json file from a flask server to chregraphe in order to program a NAO robot. I want to parse a random number from 1 to 3 and NAO say the number accordingly. Unfortunately i haven't managed to do it.
The code that i use to send the number from flask server is
import http.client
import json
import random
from flask import Flask, request
app = Flask(__name__)
#app.route('/')
def index():
IP = "10.0.0.23" # The IP address of my robot
PORT = 9559
number = random.randint(1, 3)
data = json.dumps({"number": number})
# Connect to Choregraphe
conn = http.client.HTTPConnection(IP, PORT)
# Send the data to Choregraphe
headers = { "Content-Type": "application/json" }
conn.request("POST", "/module/ALMemory/value/ExampleKey", data, headers)
return "Data sent to Choregraphe: " + data
if __name__ == '__main__':
app.run()
I'm trying to send the number to the "Examplekey"
Also i use a python script box in choregraph with the beneath code
def onInput_onStart(self, p):
# Connect to ALMemory
memory = ALProxy("ALMemory")
# Read the value stored under the key "ExampleKey"
data = memory.getData("ExampleKey")
# Parse the JSON string into a dictionary
data = json.loads(data)
# Get the "number" value from the dictionary
number = data["number"]
if number == 1:
text = "one"
elif number == 2:
text = "two"
else
text = "three"
tts = ALProxy("ALTextToSpeech", "10.0.0.23", 9559)
tts.say(text)
Welcome Tolis to StackOverflow!
While it might be starting a Flask server, your first snippet of code seems rather focused on sending an HTTP request to http://10.0.0.23:9559, where I suppose NAOqi is listening to - and NAOqi does not "speak" HTTP, it speaks Qi.
If you want to send data via HTTP, you will need to get a Flask server running on the robot, and call the relevant NAOqi APIs in response.
But bringing Flask to the robot (via Choregraphe) is no easy task. Instead I would recommend that your client code directly uses the Python SDK for NAOqi 2.5 (better for Python 2.x) or libQi Python (better for Python 3.x).
The client code would look like this (not tested):
import qi
if __name__ == "__main__":
app = qi.Application(sys.argv)
app.start()
memory = session.service("ALMemory")
number = random.randint(1, 3)
service.setData("ExampleKey", number)
Related
Actually i have a python script and soap server running using soap spyne and i need to call that soap api using c++ gsoap client so that the python script will run and get the output as a response to client
i am able to call the api using SOAP UI and python zeep client but when i try to call the client using gsoap it gave me error
DEBUG:spyne.protocol.soap.soap11:ValueError: Deserializing from unicode strings with encoding declaration is not supported by lxml
the generated wsdl file of both gsoap and soap spyne have different namespace also
```python
from spyne import Application, rpc, ServiceBase, Integer, Unicode,String
from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication
from spyne.model.complex import ComplexModel
from spyne.model.complex import Array
from twisted.internet import reactor
from twisted.web.server import Site
from twisted.web.wsgi import WSGIResource
from twisted.python import log
import sys
sys.path.insert(1,'../cloud-client/slicing')
import speech as t
class caps__CSoapReqBuf(ComplexModel):
stringarray=String
size=Integer
class caps__CSoapResponse(ComplexModel):
__namespace__ = "spyne.examples.hello.soap"
nRetCode=Integer
strResponseData=String
class caps__CSoapRequest(ComplexModel):
__namespace__ = "spyne.examples.hello.soap"
nRequestType = Integer
wstrRequestParam= String
class caps_CCallbackData(ComplexModel):
__namespace__ = "spyne.examples.hello.soap"
nPort=Integer
strFunction = String
class TranscriptionService(ServiceBase):
#rpc(String, String, caps_CCallbackData, caps__CSoapResponse, _returns=Integer)
def caps__SoapRequestString(ctx, function_name, SoapRequest, CallbackData, SoapResponse):
parameters = SoapRequest
list = parameters.split('|')
d = dict(s.split(':') for s in list)
filename = d['path']
samplerate = int(d['sr'])
outputpath = d['outputpath']
# samplerate=parameters.samplerate
if(function_name=='gettranscription'):
print("gettranscription")
out=t.main(filename,samplerate)
SoapResponse.nRetCode=1
SoapResponse.wstrResponseData=out
return 0
elif(function_name=='getocr'):
return "Do OCR"
else:
return "error"
#rpc(caps__CSoapResponse,_returns=Unicode)
def caps_SoapResponseString(ctx,caps__CSoapResponse):
response = caps__CSoapResponse.wstrResponseData
return response
application = Application([TranscriptionService], 'spyne.examples.hello.soap',
in_protocol=Soap11(validator='lxml'),
out_protocol=Soap11())
wsgi_application = WsgiApplication(application)
if __name__ == '__main__':
import logging
from wsgiref.simple_server import make_server
ip = '192.168.0.103'
port = 8090
resource = WSGIResource(reactor, reactor, wsgi_application)
site = Site(resource)
reactor.listenTCP(port, site,interface=ip)
logging.basicConfig(level=logging.DEBUG)
logging.getLogger('spyne.protocol.xml').setLevel(logging.DEBUG)
logging.info("listening to "+ ip +":"+str(port))
reactor.run()
```
Updated
After updating the code following errors follows in response.
``` Response
'<soap11env:Envelope
xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/">\n
<soap11env:Body>\n <soap11env:Fault>\n
<faultcode>soap11env:Client.ResourceNotFound</faultcode>\n
<faultstring>Requested resource
\'{http://tempuri.org/caps.xsd/Service.wsdl}\' not
found</faultstring>\n <faultactor></faultactor>\n
</soap11env:Fault>\n </soap11env:Body>\n</soap11env:Envelope>\n'
DEBUG:spyne:gc.collect() took around 40ms.
```
On that front, lxml is a bit strict on the kind of stream it thinks it can process.
I'm persuaded that the right thing to do to solve this conflict is to strip the encoding declaration from the xml string.
You can add a handler for the 'wsgi_call' event to implement this. See the events example to see what the relevant API looks like.
My solution to this is to let lxml fail and parse the payload manually using WebOb and then place it in the user defined context. You can later access ctx.udc to access the data. So:
...
from webob import Request as WebObRequest
...
HOST = '0.0.0.0'
PORT = 8000
# parse payload manually
def _on_wsgi_call(ctx):
req = WebObRequest(ctx.transport.req)
decoded = req.body.decode('utf-8')
envelope = Etree.fromstring(decoded)
# depending on your data, you may need to update this step
element = next(envelope.iter())
ctx.udc = element.text
if __name__ == '__main__':
application = initialize([YourService])
wsgi_application = WsgiApplication(application)
wsgi_application.event_manager.add_listener('wsgi_call', _on_wsgi_call)
resource = WSGIResource(reactor, reactor, wsgi_application)
site = Site(resource)
reactor.listenTCP(PORT, site, interface=HOST)
logging.info('listening on: %s:%d' % (HOST, PORT))
logging.info('wsdl is at: http://%s:%d/?wsdl' % (HOST, PORT))
sys.exit(reactor.run())
Hi I am new to writing web APIs in python. And my understanding of REST is limited
I have a simple Flask API that takes in a python dict {'pdf':pdf_as_bytes, 'filename':string}
The below is my server script:
#app.route("/predict", methods=["POST"])
def predict():
data = {"success": False}
if flask.request.method == "POST":
pdf = flask.request.files["pdf"].read()
filename = flask.request.files["filename"].read().decode("utf-8")
assert isinstance(filename, str), "Got {}".format(type(filename))
assert isinstance(pdf, bytes), "Got {}".format(type(pdf))
# further processing happens and returns a json
This works as intended when I write a python client as follows:
import requests
import os
ip = "localhost"
port = 8605
url = "http://{}:{}/predict".format(ip,port)
path_to_pdf = "./617339931.pdf"
with open(path_to_pdf, "rb") as f:
pdf = f.read() # pdf is a bytes
# the payload must have the following fields: "pdf": bytes, "filename": string object
payload = {"pdf":pdf,"filename":os.path.basename(path_to_pdf).split(".")[0]}
# post request
result = requests.post(url=url, files=payload).json()
# the resulting json always has a field called as success, which returns True or False accordingly
if result["success"] == True:
print(result["data"].keys())
But, When I send a request using Postman I get a 400 Error! Below is the screen shot of the error
I don't understand. How can I change my server code so that it works with Postman and also Python client programs
I just did the same thing, and I think it's because of the double quotes you are putting in key and value, try to take them out.
I wrote this server code:
from bottle import run, route, get, post, request, template
import json
import socket
import os
import time
#route('/')
#route('/RegisterMessage/<message_type>', method='GET')
def reg_msg_type(message_type):
print "Suscribe to", message_type, 'messages'
if message_type == 'time':
time = dict()
time['utc_time'] = 123456
time['time_zone'] = -120
return time
#configuring host, port.
run(host='192.168.0.119', port=8088, debug=True)
When I go to http://192.168.0.119:8088/RegisterMessage/time in my browser, I get this response:
{"time_zone": -120, "utc_time":123456}
Now I want to write a client in python which will retrieve those values from my server. I am unable to find anything related to this in the documentation for bottle.
I struggle a little with getting an return on my azure translation api call.
My code is based on this code https://github.com/MicrosoftTranslator/PythonConsole and it work perfectly.
I furthermore have a arangoDB with some test data. Which does it work and give me this:Result on db test
However, if i combine both as follow:
from xml.etree import ElementTree
from auth import AzureAuthClient
from arango import ArangoClient
import requests
client = ArangoClient(
protocol='http',
host='localhost',
port=32768,
username='root',
password='password',
enable_logging=True
)
db = client.database('testdb')
test = db.collection('testcol')
def GetTextAndTranslate(finalToken):
fromLangCode = "en"
toLangCode = "de"
textToTranslate = " "
for t in test:
#text to translate
textToTranslate = t['name']
# Call to Microsoft Translator Service
headers = {"Authorization ": finalToken}
translateUrl = "http://api.microsofttranslator.com/v2/Http.svc/Translate?text={}&to={}".format(textToTranslate, toLangCode)
translationData = requests.get(translateUrl, headers = headers)
# parse xml return values
translation = ElementTree.fromstring(translationData.text.encode('utf-8'))
# display translation if needed
print (translation.text)
if __name__ == "__main__":
#Add your client secret in the next line
client_secret = 'azurepassword'
auth_client = AzureAuthClient(client_secret)
bearer_token = 'Bearer ' + auth_client.get_access_token()
I just get nothing. The console needs less then a second and then I can enter new command on the terminal. But no result displayed, also tried to put it into a file. Azure tell me that I called the API, but I can't see what was processed there.
Thanks for your help!
I tried to test your code for calling Azure Translator API, but I discovered the translator part of your code works fine and the Arango part also works fine. Under your code is not complete for me, the only issue I guess is that the function GetTextAndTranslate(finalToken) shoud be defined as GetTextAndTranslate(test, finalToken) which can be passed the argument test collection like below.
def GetTextAndTranslate(test, finalToken):
# Your code
........
if __name__ == "__main__":
client = ArangoClient(
protocol='http',
host='localhost',
port=32768,
username='root',
password='password',
enable_logging=True
)
db = client.database('testdb')
test = db.collection('testcol')
#Add your client secret in the next line
client_secret = 'azurepassword'
auth_client = AzureAuthClient(client_secret)
bearer_token = 'Bearer ' + auth_client.get_access_token()
GetTextAndTranslate(test, bearer_token)
Hope it helps. Any update, please feel free to let me know.
I am trying to send a python dictionary created from client.py to my webservice, have the webservice do something to the data, and return a boolean to client.py. This is the code I have so far for the server and client:
Server side (inside webservice.py):
from flask import Flask
from flask import request
import json
app = Flask(__name__)
#app.route('/determine_escalation',methods = ['POST'])
def determine_escalation():
jsondata = request.form['jsondata']
data = json.loads(jsondata)
#stuff happens here that involves data to obtain a result
result = {'escalate':'True'}
return json.dumps(result)
if __name__ == '__main__':
app.run(debug=True)
Client side (inside client.py):
import sys
import json
import requests
conv = [{'input': 'hi', 'topic': 'Greeting'}]
s = json.dumps(conv)
res = requests.post("http://127.0.0.1:5000/determine_escalation",data=s)
print res.text
But when I print out res.text, I get this:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>400 Bad Request</title>
<h1>Bad Request</h1>
<p>The browser (or proxy) sent a request that this server could not understand.</p>
What am I doing wrong, and how can I fix this? New to Flask and JSON stuff so any help is appreciated.
OK - a few issues here:
First, you can use requests.get_json() to retrieve your JSON data at the server end:
from flask import Flask
from flask import request
import json
app = Flask(__name__)
#app.route('/determine_escalation/', methods = ['POST'])
def determine_escalation():
jsondata = request.get_json()
data = json.loads(jsondata)
#stuff happens here that involves data to obtain a result
result = {'escalate': True}
return json.dumps(result)
if __name__ == '__main__':
app.run(debug=True)
Also, when you are putting your data together, rather than using "data=s" to send the request, use "json=s":
import sys
import json
import requests
conv = [{'input': 'hi', 'topic': 'Greeting'}]
s = json.dumps(conv)
res = requests.post("http://127.0.0.1:5000/determine_escalation/", json=s).json()
print(res['escalate'])
Please note that I have added trailing slashes at the end of the URL - this is just good practice :-)
I've also incorporated MarcelK's suggested changes - removing the quotes from the boolean 'True' (server side) and using .json() to parse the response on the client side - both of these are great suggestions.
I've tested this revised version (and re-revised version) and it works fine.