wez / govee2mqtt

Govee2MQTT: Connect Govee lights and devices to Home Assistant
MIT License
435 stars 26 forks source link

H7131 space heater: HA reports temperature as °C but the actual value is Fahrenheit #58

Closed phurth closed 9 months ago

phurth commented 9 months ago

Govee Device SKU

H7131

Govee2MQTT Version

2024.01.11-9564506d

Describe the issue

After installing and configuring the add-on, there a number of issues, but this one is just that the numerical value of the temp from the heater's sensor is degrees F, while the display in HA is reporting it as degrees C. h7131_temp_ha_display

Startup Diagnostics

s6-rc: info: service s6rc-oneshot-runner: starting
s6-rc: info: service s6rc-oneshot-runner successfully started
s6-rc: info: service fix-attrs: starting
s6-rc: info: service fix-attrs successfully started
s6-rc: info: service legacy-cont-init: starting
s6-rc: info: service legacy-cont-init successfully started
s6-rc: info: service legacy-services: starting
s6-rc: info: service legacy-services successfully started
GOVEE_API_KEY=REDACTED
GOVEE_MQTT_HOST=192.168.1.49
GOVEE_EMAIL=REDACTED
GOVEE_PASSWORD=REDACTED
GOVEE_MQTT_PASSWORD=REDACTED
GOVEE_MQTT_USER=ecowitt2mqtt
GOVEE_MQTT_PORT=1883
++ cd /app
++ exec /app/govee serve
[2024-01-12T09:55:10 INFO  govee::commands::serve] Starting service. version 2024.01.11-9564506d
[2024-01-12T09:55:10 INFO  govee::commands::serve] Querying platform API for device list
[2024-01-12T09:55:11 INFO  govee::commands::serve] Querying undocumented API for device + room list
[2024-01-12T09:55:13 INFO  govee::service::iot] Connected to IoT: CONNACK code 0: Connection Accepted.
[2024-01-12T09:55:13 INFO  govee::commands::serve] Starting LAN discovery
[2024-01-12T09:55:13 INFO  govee::service::iot] IoT (re)connected with status CONNACK code 0: Connection Accepted.
[2024-01-12T09:55:13 INFO  govee::commands::serve] Waiting 10 seconds for LAN API discovery
[2024-01-12T09:55:23 INFO  govee::commands::serve] Devices returned from Govee's APIs
[2024-01-12T09:55:23 INFO  govee::commands::serve] H5074_E454 (A7:90:A4:C1:38:AA:E4:54 H5074)
[2024-01-12T09:55:23 INFO  govee::commands::serve]   Undoc: room=None supports_iot=false ble_only=true
[2024-01-12T09:55:23 WARN  govee::commands::serve]   Unknown device type. Cannot map to Home Assistant.
[2024-01-12T09:55:23 INFO  govee::commands::serve] 
[2024-01-12T09:55:23 INFO  govee::commands::serve] Smart Space Heater (REDACTED H7131)
[2024-01-12T09:55:23 INFO  govee::commands::serve]   Platform API: devices.types.heater. supports_rgb=true supports_brightness=true
[2024-01-12T09:55:23 INFO  govee::commands::serve]                 color_temp=None segment_rgb=None
[2024-01-12T09:55:23 INFO  govee::commands::serve]   Undoc: room=None supports_iot=true ble_only=false
[2024-01-12T09:55:23 INFO  govee::commands::serve] 
[2024-01-12T09:55:23 INFO  govee::commands::serve] H5074_8B55 (B7:08:A4:C1:38:D5:8B:55 H5074)
[2024-01-12T09:55:23 INFO  govee::commands::serve]   Undoc: room=None supports_iot=false ble_only=true
[2024-01-12T09:55:23 WARN  govee::commands::serve]   Unknown device type. Cannot map to Home Assistant.
[2024-01-12T09:55:23 INFO  govee::commands::serve] 
[2024-01-12T09:55:23 INFO  govee::commands::serve] H5074_24DB (AB:30:A4:C1:38:C8:24:DB H5074)
[2024-01-12T09:55:23 INFO  govee::commands::serve]   Undoc: room=None supports_iot=false ble_only=true
[2024-01-12T09:55:23 WARN  govee::commands::serve]   Unknown device type. Cannot map to Home Assistant.
[2024-01-12T09:55:23 INFO  govee::commands::serve] 
[2024-01-12T09:55:23 INFO  govee::service::http] http server addr is 0.0.0.0:8056
[2024-01-12T09:55:28 WARN  govee::cache] request https://openapi.api.govee.com/router/api/v1/device/scenes status 200: OK: parsing https://openapi.api.govee.com/router/api/v1/device/scenes response: Failed with status 400 Bad Request Bad Request: Request to https://openapi.api.govee.com/router/api/v1/device/scenes failed with code 400 Bad Request devices not support this instance. Full response: {"requestId":"uuid","msg":"devices not support this instance","code":400,"payload":{"sku":"H7131","device":"REDACTED"}}, will use prior results
[2024-01-12T09:55:28 ERROR govee::hass_mqtt::light] Unable to list scenes for Smart Space Heater (REDACTED H7131): list_scene_names: get_scene_caps: request https://openapi.api.govee.com/router/api/v1/device/scenes status 200: OK: parsing https://openapi.api.govee.com/router/api/v1/device/scenes response: Failed with status 400 Bad Request Bad Request: Request to https://openapi.api.govee.com/router/api/v1/device/scenes failed with code 400 Bad Request devices not support this instance. Full response: {"requestId":"uuid","msg":"devices not support this instance","code":400,"payload":{"sku":"H7131","device":"REDACTED"}}
[2024-01-12T09:55:28 WARN  govee::hass_mqtt::enumerator] Do something about Mode nightlightScene for Smart Space Heater (REDACTED H7131) DeviceCapability { kind: Mode, instance: "nightlightScene", parameters: Some(Enum { options: [EnumOption { name: "Flame", value: Number(1), extras: {} }, EnumOption { name: "Rainbow", value: Number(2), extras: {} }, EnumOption { name: "Rhythm", value: Number(3), extras: {} }, EnumOption { name: "Easy", value: Number(4), extras: {} }, EnumOption { name: "Sleep", value: Number(5), extras: {} }] }), alarm_type: None, event_state: None }
[2024-01-12T09:55:28 WARN  govee::hass_mqtt::enumerator] Do something about TemperatureSetting targetTemperature for Smart Space Heater (REDACTED H7131) DeviceCapability { kind: TemperatureSetting, instance: "targetTemperature", parameters: Some(Struct { fields: [StructField { field_name: "autoStop", field_type: Enum { options: [EnumOption { name: "Auto Stop", value: Number(1), extras: {} }, EnumOption { name: "Maintain", value: Number(0), extras: {} }] }, default_value: Some(Number(0)), required: false }, StructField { field_name: "temperature", field_type: Integer { unit: None, range: IntegerRange { min: 5, max: 30, precision: 1 } }, default_value: None, required: true }, StructField { field_name: "unit", field_type: Enum { options: [EnumOption { name: "Celsius", value: String("Celsius"), extras: {} }, EnumOption { name: "Fahrenheit", value: String("Fahrenheit"), extras: {} }] }, default_value: Some(String("Celsius")), required: true }] }), alarm_type: None, event_state: None }
[2024-01-12T09:55:28 INFO  govee::service::hass] Wait 500ms for hass to settle on 10 entity configs
[2024-01-12T09:55:29 INFO  govee::service::hass] MQTT connected with status=CONNACK code 0: Connection Accepted.
[2024-01-12T09:55:41 ERROR govee::hass_mqtt::light] Unable to list scenes for Smart Space Heater (REDACTED H7131): list_scene_names: get_scene_caps: request https://openapi.api.govee.com/router/api/v1/device/scenes status 200: OK: parsing https://openapi.api.govee.com/router/api/v1/device/scenes response: Failed with status 400 Bad Request Bad Request: Request to https://openapi.api.govee.com/router/api/v1/device/scenes failed with code 400 Bad Request devices not support this instance. Full response: {"requestId":"uuid","msg":"devices not support this instance","code":400,"payload":{"sku":"H7131","device":"REDACTED"}}
[2024-01-12T09:55:41 WARN  govee::hass_mqtt::enumerator] Do something about Mode nightlightScene for Smart Space Heater (REDACTED H7131) DeviceCapability { kind: Mode, instance: "nightlightScene", parameters: Some(Enum { options: [EnumOption { name: "Flame", value: Number(1), extras: {} }, EnumOption { name: "Rainbow", value: Number(2), extras: {} }, EnumOption { name: "Rhythm", value: Number(3), extras: {} }, EnumOption { name: "Easy", value: Number(4), extras: {} }, EnumOption { name: "Sleep", value: Number(5), extras: {} }] }), alarm_type: None, event_state: None }
[2024-01-12T09:55:41 WARN  govee::hass_mqtt::enumerator] Do something about TemperatureSetting targetTemperature for Smart Space Heater (REDACTED H7131) DeviceCapability { kind: TemperatureSetting, instance: "targetTemperature", parameters: Some(Struct { fields: [StructField { field_name: "autoStop", field_type: Enum { options: [EnumOption { name: "Auto Stop", value: Number(1), extras: {} }, EnumOption { name: "Maintain", value: Number(0), extras: {} }] }, default_value: Some(Number(0)), required: false }, StructField { field_name: "temperature", field_type: Integer { unit: None, range: IntegerRange { min: 5, max: 30, precision: 1 } }, default_value: None, required: true }, StructField { field_name: "unit", field_type: Enum { options: [EnumOption { name: "Celsius", value: String("Celsius"), extras: {} }, EnumOption { name: "Fahrenheit", value: String("Fahrenheit"), extras: {} }] }, default_value: Some(String("Celsius")), required: true }] }), alarm_type: None, event_state: None }

