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>"); | |
char *p2 = strcasestr(sonosResponse,"</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>"); | |
p2 = strcasestr(sonosResponse,"</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>"); | |
p2 = strcasestr(sonosResponse,"</upnp:album>"); | |
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."); | |
} | |
} |
This comment has been minimized.
This comment has been minimized.
which library? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
TCPClient client; error