Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for Mi Scale V1 #13517

Merged
merged 7 commits into from
Feb 13, 2022
Merged

Added support for Mi Scale V1 #13517

merged 7 commits into from
Feb 13, 2022

Conversation

dcoder42
Copy link

Description:

Not sure if it's useful but this PR adds support for the Xiaomi Mi Scale V1. I also added support for V2 but this is untested due to lack of hardware. The code is based on the Passive BLE monitor addon for Home Assistant.

There is probably room for optimizations. For example: In my setup i have MI32Option2 (direct bridging) enabled and all messages are directly pushed to Home Assistent where i have rules to handle "stabilized" and "weight_removed" properties. When direct bridging is not enabled the code could store weight only when stabilized=1 and weight_removed=0 so the MQTT message at the next TELEPERIOD would only transmit the stabilized weight.

Reference: https://github.com/custom-components/ble_monitor/blob/master/custom_components/ble_monitor/ble_parser/miscale.py

Checklist:

  • The pull request is done against the latest development branch
  • Only relevant files were touched
  • Only one feature/fix was added per PR and the code change compiles without warnings
  • The code change is tested and works with Tasmota core ESP8266 V.2.7.4.9
  • The code change is tested and works with Tasmota core ESP32 V.1.0.7.5
  • I accept the CLA.

NOTE: The code change must pass CI tests. Your PR cannot be merged unless tests pass

@arendst arendst added the on hold by dev team Result - Feature request put on hold by member of development team label Nov 5, 2021
@arendst
Copy link
Owner

arendst commented Nov 5, 2021

As part is untested let's hold this for now.

@kolorafa
Copy link

Tested the firmware with "MI Smart Scale 2" Model XMTZC04HM on Sonoff DUAL R3

It's showing Mi Scale V1, correctly reading Weight, Weight removed and Stabilized

(I have 5 BLE devices and the inerface keeps switching between showing 4 ATC Thermometers and Mi Scale - but assuming that work as intended)

obraz

I would love to see "When direct bridging is not enabled" supported, as "MI32Option2 1" is flooding with the sensory data

@barbudor
Copy link
Contributor

(I have 5 BLE devices and the inerface keeps switching between showing 4 ATC Thermometers and Mi Scale - but assuming that work as intended)

https://tasmota.github.io/docs/Commands/#mi32page
Default is 4

I would love to see "When direct bridging is not enabled" supported, as "MI32Option2 1" is flooding with the sensory data

Not sure to understand the point.

@kolorafa
Copy link

kolorafa commented Nov 20, 2021

Not sure to understand the point.

Because currently telemetry is always sending "weight": 0", because that is the last data received, and the actual weight never get sent
15:08:57.853 MQT: tele/tasmota_48D204/SENSOR = {"Time":"2021-11-20T15:08:57","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":1,"stabilized":0,"weight_unit":"kg","weight": 0,"RSSI":-54}}

MI32Option2 0 - getting only "weight: 0" from Scale sometimes ^^
MI32Option2 1 - you receive a lot of telemetry

Screenshot_20211120_150848