Additional Logs

No response

Home Assistant Logs

No response

Anything else?

No response

wez commented 9 months ago

Please update to the latest version of the addon, which adds some diagnostics in some state entities.

Then evaluate the following home assistant template by visiting Developer Tools | Template, replacing the entity name with what yours actually is:

{{
    {
      "meta": state_attr('sensor.space_heater_status', 'platform_metadata'),
      "state": state_attr('sensor.space_heater_status', 'platform_state'),
    }
}}

It should output a large-ish json blob, please share that here.

That should tell me whether the device gives us enough information to understand which units are in use for the returned data.

phurth commented 9 months ago

JSON below:

{
  "meta": {
    "capabilities": [
      {
        "alarmType": null,
        "eventState": null,
        "instance": "powerSwitch",
        "parameters": {
          "dataType": "ENUM",
          "options": [
            {
              "name": "on",
              "value": 1
            },
            {
              "name": "off",
              "value": 0
            }
          ]
        },
        "type": "devices.capabilities.on_off"
      },
      {
        "alarmType": null,
        "eventState": null,
        "instance": "oscillationToggle",
        "parameters": {
          "dataType": "ENUM",
          "options": [
            {
              "name": "on",
              "value": 1
            },
            {
              "name": "off",
              "value": 0
            }
          ]
        },
        "type": "devices.capabilities.toggle"
      },
      {
        "alarmType": null,
        "eventState": null,
        "instance": "nightlightToggle",
        "parameters": {
          "dataType": "ENUM",
          "options": [
            {
              "name": "on",
              "value": 1
            },
            {
              "name": "off",
              "value": 0
            }
          ]
        },
        "type": "devices.capabilities.toggle"
      },
      {
        "alarmType": null,
        "eventState": null,
        "instance": "brightness",
        "parameters": {
          "dataType": "INTEGER",
          "range": {
            "max": 100,
            "min": 1,
            "precision": 1
          },
          "unit": null
        },
        "type": "devices.capabilities.range"
      },
      {
        "alarmType": null,
        "eventState": null,
        "instance": "colorRgb",
        "parameters": {
          "dataType": "INTEGER",
          "range": {
            "max": 16777215,
            "min": 0,
            "precision": 1
          },
          "unit": null
        },
        "type": "devices.capabilities.color_setting"
      },
      {
        "alarmType": null,
        "eventState": null,
        "instance": "nightlightScene",
        "parameters": {
          "dataType": "ENUM",
          "options": [
            {
              "name": "Flame",
              "value": 1
            },
            {
              "name": "Rainbow",
              "value": 2
            },
            {
              "name": "Rhythm",
              "value": 3
            },
            {
              "name": "Easy",
              "value": 4
            },
            {
              "name": "Sleep",
              "value": 5
            }
          ]
        },
        "type": "devices.capabilities.mode"
      },
      {
        "alarmType": null,
        "eventState": null,
        "instance": "targetTemperature",
        "parameters": {
          "dataType": "STRUCT",
          "fields": [
            {
              "dataType": "ENUM",
              "defaultValue": 0,
              "fieldName": "autoStop",
              "options": [
                {
                  "name": "Auto Stop",
                  "value": 1
                },
                {
                  "name": "Maintain",
                  "value": 0
                }
              ],
              "required": false
            },
            {
              "dataType": "INTEGER",
              "defaultValue": null,
              "fieldName": "temperature",
              "range": {
                "max": 30,
                "min": 5,
                "precision": 1
              },
              "required": true,
              "unit": null
            },
            {
              "dataType": "ENUM",
              "defaultValue": "Celsius",
              "fieldName": "unit",
              "options": [
                {
                  "name": "Celsius",
                  "value": "Celsius"
                },
                {
                  "name": "Fahrenheit",
                  "value": "Fahrenheit"
                }
              ],
              "required": true
            }
          ]
        },
        "type": "devices.capabilities.temperature_setting"
      },
      {
        "alarmType": null,
        "eventState": null,
        "instance": "sensorTemperature",
        "parameters": null,
        "type": "devices.capabilities.property"
      },
      {
        "alarmType": null,
        "eventState": null,
        "instance": "workMode",
        "parameters": {
          "dataType": "STRUCT",
          "fields": [
            {
              "dataType": "ENUM",
              "defaultValue": null,
              "fieldName": "workMode",
              "options": [
                {
                  "name": "gearMode",
                  "value": 1
                },
                {
                  "name": "Fan",
                  "value": 9
                },
                {
                  "name": "Auto",
                  "value": 3
                }
              ],
              "required": true
            },
            {
              "dataType": "ENUM",
              "defaultValue": null,
              "fieldName": "modeValue",
              "options": [
                {
                  "name": "gearMode",
                  "options": [
                    {
                      "name": "Low",
                      "value": 1
                    },
                    {
                      "name": "Medium",
                      "value": 2
                    },
                    {
                      "name": "High",
                      "value": 3
                    }
                  ],
                  "value": null
                },
                {
                  "defaultValue": 0,
                  "name": "Fan",
                  "value": null
                },
                {
                  "defaultValue": 0,
                  "name": "Auto",
                  "value": null
                }
              ],
              "required": true
            }
          ]
        },
        "type": "devices.capabilities.work_mode"
      }
    ],
    "device": "REDACTED",
    "deviceName": "Smart Space Heater",
    "sku": "H7131",
    "type": "devices.types.heater"
  },
  "state": {
    "capabilities": [
      {
        "instance": "online",
        "state": {
          "value": true
        },
        "type": "devices.capabilities.online"
      },
      {
        "instance": "powerSwitch",
        "state": {
          "value": 1
        },
        "type": "devices.capabilities.on_off"
      },
      {
        "instance": "oscillationToggle",
        "state": {
          "value": 1
        },
        "type": "devices.capabilities.toggle"
      },
      {
        "instance": "nightlightToggle",
        "state": {
          "value": 1
        },
        "type": "devices.capabilities.toggle"
      },
      {
        "instance": "brightness",
        "state": {
          "value": 100
        },
        "type": "devices.capabilities.range"
      },
      {
        "instance": "colorRgb",
        "state": {
          "value": 16711680
        },
        "type": "devices.capabilities.color_setting"
      },
      {
        "instance": "nightlightScene",
        "state": {
          "value": ""
        },
        "type": "devices.capabilities.mode"
      },
      {
        "instance": "targetTemperature",
        "state": {
          "value": {
            "targetTemperature": 21,
            "unit": "Celsius"
          }
        },
        "type": "devices.capabilities.temperature_setting"
      },
      {
        "instance": "sensorTemperature",
        "state": {
          "value": 72
        },
        "type": "devices.capabilities.property"
      },
      {
        "instance": "workMode",
        "state": {
          "value": {
            "modeValue": 0,
            "workMode": 3
          }
        },
        "type": "devices.capabilities.work_mode"
      }
    ],
    "device": "F4:D2:D4:AD:FC:F1:96:70",
    "sku": "H7131"
  }
}
wez commented 9 months ago

Thanks! It appears as though there are no units defined for sensorTemperature. If you change your preference for units in the app to celsius, does the sensorTemperature reading also switch units, or does it remain in F?

phurth commented 9 months ago

Thanks! It appears as though there are no units defined for sensorTemperature. If you change your preference for units in the app to celsius, does the sensorTemperature reading also switch units, or does it remain in F?

Weird - it stays °F even if I change units in the Govee app to °C.

phurth commented 9 months ago

The relevant JSON:

{
        "instance": "targetTemperature",
        "state": {
          "value": {
            "targetTemperature": 21,
            "unit": "Celsius"
          }
        },
        "type": "devices.capabilities.temperature_setting"
      },
      {
        "instance": "sensorTemperature",
        "state": {
          "value": 68
        }
phurth commented 9 months ago

Notable is that no matter how the app is set, targetTemperature always comes through the API in celsius.

wez commented 9 months ago

FWIW, the errors about listing scenes should no longer show up in the latest version of the addon. The other more important stuff mentioned here is not yet resolved.

wez commented 9 months ago

The latest version of the addon has some logic that may resolve the temperature readings. Please let me know how you get on with it!

phurth commented 9 months ago

The sensor temp now displays the correct temp aligned with the correct Celsius label in HA. There are still two issues though: 1) My app is set to °F, so I would expect HA to display that, not °C. 2) Minor, but the entity has a display precision of something like 10 decimal points. I can adjust this in HA, but usually temps default display with a max precision of 2 decimal points.

