zibous / ha-watermeter

Data provider for smartmeter watermeter.
GNU General Public License v3.0
157 stars 27 forks source link

Alarm message is wrong and can cause crash #18

Closed TheoLeCalvar closed 10 months ago

TheoLeCalvar commented 10 months ago

Current code in the lambda that builds the alarm message (and previous alarm message) is wrong.

int error_code = int(x);
std::string message = id(alarm_error_text)[error_code];
id(watermeter_alarm_message).publish_state(message);
if(error_code==0){
  ESP_LOGD("wmbus", "Alarm message: %s, error code: %d", message.c_str(), error_code);
}else{
  ESP_LOGW("wmbus", "WARNING Alarm message: %s, error code: %d", message.c_str(), error_code);
  id(watermeter_alarm_timestamp).publish_state(id(time_sntp).now().strftime("%Y-%m-%dT%H:%M:%S %Z").c_str());
}

It uses the returned watermeter_current_alarms directly but this value is built using binary flags (see here) so it can contain multiple errors and, more serious, it values goes from 0 to 1023 which will cause an overflow on the alarm_error_text array.

Here is the quick fix I applied for my usage:

int error_code = int(x);
std::string message = "";
if(error_code==0){
    message = id(alarm_error_text)[error_code];
    id(watermeter_alarm_message).publish_state(message);
    ESP_LOGD("wmbus", "Alarm message: %s, error code: %d", message, error_code);
}
else{
  for (int i = 1; i < 10; ++i) {
    if (error_code & (1 << i)) {
      if (!message.empty()) { 
        message += ", ";
      }
      message += id(alarm_error_text)[i];
    }
  }
  id(watermeter_alarm_message).publish_state(message);
  ESP_LOGW("wmbus", "WARNING Alarm message: %s, error code: %d", message.c_str(), error_code);
  id(watermeter_alarm_timestamp).publish_state(id(time_sntp).now().strftime("%Y-%m-%dT%H:%M:%S %Z").c_str());
}
zibous commented 10 months ago

@TheoLeCalvar

Thanks. You're right, I've never had an error in recent years and that's why I didn't notice it.