A Quick and Dirty Guide to Getting Started with the Pinoccio API.

In case I haven't told you, Pinoccio is an Ardunio-esque micro-controller board, that ships 'with wings': Each board has built-in mesh networking, and the kit comes with a Wifi board.

What's particularly unique about Pinoccio is that they're not leaving it just at that. They're providing a simple scripting language (based on the phenomenally cool Bitlash project), as well as an associated web-service and API provider (called HQ).

In Pinoccio parlance, a single board is called scout and a group of scouts connected by a mesh are called a troop. Cute eh?

Today, in the spirit of taking time off from thesis writing, and getting my head away from Transactional Memory, I figured I'd spend some time digging into the API they provide. I thought I'd write up some example code here, from my perspective (a relative novice to web-services entirely).

We're going to create two scripts: issue_command.py and sync_stream.py. The first will allow issuing a scout-script command through the API, and the second, will allow you to watch the API's sync stream, which watches all the events which hit HQ.

Before those though, I'll show you api_explorer.py which will allow exploring the read only elements of the API.

Authentication:

First step is to login and get an authenticated token, which is a string the API gives you as a temporary password which you attach to all your subsequent requests. This ensures that you, and only you, can control your Pinoccio boards.

For the purposes of this blog post, I'm going to skip the right way to do this, in order to get up and running faster, by showing you the dirty way, straight from the Pinoccio API Documentation.

On the command line, you can ask the API for a token using curl:

curl -X POST -v --data '{"email":"youremail","password":"boats"}' https://api.pinocc.io/v1/login

Take note of the reply:

{"data":{"token":"ahv0onrd0fiio8813llqjo5sb1","account":19}}

You'll need the token shortly.

HTTP Requests

I've been quite impressed with the python library Requests, which makes it reasonably easy to communicate with a service, bidirectionally.

You can install it, if you don't already have it, with pip:

pip install requests

api_explorer.py

While you could do this directly with curl, it's instructive to see how requests are constructed before going on further. To that end: here's api_explorer.py

import requests
import sys

API_Root="https://api.pinocc.io/v1/"
token = "your token here!"
auth_arg = {"token" : token} 

def get(url, **kwargs): 
    """
    Issue a get request to the Pinnocio API, authenticated by the token
    """
    if "data" in kwargs: 
        kwargs["data"] = dict(kwargs["data"].items() + auth_arg.items())
    else:
        kwargs["data"] = auth_arg
    return requests.get(API_Root + url, **kwargs)


if __name__  == '__main__': 
    if len(sys.argv) > 1: 
        r = get(sys.argv[1])
        print r.status_code
        print r.text
    else:
        print "Need a command" 

This simple script allows you to provide an endpoint on the command line, and print out the API's response. The function get above constructs the appropriate URL given the endpoint name, and makes sure that we have the token on the request. The kwargs is so that we can provide arguments to the call, which we will need soon...

troops is an interesting endpoint, as it will list the troops associated with the account you used to generate the token.

SolidALumbook:matt_pinoccio mgaudet$ python api_explore.py troops
200
{"data":[{"account":1112,"token":"<token data-preserve-html-node="true" elided>","name":"Scooters","id":1,"online":true}]}

Reading this JSON output, you can see I have one troop, "Scooters", with id 1. So, we can now ask the API about the scouts in that troop:

SolidALumbook:matt_pinoccio mgaudet$ python api_explore.py 1/scouts
200
{"data":[{"name":"Razer","updated":"1397008385993","id":1,"time":1397008385992},{"name":"Rascal","updated":"1397008855488","id":2,"time":1397008855488}]}

So I have two scouts in the troop: Razer (id 1) and Rascal (id 2).

These ID's are useful when talking about issuing commands.

issue_command.py

According to the API documents, to issue a ScoutScript command to a scout, you need to know its troop id and scout id. After which, you can issue a command with HTTP GET on the end point {troop id}/{scout id}/command. Using api_explorer.py we found out that Razer is scout 1 in troop 1. So if we want to issue a command to Razer, we can make a request to the 1/1/command endpoint.

Here's a script which allows you to specify a troop id, scout id, and a ScoutScript command. As you can see it's largely identical to api_explorer.py, except that "command" is provided as an argument to the get-request.

import requests
import sys

