1technophile / OpenMQTTGateway

MQTT gateway for ESP8266 or ESP32 with bidirectional 433mhz/315mhz/868mhz, Infrared communications, BLE, Bluetooth, beacons detection, mi flora, mi jia, LYWSD02, LYWSD03MMC, Mi Scale, TPMS, BBQ thermometer compatibility & LoRa.
https://docs.openmqttgateway.com
GNU General Public License v3.0
3.6k stars 791 forks source link

Support for Mi Jia LYWSD03MMC #540

Closed endrec closed 4 years ago

endrec commented 4 years ago

Would it be possible to add Mi Jia LYWSD03 support?

I did a quick search, and it seems that others are struggling to support it as well, as it does not seem to be obvious to extract measurements from the broadcasted data. :(

There is a working Python script, which connects to these devices and can read values.

jschaeke commented 4 years ago

Indeed it isn't working with the current version. I am also interested as I've got 3 of them. For more info: https://community.openmqttgateway.com/t/xiaomi-mijia-lywsd03mmc-cant-read-values/775 -> @1technophile said: the solution is to generate a connection to the device as this ones doesn’t seem to broadcast its values.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

danielrheinbay commented 4 years ago

Actually, they do seem to broadcast temperature and humidity in their ADV frames about ever 10 mins in bursts of >20 packets, albeit encrypted. Find details how to decrypt the ADV frames here. Implementation which relies on passive monitoring: https://github.com/esphome/feature-requests/issues/552

orrpan commented 4 years ago

Actually, they do seem to broadcast temperature and humidity in their ADV frames about ever 10 mins in bursts of >20 packets, albeit encrypted. Find details how to decrypt the ADV frames here. Implementation which relies on passive monitoring: esphome/feature-requests#552

It is implemented in esphome dev branch now, tested it with three lywsd03mmc and it works well https://github.com/esphome/esphome/tree/dev/esphome/components/xiaomi_lywsd03mmc

Floyddotnet commented 4 years ago

Currently, i didn't have any new update to the state of the LYWSD03 support.

It's hard to get working together with the BLE library. in my small test project, all works as expected. after integration this changes in the OMG source, i trigger many errors in the BLE library and after fixing most of then, the whole process crashes with really useless error messages or ble wifi coexistence errors.

1technophile commented 4 years ago

Thanks for the update ! Despite the errors, did you succeed in retrieving the values in a readable format ? If you succeed in doing this I may try to stabilize the rest.

michapr commented 4 years ago

@Floyddotnet - Have you got to work it stable with multiple devices - without errors and reboots? In my test project I can get all values - but after some time (loops) the BLE process is hanging (can not make connections more) and I get different error mesages with reboot in result...

Can you send me your working test project, if possible?

Thanks, Michael

Floyddotnet commented 4 years ago

Currently i'm on a business trip and not at home.

You can check my early work at: https://github.com/Floyddotnet/OpenMQTTGateway/commit/c2c0ca703986892ae7301d8273eca6e977c82983 (main/ZgatewayBT.ino) and the branch: https://github.com/Floyddotnet/OpenMQTTGateway/commits/issue-296

I try to find my working test project remotely. if I found it, I will upload it asap.

Floyddotnet commented 4 years ago

a small note, the above changes in main/ZgatewayBT.ino reports the correct temperature if the connection could be established.

michapr commented 4 years ago

Hi, thanks. I have tried it, without all the BLE changes - the only change I made is in FreeRTOS.cpp

//      rc = ::xSemaphoreTake(m_semaphore, portMAX_DELAY) == pdTRUE;
        rc = ::xSemaphoreTake(m_semaphore, 60000) == pdTRUE;

because the project was hanging if sensor did not respond more (far away). But I still get in my small project the "Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled." most after reading the characteristic for the LYWSD03MMC sensor.

Same I get in your project (without the BLE changes).

Would be intersting to get a stable working project with the sensors only - will try later with your BLE library modifications.

BTW: can not get work MQTT publishing in your code just now (yes, IP and settings are right ... ;) ) - but not important just now...

Thanks! Michael

michapr commented 4 years ago

@Floyddotnet Additional - I get same errors as before with my simple project (without WiFi) and modified BLE lib with 3 LYWSD03MMC sensors. Reading the values for a while, then hanging or reboot... These are the same errors as in Gateway with modified BLE lib...

michapr commented 4 years ago

