Create a gist now

Instantly share code, notes, and snippets.

int LED = D1;
int PR = A0; // photoresistor port
int BUTTON = D0; // button port
bool bright;
bool pressed;
bool playing;
int brightness = 0; // to store the current brightness
// Sonos stuff grabbed from Hover_particle
// Set to IP of your Sonos player
byte sonosip[] = { 192, 168, 0, 217 };
#define SOAP_HEADER "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"><s:Body>"
#define SOAP_FOOTER "</s:Body></s:Envelope>\r\n"
#define SONOS_PAUSE "<u:Pause xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:Pause>"
#define SONOS_PLAY "<u:Play xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID><Speed>1</Speed></u:Play>"
#define SONOS_NEXT "<u:Next xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:Next>"
#define SONOS_PREVIOUS "<u:Previous xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:Previous>"
#define SONOS_SETVOLUME_HEADER "<u:SetVolume xmlns:u=\"urn:schemas-upnp-org:service:RenderingControl:1\"><InstanceID>0</InstanceID><Channel>Master</Channel><DesiredVolume>"
#define SONOS_SETVOLUME_FOOTER "</DesiredVolume></u:SetVolume></s:Body></s:Envelope>"
#define SONOS_TRANSPORT_INFO "<u:GetPositionInfo xmlns:u=\"urn:schemas-upnp-org:service:AVTransport:1\"><InstanceID>0</InstanceID></u:GetPositionInfo>"
#define SONOS_GETVOLUME "<u:GetVolume xmlns:u=\"urn:schemas-upnp-org:service:RenderingControl:1\"><InstanceID>0</InstanceID><Channel>Master</Channel></u:GetVolume>"
#define PAUSE 0
#define PLAY 1
#define NEXT 2
#define PREVIOUS 3
#define VOLUME 4
#define TRANSPORTINFO 5
#define GETVOLUME 6
TCPClient client;
unsigned long timeout;
int sonosVolume;
char songTitle[32];
char songArtist[32];
char songVolume[12];
void setup() {
pinMode(LED, OUTPUT);
pinMode(PR, INPUT);
pinMode(BUTTON, INPUT);
digitalWrite(LED, LOW);
//check environment and set bright accordingly
if(analogRead(PR)>=2000) bright=true;
else bright=false;
//set pressed state
if(digitalRead(BUTTON)==HIGH) pressed=true;
else pressed=false;
Particle.function("led", ledToggler);
Particle.variable("brightness", &brightness, INT);
//pause Sonos
playing=false;
sonos(PAUSE);
}
void loop() {
brightness=analogRead(PR);
if(digitalRead(BUTTON)==HIGH && !pressed) {
Particle.publish("button pressed", NULL);
pressed=true;
// toggle between PLAY and PAUSE when button is pressed
if(!playing) {
sonos(PLAY);
playing=true;
} else {
sonos(PAUSE);
playing=false;
}
} else if(digitalRead(BUTTON)==LOW && pressed) {
pressed=false;
}
if(brightness >= 2000 && !bright) {
Particle.publish("lights on", String(brightness), 60, PRIVATE);
bright=true;
}
else if(brightness < 2000 && bright) {
Particle.publish("lights out", String(brightness), 60, PRIVATE);
bright=false;
}
delay(1000);
}
int ledToggler(String command) {
if(command=="on") {
digitalWrite(LED, HIGH);
return 1;
}
else if(command=="off") {
digitalWrite(LED, LOW);
return 0;
}
else
{
return -1;
}
}
void out(const char *s)
{
client.write( (const uint8_t*)s, strlen(s) );
}
void sonos(int cmd)
{
char buf[512];
char soapmsg[1024];
char cmdtag[20];
sonosVolume = 35;
if (client.connect(sonosip, 1400)) {
switch (cmd) {
case PAUSE:
sprintf(soapmsg, "%s%s%s", SOAP_HEADER, SONOS_PAUSE, SOAP_FOOTER);
strcpy(cmdtag, "Pause");
break;
case PLAY:
sprintf(soapmsg, "%s%s%s", SOAP_HEADER, SONOS_PLAY, SOAP_FOOTER);
strcpy(cmdtag, "Play");
break;
case NEXT:
sprintf(soapmsg, "%s%s%s", SOAP_HEADER, SONOS_NEXT, SOAP_FOOTER);
strcpy(cmdtag, "Next");
break;
case PREVIOUS:
sprintf(soapmsg, "%s%s%s", SOAP_HEADER, SONOS_PREVIOUS, SOAP_FOOTER);
strcpy(cmdtag, "Previous");
break;
case VOLUME:
sprintf(soapmsg, "%s%s%i%s", SOAP_HEADER, SONOS_SETVOLUME_HEADER, sonosVolume, SONOS_SETVOLUME_FOOTER);
strcpy(cmdtag, "SetVolume");
break;
case TRANSPORTINFO:
sprintf(soapmsg, "%s%s%s", SOAP_HEADER, SONOS_TRANSPORT_INFO, SOAP_FOOTER);
strcpy(cmdtag, "GetPositionInfo");
break;
case GETVOLUME:
sprintf(soapmsg, "%s%s%s", SOAP_HEADER, SONOS_GETVOLUME, SOAP_FOOTER);
strcpy(cmdtag, "GetVolume");
break;
}
if (String(cmdtag) == "SetVolume" || String(cmdtag) == "GetVolume") {
out("POST /MediaRenderer/RenderingControl/Control HTTP/1.1\r\n");
} else {
out("POST /MediaRenderer/AVTransport/Control HTTP/1.1\r\n");
}
sprintf(buf, "Host: %d.%d.%d.%d:1400\r\n", sonosip[0], sonosip[1], sonosip[2], sonosip[3]);
out(buf);
sprintf(buf, "Content-Length: %d\r\n", strlen(soapmsg));
out(buf);
out("Content-Type: text/xml; charset=\"utf-8\"\r\n");
if (String(cmdtag) == "SetVolume" || String(cmdtag) == "GetVolume") {
sprintf(buf, "Soapaction: \"urn:schemas-upnp-org:service:RenderingControl:1#%s\"\r\n", cmdtag);
} else {
sprintf(buf, "Soapaction: \"urn:schemas-upnp-org:service:AVTransport:1#%s\"\r\n", cmdtag);
}
out(buf);
out("\r\n");
out(soapmsg);
/*wait 1s for timeout*/
timeout = millis();
while ((!client.available()) && ((millis() - timeout) < 1000));
int i = 0;
char sonosResponse[3072];
while (client.available()) {
char c = client.read();
Serial.print(c);
if (String(cmdtag) == "GetPositionInfo" || String(cmdtag) == "GetVolume") {
sonosResponse[i] = c;
Serial.print(sonosResponse[i]); //This line prints the entire response
i++;
}
}
if (String(cmdtag) == "GetPositionInfo") {
sonosResponse[i] = '\0';
/* Get the song title */
char *p1 = strcasestr(sonosResponse,"dc:title&gt;");
char *p2 = strcasestr(sonosResponse,"&lt;/dc:title");
int c = 0;
for (p1 = p1 + 12; p1 != p2; p1++) {
songTitle[c] = *p1;
c++;
}
songTitle[c] = '\0';
Serial.println(songTitle);
/* Get the Artist */
p1 = strcasestr(sonosResponse,"dc:creator&gt;");
p2 = strcasestr(sonosResponse,"&lt;/dc:creator");
c = 0;
for (p1 = p1 + 14; p1 != p2; p1++) {
songArtist[c] = *p1;
c++;
}
songArtist[c] = '\0';
Serial.println(songArtist);
/* Get the Album */
/*p1 = strcasestr(sonosResponse,";upnp:album&gt;");
p2 = strcasestr(sonosResponse,"&lt;/upnp:album&gt");
c = 0;
for (p1 = p1 + 15; p1 != p2; p1++) {
songAlbum[c] = *p1;
c++;
}
songAlbum[c] = '\0';
Serial.println(songAlbum);*/
} else if (String(cmdtag) == "GetVolume") {
sonosResponse[i] = '\0';
char *p1 = strcasestr(sonosResponse,"<CurrentVolume>");
char *p2 = strcasestr(sonosResponse,"</CurrentVolume>");
int c = 0;
for (p1 = p1 + 15; p1 != p2; p1++) {
songVolume[c] = *p1;
c++;
}
songVolume[c] = '\0';
Serial.println(songVolume);
sscanf(songVolume, "%d", &sonosVolume);
Serial.println(sonosVolume);
}
//while (client.available()) client.read();
//delay(100);
client.stop();
} else {
Serial.println("Not yet connected to Sonos.");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment