Search code examples
c++stringclassraspberry-piconcatenation

C++ string does not concatenate in a class


i try to write a small program to control a pump and a valve connected with two ds18b20 temperature sensors on a raspberry pi 3B+. I defined a class for the pump and one for the valve, in the future more pumps and valves will be added, i also created a class for the ds18b20 sensor that is connected over 1 wire. The sensor can read out via a "file", so there is a base directory string baseDir = "/sys/bus/w1/devices/"; followed by the device id string tSensor1 = "28-3c01a81688f4"; and the temperature "file" string tempFile = "/w1_slave";, the full path should look like this /sys/bus/w1/devices/28-3c01a81688f4/w1_slave.

BUT what i get is this TestSensor1= Error reading file at /sys/bus/w1/devices//w1_slave the device is missing, the same for TestSensor2= Error reading file at /sys/bus/w1/devices//w1_slave.

the code is directly compiled on the rPi with g++ -Wall -o oww ofen-warmwasser.cpp -lwiringPi this is my code

#include <wiringPi.h> // library to access the GPIO Pins on a raspberryPI !!deprecated!!
#include <iostream>   // cout
#include <fstream>    // file stream access
#include <string>     // string class
#include <sstream>    // string stream needed for file access to put data into string

//... code skipped ...

class temperaturSensor {
  private:
    string device;
    string baseDir = "/sys/bus/w1/devices/";
    string tempFile = "/w1_slave";
    string path = baseDir + device + tempFile;
    stringstream buffer;
    string data;
    string strTemp;
    double temp = 987.6;
  public:
    // constructor declaration
    temperaturSensor(string str);
    // methodes
    double temperatur() {
      //cout << "----->>>> " << device << " ----->>>> " << path << endl;
      ifstream infile(path);
      if (infile) {
        buffer << infile.rdbuf();
        data = buffer.str();
        infile.close();
      }
      else {
        infile.close();
        cout << "Error reading file at " << path << endl;
        return -100;
      }
      size_t crcCheck = data.find("YES");
      if (crcCheck == string::npos) {
        cout << "CRC fail not reading temperatur" << endl;
        return -101;
      }
      size_t TempPos = data.find("t=");
      if (TempPos == string::npos) {
        cout << "failed to find value -> abort!" << endl;
        return -102;
      }
      strTemp = data.substr(TempPos+2);
      temp = stod(strTemp)/1000;
      return temp;
    }
};

// constructor
    temperaturSensor::temperaturSensor(string str) {
       device = str;
    }

int main(void) {
  // test setup
  pump boilerpumpe(21);
  valve boilervalve(28);
  string tSensor1 = "28-3c01a81688f4";
  temperaturSensor testSensor1(tSensor1);
  temperaturSensor testSensor2("28-3c01a816d9c1");
  while (true)
  {
    boilerpumpe.on();
    boilervalve.close();
    cout << "TestSensor1= " << testSensor1.temperatur() << "°C \nTestSensor2= " << testSensor2.temperatur() << "°C" << endl;
    delay(5*1000);
    boilerpumpe.off();
    boilervalve.open();
    delay(5*1000);
  }
  return 0;
}

as you might see in the code i tried different things from declaring the the string device; variable from private: to public: from the end of the class to the beginning, when i cout the device variable it gets correctly displayed, i think the problem is somewhere here string path = baseDir + device + tempFile;, i also tried string path = baseDir.append(device); but with no success

any help appreciated, if more information is needed just tell me what and i try to provide

thanks etch


Solution

  • In your class declaration:

    string device;
    

    This class member is default-initialized to an empty string.

    string baseDir = "/sys/bus/w1/devices/";
    

    This class member gets default-initialized to the given string.

    string tempFile = "/w1_slave";
    

    This class member gets default-initialized to the given string.

    string path = baseDir + device + tempFile;
    

    And this class member gets initialized to the combined string. Remember that device is an empty string, so path ends up getting set to "/sys/bus/w1/devices//w1_slave", which is what your code ends up attempting to open, and fails.

    In your class's constructor:

       device = str;
    

    This sets a new value for device. However it is too late, since the other class member, and path specifically, are already initialized. It's not going to get initialized again, after the value of device gets set. C++ does not work this way.

    The simplest fix here is for your constructor to use its initialization section to initialize all class members, in order.