Friday, January 17, 2014

Using REST for communication between AVR and Linux

I changed my code on my previous post to use REST as a way to communicate between Arduino and Linux. REST is basically a web server running on the linux side which allows access to key/value pairs via web or through serial from Arduino. In particular I am using this now for sending the info about the song that is playing. From my python script I am calling curl to POST the info to the REST website and from Arduino I am doing Bridge.get calls to receive the data.

Here is the new python script:


from __future__ import print_function
import urllib
import urllib2
import subprocess
import sys

from grooveshark import Client
from grooveshark.classes import Radio

client = Client()
client.init()
cmdargs = str(sys.argv)

url_name='http://localhost/data/put/songName/'
url_artist='http://localhost/data/put/songArtist/'
url_album='http://localhost/data/put/songAlbum/'

for song in client.radio(sys.argv[1]):
    
    song_name = unicode(song.name).encode("utf-8")
    song_artist_name = unicode(song.artist.name).encode("utf-8")
    song_album_name = unicode(song.album.name).encode("utf-8")


    print(song_name)
    print(song_artist_name)
    print(song_album_name)

    url_name_curl = url_name + urllib.quote(song_name)
    urllib2.urlopen(url_name_curl)
    url_artist_curl = url_artist + urllib.quote(song_artist_name)
    urllib2.urlopen(url_artist_curl)
    url_album_curl = url_album + urllib.quote(song_album_name)
    urllib2.urlopen(url_album_curl)

    sys.stdout.flush()
    subprocess.call(['mpg123', song.stream.url])


UPDATE:
There is a pycurl library that I could have used instead (and there seem to be other alternatives, I am just not a python expert), but this seemed quicker to implement at the time. Will find an alternative... 
I am using urllib2 to do the POST requests to the REST website. Originally I was using curl (running it in a subprocess) but urllib2 avoids calling a separate process.
Important thing is to remember calling urllib.quote on the text to POST, as you will need to convert special characters to "%XX" to make it a valid URL.

On the Arduino side I am only getting the song name, but it is enough to get the idea of how this is done. This is how my sketch looks like now:


#include <FileIO.h>

#define    GENRE_NONE             0
#define    GENRE_ROCK             12
#define    GENRE_BLUES            230
#define    GENRE_ELECTRONICA      67
#define    GENRE_CLASSICROCK      3529
#define    GENRE_INDIE            136
#define    GENRE_METAL            17


int stations[] = { GENRE_NONE,
    GENRE_ROCK,
    GENRE_BLUES,
    GENRE_ELECTRONICA,
    GENRE_CLASSICROCK,
    GENRE_INDIE,
    GENRE_METAL };

int genres;
int val = 0;
int prevVal = 0;
Process radio_process;
String label;

void setup() {
  genres = sizeof(stations)/sizeof(int);
  Bridge.begin();
  Serial.begin(9600);

  while(!Serial);  // wait for Serial port to connect.
  Serial.println("Grooveshark Radio example");

  start_radio(val);  
}

void loop() {
  val = analogRead(3);
  val = (val*genres)/1023;

  
  if(val != prevVal) {
    String text;
    text = "Value: ";
    text += val;
    Serial.println(text);

    start_radio(val);
    
    prevVal = val;
  }
// removed old code to print the output of the script: 
/*
  while(radio_process.available() > 0){
    char c = radio_process.read();
    Serial.print(c);
  }
*/
  char labelbuffer[256];
  Bridge.get("songName", labelbuffer, 256); 

  if (String(labelbuffer).length() > 0 && label != String(labelbuffer)){
    label = String(labelbuffer);
    
    Serial.println(label);

  }
  
  
  delay(400);
}

void start_radio(int val) {
    String parameter = "";
    radio_process.close();
    Process killer;
    killer.begin("killall");
    killer.addParameter("mpg123");
    killer.run();
    if(stations[val] != 0) {
      radio_process.begin("python");
      radio_process.addParameter("/root/examples-pygrooveshark/radio_mpg123.py");
      parameter+= stations[val];
      radio_process.addParameter(parameter);
      radio_process.runAsynchronously();
    }
    else {
      radio_process.begin("echo");
      radio_process.addParameter("Do Nothing!!!");
      radio_process.runAsynchronously();
    }
}

No comments:

Post a Comment