API_Root="https://api.pinocc.io/v1/"
token = "your token here"
auth_arg = {"token" : token} 

def get_token(username, password): 
    pass

def get(url, **kwargs): 
    if "data" in kwargs: 
        kwargs["data"] = dict(kwargs["data"].items() + auth_arg.items())
    else:
        kwargs["data"] = auth_arg
    return requests.get(API_Root + url, **kwargs)

if __name__  == '__main__': 
    if len(sys.argv) > 3: 
        command = " ".join(sys.argv[3:])
        r = get("{}/{}/command/".format(sys.argv[1],sys.argv[2]),data={"command": command}) 
        print r.status_code
        print r.text
    else:
        print "Need a troop, a scout, and a command" 

So we can turn on the led of Razer:

SolidALumbook:matt_pinoccio mgaudet$ python issue_command.py 1 1 led.on
200
{"data":{"type":"reply","from":1,"id":"t44947","end":true,"reply":"","_cid":13,"basetime":469,"commandsPending":0,"messagesQueued":0,"account":"1112","tid":"1","_t":1397421971331,"output":"","result":false}}

Or peek at the wifi status:

SolidALumbook:matt_pinoccio mgaudet$ python issue_command.py 1 1 "wifi.report()"
200
{"data":{"type":"reply","from":1,"id":"t44948","end":true,"reply":"{\"type\":\"wifi\",\"connected\":true,\"hq\":true}\r\n","_cid":14,"basetime":400,"commandsPending":0,"messagesQueued":0,"account":"1112","tid":"1","_t":1397421998605,"output":"{\"type\":\"wifi\",\"connected\":true,\"hq\":true}\r\n","result":false}}

sync_stream.py

One of the interesting elements of the Pinnocio API is that the scouts themselves will autonomously report information back to HQ. This data can be accessed through the API from the sync endpoint.

Here's a simple script which starts listening to the sync stream until killed:

import requests
import sys
import json

API_Root="https://api.pinocc.io/v1/"
token = "your API key here!"
auth_arg = {"token" : token} 

def get_token(username, password): 
    pass

def get(url, **kwargs): 
    if "data" in kwargs: 
        kwargs["data"] = dict(kwargs["data"].items() + auth_arg.items())
    else:
        kwargs["data"] = auth_arg
    return requests.get(API_Root + url, **kwargs)

if __name__  == '__main__': 
    received = 0
    r = get("sync",stream=True)
    print r.status_code

    # Chunk size required to avoid buffering output too long!
    for line in r.iter_lines(chunk_size=1): 
        received = received + 1 
        if line: 
            print "({}) {}".format(received, json.loads(line))
        else:
            print "({}) keepalive".format(received) 

Here's what it looks like in action:

SolidALumbook:matt_pinoccio mgaudet$ python sync_stream.py 
200
(1) {u'data': {u'account': u'1112', u'type': u'connection', u'troop': u'1', u'value': {u'status': u'online', u'ip': u'<ip data-preserve-html-node="true" elided>'}, u'time': 1397420589928}}
(2) {u'data': {u'account': u'1112', u'value': {u'state': [-1, -1, -1, -1, -1, -1, -1, -1], u'_t': 1397420590333.001, u'type': u'analog', u'mode': [-1, -1, -1, -1, -1, -1, -1, -1]}, u'scout': u'1', u'troop': u'1', u'time': 1397420590333.001, u'type': u'analog'}}
(3) {u'data': {u'account': u'1112', u'value': {u'available': 1, u'_t': 1397420590149.001, u'scout': 1, u'type': u'available'}, u'scout': u'1', u'troop': u'1', u'time': 1397420590149.001, u'type': u'available'}}
(4) {u'data': {u'account': u'1112', u'value': {u'available': 1, u'_t': 1397421532918.001, u'scout': 2, u'type': u'available'}, u'scout': u'2', u'troop': u'1', u'time': 1397421532918.001, u'type': u'available'}}
(5) {u'data': {u'account': u'1112', u'value': {u'list': [], u'_t': 1397420590332.001, u'type': u'backpacks'}, u'scout': u'1', u'troop': u'1', u'time': 1397420590332.001, u'type': u'backpacks'}}
(6) {u'data': {u'account': u'1112', u'value': {u'state': [-1, -1, -1, -1, -1, -1, -1], u'_t': 1397420590333, u'type': u'digital', u'mode': [-1, -1, -1, -1, -2, -2, -2]}, u'scout': u'1', u'troop': u'1', u'time': 1397420590333, u'type': u'digital'}}
(7) {u'data': {u'account': u'1112', u'value': {u'led': [0, 255, 0], u'torch': [0, 255, 0], u'type': u'led', u'_t': 1397421971069}, u'scout': u'1', u'troop': u'1', u'time': 1397421971069, u'type': u'led'}}
(8) {u'data': {u'account': u'1112', u'value': {u'led': [0, 34, 255], u'torch': [0, 34, 255], u'type': u'led', u'_t': 1397421537370}, u'scout': u'2', u'troop': u'1', u'time': 1397421537370, u'type': u'led'}}
(9) {u'data': {u'account': u'1112', u'value': {u'scoutid': 1, u'power': u'3.5 dBm', u'troopid': 1, u'_t': 1397420590334, u'rate': u'250 kb/s', u'routes': 0, u'type': u'mesh', u'channel': 20}, u'scout': u'1', u'troop': u'1', u'time': 1397420590334, u'type': u'mesh'}}
(10) {u'data': {u'account': u'1112', u'value': {u'vcc': True, u'battery': 73, u'_t': 1397422079321, u'voltage': 392, u'type': u'power', u'charging': False}, u'scout': u'1', u'troop': u'1', u'time': 1397422079321, u'type': u'power'}}

