A web-based alternative to Scratch
Coming Up!
Next, you need to create a server on your Pi to field your block's query. As usual, Python to the rescue! Python is great for this task because, apart from having a comprehensive module for dealing with the Pi's GPIO pins, it also has a simple web server module that has everything you need to grab and answer petitions coming from Snap!.
Take a look at Listing 3. Note that this is only a fragment of the whole RPiGPIO.py
server program. You can find the complete program online [5], but what is shown here (and in Listing 4) is the skeleton of what you need to set up a web server to listen on port 8280 on your Pi.
Listing 4
RPiGPIO.py – Request Handler
01 . 02 . 03 . 04 class CORSHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): 05 def send_head(self): 06 path = self.path 07 08 self.pin=0 09 self.state=False 10 11 GPIO.setmode(GPIO.BCM) 12 13 ospath = os.path.abspath('') 14 15 regex = re.compile(".*pin=([0-9]*).*state=(LOW|HIGH)") 16 m = regex.match(path) 17 18 if 'pinwrite' in path: # write HIGH or LOW to pin 19 20 self.pin = int(m.group(1)) 21 self.state = True 22 if m.group(2) == 'LOW': 23 self.state = False 24 25 GPIO.setup(self.pin, GPIO.OUT) 26 GPIO.output(self.pin, self.state) 27 . 28 . 29 .
Listing 3
RPiGPIO.py – Server Setup
01 #!/usr/bin/python 02 03 import SimpleHTTPServer 04 import SocketServer 05 . 06 . 07 . 08 if __name__ == "__main__": 09 PORT = 8280 #R+P in ASCII Decimal 10 Handler = CORSHTTPRequestHandler 11 12 httpd = SocketServer.TCPServer(("", PORT), Handler) 13 14 print "serving at port", PORT 15 print "Go ahead and launch Snap!" 16 httpd.serve_forever()
In your command (Figure 12), note how the second block runs a call to your server. Suppose you want to send a HIGH
signal to pin 17 on your Pi, then the final string sent to the RPiGPIO.py
server will look like:
http://192.168.1.114:8280/pinwrite?pin=17&state=LOW
Now you need to write into your server the bit that is missing from Listing 3 – namely, a request handler that breaks up the requests that Snap! sends and then executes anything that needs doing on the hardware. Listing 4, another piece of the whole program [5], does exactly that.
You use regular expressions to break up the string you saw earlier and extract the pin
you want to change (lines 15 and 16) and the state
you want to change it to (21 and 23). You then use the regular GPIO calls from the RPI.GPIO module to set the pins and send out the signal.
You can check how this works by setting up a circuit like the one shown in Figure 15 (note the 10K resistor – important later). Download the code [5], copy the RPiGPIO.py
server over to your Pi, and run it with:
$ sudo python RPiGPIO.py
Next, import RPiGPIO.xml
into Snap!. You will find the block you just created under Looks. Drag it onto the workspace, right-click on it, and choose edit from the pop-up dialog. Change the IP address (currently, 192.168.1.114) to whatever your Rasp Pi's IP is on your network and then click Apply and OK.
Choose 17
for the pin
value, and HIGH
for the state
value. Click the block and watch the LED light up.
Buttoned Up
In the last example, I'll show how to implement a block that not only sends information over to the Pi, but also gets a response back. This time it will be a Predicate block that, given a pin number and a state, will return true or false, whether or not the pin number is in said state (Figure 16). In the hardware setup shown in Figure 15, you can use this block to find out whether or not the button is pressed.
The block description shown in Figure 17, and in XML form in Listing 5, is really not much more complicated than that of the two previous blocks. By embedding the HTTP call (which contains the GET method) within a predicate
block, you tell Snap! to expect an answer back from the server. In this case, the answer will be either true
or false
.
Listing 5
pinread.xml
01 <blocks app="Snap! 4.0, http://snap.berkeley.edu" version="1"> 02 <block-definition s="pin %'pin' is %'state'" type="predicate" category="operators"> 03 <header/> 04 <code/> 05 <inputs><input type="%n" readonly="true"><options>0 06 1 07 4 08 7 09 8 10 9 11 10 12 11 13 14 14 15 15 17 16 18 17 21 18 22 19 23 20 24 21 25</options></input><input type="%txt" readonly="true">LOW<options>LOW 22 HIGH</options></input></inputs> 23 <script> 24 <block s="doIfElse"> 25 <block s="reportEquals"> 26 <block s="reportURL"> 27 <block s="reportJoinWords"> 28 <list> 29 <l>192.168.1.114:8280/pinread?pin=</l> 30 <block var="pin"/> 31 <l>&state=</l> 32 <block var="state"/> 33 </list> 34 </block> 35 </block> 36 <l>true</l> 37 </block> 38 <script> 39 <block s="doReport"> 40 <block s="reportTrue"/> 41 </block> 42 </script> 43 <script> 44 <block s="doReport"> 45 <block s="reportFalse"/> 46 </block> 47 </script> 48 </block> 49 </script> 50 </block-definition> 51 </blocks>
On the server side, the request handler portion that fields the request looks like what you see in Listing 6. Again, it starts off by breaking up the GET data with the regular expressions seen in Listing 4 (lines 6 to 9).
Listing 6
RPiGPIO.py – Request Handler Part I
01 . 02 . 03 . 04 elif 'pinread'in path: # Read state of pin. 05 06 self.pin = int(m.group(1)) 07 self.state = True 08 if m.group(2) == 'LOW': 09 self.state = False 10 11 f = open(ospath + '/return', 'w+') 12 13 GPIO.setup(self.pin, GPIO.IN) 14 if(GPIO.input(self.pin) == self.state): 15 f.write(str(True)) 16 else: 17 f.write(str(False)) 18 19 f.close() 20 f = open(ospath + '/return', 'rb') 21 ctype = self.guess_type(ospath + '/rpireturn') 22 self.send_response(200) 23 self.send_header("Content-type", ctype) 24 fs = os.fstat(f.fileno()) 25 self.send_header("Content-Length", str(fs[6])) 26 self.send_header("Last-Modified", self.date_time_string(fs.st_mtime)) 27 self.send_header("Access-Control-Allow-Origin", "*") 28 self.end_headers() 29 return 30 . 31 . 32 .
It then creates a file (filehandle f
on line 11), reads the GPIO pin (lines 13 to 17), and writes True
or False
into the file. Then, it sends all the correct headers back to Snap! and finally returns the contents of f
(i.e., True
or False
).
If you followed everything in this article up to this point, you have imported RPiGPIO.xml
into Snap!, and you are running RPiGPIO.py
on your Pi, check it out!
You will find this new block in Operators. Drag it onto the workspace and, using the circuit shown in Figure 15, poll pin 24 to see if it is HIGH
. Hold down the button on your breadboard and click the block. A speech bubble with the word True should pop up. If you let go of the button and then click the block, False will pop up.
« Previous 1 2 3 4 Next »
Buy this article as PDF
Pages: 9
(incl. VAT)