Skip to content
This repository has been archived by the owner on Dec 8, 2024. It is now read-only.

Commit

Permalink
Merge branch 'feature/homewizard' into next
Browse files Browse the repository at this point in the history
  • Loading branch information
Roeland authored and Roeland committed Aug 7, 2024
2 parents 1e8a9a9 + 8db352a commit 01276b3
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 42 deletions.
2 changes: 1 addition & 1 deletion sma/config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: "SMA Energy Meter emulator"
description: "Simulate one or more SMA energy meters based on mqtt messages."
version: "rc-0.0.11.11"
version: "rc-0.0.11.12"
slug: sma
url: "https://github.com/Roeland54/SMA-Energy-Meter-emulator"
arch:
Expand Down
12 changes: 11 additions & 1 deletion sma/src/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import threading
from dynaconf import Dynaconf

settings = Dynaconf(
envvar_prefix="CONF",
settings_files=["settings.json", "/data/options.json", "settings.dev.json"],
)
)

workingdata = {
'packets': {},
'lock': threading.Lock(),
'udp_address': '239.12.255.254',
'udp_port': 9522,
'homewizard_meters': {},
'ip_serial_numbers': {}
}
32 changes: 17 additions & 15 deletions sma/src/homewizard.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,45 @@
from zeroconf import Zeroconf, ServiceBrowser, ServiceStateChange
from config import settings
from config import settings, workingdata
import logging
import requests
import hashlib
from emeter import emeterPacket
import time
import json

def setup_homewizard(userdata):
def setup_homewizard():
if settings.get("enable_homewizard", False) is False:
return None

zeroconf = Zeroconf()
browser = ServiceBrowser(zeroconf, "_hwenergy._tcp.local.", handlers=[lambda zeroconf, service_type, name, state_change: on_service_state_change(zeroconf, service_type, name, state_change, userdata)])
browser = ServiceBrowser(zeroconf, "_hwenergy._tcp.local.", handlers=[lambda zeroconf, service_type, name, state_change: on_service_state_change(zeroconf, service_type, name, state_change)])
for ip in settings.get("homewizard_manual_addresses", []):
serial_number = string_to_int(ip.lower())
ip = ip.lower()
serial_number = string_to_int(ip)
logging.info(f"HomeWizard manual entry ip/hostname: {ip}, assigned serial number: {serial_number}")
userdata['homewizard_meters'][ip] = serial_number
workingdata['homewizard_meters'][ip] = serial_number

def on_service_state_change(zeroconf, service_type, name, state_change, userdata):
def on_service_state_change(zeroconf, service_type, name, state_change):
if state_change is ServiceStateChange.Added:
logging.debug(f"Found device with name: {name}, state_change: {state_change}, trying to get info")
info = zeroconf.get_service_info(service_type, name)
if info:
hostname = info.server
logging.debug(f"Found device with hostname from ServiceInfo: {hostname}")
if hostname.startswith("p1meter") or hostname.startswith("kwhmeter"):
serial_number = string_to_int(hostname.lower())
hostname = hostname.lower()
serial_number = string_to_int(hostname)
logging.info(f"Found HomeWizard meter with hostname: {hostname}, assigned serial number: {serial_number}")
with userdata['lock']:
userdata['homewizard_meters'][hostname] = serial_number
with workingdata['lock']:
workingdata['homewizard_meters'][hostname] = serial_number

def update_homewizard(userdata):
if settings.get("enable_homewizard", False) is False or (len(userdata['homewizard_meters']) == 0 and len(settings.get("homewizard_manual_addresses", [])) == 0):
def update_homewizard():
if len(workingdata['homewizard_meters']) == 0:
return None

try:
with userdata['lock']:
hostnames = userdata['homewizard_meters']
with workingdata['lock']:
hostnames = workingdata['homewizard_meters']

for (hostname, serial_number) in hostnames.items():
packet = emeterPacket(int(serial_number))
Expand Down Expand Up @@ -82,8 +84,8 @@ def update_homewizard(userdata):
packet_data = packet.getData()[:packet.getLength()]
destination_addresses = settings.get("homewizard_destination_addresses", [])

with userdata['lock']:
userdata['packets'][serial_number] = (packet_data, destination_addresses)
with workingdata['lock']:
workingdata['packets'][serial_number] = (packet_data, destination_addresses)
logging.debug(f"Updated homewizard packet for serial number {serial_number}")

except requests.RequestException as e:
Expand Down
26 changes: 8 additions & 18 deletions sma/src/main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import threading
import util
import mqtt
import udp
Expand All @@ -7,31 +6,22 @@
def main():
util.setup_logging()

userdata = {
'packets': {},
'lock': threading.Lock(),
'udp_address': '239.12.255.254',
'udp_port': 9522,
'homewizard_meters': {},
'ip_serial_numbers': {}
}

threads=[]

mqtt_thread = mqtt.setup_mqtt(userdata)

homewizard.setup_homewizard(userdata)
mqtt_thread = mqtt.setup_mqtt()

if mqtt_thread is not None:
threads.append(mqtt_thread)
threads.append(mqtt_thread)

udp_thread = udp.setup_udp(userdata)
homewizard.setup_homewizard()

udp_thread = udp.setup_udp()

if udp_thread is not None:
threads.append(udp_thread)
threads.append(udp_thread)

for thread in threads:
thread.join()
thread.join()

if __name__ == "__main__":
main()
main()
6 changes: 3 additions & 3 deletions sma/src/mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
import os
import paho.mqtt.client as mqtt
import util
from config import settings
from config import settings, workingdata
from emeter import emeterPacket

def setup_mqtt(userdata):
def setup_mqtt():
if settings.get("enable_mqtt", False) is False:
return None

set_mqtt_settings()
mqtt_client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, userdata = userdata, protocol=mqtt.MQTTv5)
mqtt_client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, userdata = workingdata, protocol=mqtt.MQTTv5)

if settings["mqtt"]["username"] and settings["mqtt"]["password"]:
mqtt_client.username_pw_set(settings["mqtt"]["username"], settings["mqtt"]["password"])
Expand Down
10 changes: 6 additions & 4 deletions sma/src/udp.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
import logging
import threading
import homewizard
from config import workingdata

def setup_udp(userdata):
udp_thread = threading.Thread(target=udp_sender, args=(userdata,))
def setup_udp():
udp_thread = threading.Thread(target=udp_sender, args=(workingdata,))
udp_thread.daemon = True
udp_thread.start()
return udp_thread
Expand All @@ -15,7 +16,7 @@ def udp_sender(userdata):
udp_socket.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)
logging.info('Starting udp loop')
while True:
homewizard.update_homewizard(userdata)
homewizard.update_homewizard()

with userdata['lock']:
for serial_number, (packet_data, destination_addresses) in userdata['packets'].items():
Expand All @@ -25,5 +26,6 @@ def udp_sender(userdata):
logging.debug(f"Sent packet to {address} for serial number {serial_number}")
else:
udp_socket.sendto(packet_data, (userdata['udp_address'], userdata['udp_port']))
logging.debug(f"Sent multicast packet for serial number {serial_number} packet data: {packet_data}")
logging.debug(f"Sent multicast packet for serial number {serial_number}")
logging.debug(f"With packet data: {packet_data}")
time.sleep(1)

0 comments on commit 01276b3

Please sign in to comment.