14:12:17.525 CMD: MI32Option2 1
14:12:17.541 MQT: stat/tasmota_48D204/RESULT = {"MI32Option2":1}
14:12:19.757 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:19","ATCd0e158":{"mac":"a4c138d0e158","Temperature":23.8,"Humidity":41.0,"DewPoint":9.7,"Battery":75,"RSSI":-71}}
14:12:22.658 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:22","ATCa399b1":{"mac":"a4c138a399b1","Temperature":20.3,"Humidity":43.0,"DewPoint":7.3,"Battery":86,"RSSI":-90}}
14:12:25.393 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:25","ATCd0e158":{"mac":"a4c138d0e158","Temperature":23.8,"Humidity":41.0,"DewPoint":9.7,"Battery":75,"RSSI":-72}}
14:12:27.082 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:27","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":1,"stabilized":1,"weight_unit":"kg","weight": 0,"RSSI":-52}}
14:12:27.380 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:27","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":1,"stabilized":1,"weight_unit":"kg","weight": 0,"RSSI":-53}}
14:12:27.730 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:27","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":0,"weight_unit":"kg","weight": 5,"RSSI":-53}}
14:12:28.375 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:28","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":1,"stabilized":0,"weight_unit":"kg","weight": 0,"RSSI":-52}}
14:12:28.679 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:28","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":0,"weight_unit":"kg","weight": 0,"RSSI":-53}}
14:12:28.980 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:28","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":1,"stabilized":0,"weight_unit":"kg","weight": 0,"RSSI":-53}}
14:12:29.338 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:29","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":1,"stabilized":0,"weight_unit":"kg","weight": 0,"RSSI":-54}}
14:12:29.637 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:29","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":0,"weight_unit":"kg","weight": 0,"RSSI":-54}}
14:12:29.939 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:29","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":0,"weight_unit":"kg","weight": 0,"RSSI":-53}}
14:12:30.384 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:30","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":0,"weight_unit":"kg","weight": 1,"RSSI":-53}}
14:12:30.739 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:30","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":0,"weight_unit":"kg","weight": 3,"RSSI":-56}}
14:12:31.041 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:31","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":0,"weight_unit":"kg","weight": 3,"RSSI":-53}}
14:12:31.713 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:31","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-51}}
14:12:31.990 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:31","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-51}}
14:12:32.053 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:32","ATCa399b1":{"mac":"a4c138a399b1","Temperature":20.3,"Humidity":43.0,"DewPoint":7.3,"Battery":86,"RSSI":-91},"ATC8f6dc4":{"mac":"a4c1388f6dc4","Temperature":19.4,"Humidity":55.0,"DewPoint":10.1,"Battery":68,"RSSI":-86}}
14:12:32.441 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:32","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-53}}
14:12:32.741 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:32","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-53}}
14:12:33.114 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:33","ATCd0e158":{"mac":"a4c138d0e158","Temperature":23.8,"Humidity":41.0,"DewPoint":9.7,"Battery":75,"RSSI":-74}}
14:12:33.392 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:33","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-55}}
14:12:33.739 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:33","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-52}}
14:12:34.713 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:34","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-54}}
14:12:35.002 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:34","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-52}}
14:12:35.457 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:35","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-52}}
14:12:35.759 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:35","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-54}}
14:12:36.065 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:36","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-54}}
14:12:36.406 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:36","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-52}}
14:12:37.663 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:37","ATC8f6dc4":{"mac":"a4c1388f6dc4","Temperature":19.4,"Humidity":55.0,"DewPoint":10.1,"Battery":68,"RSSI":-85},"MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-55}}
14:12:37.840 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:37","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-60}}
14:12:38.147 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:38","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-52}}
14:12:38.927 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:38","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-56}}
14:12:39.564 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:39","ATC8f6dc4":{"mac":"a4c1388f6dc4","Temperature":19.4,"Humidity":55.0,"DewPoint":10.1,"Battery":68,"RSSI":-81}}
14:12:39.660 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:39","ATCa399b1":{"mac":"a4c138a399b1","Temperature":20.3,"Humidity":43.0,"DewPoint":7.3,"Battery":86,"RSSI":-87}}
14:12:40.043 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:39","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-55}}
14:12:41.103 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:41","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-55}}
14:12:41.403 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:41","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-54}}
14:12:41.502 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:41","ATC8f6dc4":{"mac":"a4c1388f6dc4","Temperature":19.4,"Humidity":55.0,"DewPoint":10.1,"Battery":68,"RSSI":-85}}
14:12:41.748 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:41","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-56}}
14:12:42.204 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:42","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-60}}
14:12:42.704 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:42","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-56}}
14:12:43.042 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:42","ATC14489a":{"mac":"a4c13814489a","Temperature":22.4,"Humidity":44.0,"DewPoint":9.5,"Battery":53,"RSSI":-81}}
14:12:43.355 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:43","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-56}}
14:12:43.954 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:43","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-51}}
14:12:44.759 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:44","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-56}}
14:12:45.063 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:45","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-58}}
14:12:45.403 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:45","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-51}}
14:12:45.698 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:45","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-56}}
14:12:46.127 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:46","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-55}}
14:12:46.243 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:46","ATCd0e158":{"mac":"a4c138d0e158","Temperature":23.8,"Humidity":41.0,"DewPoint":9.7,"Battery":75,"RSSI":-80}}
14:12:47.236 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:47","ATCa399b1":{"mac":"a4c138a399b1","Temperature":20.3,"Humidity":43.0,"DewPoint":7.3,"Battery":86,"RSSI":-97}}
14:12:47.737 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:47","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-51}}
14:12:48.083 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:48","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-54}}
14:12:48.398 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:48","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-58}}
14:12:49.522 MQT: stat/tasmota_48D204/SENSOR = {"Time":"2021-11-20T14:12:49","MISCALEV1568c44":{"mac":"70879e568c44","weight_removed":0,"stabilized":1,"weight_unit":"kg","weight": 3,"RSSI":-55}}`

MI32Page

Thanks, didn't notice that :)

@barbudor
Copy link
Contributor

Understood, for normal usage, I would imagine that requires some state machine to send information only when someone get on/off and measure is stabilized.

@kolorafa
Copy link

Sadly, it keeps sending data even when not used anymore, less frequently but still last message is weight 0, so the actual weighed value is lost (never send to Home Assistant) if direct bridging of BLE-data is not enabled.

But yes, you can always filter it on PC like Author, so it's not really a problem if you know that.

@dcoder42
Copy link
Author

This is exactly what i ment with "room for improvements". Checking the code i think this can easily be extended with this:

void MI32ParseMiScalePacket(const uint8_t * _buf, uint32_t length, const uint8_t *addr, int RSSI, int UUID){
  MiScaleV1Packet_t *_packetV1 = (MiScaleV1Packet_t*)_buf;
  MiScaleV2Packet_t *_packetV2 = (MiScaleV2Packet_t*)_buf;
  uint8_t stabilized = 0;
  uint8_t weight_removed = 0;

  // Mi Scale V1
  if (length == 10 && UUID == 0x181d){ // 14-1-1-2
    stabilized = (_packetV1->status & (1 << 5)) ? 1 : 0;
    weight_removed = (_packetV1->status & (1 << 7)) ? 1 : 0;
    if (!MI32.option.directBridgeMode && (!stabilized || weight_removed))
      return;

    uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0);
    if(_slot==0xff) return;

    if ((_slot >= 0) && (_slot < MIBLEsensors.size())){
      if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot);
      MIBLEsensors[_slot].RSSI=RSSI;
      MIBLEsensors[_slot].needkey=KEY_NOT_REQUIRED;
      MIBLEsensors[_slot].eventType.scale = 1;

      MIBLEsensors[_slot].stabilized = stabilized;
      MIBLEsensors[_slot].weight_removed = weight_removed;
      
      if (_packetV1->status & (1 << 0)) {
        strcpy(MIBLEsensors[_slot].weight_unit, PSTR("lbs"));
        MIBLEsensors[_slot].weight = (float)_packetV1->weight / 100.0f;
      } else if(_packetV1->status & (1 << 4)) {
        strcpy(MIBLEsensors[_slot].weight_unit, PSTR("jin"));
        MIBLEsensors[_slot].weight = (float)_packetV1->weight / 100.0f;
      } else {
        strcpy(MIBLEsensors[_slot].weight_unit, PSTR("kg"));
        MIBLEsensors[_slot].weight = (float)_packetV1->weight / 200.0f;
      }

      if (MIBLEsensors[_slot].weight_removed) {
        MIBLEsensors[_slot].weight = 0.0f;
      }

      if(MI32.option.directBridgeMode) {
        MIBLEsensors[_slot].shallSendMQTT = 1;
        MI32.mode.shallTriggerTele = 1;
      }
    }
  }

  // Mi Scale V2
  else if (length == 13 && UUID == 0x181b){ // 17-1-1-2
    stabilized = (_packetV2->status & (1 << 5)) ? 1 : 0;
    weight_removed = (_packetV2->status & (1 << 7)) ? 1 : 0;
    if (!MI32.option.directBridgeMode && (!stabilized || weight_removed))
      return;

    uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0);
    if(_slot==0xff) return;

    if ((_slot >= 0) && (_slot < MIBLEsensors.size())){
      if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot);
      MIBLEsensors[_slot].RSSI=RSSI;
      MIBLEsensors[_slot].needkey=KEY_NOT_REQUIRED;
      MIBLEsensors[_slot].eventType.scale = 1;

      MIBLEsensors[_slot].has_impedance = (_packetV2->status & (1 << 1)) ? 1 : 0;
      MIBLEsensors[_slot].stabilized = stabilized;
      MIBLEsensors[_slot].weight_removed = weight_removed;

      if (_packetV2->weight_unit & (1 << 4)) {
        strcpy(MIBLEsensors[_slot].weight_unit, PSTR("jin"));
        MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
      } else if(_packetV2->weight_unit == 3) {
        strcpy(MIBLEsensors[_slot].weight_unit, PSTR("lbs"));
        MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
      } else if(_packetV2->weight_unit == 2) {
        strcpy(MIBLEsensors[_slot].weight_unit, PSTR("kg"));
        MIBLEsensors[_slot].weight = (float)_packetV2->weight / 200.0f;
      } else {
        strcpy(MIBLEsensors[_slot].weight_unit, PSTR(""));
        MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
      }

      if (MIBLEsensors[_slot].weight_removed) {
        MIBLEsensors[_slot].weight = 0.0f;
      }

      if(MI32.option.directBridgeMode) {
        MIBLEsensors[_slot].shallSendMQTT = 1;
        MI32.mode.shallTriggerTele = 1;
      }
    }
  }
}

I haven't tried it out yet. Basically it should drop the packet when direct bridging is not enabled and weight is not stabilized or removed.

@mrekin
Copy link

mrekin commented Dec 7, 2021

Hi!
Implementing now the same integration for HM10 driver (but only for mibs v2 and your code more structured:) ).
Do you have plan to add this code for HM10 (and NRF24) drivers ?

p/s:
image

@dcoder42
Copy link
Author

No, i am not planing to add this to the HM10 driver. I am only planing to update this PR when i have a bit more time with the additional code that i have posted above. Still need to test it.

@mrekin
Copy link

mrekin commented Dec 10, 2021

have posted abov

No, i am not planing to add this to the HM10 driver. I am only planing to update this PR when i have a bit more time with the additional code that i have posted above. Still need to test it.

I create PR for HM10.
Mostly based on your code, with some changes (impedance/impedance_stabilized added to output, datetime added to mqtt message)
But I think I need to do some update too - in "packet dropping" logic.

@atifan
Copy link

atifan commented Dec 15, 2021

Hi I would like to test it, but how can i make a firmware? can someone give me a firmware-file for ESP32? I have an ESP32-CAM board. Would be nice if someone could release it here. thx

@kolorafa
Copy link

@atifan PR > Checks > Top Right "Artifacts"
https://github.com/arendst/Tasmota/suites/4208050805/artifacts/109074584

@atifan
Copy link

atifan commented Dec 15, 2021

@kolorafa thx very much :)

@atifan
Copy link

atifan commented Dec 15, 2021

Hi I have it running now, works fine :)
But is that normal that it only shows the rounded full kg? not the 2 after decimal? I would like to have that it shows for example "50,45 kg" instead of "50 kg". Ist this possible?

@dcoder42
Copy link
Author

You can do this with "WeightRes 2" on the console

@dcoder42
Copy link
Author

I have updated the PR with the additional changes above. When directBridgeMode is disabled only stabilized weights will be used for MQTT and WebUI. Also the "stabilized" and "weight_removed" parameters are removed in that case.

@atifan
Copy link

atifan commented Dec 16, 2021

Hi @dcoder42 thank you very much for the fast answer :)
Works fine :)

@arendst
Copy link
Owner

arendst commented Dec 16, 2021

Pls let me know if this PR is ready to merge.

@atifan
Copy link

atifan commented Dec 18, 2021

Hi, I have the problem that my settings always get resettet, maybe a bootloop problem.
For example -> all few minutes the setting "MI32Option2 1" will be resettet to "MI32Option2 0" so that the weight will not be published over mqtt. I checked power supply and it looks ok. Can that be maybe a firmware bug? Or maybe my ESP32 has a problem.

@dcoder42
Copy link
Author

MI32Options are not persistent. You need to use startup rules to keep the settings:

Example (run on console):

rule1 on System#Boot do backlog MI32Option1 1;MI32Option2 1;MI32Option6 1 endon
rule1 on

Can't really say why you get reboots. Which scale are you using? The one with or without impedance measurement?

…abilized value from V1 and changed stabilized/has_impedance to weight_stabilized/impedance_stabilized
@atifan
Copy link

atifan commented Dec 18, 2021

Hi. I am using the Xiaomi Smart Scale 2 (XMTZC04HM). Without this impedance measurement.

@dcoder42
Copy link
Author

Hi. I am using the Xiaomi Smart Scale 2 (XMTZC04HM). Without this impedance measurement.

I own the same device. I can only recommend to try another power supply or reflash the device again.

@atifan
Copy link

atifan commented Dec 19, 2021

OK thx, i will try :)

@github-actions
Copy link

This PR has been automatically marked as stale because it hasn't any activity in last few weeks. It will be closed if no further activity occurs. Thank you for your contributions.

@github-actions github-actions bot added the stale Action - Issue left behind - Used by the BOT to call for attention label Jan 13, 2022
@dcoder42
Copy link
Author

@arendst From my side this PR is ready to be merged. As stated before i have only tested the V1 version of the scale. @mrekin owns the V2 version and he is implementing basically the same for the HM10 driver in #13970 so it's not completely untested.

@github-actions github-actions bot removed the stale Action - Issue left behind - Used by the BOT to call for attention label Jan 13, 2022
@mrekin
Copy link

mrekin commented Jan 13, 2022

@mrekin owns the V2 version
HI @dcoder42 . Just recieved my ESP32 board and tested your PR.
All works fine, expect one little thing:
some time when I go out from scale (before scale stop all measurements) - It continues to "measure" impedance and send packet with impedance value like '65534' ( in normal case values ~400-500)

  • may be need to show 0 in such cases, I don't know :)

image

p/s other thing - I think ESP internal temp need to be splitted from last sensor values block.

@dcoder42
Copy link
Author

dcoder42 commented Jan 13, 2022

Thanks for testing :)

It might be related to line 1760:
if (!MI32.option.directBridgeMode && (!weight_stabilized || weight_removed /* || !impedance_stabilized */))

I commented out "impedance_stabilized" because i was not sure how it behaves. Maybe when stepping off the scale the weight values are locked for a couple of seconds while impedance might still be changing. Can you try to remove the comment to enable the additional "impedance_stabilized" check.

Should be:
if (!MI32.option.directBridgeMode && (!weight_stabilized || weight_removed || !impedance_stabilized))

I am also not sure if we should add "Ohms" as measurement unit to the impedance value.

@mrekin
Copy link

mrekin commented Jan 15, 2022

@dcoder42 tested.
With such code tasmota shows results only if all measurements done (weight and imp). So if I leave scales after weight measurement done but before imp done - no updated weight shows.

Think it is not best way - better to update weight and imp separately and check values

upd:
https://github.com/wiecosystem/Bluetooth/blob/6ece8f1819cefaaad8af896c56f2b8befc2e92b2/sandbox/huami.health.scale2/body_metrics.py#L4

  • in this project impedance check looks
         elif impedance > 3000:
            raise Exception("Impedance is too high (limit >3000ohm)")

@dcoder42
Copy link
Author

Think it is not best way - better to update weight and imp separately and check values

Maybe this will work. It should update weight and impedance independant from each other.

  // Mi Scale V2
  else if (length == 13 && UUID == 0x181b) { // 17-1-1-2
    uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0);
    if (_slot==0xff) return;

    if ((_slot >= 0) && (_slot < MIBLEsensors.size())) {
      if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot);
      MIBLEsensors[_slot].RSSI = RSSI;
      MIBLEsensors[_slot].needkey = KEY_NOT_REQUIRED;
      MIBLEsensors[_slot].eventType.scale = 1;

      weight_stabilized = (_packetV2->status & (1 << 5)) ? 1 : 0;
      weight_removed = (_packetV2->status & (1 << 7)) ? 1 : 0;
      impedance_stabilized = (_packetV2->status & (1 << 1)) ? 1 : 0;

      if (MI32.option.directBridgeMode || (weight_stabilized && !weight_removed))
      {
        MIBLEsensors[_slot].weight_stabilized = weight_stabilized;
        MIBLEsensors[_slot].weight_removed = weight_removed;

        if (_packetV2->weight_unit & (1 << 4)) {
          strcpy(MIBLEsensors[_slot].weight_unit, PSTR("jin"));
          MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
        } else if(_packetV2->weight_unit == 3) {
          strcpy(MIBLEsensors[_slot].weight_unit, PSTR("lbs"));
          MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
        } else if(_packetV2->weight_unit == 2) {
          strcpy(MIBLEsensors[_slot].weight_unit, PSTR("kg"));
          MIBLEsensors[_slot].weight = (float)_packetV2->weight / 200.0f;
        } else {
          strcpy(MIBLEsensors[_slot].weight_unit, PSTR(""));
          MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
        }

        if (weight_removed) {
          MIBLEsensors[_slot].weight = 0.0f;
        }
      }

      if (MI32.option.directBridgeMode || impedance_stabilized)
      {
        MIBLEsensors[_slot].impedance_stabilized = impedance_stabilized;
        MIBLEsensors[_slot].impedance = _packetV2->impedance;
        
        if (weight_removed) {
          MIBLEsensors[_slot].impedance = 0;
        }        
      }

      if(MI32.option.directBridgeMode) {
        MIBLEsensors[_slot].shallSendMQTT = 1;
        MI32.mode.shallTriggerTele = 1;
      }
    }
  }

@mrekin
Copy link

mrekin commented Jan 15, 2022

@dcoder42 sorry, not too fast. My board bad designed (i forgot about boot button and now need to use a set of wires)))

now is better)
but looks lile scale send imp_stabilized when it stop measurement and when i leave scale. As result weight still shows as in last measurement, but impedance set to 0.
So I update code)
Main point - update imp only if weight stable

With

// Mi Scale V2
  // 1. ScaleV2 measure weight. 
  //       After it stabilized - need to  show new value and clear old impedance because new imp may not be measured.
  // 2. ScaleV2 measure impedance
  else if (length == 13 && UUID == 0x181b) { // 17-1-1-2
    uint32_t _slot = MIBLEgetSensorSlot(addr, UUID, 0);
    if (_slot==0xff) return;

    if ((_slot >= 0) && (_slot < MIBLEsensors.size())) {
      if (BLE_ESP32::BLEDebugMode > 0) AddLog(LOG_LEVEL_DEBUG,PSTR("M32: %s: at slot %u"), kMI32DeviceType[MIBLEsensors[_slot].type-1],_slot);
      MIBLEsensors[_slot].RSSI = RSSI;
      MIBLEsensors[_slot].needkey = KEY_NOT_REQUIRED;
      MIBLEsensors[_slot].eventType.scale = 1;

      weight_stabilized = (_packetV2->status & (1 << 5)) ? 1 : 0;
      weight_removed = (_packetV2->status & (1 << 7)) ? 1 : 0;
      impedance_stabilized = (_packetV2->status & (1 << 1)) ? 1 : 0;

      if (MI32.option.directBridgeMode || (weight_stabilized && !weight_removed))
      {
        MIBLEsensors[_slot].weight_stabilized = weight_stabilized;
        MIBLEsensors[_slot].weight_removed = weight_removed;

        if (_packetV2->weight_unit & (1 << 4)) {
          strcpy(MIBLEsensors[_slot].weight_unit, PSTR("jin"));
          MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
        } else if(_packetV2->weight_unit == 3) {
          strcpy(MIBLEsensors[_slot].weight_unit, PSTR("lbs"));
          MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
        } else if(_packetV2->weight_unit == 2) {
          strcpy(MIBLEsensors[_slot].weight_unit, PSTR("kg"));
          MIBLEsensors[_slot].weight = (float)_packetV2->weight / 200.0f;
        } else {
          strcpy(MIBLEsensors[_slot].weight_unit, PSTR(""));
          MIBLEsensors[_slot].weight = (float)_packetV2->weight / 100.0f;
        }

        if (weight_removed) {
          MIBLEsensors[_slot].weight = 0.0f;
        }
        // Due to new measurement done - clear old imp value
        MIBLEsensors[_slot].impedance = 0;
        if (MI32.option.directBridgeMode || impedance_stabilized)
        {
          MIBLEsensors[_slot].impedance_stabilized = impedance_stabilized;
          MIBLEsensors[_slot].impedance = _packetV2->impedance;
          
          if (weight_removed) {
            MIBLEsensors[_slot].impedance = 0;
          } 
        }
      }

      if(MI32.option.directBridgeMode) {
        MIBLEsensors[_slot].shallSendMQTT = 1;
        MI32.mode.shallTriggerTele = 1;
      }
    }
  }

works as expected

Additionally I change
WSContentSend_PD(HTTP_MI32_HL);

  • set it before cycle (to line 3328)
  • and to the end of cycle (to line ~3444)

now ESP32 temp separated by line)

p/s Code works fine in web GUI, but can't undestand how HOME assistant autodiscovery ('SO19 1') works with ble sensors on ESP32. It works on esp8266, but there It not working.. (

@mrekin
Copy link

mrekin commented Jan 15, 2022

About Mqtt
I think

      if(MI32.option.directBridgeMode) {
        MIBLEsensors[_slot].shallSendMQTT = 1;
        MI32.mode.shallTriggerTele = 1;
      }

must be changed to something like

      if(MI32.option.directBridgeMode || weight_stabilized) {
        MIBLEsensors[_slot].shallSendMQTT = 1;
        MI32.mode.shallTriggerTele = 1;
      }

because wait for tele period between measurements is ubnormal (I check my weight and then my wife need to wait 5 min (by default) to put both values to HA - it is terrible:) )

@dcoder42
Copy link
Author

So I update code) Main point - update imp only if weight stable

Thanks. I will update the PR with this change. Maybe next week, when i have a bit more time.

Additionally I change WSContentSend_PD(HTTP_MI32_HL);
* set it before cycle (to line 3328)
* and to the end of cycle (to line ~3444)

I think this should be changed in Esp32SensorShow() in xsns_127_esp32_sensors.ino and this should be done in another PR because it is not related to the Mi Scale

p/s Code works fine in web GUI, but can't undestand how HOME assistant autodiscovery ('SO19 1') works with ble sensors on ESP32. It works on esp8266, but there It not working.. (

It's the MI32DiscoveryOneMISensor function but it is not compiled into the default firmware. To get SetOption19 to work i had to enable USE_HOME_ASSISTANT and disable USE_TASMOTA_DISCOVERY in tasmota_configurations_ESP32.h.

@mrekin
Copy link

mrekin commented Jan 15, 2022

It's the MI32DiscoveryOneMISensor function but it is not compiled into the default firmware. To get SetOption19 to work i had to enable USE_HOME_ASSISTANT and disable USE_TASMOTA_DISCOVERY in tasmota_configurations_ESP32.h.

Thanks! I'll check

…e mode is enabled.

Fixed impedance measurement on V2 scale.
@dcoder42
Copy link
Author

IMO this is ready to be merged

@arendst arendst merged commit 5dabb62 into arendst:development Feb 13, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
on hold by dev team Result - Feature request put on hold by member of development team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants