Skip to content

Commit

Permalink
Add support for pvvx custom packet format
Browse files Browse the repository at this point in the history
  • Loading branch information
apnar committed May 7, 2021
1 parent ce728e9 commit 58f7041
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 18 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ Read Bluetooth Advertising Packets from BLE temperature sensors and publish data

This program decodes the bluetooth advertising packets for the following BLE temperature and humidity sensors:
```
// 1 = Xiaomi LYWSD03MMC-ATC https://github.com/atc1441/ATC_MiThermometer & https://github.com/pvvx/ATC_MiThermometer
// 1 = Xiaomi LYWSD03MMC-ATC https://github.com/atc1441/ATC_MiThermometer or https://github.com/pvvx/ATC_MiThermometer
// 2 = Govee H5052 (type 4 advertising packets)
// 3 = Govee H5072
// 4 = Govee H5102
// 5 = Govee H5075
// 6 = Govee H5074 (type 4 advertising packets)
// 99 = Display raw type 0 and type 4 advertising packets for this BLE MAC address
```
When using the LYWSD03MMC you need to flash one of the custom firmwares above. Both the atc1441 and pvvx custom formats are supported. With pvvx custom you get more resolution for humidity.

The program uses the bluetooth and mqtt client libraries, steps to image Raspberry Pi and install necessary libraries to compile program are show at bottom of this readme.

Presuming reasonably modern systemd based linux system you can build and run like this:
Expand Down
74 changes: 57 additions & 17 deletions ble_sensor_mqtt_pub.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// Intel Edison Playground
// Copyright (c) 2015 Damian Kołakowski. All rights reserved.
//
// YAML config parsing based on:
// YAML config parsing based on:
// https://github.com/smavros/yaml-to-struct
//

Expand Down Expand Up @@ -1248,32 +1248,72 @@ int main(int argc, char *argv[])

// length of packet and subpacket

// printf("full packet length = %3d %02X\n", bluetooth_adv_packet_length, bluetooth_adv_packet_length);
// printf("sub packet length = %3d %02X\n", adv_info->length, adv_info->length);
//printf("full packet length = %3d %02X\n", bluetooth_adv_packet_length, bluetooth_adv_packet_length);
//printf("sub packet length = %3d %02X\n", adv_info->length, adv_info->length);

ad_length = (unsigned int)adv_info->data[0];
// printf("ADV_IND AD Data Length = %3d %02X\n", ad_length, ad_length);
//printf("ADV_IND AD Data Length = %3d %02X\n", ad_length, ad_length);
ad_type = (unsigned int)adv_info->data[1];
// printf("ADV_IND AD Type = %3d %02X\n", ad_type, ad_type);
//printf("ADV_IND AD Type = %3d %02X\n", ad_type, ad_type);

int16_t temperature_int = (adv_info->data[10] << 8) | adv_info->data[11];
double temperature_celsius = (double)temperature_int / 10.0;
int16_t temperature_int;
double temperature_celsius;
double temperature_fahrenheit;
int16_t humidity_int;
double humidity;
uint8_t battery_pct_int;
uint16_t battery_mv_int;
uint8_t frame_int;

// check for pvvx firmware custom format
if (bluetooth_adv_packet_length == 34)
{
if (logging_level == LOG_DEBUG)
{
fprintf(stdout, "Parsing as PVVX Firmware\n");
}

double temperature_fahrenheit = temperature_celsius * 9.0 / 5.0 + 32.0;
temperature_int = (adv_info->data[10]) | (adv_info->data[11] << 8);
temperature_celsius = (double)temperature_int / 100.0;

uint8_t humidity_int = adv_info->data[12];
temperature_fahrenheit = temperature_celsius * 9.0 / 5.0 + 32.0;

uint8_t battery_pct_int = adv_info->data[13];
humidity_int = (adv_info->data[12]) | (adv_info->data[13] << 8);
humidity = (double)humidity_int / 100.0;

uint16_t battery_mv_int = (adv_info->data[14] << 8) | adv_info->data[15];
battery_pct_int = adv_info->data[16];

uint8_t frame_int = adv_info->data[16];
battery_mv_int = (adv_info->data[14]) | (adv_info->data[15] << 8);

frame_int = adv_info->data[17];
}
else
{
if (logging_level == LOG_DEBUG)
{
fprintf(stdout, "Parsing as ATC Firmware\n");
}

temperature_int = (adv_info->data[10] << 8) | adv_info->data[11];
temperature_celsius = (double)temperature_int / 10.0;

temperature_fahrenheit = temperature_celsius * 9.0 / 5.0 + 32.0;

humidity_int = adv_info->data[12];
humidity = (double)humidity_int;

battery_pct_int = adv_info->data[13];

battery_mv_int = (adv_info->data[14] << 8) | adv_info->data[15];

frame_int = adv_info->data[16];
}

if (logging_level == LOG_DEBUG)
{
fprintf(stdout, "temp c = %.1f\n", temperature_celsius);
fprintf(stdout, "temp f = %.1f\n", temperature_fahrenheit);
fprintf(stdout, "humidity pct = %3d\n", humidity_int);
fprintf(stdout, "humidity pct = %.1f\n", humidity);
fprintf(stdout, "battery pct = %3d\n", battery_pct_int);
fprintf(stdout, "battery mv = %4d\n", battery_mv_int);
fprintf(stdout, "frame = %3d\n", frame_int);
Expand All @@ -1285,11 +1325,11 @@ int main(int argc, char *argv[])
if (config.publish_type == 1)
{
payload_length = snprintf(payload_buffer, MAXIMUM_JSON_MESSAGE,
"{\"timestamp\":\"%04d%02d%02d%02d%02d%02d\",\"mac\":\"%s\",\"rssi\":%d,\"tempf\":%#.1F,\"units\":\"F\",\"tempc\":%#.1F,\"humidity\":%i,\"batterypct\":%i,\"batterymv\":%i,\"frame\":%i,\"name\":\"%s\",\"location\":\"%s\",\"type\":\"%d\"}",
"{\"timestamp\":\"%04d%02d%02d%02d%02d%02d\",\"mac\":\"%s\",\"rssi\":%d,\"tempf\":%#.1F,\"units\":\"F\",\"tempc\":%#.1F,\"humidity\":%#.1F,\"batterypct\":%i,\"batterymv\":%i,\"frame\":%i,\"name\":\"%s\",\"location\":\"%s\",\"type\":\"%d\"}",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
addr, rssi_int, temperature_fahrenheit,
temperature_celsius,
humidity_int, battery_pct_int, battery_mv_int, frame_int,
humidity, battery_pct_int, battery_mv_int, frame_int,
config.sensors[mac_index].name,
config.sensors[mac_index].location,
config.sensors[mac_index].type);
Expand All @@ -1298,11 +1338,11 @@ int main(int argc, char *argv[])
else
{
payload_length = snprintf(payload_buffer, MAXIMUM_JSON_MESSAGE,
"{\"timestamp\":\"%04d%02d%02d%02d%02d%02d\",\"mac-address\":\"%s\",\"rssi\":%d,\"temperature\":%#.1F,\"units\":\"F\",\"temperature-celsius\":%#.1F,\"humidity\":%i,\"battery-pct\":%i,\"battery-mv\":%i,\"frame\":%i,\"sensor-name\":\"%s\",\"location\":\"%s\",\"sensor-type\":\"%d\"}",
"{\"timestamp\":\"%04d%02d%02d%02d%02d%02d\",\"mac-address\":\"%s\",\"rssi\":%d,\"temperature\":%#.1F,\"units\":\"F\",\"temperature-celsius\":%#.1F,\"humidity\":%.0F,\"battery-pct\":%i,\"battery-mv\":%i,\"frame\":%i,\"sensor-name\":\"%s\",\"location\":\"%s\",\"sensor-type\":\"%d\"}",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
addr, rssi_int, temperature_fahrenheit,
temperature_celsius,
humidity_int, battery_pct_int, battery_mv_int, frame_int,
humidity, battery_pct_int, battery_mv_int, frame_int,
config.sensors[mac_index].name,
config.sensors[mac_index].location,
config.sensors[mac_index].type);
Expand Down

0 comments on commit 58f7041

Please sign in to comment.