{"id":971,"date":"2017-04-27T22:50:05","date_gmt":"2017-04-27T20:50:05","guid":{"rendered":"http:\/\/heppg.de\/ikg\/wordpress\/?p=971"},"modified":"2017-04-27T22:50:56","modified_gmt":"2017-04-27T20:50:56","slug":"raspberry-pi-gpio-to-web-page","status":"publish","type":"post","link":"https:\/\/heppg.de\/ikg\/wordpress\/?p=971","title":{"rendered":"Raspberry Pi GPIO to web page"},"content":{"rendered":"<p>In the Rasperry Pi forum, there are quite often questions on how to get a GPIO pin status displayed on a web page.<\/p>\n<p>Common attempts are with CGI scripts; webiopi or other frameworks are proposed. CGI is quite outdated; and complex frameworks handle many technologies under the hood and leave few opportunities to learn.<\/p>\n<p>I usually propose an architecture based on a python web application server, using websockets to send events to the browser. The browser uses javascript to display the data. Collection of GPIO events is done in a thread and data are sent through a queue to the python web application server. This architecture can be tested step by step and can be adjusted to different needs.<\/p>\n<p>An overall sketch of the modules shows the connection between the components.<\/p>\n<p><a href=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2017\/04\/tornado_websocket.svg_.png\" rel=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2017\/04\/tornado_websocket.svg.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-979 \" src=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2017\/04\/tornado_websocket.svg_.png\" alt=\"\" width=\"514\" height=\"754\" srcset=\"https:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2017\/04\/tornado_websocket.svg_.png 661w, https:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2017\/04\/tornado_websocket.svg_-204x300.png 204w, https:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2017\/04\/tornado_websocket.svg_-624x916.png 624w\" sizes=\"auto, (max-width: 514px) 100vw, 514px\" \/><\/a><\/p>\n<p>Basic sequence is: (1) Browser requests web page from server, (2) server provides web page and (3) javascript in browser is activated. (4) Javascript opens a websocket to the server. In the server, there are handler for the http request and web socket. The peripheral access is handled in a separate class and (5) sends data through a queue to the web socket handler. (6) in browser, javascript sets the received data into the html-document.<\/p>\n<p><strong>(1)<\/strong> Browser requests web page. The python web application server is responsible to handle this.<\/p>\n<p><strong> (2)<\/strong> To provide the page, the &#8216;tornado&#8217; package is used. All these web app servers consist of Handler classes for various purpose. The tornado\u00a0 framework uses a mapping from web request pathes to the Handlers.<\/p>\n<pre>def make_app():\r\n\u00a0\u00a0\u00a0 return tornado.web.Application(\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 [\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (r\"\/\"\u00a0 , MainHandler),\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (r\"\/ws\", ClientWebSocketHandler),\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ]\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 )<\/pre>\n<p>The &#8216;root&#8217; path for a web page is &#8216;\/&#8217;. This is the\u00a0 path a browser requests when http:\/\/heppg.de is requested. The http requests have various types, the usual request for a page is a &#8216;get&#8217; request. The tornado routes this request to the MainHandler, and as it is a get request the method called is the &#8216;get()&#8217;-method.<\/p>\n<p>To tell the whole story, the app server is initialized with<\/p>\n<pre>if __name__ == \"__main__\":\r\n\u00a0\u00a0\u00a0 print(\"start\")\r\n\u00a0\u00a0\u00a0 app = make_app()\r\n\u00a0\u00a0\u00a0 app.listen(8080)\r\n\u00a0\u00a0\u00a0 try:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 tornado.ioloop.IOLoop.current().start()\r\n\u00a0\u00a0\u00a0 except KeyboardInterrupt:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 peripheral.stop()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 runMessageSend = False\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 tornado.ioloop.IOLoop.current().stop()\r\n\u00a0\u00a0\u00a0 print(\"stopped\")<\/pre>\n<p>In this code, there is also the port 8080 in the listen-statement. The url for a browser is<\/p>\n<pre>http:\/\/localhost:8080<\/pre>\n<p>or<\/p>\n<pre>http:\/\/127.0.0.1:8080<\/pre>\n<p>There is extensive documentation on the tornado web site &#8216;.tornadoweb&#8217;.<\/p>\n<p>A basic implementation for the MainHandler is<\/p>\n<pre>class MainHandler(tornado.web.RequestHandler):\r\n\u00a0\u00a0\u00a0 def get(self):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.write( \"<span style=\"color: #339966;\">hello world<\/span>\" )<\/pre>\n<p>Instead of the simple &#8216;hello world&#8217; a web page is produced. Html pages are xml structures, containing &lt;head&gt; and &lt;body&gt;-Elements.<\/p>\n<pre>class MainHandler(tornado.web.RequestHandler):\r\n\u00a0\u00a0\u00a0 def get(self):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.write( <span style=\"color: #339966;\">\"\"\"&lt;html&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0 &lt;head&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;title&gt;Websocket sample&lt;\/title&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0 &lt;\/head&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0 &lt;body&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Sample connection to a Raspberry Pi<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0 &lt;\/body&gt;<\/span>\r\n<span style=\"color: #339966;\">&lt;\/html&gt;\"\"\"<\/span><\/pre>\n<p>The quotation with the three quotes allows to use multiline content, which makes editing simpler.<\/p>\n<p>So far the page contains only the basic elements. As we later need some boxes to add text, these are defined with labels.<\/p>\n<pre><span style=\"color: #339966;\">\"\"\"&lt;html&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0 &lt;head&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;title&gt;Websocket sample&lt;\/title&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0 &lt;\/head&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0 &lt;body&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Sample connection to a Raspberry Pi<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;hr\/&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;div&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;div\u00a0 style=\"position:relative; width:400px; height:80px;\" &gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;div id=\"addr\" style=\"width:400px; height:20px;\"&gt;\u00a0\u00a0\u00a0 addr\u00a0\u00a0\u00a0 &lt;\/div&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;div id=\"status\" style=\"width:400px; height:20px;\"&gt;\u00a0 status\u00a0 &lt;\/div&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;div id=\"msg\" style=\"width:400px; height:20px;\"&gt;\u00a0\u00a0\u00a0\u00a0 message &lt;\/div&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/div&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/div&gt;<\/span>\r\n\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;hr\/&gt;<\/span>\r\n\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Connection Status<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;div id=\"connection\" style=\"position:relative; width:200px; height:40px;background:lightgrey; font: 30px arial, sans-serif;\" &gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 connection<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/div&gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Message display<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;div id=\"feld\" style=\"position:relative; width:200px; height:40px;background:lightgrey; font: 30px arial, sans-serif;\" &gt;<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 message<\/span>\r\n<span style=\"color: #339966;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 &lt;\/div&gt; ...\"\"\"<\/span><\/pre>\n<p><strong>(3)<\/strong> The javascript part plays its role now. With javascript, websockets can be opened and data can be send to the server or received from the server.<\/p>\n<p><strong>(4)<\/strong> To open a socket, the address needs to be build from the servers address. As the web page is received from the server, this is already known inside the browser context. Instead of http:\/\/ as the protocol, the protocol used is ws:\/\/. For a local connection, this results in &#8220;ws:\/\/localhost:8080\/ws&#8221;. The trailing &#8220;\/ws&#8221; is needed for the tornado routing which addresses this request to the WebSocketHandler.<\/p>\n<pre><span style=\"color: #0000ff;\">var addr = \"ws:\/\/\" + window.location.hostname + \":\" + window.location.port + \"\/ws\";<\/span>\r\n<span style=\"color: #0000ff;\">var websocket = new WebSocket( addr );<\/span><\/pre>\n<p>Javascript uses &#8216;callback&#8217; methods on websocket events.<\/p>\n<pre><span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0 websocket.onmessage = function(e){<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ...<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0 }<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0 \u00a0<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0 websocket.onopen = function(){<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 console.log('Connection open!');<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ...<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0 }<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0 \u00a0<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0 websocket.onclose = function(){<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 console.log('Connection closed');<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ...<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0 }<\/span><\/pre>\n<p>The content is abbreviated &#8230; for clarity. The <span style=\"color: #0000ff;\">console.log(&#8216;hello&#8217;);<\/span> is a convenient way to debug javascript in a browser. If firefox is used, the debugger is available inside the browser. In earlier releases there was usually &#8216;firebug&#8217; used, an extension to firefox. In newer releases &#8211; here I use 53.3 &#8211; firebug is no longer supported and &#8220;Firefox DevTools&#8221; instead. These are activated with a right click in the page and &#8216;inspect element&#8217;.<\/p>\n<p><a href=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2017\/04\/tornado_debug.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-976 size-full\" src=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2017\/04\/tornado_debug.png\" alt=\"\" width=\"536\" height=\"171\" srcset=\"https:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2017\/04\/tornado_debug.png 536w, https:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2017\/04\/tornado_debug-300x96.png 300w\" sizes=\"auto, (max-width: 536px) 100vw, 536px\" \/><\/a><\/p>\n<p>Really useful for finding out what the system is doing. Of course the debugger is also sometimes needed.<\/p>\n<p>When the connection is opened, the callback function sets the status color.<\/p>\n<pre><span style=\"color: #339966;\">\u00a0<span style=\"color: #0000ff;\">\u00a0\u00a0 websocket.onopen = function(){<\/span><\/span><span style=\"color: #0000ff;\">\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 console.log('Connection open!');\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 document.getElementById(\"connection\").style.background = 'lightgreen';\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 document.getElementById(\"status\").innerHTML = 'connected !';\r\n\u00a0\u00a0\u00a0 }<\/span><\/pre>\n<p>The elements retrieved from the html document are the named &#8216;div&#8217; sections &#8216;connection&#8217; and &#8216;status&#8217;.<\/p>\n<p>Next important step is inside the python app server. When socket is opened, an instance of ClientWebSocketHandler is created. In the current application, the class starts a thread which shuffles data from a queue into the send method. So whenever a message is on the queue, this message is sent to the browser.<\/p>\n<pre># a variable to gracefully stop the threadsrunMessageSend = True\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\r\nclass ClientWebSocketHandler(tornado.websocket.WebSocketHandler):\r\n\u00a0\u00a0\u00a0 def __init__(self, args, kwargs):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 tornado.websocket.WebSocketHandler.__init__(self, args, kwargs)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 print(\"ClientWebSocketHandler.init\")\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.my_thread = threading.Thread(target = self.run)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.my_thread.start()\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 def run(self):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 while runMessageSend:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 try:\r\n                # something on the queue ?\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 s = sendQueue.get(block=True, timeout=0.1)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 except Exception:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 continue \r\n            # doublecheck if connection available\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if self.ws_connection is None:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 print(\"discard \", s) \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 print(\"send \", s) \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 try:\r\n                    # and send toward the browser\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.write_message(s )\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 except Exception:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 pass<\/pre>\n<p><strong>(5)<\/strong> The other side of the queue can be used as needed. As a sample, here just a debug-Sending class which sends &#8216;on&#8217;, &#8216;off&#8217; packed in a json telegram.<\/p>\n<pre># messages from Periphaeral Class to Websocket\r\nsendQueue= Queue.Queue()\r\n\r\nclass PeripheralDebug:\r\n    \"\"\"Debug class\"\"\"\r\n\u00a0\u00a0\u00a0 def __init__(self, sendQueue):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.sendQueue = sendQueue\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 def start(self):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.runit = True\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 blinkThread = threading.Thread(target=self.blink)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 blinkThread.start()\r\n\u00a0\r\n\u00a0\u00a0\u00a0 def stop(self):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.runit = False\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 def blink(self):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 cnt = 0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 while self.runit:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.sendQueue.put( { 'data': 'on', 'cnt' : cnt } )\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 cnt += 1\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 time.sleep(0.5)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.sendQueue.put( { 'data': 'off', 'cnt' : cnt } )\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 cnt += 1\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 time.sleep(0.5)<\/pre>\n<p>The json telegrams &#8220;{ &#8216;data&#8217;: &#8216;on&#8217;, &#8216;cnt&#8217; : cnt }&#8221; contain the &#8216;data&#8217;-element and a counter &#8216;cnt&#8217;. It is usually a good idea to pack a telegram counter into a telegram. This helps to find out whether messages are lost or a connection was broken for some time.<\/p>\n<p>The queue is created with Queue.Queue(), which is typical for python 2; in python3 it is more consistent with queue.Queue().<\/p>\n<p>The PeripheralDebug-Class is started with<\/p>\n<pre>peripheral = PeripheralDebug()\r\nperipheral.start()<\/pre>\n<p>Instead of this debug-Class, a &#8216;real&#8217; PeripheralGPIO class can be used. When the Telegram is the same, and the queue is same queue as before, this can be exchanged easily.<\/p>\n<pre>class PeripheralGPIO:\r\n    \"\"\"Connection to a GPIO pin\"\"\"\r\n\u00a0\u00a0\u00a0 def __init__(self, sendQueue):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.sendQueue = sendQueue\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GPIO.setmode(GPIO.BCM)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GPIO.setwarnings(False)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.channel = 4\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 GPIO.setup(self.channel, GPIO.IN, pull_up_down=GPIO.PUD_UP)\r\n\r\n\u00a0\u00a0\u00a0 def start(self):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.runit = True\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 blinkThread = threading.Thread(target=self.run)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 blinkThread.start()\r\n\r\n\u00a0\u00a0\u00a0 def stop(self):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.runit = False\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\n\u00a0\u00a0\u00a0 def run(self):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 cnt = 0\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 prev = None\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 while self.runit:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 res =\u00a0 GPIO.input(self.channel)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if prev != res:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if res:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.sendQueue.put( { 'data': 'on', 'cnt' : cnt } )\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 self.sendQueue.put( { 'data': 'off', 'cnt' : cnt } )\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 cnt += 1\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 prev = res\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # for debouncing and limiting number of events per time\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 time.sleep(0.01)<\/pre>\n<p>In IT terminology, these two classes PeripheralGPIO and PeripheralDebug use the same interface. Unfortunately,\u00a0 in python Interfaces are not very prominent. To make this &#8216;Factory Pattern&#8217; complete, there is also a PeripheralFactory which returns either the debug-version or the GPIO-version of these classes.<\/p>\n<pre>class PeripheralFactory:\r\n\u00a0\u00a0\u00a0 @staticmethod\r\n\u00a0\u00a0\u00a0 def getPeripheral(debug):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if debug:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return PeripheralDebug(sendQueue)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else:\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return PeripheralGPIO(sendQueue)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\r\nperipheral = PeripheralFactory.getPeripheral(debug)\r\nperipheral.start()<\/pre>\n<p><strong>(6)<\/strong> Last step is to display the data from the websocket in the browser, so javascript gets this task:<\/p>\n<pre><span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0 websocket.onmessage = function(e){<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var server_message = e.data;<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 var obj = JSON.parse(server_message);<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 document.getElementById(\"feld\").innerHTML = obj.data;<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 if ( obj.data == \"on\" )<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 document.getElementById(\"feld\").style.background = 'yellow';<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 else<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 document.getElementById(\"feld\").style.background = 'lightblue';<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 console.log(server_message);<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 document.getElementById(\"msg\").innerHTML = server_message;<\/span>\r\n<span style=\"color: #0000ff;\">\u00a0\u00a0\u00a0 }<\/span><\/pre>\n<p>The message data are retrieved from the event-attribute data &#8220;e.data&#8221;. As this message is\u00a0 json, this is parsed with <span style=\"color: #0000ff;\">JSON.parse(server_message);<\/span> returning an object. The data part of the json dictionary is retrieved with obj.data and accordingly the status box is getting its color.<span style=\"color: #0000ff;\"><br \/>\n<\/span><\/p>\n<p>The complete code can be <a href=\"http:\/\/heppg.de\/ikg\/wordpress\/wp-content\/uploads\/2017\/04\/tornado_websocket.py\">downloaded here<\/a>.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the Rasperry Pi forum, there are quite often questions on how to get a GPIO pin status displayed on a web page. Common attempts are with CGI scripts; webiopi or other frameworks are proposed. CGI is quite outdated; and complex frameworks handle many technologies under the hood and leave few opportunities to learn. I [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[43,42],"tags":[],"class_list":["post-971","post","type-post","status-publish","format-standard","hentry","category-gpio","category-python"],"_links":{"self":[{"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/971","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=971"}],"version-history":[{"count":5,"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/971\/revisions"}],"predecessor-version":[{"id":980,"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/971\/revisions\/980"}],"wp:attachment":[{"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=971"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=971"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/heppg.de\/ikg\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=971"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}