Download code:

All this code has been uploaded to github here, as PinoccioApiTools.

Conclusion

Pinoccio is providing some very powerful tools for building some interesting projects, minimizing a lot of pain points that previous solutions suffered from. I'm really excited by this.

What Caught My Eye - Week 12

Technology & Tech Culture:

  • This video featuring Monty Montgomery from Xiph is a phenomenal and cogent explanation of how analog to digital to analog conversion works, and why the stair-step chart we often see is a horrible lie.
  • Hiring is a bit of voodoo, and often times I hear people talk about Passion, which is a bit of a bugbear of mine. This post talks about how excellent candidates can be overlooked because the signifiers of 'Passion' aren't there.

Arts and Culture

Examining "Reproducibility in Computer Science"

I'm heartened to see Professor Shriram Krishnamurthi spearheading an effort to help evaluate yesterday's reproducibility project.

We are evaluating the results presented by the study at the University of Arizona. Our goal is to allow authors and any other interested parties to review that study’s findings about an individual paper, and attempt to reconstruct their findings. We will summarize the results here.
We are grateful to Collberg, et al. for initiating this discussion and making all their data available. This is a valuable service based on an enormous amount of manual labor. Even if we end up disagreeing with some of their findings, we remain deeply appreciative of their service to the community by highlighting these important issues.
We do wish disagree with the use of the term “reproducibility”, which many people associate with an independent reconstruction of the work. For instance, this paper spells out the difference between repeatability and reproducibility and provides an interesting case study.

I've already submit a dispute, where code isn't available where it was thought that it was. I plan to do a little more looking, time permitting.

Others have successfuly built projects reported as failures. I think that the community is going to help repair the results of the other study.

Combined, they're going to say much more about the state of the field!


Edited to Add: 

Looks like Dr. Krishnamurthi's effort sprung from two discussions on social media, which are worth trawling for insight: 

Source: http://cs.brown.edu/~sk/Memos/Examining-Re...

Reproducibility in CS

So, there’s a project from the University of Arizona that’s trying to investigate CS papers and see how reproducible they are.

Image from the Reproducibility in Computer Science page, retrieved&nbsp;March 19, 2014.&nbsp;

Image from the Reproducibility in Computer Science page, retrieved March 19, 2014. 

It’s a cool project. Made a pretty picture to be sure! The problem is, their pretty picture is… pretty misleading when it comes to build failures.

There’s many more like this — I took a cursory look through their results, and here’s a couple of categories:

Path setup failures:

Miscellaneous student errors:

I’m a little sad that this is what they decided to put out. Their definition of reasonable effort is

In our experiments we instructed the students to spend no more than 30 minutes on building the systems. In many cases this involved installing additional libraries and compilers, editing makefiles, etc. The students were also instructed to be liberal in their evaluations, and, if in doubt, mark systems as buildable.

