I’m having a hard time putting all the pieces together to get an agent to respond to http requests. Ive seen this response from Craig Add a new page to Volttron Central but am still not sure how to put everything together. Hopefully this question can serve as a tutorial or at least a place to point to a specific place in the docs.
To that end here is the simplest statement of my question I can think of:
Say I have a default version of VOLTTRON installed on Ubuntu by running bootstrap.py. I’m on the develop branch since that is what the response to the question above points to, if that is not correct or other branches also have this functionality please specify.
And say I have the following agent code
class Hello_Internet(Agent):
def hello_internet(self):
return “Hello Internet”
What needs to happen in order to be able to send a request to a url that is of the form “something/hello_internet” and get back a response of “Hello Internet” via the method of the HelloInternet agent? And what is the “something” in the url? Bonus points for getting the request type and other associated information (querystring, post request body).
In the spirit of showing what I’ve already tried hopefully the following won’t muddy the waters too much. Ideally you’ll just say I’ve completely lost the plot and then we can edit the below out later.
I started with adding the flag –bind-web-address "http://127.0.0.1:5555" to the params when starting the platform itself.
Then I updated my agent class to
class Hello_Internet(Agent):
@RPC.export
def hello_internet(self):
return "Hello Internet"
@Core.receiver('onstart')
def on_message_bus_start(self, sender, **kwargs):
self.vip.rpc.call(MASTER_WEB, 'register_agent_route',
r'^/hello_internet',
self.core.identity,
"hello_internet").get(timeout=30)
At this point when I start the platform it logs this on start:
volttron.platform.web INFO: Starting web server binding to 127.0.0.1:5555.
And this when the agent starts:
volttron.platform.web INFO: Registering agent route expression: ^/hello_internet peer: None function: hello_internet
But if I actually browse to 127.0.0.1:5555 then the platform gives this error under the debugger:
“~/workspace/volttron/env/local/lib/python2.7/site-packages/gevent/server.py", line 102, in wrap_socket_and_handle
ssl_socket = self.wrap_socket(client_socket, **self.ssl_args)
TypeError: wrap_socket() got an unexpected keyword argument 'error_log'
<Greenlet at 0x7f9ea46e7e10: <bound method WSGIServer.wrap_socket_and_handle of <WSGIServer at 0x7f9ea46cba90 fileno=58 address=127.0.0.1:5555>>(<socket at 0x7f9ea46cb9d0 fileno=61 sock=127.0.0.1, ('127.0.0.1', 40583))> failed with TypeError
For what it's worth the self.ssl_agrs in the above looks like
dict: {'error_log': <open file '~/.volttron/log/web.error.log', mode 'wb' at 0x7f9ea5a2c5d0>,
'server_side': True}
The ~/.volttron/log/web.error.log file exists but is empty.
This happens before the hello_internet function can be called.
I’ve tried updating gevent and that did not resolve the problem. I tried switching –bind-web-address to https://127.0.0.1:5555 and going there instead plus a few other things that are only going to make things more confusing I think but so far no success.
EDIT
Thanks for your quick response. I updated my libraries to match Craig's pip list below. In some cases I may have updated to a newer library version like gevent 1.1.2 instead of 1.1.1. I also changed the hello_internet function signature to match Craig's suggestion and changed the bound address from https to http.
Now when I start the platform and agent and try to browse to the bound ip I get "Internal Server Error" from the browser and the platform gives this traceback:
~/workspace/volttron/env/local/lib/python2.7/site-packages/zmq/sugar/socket.py", line 363, in send_multipart
i, rmsg,
TypeError: Frame 0 (None) does not support the buffer interface.
{'GATEWAY_INTERFACE': 'CGI/1.1',
'HTTP_ACCEPT': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'HTTP_ACCEPT_ENCODING': 'gzip, deflate',
'HTTP_ACCEPT_LANGUAGE': 'en-US,en;q=0.5',
'HTTP_CONNECTION': 'keep-alive',
'HTTP_HOST': '127.0.0.1:5555',
'HTTP_USER_AGENT': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:43.0) Gecko/20100101 Firefox/43.0',
'PATH_INFO': '/hello_internet',
'QUERY_STRING': '',
'REMOTE_ADDR': '127.0.0.1',
'REMOTE_PORT': '40704',
'REQUEST_METHOD': 'GET',
'SCRIPT_NAME': '',
'SERVER_NAME': 'localhost',
'SERVER_PORT': '5555',
'SERVER_PROTOCOL': 'HTTP/1.1',
'SERVER_SOFTWARE': 'gevent/1.1 Python/2.7',
'wsgi.errors': <open file '/home/bob/.volttron/log/web.error.log', mode 'wb' at 0x7f77dc4386f0>,
'wsgi.input': <gevent.pywsgi.Input object at 0x7f77dc341e20>,
'wsgi.multiprocess': False,
'wsgi.multithread': False,
'wsgi.run_once': False,
'wsgi.url_scheme': 'http',
'wsgi.version': (1, 0)} failed with TypeError