Skip to content

Instantly share code, notes, and snippets.

@Brunty
Forked from ndfred/glowmqtt.py
Created October 13, 2021 09:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Brunty/20170da7cc6c27889a5ff2aed309aaec to your computer and use it in GitHub Desktop.
Save Brunty/20170da7cc6c27889a5ff2aed309aaec to your computer and use it in GitHub Desktop.
Fetch data from a Hildebrand Glow device over MQTT
import datetime
import logging
import json
import paho.mqtt.client as mqtt # pip3 install paho-mqtt
GLOW_LOGIN = "GLOW_LOGIN"
GLOW_PASSWORD = "GLOW_PASSWORD"
GLOW_DEVICE_ID = "GLOW_DEVICE_ID"
# Fields gathered from the ZigBee Smart Energy Standard document
# 0702: Metering
# - 00: Reading Information Set
# - 00: CurrentSummationDelivered: meter reading
# - 01: CurrentSummationReceived
# - 02: CurrentMaxDemandDelivered
# - 07: ReadingSnapshotTime (UTC time)
# - 14: Supply Status (enum): 0x2 is on
# - 02: Meter Status
# - 00: Status (bit map): 10 means power quality event
# - 03: Formatting
# - 00: UnitofMeasure (enum): 00 means kWh, 01 means m3
# - 01: Multiplier
# - 02: Divisor
# - 03: SummationFormatting (bit map):
# 2B means 3 digits after the decimal point, 2 digits before the decimal point
# FB means 3 digits after the decimal point, 16 digits before the decimal point,
# no leading zeros
# - 04: DemandFormatting
# - 06: MeteringDeviceType: 00 means Electric Metering, 80 means Mirrored Gas Metering
# - 07: SiteID: MPAN encoded in UTF-8
# - 08: MeterSerialNumber (string)
# - 12: AlternativeUnitofMeasure (enum)
# - 04: Historical Consumption
# - 00: InstantaneousDemand (signed): current consumption
# - 01: CurrentDayConsumptionDelivered
# - 30: CurrentWeekConsumptionDelivered
# - 40: CurrentMonthConsumptionDelivered
# - 0C: Alternative Historical Consumption
# - 01: CurrentDayConsumptionDelivered
# - 30: CurrentWeekConsumptionDelivered
# - 40: CurrentMonthConsumptionDelivered
# 0705: Prepayment
# - 00: Prepayment Information Set
# - 00: PaymentControlConfiguration (bit map)
# - 01: CreditRemaining (signed)
# 0708: Device Management
# - 01: Supplier Control Attribute Set
# - 01: ProviderName (string)
def on_connect(client, _userdata, _flags, result_code):
if result_code != mqtt.MQTT_ERR_SUCCESS:
logging.error("Error connecting: %d", result_code)
return
result_code, _message_id = client.subscribe("SMART/HILD/" + GLOW_DEVICE_ID)
if result_code != mqtt.MQTT_ERR_SUCCESS:
logging.error("Couldn't subscribe: %d", result_code)
return
logging.info("Connected and subscribed")
def on_message(_client, _userdata, message):
payload = json.loads(message.payload)
current_time = datetime.datetime.now().strftime("%H:%M:%S")
electricity_consumption = int(payload["elecMtr"]["0702"]["04"]["00"], 16)
electricity_daily_consumption = int(payload["elecMtr"]["0702"]["04"]["01"], 16)
electricity_weekly_consumption = int(payload["elecMtr"]["0702"]["04"]["30"], 16)
electricity_monthly_consumption = int(payload["elecMtr"]["0702"]["04"]["40"], 16)
electricity_multiplier = int(payload["elecMtr"]["0702"]["03"]["01"], 16)
electricity_divisor = int(payload["elecMtr"]["0702"]["03"]["02"], 16)
electricity_meter = int(payload["elecMtr"]["0702"]["00"]["00"], 16)
gas_daily_consumption = int(payload["gasMtr"]["0702"]["0C"]["01"], 16)
gas_weekly_consumption = int(payload["gasMtr"]["0702"]["0C"]["30"], 16)
gas_monthly_consumption = int(payload["gasMtr"]["0702"]["0C"]["40"], 16)
gas_multiplier = int(payload["gasMtr"]["0702"]["03"]["01"], 16)
gas_divisor = int(payload["gasMtr"]["0702"]["03"]["02"], 16)
gas_meter = int(payload["gasMtr"]["0702"]["00"]["00"], 16)
electricity_daily_consumption = electricity_daily_consumption * electricity_multiplier / electricity_divisor
electricity_weekly_consumption = electricity_weekly_consumption * electricity_multiplier / electricity_divisor
electricity_monthly_consumption = electricity_monthly_consumption * electricity_multiplier / electricity_divisor
electricity_meter = electricity_meter * electricity_multiplier / electricity_divisor
gas_daily_consumption = gas_daily_consumption * gas_multiplier / gas_divisor
gas_weekly_consumption = gas_weekly_consumption * gas_multiplier / gas_divisor
gas_monthly_consumption = gas_monthly_consumption * gas_multiplier / gas_divisor
gas_meter = gas_meter * gas_multiplier / gas_divisor
assert(int(payload["elecMtr"]["0702"]["03"]["00"], 16) == 0) # kWh
assert(int(payload["gasMtr"]["0702"]["03"]["01"], 16) == 1) # m3
assert(int(payload["gasMtr"]["0702"]["03"]["12"], 16) == 0) # kWh
logging.info("Reading at %s", current_time)
logging.info("* electricity consumption: %dW", electricity_consumption)
logging.info("* daily electricity consumption: %.3fkWh", electricity_daily_consumption)
logging.info("* weekly electricity consumption: %.3fkWh", electricity_weekly_consumption)
logging.info("* monthly electricity consumption: %.3fkWh", electricity_monthly_consumption)
logging.info("* electricity meter: %.3fkWh", electricity_meter)
logging.info("* daily gas consumption: %.3fkWh", gas_daily_consumption)
logging.info("* weekly gas consumption: %.3fkWh", gas_weekly_consumption)
logging.info("* monthly gas consumption: %.3fkWh", gas_monthly_consumption)
logging.info("* gas meter: %.3fm3", gas_meter)
logging.info("Full payload: %s", json.dumps(payload, indent=2))
def loop():
logging.basicConfig(level=logging.DEBUG, format='%(message)s')
client = mqtt.Client()
client.username_pw_set(GLOW_LOGIN, GLOW_PASSWORD)
client.on_connect = on_connect
client.on_message = on_message
client.connect("glowmqtt.energyhive.com")
client.loop_forever()
if __name__ == "__main__":
loop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment