Multiple ethernet clients

I have two ethernet enabled arduino thermostats. They are running essentially the same code and respond to the same http get commands. I want to set up a third arduino to talk to them and show their status. This I can do pretty easily, but I have to duplicate the code for each one because I can't figure out how to call a common routine and pass it who I want to talk to. It's easy enough to:

getstuff() //where getstuff uses the thermostat1.available and so forth

So I could create a getstuff2(), but that would mean duplicating the code from getstuff.....wouldn't it?

I'm old to c, but new to c++ and some advice would be nice.

why don't you do getStuff(ip1) and getStuff(ip2)?

If I was working direct with the board I probably would do just that. However, I' confused by the "client thermo(thermoAddr,80)" and then the thermo.connect(), thermo.available(), etc. It seems that I would have to have a

client thermo1(thermoaddr1,80); client thermo2(thermoaddr2,80);

and then the code to match each of the above. I have this working beautifully for one of the devices, but I really hate duplicating code (and bugs) to do another one. There's obviously something I'm overlooking.

client thermo={client (thermoaddr1,80), client (thermoaddr1,80)};

then you won’t pass the ip but the array index of the client like
getStuff(index1) and getStuff(index2)

THANK YOU.

I couldn’t get it to work exactly as you described; compiled properly and executed but something somewhere didn’t work for me. I had to declare the clients first them put them in an array.

Client therm1 (addr,80);
Client therm2 (addr2,80);
Client therms={therm1,therm2};

Then used the index to pick which one in the code like therms[idx].connect and it worked. I’ll claim that I intentionally did it that way for ‘clarity’ and ease of later maintenance .

I couldn't get it to work exactly as you described

maybe because arduino* isn't a full c++

i'm happy to help writing good code :)

*okok, wired :)

Do you have any working code you could share? Being able to connect to different servers when desired would add a lot of functionality to the ethernet shields.

Sure, it’s sort of working somewhat, most of the time. We all know that we are never, ever done with any project, we just get it working well enough and start using it. There will always be improvements over time.

Some stuff is missing of course, like the declaration of the client and so forth, but that can be lifted directly off the examples. But basically I do exactly as described above, pass in an index into an array of objects. You could do the same thing by simply passing the object. The respReq parameter is for interactions that don’t need a response.

The little routine down at the bottom is to make darn sure it works or I reboot the board and reset the ethernet card. I have had a lot of trouble with the network card hanging up. This kind of thing fixes that.

Hey, it ain’t pretty, but it works pretty well and can only get better.

boolean Thermoconnected = false;

boolean tryGetThermostat(int idx,char* command, boolean respReq){
  char* ptr;
  char* data;
  int cnt, len;
  int waitcnt = 0;
  long timer = 0;
  
  while(1){
    if (!Thermoconnected){
      strcpy_P(Dbuf2,PSTR("%s Thermostat Connecting..."));
      sprintf(Dbuf,Dbuf2, (idx==0) ? "North" : "South");
      Serial.print(Dbuf);
      if (Thermostats[idx].connect()) {
        Thermoconnected = true;
        lastthermoCheck = millis();
        waitcnt++;
        strcpy_P(Dbuf,PSTR("OK"));
        Serial.println(Dbuf);
        strcpy_P(Dbuf2,PSTR("GET /%s HTTP/1.0"));
        sprintf(Dbuf,Dbuf2,command);
        Thermostats[idx].println(Dbuf);
        timer = millis(); // to time the response, just in case 
      }
      else{
        strcpy_P(Dbuf,PSTR("failed"));
        waitcnt++;
        timer = millis();  // if the connection failed I don't need to time it.
        Serial.println(Dbuf);
        Thermostats[idx].flush();
        Thermostats[idx].stop();
        while (Thermostats[idx].status() != 0){
          delay(5);
        }
      }
    }
    if (Thermostats[idx].available() > 0){
      ptr = Dbuf;
      while (Thermostats[idx].available()) {
        *ptr++ = Thermostats[idx].read();
      }
      Thermostats[idx].flush(); //suck out any extra chars  
      Thermostats[idx].stop();
      while (Thermostats[idx].status() != 0){
        delay(5);
      }
      Thermoconnected = false;
      
      *ptr='\0';
      if(!respReq){ //response not required
        return(true);
      }
//       Serial.println(Dbuf+44); //debug only
      // finally got some data
      ThermoData[idx].currentTemp = atof(strtok_r(Dbuf+44, ",", &ptr));   // first item is current temp
      data = strtok_r(0, ",", &ptr);                  // first find the token
      len = strcspn(data, ",");                       // then the length
      memset(ThermoData[idx].state,0,sizeof(ThermoData[idx].state)); //make sure it's empty
      strncpy(ThermoData[idx].state, data, len);          // copy out what it's doing currently
      ThermoData[idx].tempSetting = atof(strtok_r(ptr, ",", &ptr));   // temp setting
      data = strtok_r(0, ",", &ptr);  
      len = strcspn(data, ","); 
      memset(ThermoData[idx].mode,0,sizeof(ThermoData[idx].mode));
      strncpy(ThermoData[idx].mode, data, len);           // Mode setting (cool, heat, off)
      data = strtok_r(0, ",", &ptr);  
      len = strcspn(data, ","); 
      memset(ThermoData[idx].fan,0,sizeof(ThermoData[idx].fan));
      strncpy(ThermoData[idx].fan, data, len);            // Fan setting (Auto, On, Recirc - no off)
      data = strtok_r(0, ",", &ptr);  
      len = strcspn(data, ",\n\r"); 
      memset(ThermoData[idx].peak,0,sizeof(ThermoData[idx].peak));
      strncpy(ThermoData[idx].peak, data, len);           // In peak period ?
      strcpy_P(Dbuf2,PSTR("Temp is %d, Heat pump is %s, \nTemp Setting is %d, Mode %s, Fan %s, %s Period"));
      sprintf(Dbuf,Dbuf2, ThermoData[idx].currentTemp,
        ThermoData[idx].state,
        ThermoData[idx].tempSetting,
        ThermoData[idx].mode,
        ThermoData[idx].fan,
        ThermoData[idx].peak);
      Serial.println(Dbuf);
      return(true);
    }
    if (millis() - timer >5000){
      strcpy_P(Dbuf,"Timeout waiting");
      Serial.println(Dbuf);
      Thermostats[idx].flush();
      Thermostats[idx].stop();
      while (Thermostats[idx].status() != 0){
        delay(5);
      }
      Thermoconnected = false;
    }
    
    if (!Thermoconnected){
      strcpy_P(Dbuf2,PSTR("Thermo try # %d"));
      sprintf(Dbuf,Dbuf2,waitcnt);
      Serial.println(Dbuf);
      delay (1000);
    }
    if (waitcnt > 9){
      Thermostats[idx].flush();
      Thermostats[idx].stop();
      while (Thermostats[idx].status() != 0){
        delay(5);
      }
      return(false);
    }
  }
}
void getThermostat(int idx, char* command, boolean respReq ){
  if(tryGetThermostat(idx, command, respReq) == false){
    strcpy_P(Dbuf,PSTR("Thermo comm failure, rebooting"));
    Serial.println(Dbuf);
    resetFunc();  //call reset if you can't get the comm to work
  }
  return;
}