GroveStreams is a helper class to assist with pushing data into the GroveStreams.com IoT platform.

Dependents:   GroveStreams-Temp

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers GroveStreams.cpp Source File

GroveStreams.cpp

00001 /*
00002  GroveStreams is a helper class to assist with pushing data into the
00003   GroveStreams.com IoT platform.
00004   
00005  License:
00006   Copyright (C) 2017 GroveStreams LLC.
00007   Licensed under the Apache License, Version 2.0 (the "License");
00008   you may not use this file except in compliance with the License.
00009   You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
00010 
00011   Unless required by applicable law or agreed to in writing, software
00012   distributed under the License is distributed on an "AS IS" BASIS,
00013   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014   See the License for the specific language governing permissions and
00015   limitations under the License.
00016 */
00017 
00018 #include "GroveStreams.h"
00019 
00020 GroveStreams::GroveStreams(const char* apiKey, LcdDiscoF746NgTracer* pLcd)
00021 {
00022     init(apiKey, pLcd);
00023 }
00024 
00025 GroveStreams::GroveStreams(const char* apiKey)
00026 {
00027     init(apiKey, NULL);
00028 }
00029 
00030 GroveStreams::~GroveStreams() {
00031     _eth.disconnect();
00032 }
00033 
00034 int GroveStreams::init(const char* apiKey, LcdDiscoF746NgTracer* pLcd)
00035 {
00036     _domain = "grovestreams.com";
00037     _port = 80;
00038     _apiKey = apiKey;
00039     _myIPAddress = NULL;  //Don't Change. Set below from DHCP. Needed by GroveStreams to verify that a device is not uploading more than once every 10s.
00040     _pLcd = pLcd;
00041 
00042     return startEthernet();
00043 }
00044 
00045 void GroveStreams::printf(const char* format, ...)
00046 {
00047 
00048     va_list args;
00049     va_start(args, format);
00050 
00051     if (_pLcd != NULL) {
00052         char sbuffer[512];
00053         vsprintf(sbuffer, format, args);
00054         _pLcd->println(sbuffer);
00055     } else {
00056         vprintf(format, args);
00057     }
00058 
00059     va_end(args);
00060 }
00061 
00062 unsigned long GroveStreams::send(const char* componentId, const char* samples)
00063 {
00064     char resultBuffer[256]= {0};
00065     return send(componentId, samples, NULL, NULL, resultBuffer, sizeof resultBuffer);
00066 }
00067 
00068 unsigned long GroveStreams::send(const char* componentId, const char* samples, char* resultBuffer, size_t resultBufferSize)
00069 {
00070     return send(componentId, samples, NULL, NULL, resultBuffer, resultBufferSize);
00071 }
00072    
00073 unsigned long GroveStreams::send(const char* componentId, const char* samples, const char* componentName, 
00074                                  const char* compTmplId, char* resultBuffer, size_t resultBufferSize)
00075 {
00076     int failedCounter = 0;
00077     int result = 1;
00078 
00079     while (failedCounter < 3 && result != 0) {
00080         
00081         result = sendNoRetry(componentId, samples, componentName, compTmplId, resultBuffer, resultBufferSize);
00082         
00083         this->printf("send result code: %d", result);
00084         
00085         if (result != 0) {
00086             //Wait and try again
00087             failedCounter++;
00088             this->printf("send failed %d times", failedCounter);
00089             wait(2);
00090         }
00091 
00092         if (failedCounter > 3 ) {
00093             this->printf("Too many failures. Restarting Ethernet.");
00094             startEthernet();
00095         }
00096     }
00097 
00098     return result;
00099 }
00100 
00101 unsigned long GroveStreams::sendNoRetry(const char* componentId, const char* samples, const char* componentName, 
00102                                         const char* compTmplId, char* resultBuffer, size_t resultBufferSize)
00103 {
00104     //Assemble the url that is used to pass the temperature readings to GroveStreams and call it
00105 
00106     network::tcp::Socket socket;
00107 
00108     int openResult = socket.open();
00109     if (openResult == 0) {
00110 
00111         int connResult = socket.connect(_domain, _port);
00112         if(connResult == 0) {
00113 
00114             char compNamePart[100] = {0};
00115             if (strlen(componentName) > 0) {
00116                 sprintf(compNamePart, "&compName=%s",componentName);
00117             }
00118 
00119             char compTmplIdPart[100] = {0};
00120             if (strlen(compTmplId) > 0) {
00121                 sprintf(compTmplIdPart, "&compTmplId=%s",compTmplId);
00122             }
00123 
00124             //You may need to increase the size of sbuffer if any other char array sizes have increased
00125             char sbuffer[512]= {0};
00126 
00127             sprintf(sbuffer, "PUT /api/feed?compId=%s%s%s&api_key=%s%s HTTP/1.1\r\nHost: \r\nConnection: close\r\nX-Forwarded-For:%s\r\n\r\n",
00128                     componentId, compTmplIdPart, compNamePart, _apiKey, samples, _myIPAddress);
00129 
00130             this->printf("send sbuffer size: %d", strlen(sbuffer));
00131 
00132             int scount = socket.write(sbuffer, strlen(sbuffer));
00133             this->printf("sent %d bytes: [%.*s]", scount, strstr(sbuffer, "\r\n")-sbuffer, sbuffer);
00134 
00135             //Read status line
00136             
00137             int rcount = socket.read(resultBuffer, resultBufferSize);
00138 
00139             this->printf("HTTP Response size: %d bytes", rcount);
00140             this->printf("HTTP Response Status:[%.*s]", strstr(resultBuffer, "\r\n")-resultBuffer, resultBuffer);
00141             
00142             //Only return the body
00143             strcpy(resultBuffer, strstr(resultBuffer, "\r\n\r\n") + strlen("\r\n\r\n"));
00144             strcat(resultBuffer, "\0");
00145             this->printf("HTTP Body: [%s]", resultBuffer);
00146             
00147             socket.close();
00148         } else {
00149 
00150             this->printf("Socket Connect Failed: %d", connResult);
00151         }
00152 
00153     } else {
00154         this->printf("Socket Open Failed: %d", openResult);
00155         socket.close();
00156         return 1;
00157     }
00158 
00159     return 0;
00160 }
00161 
00162 
00163 int GroveStreams::startEthernet()
00164 {
00165     //Start or restart the Ethernet connection.
00166     int result = _eth.disconnect();
00167     if (result != 0) {
00168         this->printf("Ethernet diconnect Failed: %d", result);
00169         return result;
00170     }
00171 
00172     this->printf("Connecting STM32 to network...");
00173 
00174     //Connect to the network and obtain an IP address using DHCP
00175     result = _eth.init();
00176     if (result != 0) {
00177         this->printf("Ethernet init Failed: %d", result);
00178         return result;
00179     }
00180 
00181     result = _eth.connect();
00182     if (result != 0) {
00183         this->printf("Ethernet connect Failed: %d", result);
00184         return result;
00185     } else {
00186         this->printf("STM32 connected to network");
00187 
00188         //Set the mac and ip variables so that they can be used during sensor uploads later
00189         _myIPAddress = _eth.getIPAddress();
00190 
00191         this->printf("IP address: %s", _myIPAddress ? _myIPAddress : "No IP");
00192     }
00193 
00194     return 0;
00195 }
00196 
00197 const char* GroveStreams::getMACAddress()
00198 {
00199     return _eth.getMACAddress();
00200 }