Advertisement
mikecmills2

GroveStreams Arduino Ethernet

Oct 6th, 2013
11,908
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.93 KB | None | 0 0
  1. /*
  2.  
  3.  Arduino GroveStreams Stream Feed via Ethernet
  4.  
  5.  The GroveStreams client sketch is designed for the Arduino and Ethernet.
  6.  A full "how to" guide for this sketh can be found at https://www.grovestreams.com/developers/getting_started_arduino_temp.html
  7.  This sketch updates several stream feeds with an analog input reading,
  8.  from a temperature probe, via the GroveStreams API: https://www.grovestreams.com/developers/api.html
  9.  The Arduino uses DHCP and DNS for a simpler network setup.
  10.  The sketch also includes Internet Connection Reset logic to ensure the
  11.  Arduino stays connected and can regain connectivity after a network outage.
  12.  Use the Serial Monitor on the Arduino IDE to see verbose network feedback
  13.  and the GroveStreams connectivity status.
  14.  
  15.  License:
  16.   Copyright 2014 GroveStreams LLC.
  17.   Licensed under the Apache License, Version 2.0 (the "License");
  18.   you may not use this file except in compliance with the License.
  19.   You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
  20.  
  21.   Unless required by applicable law or agreed to in writing, software
  22.   distributed under the License is distributed on an "AS IS" BASIS,
  23.   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  24.   See the License for the specific language governing permissions and
  25.   limitations under the License.
  26.  
  27.  GroveStreams Setup:
  28.  
  29.  * Sign Up for Free User Account - https://www.grovestreams.com
  30.  * Create a GroveStreams organization while selecting the Arduino blueprint
  31.  * Enter a unique MAC Address for this network in this sketch under "Local Network Settings"
  32.  *    (Newer shields have the mac address on a sticker on the shield. Use that.)
  33.  *    (A MAC address can also be generated within a GroveStreams organization: Tools toolbar button - Generate MAC Address)
  34.  *    (The MAC address is used to identify this device within GroveStreams. It must be unique within your GS organization)
  35.  * Enter your GroveStreams secret api key under "GroveStreams Settings" in this sketch  
  36.  *    (The api key can be retrieved from within a GroveStreams organization: click the Api Keys toolbar button,
  37.  *     select your Api Key, and click View Secret Key. Paste the Secret Key below)
  38.  
  39.  Arduino Requirements:
  40.  
  41.  * Arduino with Ethernet Shield or Arduino Ethernet
  42.  * Arduino 1.0 IDE
  43.  
  44.  Network Requirements:
  45.  
  46.  * Ethernet port on Router    
  47.  * DHCP enabled on Router
  48.  * Unique MAC Address for Arduino
  49.  
  50.  Additional Credits:
  51.  Example sketches from Arduino team, Ethernet by David A. Mellis
  52.  Sketch review and advice from Arduino enthusiast and expert David Thompson, http://www.desert-home.com/
  53.  */
  54.  
  55. #include <SPI.h>
  56. #include <Ethernet.h>
  57.  
  58.  
  59.  
  60. // Local Network Settings
  61. byte mac[] = {
  62.   0x90, 0xA2, 0xDA, 0x0E, 0x60, 0xA3 };  // Change this!!! Must be unique on local network.
  63.                                          // Look for a sticker on the back of your Ethernet shield.
  64.  
  65. // GroveStreams Settings
  66. char gsApiKey[] = "YOUR_SECRET_API_KEY_HERE";   //Change This!!!
  67. char gsComponentName[] = "Temperature";        //Optionally change. Set this to give your component a name when it initially registers.
  68.  
  69. char gsDomain[] = "grovestreams.com";   //Don't change. The GroveStreams domain.
  70. char gsComponentTemplateId[] = "temp";  //Don't change. Tells GS what template to use when the feed initially arrives and a new component needs to be created.
  71.                                         // The blueprint is expecting "temp".
  72.  
  73. //GroveStreams Stream IDs. Stream IDs tell GroveStreams which component streams the values will be assigned to.
  74. //Don't change these unless you edit your GroveStreams component definition and change the stream IDs to match these.
  75. char gsStreamId1[] = "s1";   //Don't change. Temp C.
  76. char gsStreamId2[] = "s2";   //Don't change. Temp F.
  77.  
  78. // Other Settings
  79. const unsigned long updateFrequency = 20000UL;    // Update frequency in milliseconds (20000 = 20 seconds). Change this to change your sample frequency.
  80.  
  81. const int temperaturePin = 0;          // You might need to change depending on the Pin you are using. The Temperature pin number.    
  82. char samples[35];                      // Change this buffer size only if you increase or decrease the size of samples being uploaded.
  83.  
  84. char myIPAddress[20];  //Don't Change. Set below from DHCP. Needed by GroveStreams to verify that a device is not uploading more than once every 10s.
  85. char myMac[20];        //Don't Change. Set below from the above mac variable. The readable Mac is used by GS to determine which component the
  86.                        // feeds are uploading into. It must match an existing GroveStreams component's ID
  87.  
  88. unsigned long lastSuccessfulUploadTime = 0; //Don't change. Used to determine if samples need to be uploaded.
  89. int failedCounter = 0;                      //Don't change. Used for Internet Connection Reset logic
  90.  
  91. // Initialize Arduino Ethernet Client
  92. EthernetClient client;
  93.  
  94.  
  95. void setup()
  96. {
  97.   // Start Serial for debugging on the Serial Monitor
  98.   Serial.begin(9600);
  99.  
  100.   // Start Ethernet on Arduino
  101.   startEthernet();
  102. }
  103.  
  104. void loop()
  105. {
  106.  
  107.   // Update sensor data to GroveStreams
  108.   if(millis() - lastSuccessfulUploadTime > updateFrequency)
  109.   {
  110.     updateGroveStreams();
  111.   }
  112.  
  113. }
  114.  
  115. void updateGroveStreams()
  116. {
  117.   //Assemble the url that is used to pass the temperature readings to GroveStreams and call it
  118.   unsigned long connectAttemptTime = millis();
  119.  
  120.   if (client.connect(gsDomain, 80))
  121.   {        
  122.    
  123.     //You may need to increase the size of urlBuf if any other char array sizes have increased
  124.     char urlBuf[175];
  125.  
  126.     sprintf(urlBuf, "PUT /api/feed?compTmplId=%s&compId=%s&compName=%s&api_key=%s%s HTTP/1.1",
  127.            gsComponentTemplateId, myMac, gsComponentName, gsApiKey, getSamples());
  128.        
  129.     //Uncomment the next three lines for debugging purposes
  130.     Serial.println(urlBuf);    
  131.     //Serial.print(F("urlBuf length = "));
  132.     //Serial.println(strlen(urlBuf));
  133.      
  134.     client.println(urlBuf);  //Send the url with temp readings in one println(..) to decrease the chance of dropped packets
  135.     client.print(F("Host: "));
  136.     client.println();
  137.     client.println(F("Connection: close"));
  138.     client.print(F("X-Forwarded-For: "));     //Include this line and the next line if you have more than one device uploading behind
  139.     client.println(myIPAddress);              // your outward facing router (avoids the GS 10 second upload rule)
  140.     client.println(F("Content-Type: application/json"));
  141.    
  142.     client.println();
  143.  
  144.  
  145.     if (client.connected())
  146.     {
  147.            
  148.       //Begin Report Response
  149.       while(!client.available())
  150.       {
  151.         delay(1);
  152.       }
  153.  
  154.       while(client.available())
  155.       {
  156.         char c = client.read();
  157.         Serial.print(c);
  158.       }
  159.       //End Report Response
  160.      
  161.       //Client is now disconnected; stop it to cleannup.
  162.       client.stop();
  163.    
  164.       lastSuccessfulUploadTime = connectAttemptTime;
  165.       failedCounter = 0;
  166.     }
  167.     else
  168.     {
  169.       handleConnectionFailure();
  170.     }
  171.  
  172.   }
  173.   else
  174.   {
  175.      handleConnectionFailure();
  176.   }
  177.  
  178. }
  179.  
  180. void handleConnectionFailure() {
  181.   //Connection failed. Increase failed counter
  182.   failedCounter++;
  183.  
  184.   Serial.print(F("Connection to GroveStreams Failed "));
  185.   Serial.print(failedCounter);  
  186.   Serial.println(F(" times"));
  187.   delay(1000);
  188.      
  189.   // Check if Arduino Ethernet needs to be restarted
  190.   if (failedCounter > 3 )
  191.   {
  192.     //Too many failures. Restart Ethernet.
  193.     startEthernet();
  194.   }
  195.  
  196.  }
  197.  
  198. void startEthernet()
  199. {
  200.   //Start or restart the Ethernet connection.
  201.   client.stop();
  202.  
  203.   Serial.println(F("Connecting Arduino to network..."));
  204.   Serial.println();  
  205.  
  206.   //Wait for the connection to finish stopping
  207.   delay(2000);
  208.  
  209.   //Connect to the network and obtain an IP address using DHCP
  210.   if (Ethernet.begin(mac) == 0)
  211.   {
  212.     Serial.println(F("DHCP Failed, reset your Arduino and try again"));
  213.     Serial.println();
  214.   }
  215.   else
  216.   {
  217.     Serial.println(F("Arduino connected to network using DHCP"));
  218.  
  219.     //Set the mac and ip variables so that they can be used during sensor uploads later
  220.     Serial.print(F(" MAC: "));
  221.     Serial.println(getMacReadable());
  222.     Serial.print(F(" IP address: "));
  223.     Serial.println(getIpReadable(Ethernet.localIP()));
  224.     Serial.println();
  225.   }
  226.  
  227. }
  228.  
  229. char* getMacReadable()
  230. {
  231.   //Convert the mac address to a readable string
  232.   sprintf(myMac, "%02x:%02x:%02x:%02x:%02x:%02x\0", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  233.  
  234.   return myMac;
  235. }
  236.  
  237. char* getIpReadable(IPAddress ipAddress)
  238. {
  239.   //Convert the ip address to a readable string
  240.   unsigned char octet[4]  = {0,0,0,0};
  241.   for (int i=0; i<4; i++)
  242.   {
  243.     octet[i] = ( ipAddress >> (i*8) ) & 0xFF;
  244.   }
  245.   sprintf(myIPAddress, "%d.%d.%d.%d\0",octet[0],octet[1],octet[2],octet[3]);
  246.  
  247.   return myIPAddress;
  248. }
  249.  
  250. char* getSamples()
  251. {
  252.   //Get the temperature analog reading and convert it to a string
  253.   float voltage, degreesC, degreesF;
  254.  
  255.   voltage = (analogRead(temperaturePin) * 0.004882814);
  256.   degreesC = (voltage - 0.5) * 100.0;
  257.   degreesF = degreesC * (9.0/5.0) + 32.0;
  258.  
  259.   char tempC[15] = {0}; //Initialize buffer to nulls
  260.   dtostrf(degreesC, 12, 3, tempC); //Convert float to string
  261.  
  262.   char tempF[15] = {0}; //Initialize buffer to nulls
  263.   dtostrf(degreesF, 12, 3, tempF); //Convert float to string
  264.  
  265.   //Assemble the samples into URL parameters which are seperated with the "&" character
  266.   //
  267.   // Example: &s1=25.684&s2=78.231
  268.   sprintf(samples, "&%s=%s&%s=%s", gsStreamId1, trim(tempC), gsStreamId2, trim(tempF));
  269.  
  270.   return samples;
  271. }
  272.  
  273. char* trim(char* input)                                        
  274. {
  275.   //Trim leading and ending spaces
  276.   int i,j;
  277.   char *output=input;
  278.   for (i = 0, j = 0; i<strlen(input); i++,j++)          
  279.   {
  280.     if (input[i]!=' ')                          
  281.       output[j]=input[i];                    
  282.     else
  283.       j--;                                    
  284.   }
  285.   output[j]=0;
  286.  
  287.   return output;
  288. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement