[PYTHON] Set up your own web server within your Pepper app project

I want to send an HTTP request to Pepper from the outside and use this as a trigger to make something Pepper. I will explain how to achieve such a thing.

Target

This article is intended for those who are familiar with Pepper's development environment, Choregraphe, and who have some understanding of Python programs.

Overview

Pepper has a web server function as standard, and you can access the resources in the html folder of the app from a PC etc. at http: // / apps / app ID /. However, this has the following restrictions:

--When accessing from the outside, you must enter the robot ID and password first. --Only access to static content. You cannot take a request and take an action or generate a dynamic response.

I want to receive an HTTP request on the Pepper side and take some action. In such a case, you need to prepare your own web server. What to do, Python has a standard module for setting up a simple web server, so let's use it.

(The method introduced here is just how to receive HTTP requests within the local network. In order for Pepper to receive HTTP requests directly via the Internet, some special mechanism is required for that purpose.)

Sample code

I made a sample code. Bring the Python Script box and edit the code inside.

スクリプトエディタ_と_MyWebServer_-_Choregraphe__バーチャルロボットに接続_.jpg

Below is the code for the sample Python Script box.

python


import BaseHTTPServer

class MyClass(GeneratedClass):
    def __init__(self):
        GeneratedClass.__init__(self)

    def onLoad(self):
        self.httpd = None

    def onUnload(self):
        if self.httpd is not None:
            self.httpd.shutdown()
            self.httpd.server_close()

    def onInput_onStart(self):

        #Port number to receive HTTP request http://Robot IP:port number/Receive the request at
        PORT = 8000

        MyHandler.setParent(self)
        self.httpd = BaseHTTPServer.HTTPServer(('', PORT), MyHandler)
        self.httpd.allow_reuse_address = True
        self.httpd.serve_forever()

    def onInput_onStop(self):
        self.onUnload() #it is recommended to reuse the clean-up as the box is stopped
        self.onStopped(p) #activate the output of the box

    # BaseHTTPServer.Called when there is an HTTP GET request via BaseHTTPRequestHandler
    #The http object contains the content indicated by the following document
    # http://docs.python.jp/2/library/basehttpserver.html#BaseHTTPServer.BaseHTTPRequestHandler
    def do_GET(self, http):
    
        #For browser requests, favicon separate from the actual request.Request to ico comes, ignore this
        if http.path.endswith('favicon.ico'):
            return;
        
        self.logger.info("request url:" + http.path)
        
        http.send_response(200)
        http.send_header("Content-type", "text/plain")
        http.end_headers()
        http.wfile.write("This is a test response")

class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    _parent = None

    def do_GET(self):
        MyHandler._parent.do_GET(self)
        
    @staticmethod
    def setParent(parent):
        MyHandler._parent = parent
        

After running the app, try accessing it from a browser such as a PC on the same LAN at http: // : 8000 /. Your browser should say "This is a test response".

Explanation of sample code

The HTTP server function is realized by using the BaseHTTPServer module. In this example, we are waiting for a request on port 8000. When the onStart input is called, it spawns the HTTP server process and waits for the request until the box is unloaded. (Unloading will occur when the app is closed, or when the box is inside the diagram box or inside the Timeline box, when the box is removed)

The request is made by the instance of MyHandler class given at the time of instantiation of BaseHTTPServer.HTTPServer, but I wanted to link it with box processing.

python


        MyHandler.setParent(self)

At the point of, I pass an instance of the box to the class forcibly so that it can be processed on the box instance side. Box method

python


    def do_GET(self, http):

Receives and processes HTTP GET requests. Where self is an instance of the box and http is an instance of the BaseHTTPRequestHandler class that received the request.

python


        self.logger.info("request url:" + http.path)

For the time being, output the path part of the request URL to the log, then

python


        http.send_response(200)
        http.send_header("Content-type", "text/plain")
        http.end_headers()
        http.wfile.write("This is a test response")

Is generating an HTTP response.

Please refer to the following URL for details on what kind of information is contained in the BaseHTTPRequestHandler instance.

http://docs.python.jp/2/library/basehttpserver.html#BaseHTTPServer.BaseHTTPRequestHandler

This example takes the form of programmatically generating an HTTP response. If you basically want to return the files in the project, the implementation is added based on BaseHTTPRequestHandler SimpleHTTPRequestHandler class of SimpleHTTPServer module I think you should use .html). I hope you can try various things around here depending on the application.

Finally

If Pepper can receive HTTP requests dynamically, it will be easier to link with various devices that have an interface from the standpoint of a Web API client. I hope it helps you in new ways to use Pepper.

Recommended Posts

Set up your own web server within your Pepper app project
Set up a simple local server on your Mac
Set up a web server with CentOS7 + Anaconda + Django + Apache
Try docker: Create your own container image for your Python web app
Set up a local web server in 30 seconds using python 3's http.server
Set up a Samba server with Docker
Port forwarding your web server using iptables
Create your own DNS server with Twisted
Set up a mail server using Twisted
Build a web server on your Chromebook
Is your network stack set up correctly?