Hardware components | ||||||
| × | 1 | ||||
Software apps and online services | ||||||
|
So you're biking or running along when the SLOWEST song starts playing on Spotify. Then you have to stop, change songs, and get back into your rhythm until it happens again.
With the BPMBiker, your GPS and speed are automatically logged with the LinkedItOne and uploaded to an Azure Mobile Service where they are stored in a database. An Azure WebJob there can check your average speed for the last few seconds of each song and then launch a Spotify playlist with the appropriate beats per minute for your pace. (WebJob to launch playlist still under development)
GPSSpeed for LinkItONE
C/C++Log and upload GPS and speed data from your LinkItONE to an Azure Mobile Service over WiFi
#include <LWiFi.h>
#include <LWiFiClient.h>
#include <LWiFiServer.h>
#include <SPI.h>
#include <LGPS.h>
gpsSentenceInfoStruct info;
char buff[256];
double lat;
double lon;
double spd;
String dataString;
const char *server = "your-service.azure-mobile.net";
const char *table_name = "your-table-name";
const char *ams_key = "your-application-key";
#define WIFI_AP "your-SSID"
#define WIFI_PASSWORD "your-wifi-password"
#define WIFI_AUTH LWIFI_WPA // choose from LWIFI_OPEN, LWIFI_WPA, or LWIFI_WEP.
LWiFiClient client;
char buffer[64];
void send_request()
{
Serial.println("\nconnecting...");
if(client.connect(server, 80)){
Serial.print("sending");
// POST URI
sprintf(buffer, "POST /tables/%s HTTP/1.1", table_name);
client.println(buffer);
// Host header
sprintf(buffer, "Host: %s", server);
client.println(buffer);
// Azure Mobile Services application key
sprintf(buffer, "X-ZUMO-APPLICATION: %s", ams_key);
client.println(buffer);
// JSON content type
client.println("Content-Type: application/json");
// POST body
sprintf(buffer, "{\"latitude\": %f, \"longitude\": %f, \"speed\": %f}", lat, lon, spd);
Serial.println(buffer);
// Content length
client.print("Content-Length: ");
client.println(strlen(buffer));
// End of headers
client.println();
// Request body
Serial.println(buffer);
client.println(buffer);
} else{
Serial.println("connection failed");
}
}
void wait_response()
{
while(!client.available()){
if (!client.connected()) {
return;
}
}
}
void read_response()
{
bool print = true;
while (client.available()){
char c = client.read();
if (c=='\n')
print = false;
if (print)
Serial.print(c);
}
}
void end_request()
{
client.stop();
}
static unsigned char getComma(unsigned char num,const char *str)
{
unsigned char i,j = 0;
int len=strlen(str);
for(i = 0;i < len;i ++)
{
if(str[i] == ',')
j++;
if(j == num)
return i + 1;
}
return 0;
}
static double getDoubleNumber(const char *s)
{
char buf[10];
unsigned char i;
double rev;
i=getComma(1, s);
i = i - 1;
strncpy(buf, s, i);
buf[i] = 0;
rev=atof(buf);
return rev;
}
static double getIntNumber(const char *s)
{
char buf[10];
unsigned char i;
double rev;
i=getComma(1, s);
i = i - 1;
strncpy(buf, s, i);
buf[i] = 0;
rev=atoi(buf);
return rev;
}
void parseGPRMC(const char* GPRMCstr)
{
/* Refer to http://www.gpsinformation.org/dale/nmea.htm#RMC
* Sample data: $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A
Where:
RMC Recommended Minimum sentence C
123519 Fix taken at 12:35:19 UTC
A Status A=active or V=Void.
4807.038,N Latitude 48 deg 07.038' N
01131.000,E Longitude 11 deg 31.000' E
022.4 Speed over the ground in knots
084.4 Track angle in degrees True
230394 Date - 23rd of March 1994
003.1,W Magnetic Variation
*6A The checksum data, always begins with *
*/
int tmp, hour, minute, second, date, num ;
if(GPRMCstr[0] == '$')
{
tmp = getComma(1, GPRMCstr);
hour = (GPRMCstr[tmp + 0] - '0') * 10 + (GPRMCstr[tmp + 1] - '0');
minute = (GPRMCstr[tmp + 2] - '0') * 10 + (GPRMCstr[tmp + 3] - '0');
second = (GPRMCstr[tmp + 4] - '0') * 10 + (GPRMCstr[tmp + 5] - '0');
sprintf(buff, "UTC timer %2d-%2d-%2d", hour, minute, second);
Serial.println(buff);
tmp = getComma(3, GPRMCstr);
lat = getDoubleNumber(&GPRMCstr[tmp]);
tmp = getComma(5, GPRMCstr);
lon = getDoubleNumber(&GPRMCstr[tmp]);
sprintf(buff, "latitude = %10.4f, longitude = %10.4f", lat, lon);
Serial.println(buff);
tmp = getComma(7, GPRMCstr);
spd = getDoubleNumber(&GPRMCstr[tmp]);
sprintf(buff, "speed = %f", spd);
Serial.println(buff);
}
else
{
Serial.println("Not get data");
}
}
void setup() {
// put your setup code here, to run once:
LWiFi.begin();
Serial.begin(115200);
while(!Serial);
Serial.println("Wifi Power on...");
while (0 == LWiFi.connect(WIFI_AP, LWiFiLoginInfo(WIFI_AUTH, WIFI_PASSWORD)))
{
Serial.println("wifi failed");
delay(1000);
}
LGPS.powerOn();
Serial.println("LGPS Power on, and waiting ...");
delay(3000);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println("LGPS loop");
LGPS.getData(&info);
Serial.println((char*)info.GPRMC);
parseGPRMC((const char*)info.GPRMC);
send_request();
wait_response();
read_response();
end_request();
delay(2000);
}
Thanks to Mohamed Fadiga and Thomas Conte.
Comments