-
-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Initial 5074 testing * Fixed decimal rounding issue * Adding refrence material * Now using geti for two's complement * Updated notes for new temperature method * Fixed internal anchor link Co-authored-by: cornking03 <[email protected]>
- Loading branch information
1 parent
692567f
commit 3066bc8
Showing
3 changed files
with
149 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
def handle_GVH5074(value, trigger, msg) | ||
if trigger == details_trigger | ||
var this_device = device_config[value['mac']] | ||
var p = bytes(value['p']) | ||
var i = 0 | ||
var adv_len = 0 | ||
var adv_data = bytes('') | ||
var adv_type = 0 | ||
|
||
while i < size(p) | ||
adv_len = p.get(i,1) | ||
adv_type = p.get(i+1,1) | ||
adv_data = p[i+2..i+adv_len] | ||
if (adv_type == 0xFF) && (adv_len == 0x0A) | ||
var last_data = this_device['last_p'] | ||
if adv_data == last_data | ||
return 0 | ||
else | ||
device_config[value['mac']]['last_p'] = adv_data | ||
end | ||
|
||
if this_device['discovery'] && !this_device['done_disc'] | ||
publish_sensor_discovery(value['mac'], 'Temperature', 'temperature', '°C') | ||
publish_sensor_discovery(value['mac'], 'Humidity', 'humidity', '%') | ||
publish_sensor_discovery(value['mac'], 'DewPoint', 'temperature', '°C') | ||
publish_sensor_discovery(value['mac'], 'Battery', 'battery', '%') | ||
publish_sensor_discovery(value['mac'], 'RSSI', 'signal_strength', 'dB') | ||
device_config[value['mac']]['done_disc'] = true | ||
end | ||
|
||
var output_map = {} | ||
output_map['Time'] = tasmota.time_str(tasmota.rtc()['local']) | ||
output_map['alias'] = this_device['alias'] | ||
output_map['mac'] = value['mac'] | ||
output_map['via_device'] = device_topic | ||
output_map['RSSI'] = value['RSSI'] | ||
if this_device['via_pubs'] | ||
output_map['Time_via_' + device_topic] = output_map['Time'] | ||
output_map['RSSI_via_' + device_topic] = output_map['RSSI'] | ||
end | ||
|
||
output_map['Battery'] = adv_data.geti(7, 1) | ||
# .geti() will take the two's complement when it extracts data | ||
output_map['Temperature'] = adv_data.geti(3,2) / 100.0 | ||
output_map['Humidity'] = adv_data.get(5, 2) / 100.0 | ||
|
||
output_map['DewPoint'] = round(get_dewpoint(output_map['Temperature'], output_map['Humidity']), this_device['temp_precision']) | ||
output_map['Temperature'] = round(output_map['Temperature'], this_device['temp_precision']) | ||
output_map['Humidity'] = round(output_map['Humidity'], this_device['humi_precision']) | ||
var this_topic = base_topic + '/' + this_device['alias'] | ||
tasmota.publish(this_topic, json.dump(output_map), this_device['sensor_retain']) | ||
|
||
if this_device['publish_attributes'] | ||
for output_key:output_map.keys() | ||
tasmota.publish(this_topic + '/' + output_key, string.format('%s', output_map[output_key]), this_device['sensor_retain']) | ||
end | ||
end | ||
|
||
end | ||
i = i + adv_len + 1 | ||
end | ||
end | ||
end | ||
|
||
# map function into handles array | ||
device_handles['GVH5074'] = handle_GVH5074 | ||
require_active['GVH5074'] = true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
# Notes for GVH7074 | ||
|
||
https://github.com/w1gx/govee-ble-scanner/wiki/Sniffing-BLE-advertising-packets was helpful in decoding the GVH5074 | ||
|
||
Full 'p' strings captured from ESP32 serial monitor | ||
``` | ||
02010607030A18F5FE88EC1109476F7665655F48353037345F414141410AFF88EC00650775126402 | ||
02010607030A18F5FE88EC1109476F7665655F48353037345F414141410AFF88EC00650769126402 | ||
02010607030A18F5FE88EC1109476F7665655F48353037345F414141410AFF88EC0069075C126402 | ||
``` | ||
|
||
## Flags | ||
`02 01 06` | ||
|
||
`02` - two bytes | ||
|
||
`01` - Type = Flags | ||
|
||
`06` - Value (bitwise - 00000110) Bit 1 : "LE General Discoverable Mode", Bit 2: "BR/EDR Not Supported." | ||
|
||
## Service Class | ||
`07 03 0A 18 F5 FE 88 EC` | ||
|
||
`07` - 7 bytes | ||
|
||
`03` - Type = Service Class | ||
|
||
`0A 18` -> 18 0A (little endian) - Device Information | ||
|
||
`F5 FE` -> FE F5 (little endian) - Dialog Semiconductor GmbH | ||
|
||
`88 EC` -> EC 88 (little endian) - unknown | ||
|
||
## Complete Local Name | ||
`11 09 47 6F 76 65 65 5F 48 35 30 37 34 5F 41 41 41 41` | ||
|
||
`11` - 17 bytes | ||
|
||
`09` - Type = Complete Local Name | ||
|
||
`47 6F 76 65 65 5F 48 35 30 37 34 5F 41 41 41 41` = Govee_H5074_AAAA (AAAA = last 4 of mac) | ||
|
||
## Manufacturer Specific Data | ||
`0A FF 88 EC 00 65 07 75 12 64 02` | ||
|
||
`0A` - 10 bytes | ||
|
||
`FF` - Type = Manufacturer Specific Data | ||
|
||
`88 EC 00` - unknown - same across all 'p' strings | ||
|
||
`65 07` -> `07 65` (little endian) = See notes on [temperature](#temperature) below | ||
|
||
`75 12` -> `12 75` (little endian) = 4725 in decimal. Divide by 100 to get relative humidity | ||
|
||
`64` - 100 in decimal. Assuming this is battery percentage, but not sure. | ||
|
||
`02` - unknown | ||
|
||
## Temperature | ||
The GVH5074 uses [Two's Complement](https://en.wikipedia.org/wiki/Two%27s_complement#Converting_to_two's_complement_representation) for negative numbers. | ||
> In two's complement notation, a non-negative number is represented by its ordinary binary representation; in this case, the most significant bit is 0. Though, the range of numbers represented is not the same as with unsigned binary numbers. For example, an 8-bit unsigned number can represent the values 0 to 255 (11111111). However a two's complement 8-bit number can only represent positive integers from 0 to 127 (01111111), because the rest of the bit combinations with the most significant bit as '1' represent the negative integers −1 to −128. | ||
> | ||
> The two's complement operation is the additive inverse operation, so negative numbers are represented by the two's complement of the absolute value. | ||
The berry language has a `geti` [method](https://github.com/berry-lang/berry/wiki/Chapter-7#get-geti-methods) that will return a signed value. | ||
|
||
> Read a 1/2/4 bytes value from any offset in the bytes array. The standard mode is little endian, if you specify a negative size it enables big endian. `get` returns unsigned values, while `geti` returns signed values. | ||
> `b.geti(<offset>, <size>) -> bytes object` | ||
In order to get the temperature in °C, use the `geti` method and then divide by 100.0 | ||
``` | ||
# Example | ||
adv_data = bytes('88EC0052FA6E166402') | ||
temp = adv_data.geti(3,2) / 100.0 | ||
``` | ||
Output | ||
``` | ||
-14.54 | ||
``` |