zewelor / bt-mqtt-gateway

A simple Python script which provides a Bluetooth to MQTT gateway, easily extensible via custom workers. See https://github.com/zewelor/bt-mqtt-gateway/wiki for more information.
MIT License
548 stars 116 forks source link

Problem with negative temperature / signed values #248

Open lobl opened 2 years ago

lobl commented 2 years ago

[x] I've read the Troubleshooting Wiki, my problem is not described there and I am already using the specified minimum bluez version.

Describe the bug

Put a lywsd03mmc sensor into the freezer, which is around -18 to -25 C.
The sensor works fine for months now and shows the correct temperature on the internal display. But on MQTT the temperature shows up false, it's always in the area of 6532.2 C, depending on the freezers temperature. Looks like a problem with signed values. Or can it be configured somewhere?

To Reproduce Steps to reproduce the behavior:

  1. Put sensor in the freezer
  2. Edit config.yml (see config section)
  3. Start docker container
  4. Check MQTT for the temperature

Expected behavior Negative temperature from the sensor in the freezer should appear in MQTT, instead a positive temperature shows up.

Config

config.yml:

mqtt:
  host: 192.168.178.109
  port: 1883
  username:
  password:
  client_id: bt-mqtt-gateway
  availability_topic: #status/bluetooth2mqtt

manager:
  workers:
    lywsd03mmc:
      args:
        devices:
          gefrierfach:  a4:c1:38:4f:1d:f0
        topic_prefix: tele
        passive: true         # Set to true for sensors running custom firmware and advertising type custom. See https://github.com/zewelor/bt-mqtt-gateway/wiki/Devices#lywsd03mmc
        #command_timeout: 30   # Optional timeout for getting data for non-passive readouts
        scan_timeout: 20      # Optional timeout for passive scanning
      update_interval: 30

Debug gateway logs

There is no error in the log. It seems fine, except the temperature is way off.

2022-02-05 17:56:23,349 DEBUG bt-mqtt-gw.workers_manager workers_manager.py:57:execute - Execution result of command Lywsd03MmcWorker.status_update: [ { "topic": "tele/gefrierfach", "payload": "{"temperature": 6532.3, "humidity": 71, "battery": 26}" } ]

Server (please complete the following information):

Additional context

Information from sensor (via TelinkMiFlasher):

Advertising type: Atc1441 Hardware Version: LYWSD03MMC B1.4, Software Version: 3.5, Sensor: SHT4x

jewelooper commented 1 year ago

The processScanValue method is missing a conversion to a signed integer value. Something like this should supply correct positive and negative temperature values:

temperature = int(data[16:20], 16)
temperature = ((temperature+0x8000)&0xFFFF) - 0x8000
temperature = temperature / 10