@1technophile , @Floyddotnet I have tried to add the simple implementation from https://github.com/karolkalinski/esp32-snippets but cannot get to work it... Additional, it will work only with low power mode, because a reboot will be needed for stable processing of the LYWSD03MMC sensor over a long time (we can find a lot of such comments in web, seems to be an issue in BLE lib).

If somebody have an idea how it can work - tell me please ;) In this time I use a second ESP32 for gateway for these sensors.

Thanks!

1technophile commented 4 years ago

Hi @michapr ,

Thanks for your investigations, we may try also to stop and restart the BLE component, but last time I tried that I didn't had so much chance with these functions.

Could you give me or point me a minimal code that retrieve the data and print it to the serial monitor?

Floyddotnet commented 4 years ago

Hi @michapr, hi @1technophile,

i'm sure that https://github.com/karolkalinski/esp32-snippets/blob/master/Mijia-LYWSD03MMC-Client/Mijia-LYWSD03MMC-Client.ino works on my esp32 an my LYWSD03MMC.

but you need on of the fixes (which I hinted at in the beginning) for the ble libary: https://github.com/nkolban/esp32-snippets/issues/765#issuecomment-453900444

and you should doublecheck the length of pData. This must be exact 5, otherwise it can crash in realy raw situations. my esp runs over 3 days with this script without any issuses.

static void notifyCallback(
  BLERemoteCharacteristic* pBLERemoteCharacteristic,
  uint8_t* pData,
  size_t length,
  bool isNotify) {
  float temp;
  float humi;
  Serial.print("Notify callback for characteristic ");
  Serial.println(pBLERemoteCharacteristic->getUUID().toString().c_str());

  if(length == 5) { // <-- this check is needed
    temp = (pData[0] | (pData[1] << 8)) * 0.01; //little endian 
    humi = pData[2];
    Serial.printf("temp = %.1f : humidity = %.1f \n", temp, humi);
  }

  pClient->disconnect();
}

you can choise of one of the following fixes for BLEREmoteService.cpp:170

fix the type declaration to array

esp_gattc_char_elem_t result[10];
 while (true) { 
    uint16_t count = 10; 

or decrease the count of chars be progresses to 1

esp_gattc_char_elem_t result;
 while (true) { 
    uint16_t count = 1; 

i have checking my source https://github.com/Floyddotnet/OpenMQTTGateway/commit/4fa3aa6ccb86ab412e695db00947edfbf1cff475 and i see, i did the latter.

both have benefitis. the first one is the better, but consumes more memory. but i think, its better to use the first one. i repost my solution only for clearification and completeness.

i hope this will help you

ps: i'm back at home tonight from my buissness-trip. if i can help or provide more, please feel free to ask.

michapr commented 4 years ago

Hi @Floyddotnet , the

 while (true) { 
    uint16_t count = 1; 

I had already inside. Added the length check (good idea ;) ...) But anyway the sketch is hanging after some loops here:

    void onDisconnect(BLEClient* pclient) {
      Serial.println("Disconnected"); 

(removing the restart...)

It happen if the "onConnect" will not be called before, so the pclient->connect(htSensorAddress); will not come back. (Sensor is near the ESP - about 1m)

Even only with one sensor. Would be interesting where is the difference between our "basic" projects.

Michael

1technophile commented 4 years ago

Added here for testing purposes at this time.

michapr commented 4 years ago

Hi, thank you for this! I have tested it today. At first remark - there is needed a new lib - NimBLE, should be installed before. This lib contain the FreeRTOS.h/FreeRTOS.cpp, so there will be a conflict if FreeRTOS was installed before.

Then - all is working as expected (good job!), but the BLE problems above are the same.

Within 3,5 hours the ESP was restarted 15times:

...
09:08:29.580 -> N: Found 6 devices, scan end deinit controller
09:08:29.626 -> N: BLE Connect begin
09:08:33.630 -> N: Subject: /BTtoMQTT/A4C138C18C71
09:08:33.630 -> N: Received json : {"id":"A4:C1:38:C1:8C:71","model":"LYWSD03MMC","tempc":22.92,"tempf":73.256,"hum":58,"volt":2.292,"batt":19.2}
09:09:01.467 -> N: Subject: /BTtoMQTT/A4C1386BF6B2
09:09:01.467 -> N: Received json : {"id":"A4:C1:38:6B:F6:B2","model":"LYWSD03MMC","tempc":22.59,"tempf":72.662,"hum":58,"volt":2.46,"batt":36}
09:09:14.794 -> Guru Meditation Error: Core  0 panic'ed (LoadProhibited). Exception was unhandled.
09:09:14.794 -> Core 0 register dump:
09:09:14.794 -> PC      : 0x4018fbc3  PS      : 0x00060a30  A0      : 0x800d3204  A1      : 0x3ffddc20  
09:09:14.794 -> A2      : 0x00000000  A3      : 0x51433f8d  A4      : 0x3ffc3ff8  A5      : 0x51433f8d  
09:09:14.794 -> A6      : 0x00000000  A7      : 0x00000000  A8      : 0x800ec63c  A9      : 0x3ffddbd0  
09:09:14.841 -> A10     : 0x00000000  A11     : 0x00000001  A12     : 0x00000007  A13     : 0x00000002  
09:09:14.841 -> A14     : 0x00000021  A15     : 0x00000000  SAR     : 0x00000019  EXCCAUSE: 0x0000001c  
09:09:14.841 -> EXCVADDR: 0x00000018  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0x00000000  
09:09:14.841 -> 
09:09:14.841 -> Backtrace: 0x4018fbc3:0x3ffddc20 0x400d3201:0x3ffddc40 0x400d3724:0x3ffddcc0 0x4008dfad:0x3ffddce0
09:09:14.841 -> 
09:09:14.841 -> Rebooting...
...

It is not very "critical", because all will work again. For 139 BLE connect procedures - 15 reboots.

Would be great to have a possibility to define the interval for these BLE connections, it will save battery when requesting every 10 or 15 minutes.

Anyway - a good step for usage of devices with BLE connection requirement !!
THANKS!

1technophile commented 4 years ago

Thanks for the feedback, I get also this error after a few hours, I'm going to check how we can avoid it. And I will add also add a separate timer for the BLEconnect process.

1technophile commented 4 years ago

I have pushed a set of modifications to the branch. Running now without reset for 7h: image

michapr commented 4 years ago

Very good job!

in lines 506 and 595 seems to be a unnecessary ")": Log.trace(F("Callback process canceled by processLock" CR)));

I have installed - and it is working stable until now.

1technophile commented 4 years ago

in lines 506 and 595 seems to be a unnecessary ")": Log.trace(F("Callback process canceled by processLock" CR)));

Corrected thanks

I have added the number of scan before a connect variable ScanBeforeConnect in config_BT.h

michapr commented 4 years ago

I have seen (while checking this feature) that it maybe not optimal, becase not every device will be found at every scan. I have multiple LYWSD03MMC - and sometimes one will be found, sometimes two and sometimes all 3 together with other devices.. So if connect after 5 scans (as sample) - it will take the result of last scan, I think so? (not all devices) Would it be possible to collect the devices while "ScanBeforeConnect" - or you already made it? ;)

1technophile commented 4 years ago

So if connect after 5 scans (as sample) - it will take the result of last scan, I think so? (not all devices)

No, it will take all the devices identified (models requiring a connect) during the scans from the gateway start.

michapr commented 4 years ago

I have tried, it is working fine!

You can add the new sensor MHO-C401 It is a nice sensor (paper ink) for low price. https://de.aliexpress.com/i/4001174769598.html

As I have seen it is (BLE-) compatible with LYWSD03MMC. I have added it in code (as LYWSD03MMC) and it is working stable:

related logs:

N: Device detected: A4:C1:38:E6:41:F3
N: Received json : {"id":"A4:C1:38:E6:41:F3","rssi":-77,"distance":7.119795,"servicedata":"30588703fdf341e638c1a4280100"}

N: Received json : {"id":"A4:C1:38:E6:41:F3","model":"LYWSD03MMC","tempc":23.36,"tempf":74.048,"hum":68,"volt":2.814,"batt":71.4}
...

Detection: (here must be inserted new model in code of course)

        Log.trace(F("Is it a MHO-C401?" CR));
      if (strstr(service_data, "588703") != NULL ) {
          Log.notice(F("MHO-C401 add to list for future connect" CR));
          if (device->sensorModel == -1)
            createOrUpdateDevice(mac, device_flags_init, LYWSD03MMC);
      }

servicedata lenght is all the time the same.

1technophile commented 4 years ago

MHO-C401 added in the linked PR, thanks for the idea!