Bokeh server + Flask on Rasp Pi - Failed to load resource: net::ERR_CONNECTION_REFUSED - autoload.js

I am struggling to get Flask + interactive Bokeh server working on my Rasp Pi. From inspecting the html, I get the error= net::ERR_CONNECTION_REFUSED - autoload.js .

I have my Server set up:

    server = Server({'/bkapp': make_interactive}, io_loop=IOLoop(),
                     allow_websocket_origin=["0.0.0.0", "127.0.0.1"])

Given Brian’s statement in this post, I would assume the allow_websocket_origin would allow the connection. But this is not the case.

Perhaps this is related to another oddity. When I start the flask app, I get:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
    self.run()
  File "/usr/lib/python3.7/threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File "/home/pi/projects/FitHome_EDA/app.py", line 36, in bk_worker
    port=5006, allow_websocket_origin=["0.0.0.0", "127.0.0.1"])
  File "/home/pi/projects/FitHome_EDA/venv/lib/python3.7/site-packages/bokeh/server/server.py", line 393, in __init__
    sockets, self._port = bind_sockets(self.address, self.port)
  File "/home/pi/projects/FitHome_EDA/venv/lib/python3.7/site-packages/bokeh/server/util.py", line 66, in bind_sockets
    ss = netutil.bind_sockets(port=port or 0, address=address)
  File "/home/pi/projects/FitHome_EDA/venv/lib/python3.7/site-packages/tornado/netutil.py", line 174, in bind_sockets
    sock.bind(sockaddr)
OSError: [Errno 98] Address already in use  

Any advice on steps to get this challenge working would be very much appreciated. Thank you.

@happyday The “address already in use” error does not have anything to do with Bokeh, per se. That is an OS level error message that means you did not stop the previous server processes, and they are still running and listening on the network address (so nothing else new can use that address, that’s what the error means).

I think once you resolve that, the allow_websocket_origin setting will resolve the “permission denied” problem.

@Bryan Thank you for the response. By commenting out:

# Thread(target=bk_worker).start()  

The “address in use” error no longer occurs (not a surprise… apparently no sharing of network goo happens easily with Rasp Pi / Python???).

I assume this means:

  • I must run a Flask app with bokeh server as a single process/no threads.
  • a single process/no threads will work.

HOWEVER, when I attempt to access the html, I see:

192.168.86.249/:21 GET http://localhost:5006/bkapp/autoload.js?bokeh-autoload-element=1002&bokeh-app-path=/bkapp&bokeh-absolute-url=http://localhost:5006/bkapp net::ERR_CONNECTION_REFUSED     192.168.86.249/:21 

Note: 192.168.86.249 is the address of my Raspberry Pi.

Netstat points out:

$ netstat -tulpn
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.1:28017         0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:40853         0.0.0.0:*               LISTEN      844/node            
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:8000            0.0.0.0:*               LISTEN      3480/python3        
tcp        0      0 127.0.0.1:27017         0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:5006            0.0.0.0:*               LISTEN      3480/python3        
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
tcp6       0      0 :::5006                 :::*                    LISTEN      3480/python3        
udp        0      0 0.0.0.0:56692           0.0.0.0:*                           -                   
udp        0      0 0.0.0.0:68              0.0.0.0:*                           -                   
udp        0      0 0.0.0.0:5353            0.0.0.0:*                           -                   
udp6       0      0 :::38607                :::*                                -                   
udp6       0      0 :::5353                 :::*                    

Which leads me to expect setting:

    server = Server({'/bkapp': make_interactive}, io_loop=IOLoop(), address='0.0.0.0',
                    allow_websocket_origin=["0.0.0.0"])  

Should work. Can you please help me figure out what I am not understanding/doing wrong?

Thank you.

I don’t think this is accurate. However, note that this is not an area of expertise for me. But you can e.g. use a proxy like nginx to front multiple Bokeh server processes, or if you are embedding the Bokeh server directly in the Flask app, you could use gunicorn in that case.

I’m not sure what

allow_websocket_origin=["0.0.0.0"]

is intended to do. If you want to disable origin checks you should set the value to "*"

Can you please help me figure out what I am not understanding/doing wrong?

You have not described what is actually happening at this point. Are there errors or warnings in the server console log? What about the browser JS log?

@Bryan - thank you. I apologize for being dense.

re: Are there errors or warnings in the server console log?

Sadly (like I said, sorry I am so dense) I have spent quite a bit of time attempting to get logging information.

I set up ${HOME}/.bokeh/bokeh.yaml

to be:

settings:
  BOKEH_PY_LOG_LEVEL: 'debug'

I thought this would provide logging info to my console. It did not. So my next question is,
re: …server console log? -> how do i get a log file that shows me debug and error warnings from I assume server.py?

Note: I hoped there would be an example because I was too stupid to figure it out, but could not find one.

Help appreciated and needed. Thank you.

Setting BOKEH_PY_LOG_LEVEL will cause the bokeh serve application to emit log messages. If you are embedding Bokeh as a library it will be up to you to initialize the Python logging system (e.g. probably by calling logging.basicConfig(...) yourself in your code). The reason is that in general it is not advised for library code to dictate any sort of logging policy itself (although we make a slight exception to force deprecation warnings to show up).

@Bryan Thank you. I tried the exact code on my Mac (running Flask on my Mac), and it worked.

The challenge then is what is different on the Rasp Pi? This confuses me because this is happening when the client script:

<script src="http://localhost:5006/bkapp/autoload.js?bokeh-autoload-element=1007&bokeh-app-path=/bkapp&bokeh-absolute-url=http://localhost:5006/bkapp" id="1007"></script>  

runs. On the mac, the path can resolve to the make_interactive function I associate with /bkapp in

    server = Server({'/bkapp': make_interactive}, io_loop=IOLoop(), allow_websocket_origin=["*"])

Yet, I get

WebSocket connection to 'ws://localhost:5006/bkapp/ws?bokeh-protocol-version=1.0&bokeh-session-id=snTq7vrlVWsZRhq1FoJLR0zdczk6EfzDTlP6QQqOn8Kg' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED  

the js code says:

o.pull_session = function(e, n, o) {
        return new Promise(function(s, r) {
            new _(e,n,o,function(e) {
                try {
                    s(e)
                } catch (n) {
                    throw t.logger.error("Promise handler threw an error, closing session " + n),
                    e.close(),
                    n
                }
            }
            ,function() {
                r(new Error("Connection was closed before we successfully pulled a session"))
            }
            ).connect().then(function(e) {}, function(e) {
                throw t.logger.error("Failed to connect to Bokeh server " + e),
                e
            })
        }
        )

The web socket could not be open on the Rasp Pi. But why? Looking at the active ports:

python    10325      pi    7u  IPv4  69521      0t0  TCP *:8000 (LISTEN)
python    10325      pi    8u  IPv4  70791      0t0  TCP *:5006 (LISTEN)
python    10325      pi    9u  IPv6  70792      0t0  TCP *:5006 (LISTEN)

port 5006 is available to all addresses?

Any advice needed and appreciated. Thank you.

I’m afraid I don’t have ay experience with Rasp Pi’s to be able to suggest much. The connection refused message could be coming from the Bokeh server, or I guess it could be coming from a Rasp Pi firewall or something? The only way I know to to know is to examine the Bokeh server logs. If the Bokeh server is rejecting the connection, it will say why. If nothing is there, then the rejection is happening before the connection even gets to the Bokeh server.

@Bryan thank you. I got it to work. It took me awhile to figure out how all this worked. Bottom line, I was not passing the right url to server_document. This means I sent the wrong ws address. Which meant the client couldn’t find the ws on the rasp pi. dumb on my part…

The next challenge was DateSlider - I use this widget + a plot. DateSlider uses a (64 bit) time_t timestamp. Rasp Pi 3 is 32 bit OS. I modified the date message handler to get it to work.

Thanks.