Yet, as you can see above, it appears nobody actually looked at what the students said. They were taken at their word, and they were far from liberal!

Moreover, I also disagree that an undergrad given 30 minutes is a good check. Especially considering the quality of the above results.

Shaming researchers through bad methodology like this isn't going to get more people to put out code.

I love the idea of this investigation, but I don’t love the methodology.


Edited to Add:: One thing that I did love from this project was their proposal in the technical report:

Our proposal is therefore much more modest. Rather than forcing authors to make their systems available, we propose instead that every article be required to specify the level of reproducibility a reader or reviewer should expect.

This is a worthwhile baby-step in and of itself, and should probably be integrated into paper classification systems. THis would eventually provide evolutionary pressure towards reproducibility.

What Caught My Eye - Week 11

This one is going to be short and sweet. I've been sucking at keeping track this week, and sufficiently busy and burnt-out that I've not collected as much as usual.

Arts and Culture

  • The Black Hand Files:

    A few months ago, my child came in and calmly announced, "I have a friend named Black Hand. He's here right now. You can't see him."

  • William Shakespeare presents: Terminator The Second

  • Some more on John Roderick's trip to a Miley Cyrus Concert

    John Roderick explains that, contrary to his first impression, he watches the show in utter amazement, slowly understanding that Miley Cyrus is in complete control of every aspect of her career.

    The whole event was completely unironic. There was no cynicism to it. The net result was a total positivity towards the 8-10000 girls all dressed like sex workers. You realize that they are not dressing like that for the male gaze, because there are no men here. They are dressing like that for one another, for their own pleasure, and in homage to Miley, and she's dressing like that for them. And the other amazing thing was that not a single person looked at me like I was a creep. Every single girl that made eye contact with me — which was hundreds and hundreds of them — they all smiled and were like "Hi!" or "Excuse me!" I never for a moment had that feeling of "Omg, What are you doing here?" That was absent from the place.

What Caught My Eye - Week 10

Diversity, Culture, Feminism

  • "When a pipeline leaks, we don't blame the water" is a key theme of this piece by Frances Hocutt, describing how she left her love, chemsistry. This piece, and the next are from a fantastic looking magazine, Model View Culture, which looks to be filled with interesting writing.

    So, someone you know is considering leaving a STEM field and you wish she wouldn't, or you vaguely wish she felt more supported in her current position. You have opinions about the proverbial leaky pipeline. You're sad or angry that you'll be the only woman in the lab once your coworker leaves. You're frustrated that your brilliant, driven mentee quit her job and left the field. You want to get more women in STEM, so you focus your efforts on trying to recruit new women and girls. You're recognized for your outreach efforts -- and your colleague's going-away lunch takes you by surprise.

    So. What can you do?

    You can recognize that our choices to leave are rational decisions that demonstrate self-knowledge and self-respect. We have weighed whether we love the work more than we hate the context we do it in. You can accept our analysis and respect our agency, and not try to convince us that you know better or that we should have worked (even) harder. If you’re part of a majority and we are not, you can acknowledge that we've probably already worked harder than you have to get to the same place.

  • Quantify Everything: A Dream of a Feminist Data Future talks about a historical view of data, and how the definition is changing.

    “Data” has historically been a neglected byproduct of action and interaction, and looking after it has been less a priority than an accident. That data has taken on masculine and technologically essential attributes in recent years is a testament to how quickly and pervasively market semantics can work. For centuries, collecting, caretaking, curating and analyzing data has been the domain of women’s work—look at the histories of librarianship, nursing and programming.

  • TRIGGER WARNING: This is an article about the insidious spread of trigger warnings

    Trigger warnings are presented as a gesture of empathy, but the irony is they lead only to more solipsism, an over-preoccupation with one’s own feelings—much to the detriment of society as a whole. Structuring public life around the most fragile personal sensitivities will only restrict all of our horizons. Engaging with ideas involves risk, and slapping warnings on them only undermines the principle of intellectual exploration. We cannot anticipate every potential trigger—the world, like the Internet, is too large and unwieldy. But even if we could, why would we want to? Bending the world to accommodate our personal frailties does not help us overcome them.

Art and News

Just what it says, guy turns himself into a haybale