GroveStreams

Multiple component streams from 1 code?404

Ex33 private msg quote post Address this user
Basically can I use one Arduino Sketch to create 4 components each with 2 streams in it? Been trying for quite sometime now cant seem to find a way to make it happen.

So far what I managed to get is 1 out of the 4 component streams i need with the following code

#include <SPI.h>
#include <Ethernet.h>
 
int logValue1=0;
int logValue2=0;
int logValue3=0;
int a,b,c;
 
void handleConnectionFailure();
void startEthernet();
char* getMacReadable();
char* getIpReadable(IPAddress ipAddress);
char* getSamples1();
char* getSamples2();
char* getSamples3();
char* getSamples4();
char* trim(char* input);
 
byte mac[] = {
  0x90, 0xA2, 0xDA, 0x0E, 0x60, 0xA3 };  
 
 
char gsApiKey[] = "API_KEY";  
char gsComponentName1[] = "Station1";
char gsComponentName2[] = "Station2";
char gsComponentName3[] = "Station3";
char gsComponentName4[] = "Station4";
 
char gsDomain[] = "grovestreams.com";   
char gsComponentTemplateId1[] = "Station1";  
char gsComponentTemplateId2[] = "Station2";
char gsComponentTemplateId3[] = "Station3";
char gsComponentTemplateId4[] = "Station4";                                     
 
char gsStreamId1[] = "set1";   
char gsStreamId2[] = "set2";  
char gsStreamId3[] = "set3";
char gsStreamId4[] = "set4";
char gsStreamId5[] = "set5";
char gsStreamId6[] = "set6";
char gsStreamId7[] = "set7";
char gsStreamId8[] = "set8";  
 
 
const unsigned long updateFrequency = 60000UL;   
 
char samples[35];                      
 
char myIPAddress[20];  
char myMac[20];        
 
 
unsigned long lastSuccessfulUploadTime = 0; 
int failedCounter = 0;                      
 
EthernetClient client;
 
 
void setup()
{
  pinMode (13 ,OUTPUT); //Red
  pinMode (12 ,OUTPUT); //Yellow
  pinMode (11 ,OUTPUT); //Green
  pinMode (9 ,OUTPUT);  //Red
  pinMode (8 ,OUTPUT);  //Yellow
  pinMode (7 ,OUTPUT);  //Green
  //pinMode (6, INPUT); // For switch
  pinMode(A13, INPUT); //analog
  pinMode(A12, INPUT); //analog
  pinMode(A11, INPUT); //analog
  Serial.begin(9600);
 
 
  startEthernet();
}
 
void loop()
{
  logValue1= analogRead(A13);
  logValue2= analogRead(A12);
 
  a = logValue1;
  b = logValue2;
 
  if(millis() - lastSuccessfulUploadTime > updateFrequency)
  {
    updateGroveStreams();
  }
 
}
 
void updateGroveStreams() 
{
  //Assemble the url that is used to pass the temperature readings to GroveStreams and call it
  unsigned long connectAttemptTime = millis();
 
  if (client.connect("proxy.tp.edu.sg", 80))
  {        
 
    char urlBuf[175]; 
 
    sprintf(urlBuf, "PUT http://www.grovestreams.com/api/feed?compTmplId=%s&compId=%s&compName=%s&api_key=%s%s HTTP/1.1",
           gsComponentTemplateId1, myMac, gsComponentName1, gsApiKey, getSamples1());
    sprintf(urlBuf, "PUT http://www.grovestreams.com/api/feed?compTmplId=%s&compId=%s&compName=%s&api_key=%s%s HTTP/1.1",
           gsComponentTemplateId2, myMac, gsComponentName2, gsApiKey, getSamples2());
    sprintf(urlBuf, "PUT http://www.grovestreams.com/api/feed?compTmplId=%s&compId=%s&compName=%s&api_key=%s%s HTTP/1.1",
           gsComponentTemplateId3, myMac, gsComponentName3, gsApiKey, getSamples3());
    sprintf(urlBuf, "PUT http://www.grovestreams.com/api/feed?compTmplId=%s&compId=%s&compName=%s&api_key=%s%s HTTP/1.1",
           gsComponentTemplateId4, myMac, gsComponentName4, gsApiKey, getSamples4());
 
    Serial.println(urlBuf);    
    //Serial.print(F("urlBuf length = ");
    //Serial.println(strlen(urlBuf));
 
    client.println(urlBuf);  
    client.print(F("Host:"));
    client.println();
    client.println(F("Connection: close"));
    client.print(F("X-Forwarded-For: "));     
    client.println(myIPAddress);              
    client.println(F("Content-Type: application/json"));
 
    client.println();
 
 
    if (client.connected())
    {
 
 
      while(!client.available())
      {
        delay(1);
      }
 
      while(client.available())
      {
        char c = client.read();
        Serial.print(c);
      }
 
      client.stop();
 
      lastSuccessfulUploadTime = connectAttemptTime;
      failedCounter = 0;
    }
    else
    {
      handleConnectionFailure();
    }
 
  }
  else
  {
     handleConnectionFailure();
  }
 
}
 
void handleConnectionFailure() { 
 
  failedCounter++;
 
  Serial.print(F("Connection to GroveStreams Failed "));
  Serial.print(failedCounter);  
  Serial.println(F(" times"));
  delay(1000);
 
  if (failedCounter > 3 )
  {
 
    startEthernet();
  }
 
 }
 
void startEthernet()
{
 
  client.stop();
 
  Serial.println(F("Connecting Arduino to network..."));
  Serial.println();  
 
  delay(2000);
 
  if (Ethernet.begin(mac) == 0)
  {
    Serial.println(F("DHCP Failed, reset your Arduino and try again"));
    Serial.println();
  }
  else
  {
    Serial.println(F("Arduino connected to network using DHCP"));
 
    Serial.print(F(" MAC: "));
    Serial.println(getMacReadable());
    Serial.print(F(" IP address: "));
    Serial.println(getIpReadable(Ethernet.localIP()));
    Serial.println();
  }
 
}
 
char* getMacReadable()
  {
  sprintf(myMac, "%02x:%02x:%02x:%02x:%02x:%02x�", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
 
  return myMac;
}
 
char* getIpReadable(IPAddress ipAddress)
 {
  unsigned char octet[4]  = {0,0,0,0};
  for (int i=0; i<4; i++)
  {
    octet[i] = ( ipAddress >> (i*8) ) & 0xFF;
  }
  sprintf(myIPAddress, "%d.%d.%d.%d�",octet[0],octet[1],octet[2],octet[3]);
 
  return myIPAddress;
}
 
char* getSamples1()    
{
 
  float PCV1,MFCV1; 
  int val;
 
   PCV1 = logValue1; 
   MFCV1 = logValue2;
 
  char PCa[15] = {0}; 
  dtostrf(PCV1, 12, 3,trim(PCa)); 
 
  char MFCa[15] = {0}; 
  dtostrf(MFCV1, 12, 3,trim(MFCa)); 
 
 
  sprintf(samples, "&%s=%s&%s=%s", gsStreamId1, trim(PCa),gsStreamId2, trim(MFCa)); 
 
  return samples;
}
 
char* getSamples2()
{
 
  float PCV2,MFCV2; 
  int val;
 
   PCV2 = logValue1; 
   MFCV2 = logValue2; 
 
  char PCb[15] = {0}; 
  dtostrf(PCV2, 12, 3,trim(PCb)); 
 
  char MFCb[15] = {0}; 
  dtostrf(MFCV2, 12, 3,trim(MFCb)); 
 
 
  sprintf(samples, "&%s=%s&%s=%s", gsStreamId3, trim(PCb),gsStreamId4, trim(MFCb)); // change to set 3, 4, 5, 6, 7, 8
 
  return samples;
}
 
char* getSamples3()   
{
 
  float PCV3,MFCV3; 
  int val;
 
   PCV3 = logValue1;
   MFCV3 = logValue2; 
 
  char PCc[15] = {0}; 
  dtostrf(PCV3, 12, 3,trim(PCc));
 
  char MFCc[15] = {0}; 
  dtostrf(MFCV3, 12, 3,trim(MFCc)); 
 
 
 
  sprintf(samples, "&%s=%s&%s=%s", gsStreamId5, trim(PCc),gsStreamId6, trim(MFCc)); // change to set 3, 4, 5, 6, 7, 8
 
  return samples;
}
 
char* getSamples4() //change no 2 ,3 ,4   
{
 
  float PCV4,MFCV4; 
  int val;
 
   PCV4 = logValue1; 
   MFCV4 = logValue2; 
 
  char PCd[15] = {0}; 
  dtostrf(PCV4, 12, 3,trim(PCd)); 
 
  char MFCd[15] = {0};
  dtostrf(MFCV4, 12, 3,trim(MFCd)); 
 
  sprintf(samples, "&%s=%s&%s=%s", gsStreamId7, trim(PCd),gsStreamId8, trim(MFCd));
 
  return samples;
}
 
char* trim(char* input)                        
{
 
  int i,j;
  char *output=input;
  for (i = 0, j = 0; i<strlen(input); i++,j++)          
  {
    if (input[i]!=' ')                          
      output[j]=input[i];                    
    else
      j--;                                    
  }
  output[j]=0;
 
  return output;
 
    }


This was edited from the code found in a arduino quick start tutorial found on the site.
Post 1 IP   flag post
MikeMills private msg quote post Address this user
I don't believe your code is making one HTTP call. It is trying to append all of the URLs together and make a single call. So your'e ending up with one big ugly URL that the internet can't understand.

You either need to change the code so that you're making four separate internet calls (create four updateGroveStreams() functions; one for each URL) or you can do one call by using our API that passes data as JSON within the HTTP body. Use this API. You don't need to pass the time; GS will set it for you.

You might not have enough memory for the first technique above, but give it a try. The second technique will be challenging for programming novice.
Post 2 IP   flag post
Ex33 private msg quote post Address this user
Alright. Thanks. Will give it a try when I can
Post 3 IP   flag post
seckford private msg quote post Address this user
The code below collects a number of DS18B20 readings and runs ok on an Arduino 328, but memory is _very_ tight.

 
/** Sensor ROM ID code */
typedef uint8_t ROMID[8];
 
/** Sensor I/O pin settings and error code */
typedef struct Io {
    uint8_t pins_AB;        /**< DS2413 settings for pins A and B */
    uint8_t err;            /**< DS2413 PIO error code */
    } IO;
 
/** Sensor temperature value and error code */
typedef struct Degree {
    uint16_t raw;           /**< DS18B20 raw data */
    uint16_t itgr;          /**< DS18B20 data integer part */
    uint16_t frac;          /**< DS18B20 data fractional part */
    uint8_t sign;           /**< DS18B20 data sign value */
    uint8_t err;            /**< DS18B20 error code */
    } DEG;
 
/* It doesn't seem worth saving a total of 8 bytes with a union */
 
/** Sensor ID and temperature or IO readings */
typedef struct Sensor {
    uint8_t rom[8];         /**< Sensor ROM ID code */
    uint8_t err;            /**< Sensor error code */
    char str[8];            /**< Sensor result as string */
    DEG celsius;            /**< DS18B20 temperature raw and floating point */
    IO pins;                /**< DS2413 I/O pins */
    } SENSOR;
 
/**
** Send data via HTTP to the GroveStreams server.
**
** @remark      No parameters
** @return      OK if successful, FAILED otherwise
**
** @note The various PUT preamble strings take up 155 bytes, and each
**       two-digit precision sensor reading takes up 15 bytes.  A buffer
**       length of 240 should therefore cover four (@ref MAXSENS) sensors.
**
** @internal s e n d _ d a t a
*/
static int send_data(void)
{
    unsigned int u, v;
    int avbl, rc = OK;
    char *pc, txbuff[240], rxbuff[64];
    char thhdr[9] = "&therm1=";
 
    /* Collect data for tranmission.
    **
    ** The data needs to be sent in one string to avoid extra cost.
    ** The PUT setup strings total 155 bytes, and each temperature
    ** measurement adds 15 bytes.
    */
    strcpy(txbuff, "PUT /api/feed?&compTmplId=temp");
    strcat(txbuff, "&compId=" GS_ID);
    /* Name component on initial registration (optional) ??? ###
    strcat(txbuff, "&compName=Temperature";
    */
    strcat(txbuff, "&org=" GS_UUID);
    strcat(txbuff, "&api_key=" GS_PUT_KEY);
    /* Sensors are always read in sorted order, but the order in
    ** which they are written to GroveStreams may be different.
    */
    for (u = 0 ; u < Sensor_count ; u++) {
        if (Sensors[u].err != ERR_MISS) {
            thhdr[6] =  (char) ('1' + u);
            strcat(txbuff, thhdr);
            strcat(txbuff, Sensors[u].str);
        }
    }
    strcat(txbuff, " HTTP/1.1");
 
    /* Talk to the GroveStreams server.
    ** connect() accepts an address or a URL.
    */
    PRINT(F("Connecting to "));
    PRINTLN(Dest);
 
    if (Client.connect(Dest, TGTPORT)) {
        Serial.println("Connection succeeded");
 
        /* Send the data; an HTTP request is ended by a blank line */
        Client.println(txbuff);
 
        Client.println("Host: grovestreams.com");
#if 0
        /* Avoid the ten-second rule when using more that one device
        ** behind a router.
        */
        Client.print("X-Forwarded-For: ");
        Client.println(Ethernet.localIP());
        /* Optional */
        Client.println("Cookie: api_key=" GS_PUT_KEY);
#endif
        Client.println("Content-Type: application/json");
        Client.println("Connection: close");
        Client.println();
 
        /* client.read() returns the number of bytes available, or -1 on error.
        ** The expected response is "HTTP/1.1 200 OK"
        ** Should a response failure update the failure count ??? ###
        **
        ** The response is asynchronous; there may be a delay before it
        ** arrives.  We poll to check for input, then poll to read a message.
        */
#undef TICKS_RD
#define TICKS_RD 1000           /**< 1 msec delay count */
        for (u = 0 ; u < TICKS_RD && Client.available() == 0 ; u++)
            delay(1UL);
 
        /* Client.read(buff, size) is based on a socket recv() call, which
        ** blocks if no data is available.  It returns any data present in
        ** the socket buffer, up to the given limit.
        */
        rxbuff[0] = '';
        if (u < TICKS_RD) {
#if 0
            /* Polled read */
            for (u = 0 ; u < (sizeof(rxbuff) - 1) && Client.available() != 0 ; u++)
                rxbuff[u] = Client.read();
            rxbuff[u] = '';
            avbl = u;
            if (avbl > 0) {
#else
            /* Block read; will the whole message always be available?
            ** GroveStreams sends a response string of more than 80 bytes,
            ** but the 200 OK is early in the string so it should always
            ** be present.
            */
            if ((avbl = Client.read((uint8_t *) rxbuff, sizeof(rxbuff))) > 0) {
                if (avbl > (int) (sizeof(rxbuff) - 1u))
                    rxbuff[sizeof(rxbuff) - 1] = '';
                else
                    rxbuff[avbl] = '';
#endif
                rc = FAILED;
                for (pc = rxbuff ; *pc != '' ; pc++) {
                    if (strncmp(OKSTR, pc, sizeof(OKSTR) - 1) == SAME) {
                        rc = OK;
                        break;
                    }
                }
            }
        }
        /* Don't fail if there's no return string at all */
        else {
            avbl = 0;
        }
 
        /* Clean up the connection, or in the end it hangs */
        Client.flush();
        Client.stop();
 
        PRINTLN(F("Sent reading to GroveStreams: "));
        PRINTLN(txbuff);
 
        if (avbl > 0) {
            PRINTLN(F("GroveStreams partial response: "));
            PRINTLN(rxbuff);
        }
        else {
            PRINTLN(F("No response from GroveStreams"));
        }
    }
    else {
        /* We found no connection */
        Serial.println("Connection failed with data:");
        Serial.println(txbuff);
        Serial.flush();
        /* Client.flush(); hang ??? ### */
        Client.stop();
        rc = FAILED;
    }
 
    return rc;
}
 
Post 4 IP   flag post
Ex33 private msg quote post Address this user
Thanks for the code seckford! But i dont really understand it that well...

And MikeMills thanks for the suggestion! With your suggestion I can get all the streams going, but it doesnt really work as i want it to... Basically it gives me 1 component with all my 8 streams, not the 4 components with 2 streams inside each. If the process is too advance then never mind ill try to find my own way to make it work.
Post 5 IP   flag post
Ex33 private msg quote post Address this user
Never mind, i got it to work already, didnt see the link mike posted.
Post 6 IP   flag post
2965 6 6
Log in or sign up to compose a reply.