wez commented 9 months ago

My understanding was the HA will auto-translate temperature units for entities, but it seems like that is not true. I need to figure out if there is a way to make it do that, otherwise, there will need to be a way to configure your choice of units in govee2mqtt and I'll need to translate them on this side. I'm hoping to avoid that, as it feels complex both for users and for the code internals.

re: precision, hmm, I hadn't considered it, but yes it makes sense

phurth commented 9 months ago

The strange thing is that the value being returned in sensorTemperature is in °F but no unit is listed. The targetTemperature is always returned in °C but does at least list the unit. It feels like there's something not right in the API.

Thanks for your efforts either way. This is a great project since Govee seems to have a bunch of neat products that don't work with the core HA integration. Before your add-on I had to set up the heater in Homebridge since there is a (partially) working integration, and then use HomeKit to get it in to HA. Pretty clunky but your approach is much better.

wez commented 9 months ago

It feels like there's something not right in the API.

There's a LOT that isn't right in the API! It's horrendously inconsistent, but still better than what was available before.

wez commented 9 months ago

I'm tracking the remaining portion of this in:

Alex565rf commented 9 months ago

{{ (states('sensor.chauffage_bureau_alex_temperature') | float -32 ) * 5/9}}

Create a template with this it should create a new sensor in C even if the data is in F. You should be able to do that the other way around too.