Skip to content

How to read 1byte data? #118

Description

@Eugen4

Installation specifics

  • Heating type: Vitotronic 200
  • Protocol: P300
  • Board: ESP8266 (Wemos D1 mini)

Symptom

Thank you for your project!
I'm making first steps with VitoWiFi v3 based on project's examples.

I was able to read 2byte temperature - VitoWiFi::Datapoint("T1", 0x0810, 2, VitoWiFi::div10)
Output was
Raw data received: a2 01
T1: 41.8

But I wasn't able to read 1byte temperature. I tryed different conversion types, but without success.

  • VitoWiFi::Datapoint("T2", 0x2306, 1, VitoWiFi::div10)
    Output was
    Raw data received: 0c
    T2: 1.2

  • VitoWiFi::Datapoint("T2", 0x2306, 1, VitoWiFi::noconv)
    Output was
    Raw data received: 0c
    T2: ON

Can you please edvise how to read and write 1byte data?

Activity

  1. bertmelis commented on Dec 14, 2024

    @bertmelis
    Owner

    0C is 12 in decimal. Could that be the correct temperature?

    How you print it in your Serial monitor is in your code. If you share the code, I can assist.

  2. Eugen4 commented on Dec 14, 2024

    @Eugen4
    Author

    Yes, it is correct. 12 degrees.

    My code is almost the same as your example

    #include <Arduino.h>
    
    #include <VitoWiFi.h>
    #include <SoftwareSerial.h>
    const int sRX = D1; // software RX on D2(GPIO 4)
    const int sTX = D2; // software TX on D1(GPIO 5)
    
    
    
    EspSoftwareSerial::UART swSer(sRX, sTX);
    
    // optolink on softwareserial, logging output on hardware UART
    
    VitoWiFi::VitoWiFi<VitoWiFi::VS2> vitoWiFi(&swSer);
    bool readValues = false;
    uint8_t datapointIndex = 0;
    uint8_t roomTemperature = 20;
    bool writeRoomTemp = false;
    
    VitoWiFi::Datapoint datapoints[] = {
      VitoWiFi::Datapoint("T0", 0x5525, 2, VitoWiFi::div10),
      VitoWiFi::Datapoint("T1", 0x0810, 2, VitoWiFi::div10),
      VitoWiFi::Datapoint("T2 A1M1", 0x2306, 1, VitoWiFi::noconv),
      VitoWiFi::Datapoint("T3 A1M1", 0x2307, 1, VitoWiFi::noconv),  
      VitoWiFi::Datapoint("T4 M2", 0x3306, 1, VitoWiFi::noconv),
      VitoWiFi::Datapoint("T5 M2", 0x3307, 1, VitoWiFi::noconv),
      VitoWiFi::Datapoint("T6 M3", 0x4306, 1, VitoWiFi::noconv),
      VitoWiFi::Datapoint("T7 M3", 0x4307, 1, VitoWiFi::noconv)
     
    };
    
    void setRoomTemp(uint8_t value) {
      roomTemperature = value;
      writeRoomTemp = true;
    }
    
    void onResponse(const VitoWiFi::PacketVS2& response, const VitoWiFi::Datapoint& request) {
      // raw data can be accessed through the 'response' argument
      Serial.print("Raw data received:");
      const uint8_t* data = response.data();
      for (uint8_t i = 0; i < response.dataLength(); ++i) {
        Serial.printf(" %02x", data[i]);
      }
      Serial.print("\n");
    
      // the raw data can be decoded using the datapoint. Be sure to use the correct type
      Serial.printf("%s: ", request.name());
      if (request.converter() == VitoWiFi::div10) {
        float value = request.decode(response);
        Serial.printf("%.1f\n", value);
      } else if (request.converter() == VitoWiFi::noconv) {
        float value = request.decode(response);
        // alternatively, we can just cast response.data()[0] to bool
        //Serial.printf("%s\n", value);
        Serial.printf("%f\n", value);
      }
    }
    
    void onError(VitoWiFi::OptolinkResult error, const VitoWiFi::Datapoint& request) {
      Serial.printf("Datapoint \"%s\" error: ", request.name());
      if (error == VitoWiFi::OptolinkResult::TIMEOUT) {
        Serial.print("timeout\n");
      } else if (error == VitoWiFi::OptolinkResult::LENGTH) {
        Serial.print("length\n");
      } else if (error == VitoWiFi::OptolinkResult::NACK) {
        Serial.print("nack\n");
      } else if (error == VitoWiFi::OptolinkResult::CRC) {
        Serial.print("crc\n");
      } else if (error == VitoWiFi::OptolinkResult::ERROR) {
        Serial.print("error\n");
      }
    }
    
    void setup() {
      delay(1000);
      Serial.begin(74880);
      Serial.print("Setting up vitoWiFi\n");
    
      vitoWiFi.onResponse(onResponse);
      vitoWiFi.onError(onError);
      vitoWiFi.begin();
    
      Serial.print("Setup finished\n");
    }
    
    void loop() {
      static uint32_t lastMillis = 0;
      if (millis() - lastMillis > 60000UL) {  // read all values every 60 seconds
        lastMillis = millis();
        readValues = true;
        Serial.println("readValues = true;");
        datapointIndex = 0;
      }
    
      if (readValues) {
    
      	Serial.print("Reading. Index = ");
      	Serial.println(datapointIndex);
        if (vitoWiFi.read(datapoints[datapointIndex])) {
          ++datapointIndex;
        } else Serial.println("NOT vitoWiFi.read");
        if (datapointIndex == 8) {
          readValues = false;
          Serial.println("readValues = false;");
        }
      }
    
      vitoWiFi.loop();
    }
    

    The second question: is this a normal output? A lot of NOT vitoWiFi.read, but all datapoints (raw data) has been read correctly

    state 3 --> 4
    readValues = true;
    Reading. Index = 0
    reading packet OK
    state 4 --> 5
    Reading. Index = 1
    NOT vitoWiFi.read
    state 5 --> 6
    Reading. Index = 1
    NOT vitoWiFi.read
    state 6 --> 7
    Reading. Index = 1
    NOT vitoWiFi.read
    state 7 --> 8
    Reading. Index = 1
    NOT vitoWiFi.read
    Reading. Index = 1
    NOT vitoWiFi.read
    Reading. Index = 1
    NOT vitoWiFi.read
    rcv: 0x06
    state 8 --> 9
    Reading. Index = 1
    NOT vitoWiFi.read
    Reading. Index = 1
    NOT vitoWiFi.read
    Reading. Index = 1
    NOT vitoWiFi.read
    Reading. Index = 1
    NOT vitoWiFi.read
    state 9 --> 10
    Raw data received: bd ff
    T0: -6.7
    Reading. Index = 1
    reading packet OK
    state 10 --> 4
    Reading. Index = 2
    NOT vitoWiFi.read
    state 4 --> 5
    Reading. Index = 2
    NOT vitoWiFi.read
    state 5 --> 6
    Reading. Index = 2
    NOT vitoWiFi.read
    state 6 --> 7
    Reading. Index = 2
    NOT vitoWiFi.read
    state 7 --> 8
    
  3. bertmelis commented on Dec 15, 2024

    @bertmelis
    Owner

    Yes, it is correct. 12 degrees.

    So the response is correct.

    It comes down to matching the response to the right output formatting. You could distinguish by datapoint name or by datapoint address:

    void onResponse(const VitoWiFi::PacketVS2& response, const VitoWiFi::Datapoint& request) {
      // raw data can be accessed through the 'response' argument
      Serial.print("Raw data received:");
      const uint8_t* data = response.data();
      for (uint8_t i = 0; i < response.dataLength(); ++i) {
        Serial.printf(" %02x", data[i]);
      }
      Serial.print("\n");
    
      // Now we have different methods of printing the value.
      Serial.printf("%s: ", request.name());
      if (request.address() == 0x2306) {  // you might want to include all relevant addresses here?
        Serial.printf("%u\n", response.data()[0]);
        return;
      }
      if (request.converter() == VitoWiFi::div10) {
        float value = request.decode(response);
        Serial.printf("%.1f\n", value);
        return;
      }
      if (request.converter() == VitoWiFi::noconv) {
        float value = request.decode(response);
        // alternatively, we can just cast response.data()[0] to bool
        //Serial.printf("%s\n", value);
        Serial.printf("%f\n", value);
        return;
      }
    }
  4. Eugen4 commented on Dec 15, 2024

    @Eugen4
    Author

    @bertmelis, thanks alot. I will try this soon.

  5. bertmelis commented on Dec 16, 2024

    @bertmelis
    Owner

    Alternatively, you define the datapoints outside the array. Then you create an array of pointers to the datapoints.

    VitoWiFi::Datapoint T0("T0", 0x5525, 2, VitoWiFi::div10);
    VitoWiFi::Datapoint T1("T1", 0x0810, 2, VitoWiFi::div10);
    VitoWiFi::Datapoint T2_A1M1("T2 A1M1", 0x2306, 1, VitoWiFi::noconv);
    
    VitoWiFi::Datapoint* datapoints[] = {
      T0, T1, T2
    }; 

    Then you have to dereference the pointer when reading/writing the datapoint:

    vitoWiFi.read(datapoints[datapointIndex])
    // becomes
    vitoWiFi.read(*datapoints[datapointIndex])

    In the callback you can check using pointer/address equality.

    if (&request == &T0 ||
        &request == &T1) {
      // div10 conversion, display float
    } else if (&request == & T2_A1M1) {
      // noconv, display int
    }
    
  6. Eugen4 commented on Dec 24, 2024

    @Eugen4
    Author

    @bertmelis thank you for support, I was able to read 1byte data.

    Do I need to change something in following code to write data?

    if (writeRoomTemp1) {
        if (vitoWiFi.write(datapoints[1], Temperature1)) { // this section for 1byte noconv
          writeRoomTemp1 = false;
        }
      }
    if (writeRoomTemp2) {
        if (vitoWiFi.write(datapoints[2], Temperature2)) { / // this section for 2byte div10
          writeRoomTemp2 = false;
        }
      }
    
    
  7. bertmelis commented on Dec 24, 2024

    @bertmelis
    Owner

    Consult the table in the README: https://github.com/bertmelis/VitoWiFi?tab=readme-ov-file#conversion-types

    A 1-byte noconv datapoint can be written to by using an uint8_t. A 2-byte div10 datapoint expects a float.

    So in your code snippet, Temperature1 needs to be uint8_t and Temperature2 needs to be float.

  8. Repository owner locked and limited conversation to collaborators on Apr 21, 2025
  9. converted this issue into a discussion #128 on Apr 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions