Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions LYWSD03MMC.py
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,49 @@ def decode_data_atc(mac, adv_type, data_str, rssi, measurement):
measurement.rssi = rssi
return measurement

def decode_data_lywsdcgq(mac, adv_type, data_str, rssi, measurement):
preeamble = "5020aa01"
packetStart = data_str.find(preeamble)
offset = packetStart + len(preeamble)
strippedData_str = data_str[offset:offset+28]
strippedData_str = data_str[offset:]
macStr = mac.replace(":","").upper()
dataIdentifier = data_str[(offset+14):(offset+16)].upper()

if(dataIdentifier == "0D") and not args.onlydevicelist or (dataIdentifier == "0D" and mac in sensors) and len(strippedData_str) == 28:
print("BLE packet - lywsdcgq 0D: %s %02x %s %d" % (mac, adv_type, data_str, rssi))
temperature = int.from_bytes(bytearray.fromhex(strippedData_str[20:24]),byteorder='little',signed=True) / 10.
humidity = int.from_bytes(bytearray.fromhex(strippedData_str[24:28]),byteorder='little',signed=True) / 10.

measurement.humidity = humidity
measurement.temperature = temperature
measurement.rssi = rssi
return measurement

elif(dataIdentifier == "06") and not args.onlydevicelist or (dataIdentifier == "06" and mac in sensors) and len(strippedData_str) == 24:
print("BLE packet - lywsdcgq 06: %s %02x %s %d" % (mac, adv_type, data_str, rssi))
humidity = int.from_bytes(bytearray.fromhex(strippedData_str[20:24]),byteorder='little',signed=True) / 10.

measurement.humidity = humidity
measurement.rssi = rssi
return measurement

elif(dataIdentifier == "04") and not args.onlydevicelist or (dataIdentifier == "04" and mac in sensors) and len(strippedData_str) == 24:
print("BLE packet - lywsdcgq 04: %s %02x %s %d" % (mac, adv_type, data_str, rssi))
temperature = int.from_bytes(bytearray.fromhex(strippedData_str[20:24]),byteorder='little',signed=True) / 10.

measurement.temperature = temperature
measurement.rssi = rssi
return measurement

elif(dataIdentifier == "0A") and not args.onlydevicelist or (dataIdentifier == "0A" and mac in sensors) and len(strippedData_str) == 22:
print("BLE packet - lywsdcgq 0A: %s %02x %s %d" % (mac, adv_type, data_str, rssi))
batteryPercent = int.from_bytes(bytearray.fromhex(strippedData_str[20:22]),byteorder='little',signed=False)

measurement.battery = batteryPercent
measurement.rssi = rssi
return measurement

# Tested with Qingping CGG1 and CGDK2
def decode_data_qingping(mac, adv_type, data_str, rssi, measurement):
preeamble = "cdfd88"
Expand Down Expand Up @@ -725,6 +768,8 @@ def le_advertise_packet_handler(mac, adv_type, data, rssi):
measurement = (
decode_data_atc(mac, adv_type, data_str, rssi, measurement)
or
decode_data_lywsdcgq(mac, adv_type, data_str, rssi, measurement)
or
decode_data_qingping(mac, adv_type, data_str, rssi, measurement)
)

Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ Once you're connected to the LYWSD03MMC it advertises its values about every 6 s

This script was originally made to support LYWSD03MMC devices running Xiaomi firmware but support for other hardware and firmware was added later.

Passive mode (recommended) device support: LYWSD03MMC, MHO-C401, CGG1-M, CGGDK2
Passive mode (recommended) device support: LYWSD03MMC, MHO-C401, CGG1-M, CGGDK2, LYWSDCGQ

Normal (active connection) device support: LYWSD03MMC

Qingping format advertisements are supported so it's possible this script also supports advertisements sent by other types of Qingping CGG* devices but this is not tested. CGG1-M (Mijia version) devices can also run custom ATC firmware by pvvx. Then they behave exactly the same as LYWSD03MMCs running custom firmware. Qingping sensors only send Qingping format advertisements when running the original Qingping firmware.

LYWSDCGQ format (the old round one with an aaa battery) is supported. The sensor can send four types of advertisements: 1) both temperature and humidity, 2) only temperature, 3) only humidity and 4) only battery. All of these are supported. The missing values are 0 for the callback, so this needs to be handled in the callback script implementation. There are roughly about 20 advertisements with both temperature and humidity per minute and about two single information advertisements per minute for each information, temperature, humidity and battery.

## Prequisites / Requirements

This is not needed if you are using the docker image. See [Docker usage](#docker-usage)
Expand Down