2023.9.12.1
This commit is contained in:
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"githubPullRequests.ignoredPullRequestBranches": [
|
||||
"main"
|
||||
]
|
||||
}
|
||||
51
README.md
51
README.md
@@ -71,22 +71,7 @@ library.
|
||||
|
||||
Example message published to `homeconnect/dishwasher`:
|
||||
|
||||
```
|
||||
{
|
||||
"state": "Run",
|
||||
"door": "Closed",
|
||||
"remaining": "2:49",
|
||||
"power": true,
|
||||
"lowwaterpressure": false,
|
||||
"aquastop": false,
|
||||
"error": false,
|
||||
"remainingseconds": 10140
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Full state information</summary>
|
||||
|
||||
```
|
||||
{
|
||||
'AllowBackendConnection': False,
|
||||
@@ -154,7 +139,6 @@ Example message published to `homeconnect/dishwasher`:
|
||||
```
|
||||
</details>
|
||||
|
||||
|
||||
### Clothes washer
|
||||
|
||||

|
||||
@@ -167,21 +151,7 @@ binary data over the websocket (type 0x82).
|
||||
|
||||
Example message published to `homeconnect/washer`:
|
||||
|
||||
```
|
||||
{
|
||||
"state": "Ready",
|
||||
"door": "Closed",
|
||||
"remaining": "3:48",
|
||||
"power": true,
|
||||
"lowwaterpressure": false,
|
||||
"aquastop": false,
|
||||
"error": false,
|
||||
"remainingseconds": 13680
|
||||
}
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Full state information</summary>
|
||||
|
||||
```
|
||||
{
|
||||
@@ -252,11 +222,9 @@ Example message published to `homeconnect/washer`:
|
||||
|
||||

|
||||
|
||||
The coffee machine needs a better mapping to MQTT messages.
|
||||
Example message published to `homeconnect/coffeemaker`:
|
||||
|
||||
<details>
|
||||
<summary>Full state information</summary>
|
||||
|
||||
```
|
||||
{
|
||||
'LastSelectedBeverage': 8217,
|
||||
@@ -400,3 +368,20 @@ Synchronize with time server, `false` is disabled
|
||||
## FRIDA tools
|
||||
|
||||
Moved to [`README-frida.md`](README-frida.md)
|
||||
|
||||
## Home assistant
|
||||
|
||||
For integration with Home Assistant, the following MQTT sensor can be used to create a read only sensor
|
||||
|
||||
```yaml
|
||||
- unique_id: "coffee_machine"
|
||||
name: "Coffee Machine"
|
||||
state_topic: "homeconnect/coffeemaker/state"
|
||||
value_template: "{{ value_json.PowerState }}"
|
||||
json_attributes_topic: "homeconnect/coffeemaker/state"
|
||||
json_attributes_template: "{{ value_json | tojson }}"
|
||||
```
|
||||
|
||||
## Notes
|
||||
- Sometimes when the device is off, there is the error `ERROR [ip] [Errno 113] No route to host`
|
||||
- There is a lot more information available, like the status of a program that is currently active. This needs to be integrated if possible. For now only the values that relate to the `config.json` are published
|
||||
13
changelog.md
Normal file
13
changelog.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## 2023.9.12.1
|
||||
### Added
|
||||
- Ability to configure MQTT clientname
|
||||
|
||||
### Changed
|
||||
- There was a default set of values being published. Now the device publishes what is present as access read, or readWrite in the `config.json`
|
||||
|
||||
### Fixed
|
||||
- MQTT was not always published to the correct topic
|
||||
60
hc2mqtt
60
hc2mqtt
@@ -12,7 +12,6 @@ import paho.mqtt.client as mqtt
|
||||
from HCDevice import HCDevice
|
||||
from HCSocket import HCSocket, now
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument("config_file")
|
||||
@click.option("-h", "--mqtt_host", default="localhost")
|
||||
@@ -24,15 +23,16 @@ from HCSocket import HCSocket, now
|
||||
@click.option("--mqtt_cafile")
|
||||
@click.option("--mqtt_certfile")
|
||||
@click.option("--mqtt_keyfile")
|
||||
@click.option("--mqtt_clientname")
|
||||
def hc2mqtt(config_file: str, mqtt_host: str, mqtt_prefix: str, mqtt_port: int, mqtt_username: str,
|
||||
mqtt_password: str, mqtt_ssl: bool, mqtt_cafile: str, mqtt_certfile: str, mqtt_keyfile: str):
|
||||
mqtt_password: str, mqtt_ssl: bool, mqtt_cafile: str, mqtt_certfile: str, mqtt_keyfile: str, mqtt_clientname: str):
|
||||
click.echo(f"Hello {config_file=} {mqtt_host=} {mqtt_prefix=} {mqtt_port=} {mqtt_username=} {mqtt_password=} "
|
||||
f"{mqtt_ssl=} {mqtt_cafile=} {mqtt_certfile=} {mqtt_keyfile=}")
|
||||
f"{mqtt_ssl=} {mqtt_cafile=} {mqtt_certfile=} {mqtt_keyfile=} {mqtt_clientname=}")
|
||||
|
||||
with open(config_file, "r") as f:
|
||||
devices = json.load(f)
|
||||
|
||||
client = mqtt.Client()
|
||||
client = mqtt.Client(mqtt_clientname)
|
||||
|
||||
if mqtt_username and mqtt_password:
|
||||
client.username_pw_set(mqtt_username, mqtt_password)
|
||||
@@ -55,36 +55,40 @@ def hc2mqtt(config_file: str, mqtt_host: str, mqtt_prefix: str, mqtt_port: int,
|
||||
|
||||
# Map their value names to easier state names
|
||||
topics = {
|
||||
"OperationState": "state",
|
||||
"DoorState": "door",
|
||||
"RemainingProgramTime": "remaining",
|
||||
"PowerState": "power",
|
||||
"LowWaterPressure": "lowwaterpressure",
|
||||
"AquaStopOccured": "aquastop",
|
||||
"InternalError": "error",
|
||||
"FatalErrorOccured": "error",
|
||||
"InternalError": "Error",
|
||||
"FatalErrorOccured": "Error",
|
||||
}
|
||||
global dev
|
||||
dev = {}
|
||||
|
||||
def client_connect(client, device, mqtt_topic):
|
||||
def on_message(client, userdata, msg):
|
||||
global dev
|
||||
print(msg.topic)
|
||||
mqtt_state = msg.payload.decode()
|
||||
mqtt_topic = msg.topic.split('/')
|
||||
print(now(),f"received mqtt message {mqtt_state}")
|
||||
try:
|
||||
msg = json.loads(mqtt_state)
|
||||
if 'uid' in msg:
|
||||
dev.get("/ro/values",1,"POST",msg)
|
||||
dev[mqtt_topic[-2]].get("/ro/values",1,"POST",msg)
|
||||
else:
|
||||
raise Exception(f"Payload {msg} is not correctly formatted")
|
||||
except Exception as e:
|
||||
print("ERROR", e, file=sys.stderr)
|
||||
|
||||
global dev
|
||||
host = device["host"]
|
||||
device_topics = topics
|
||||
|
||||
for value in device["features"]:
|
||||
if "access" in device["features"][value] and "read" in device["features"][value]['access'].lower():
|
||||
name = device["features"][value]['name'].split(".")
|
||||
device_topics[name[-1]] = name[-1]
|
||||
device_topics[value] = name[-1] #sometimes the returned key is a digit, making translation possible
|
||||
|
||||
state = {}
|
||||
for topic in topics:
|
||||
state[topics[topic]] = None
|
||||
for topic in device_topics:
|
||||
if not topic.isdigit(): #We only want the named topics
|
||||
state[device_topics[topic]] = None
|
||||
|
||||
mqtt_set_topic = mqtt_topic + "/set"
|
||||
print(now(), device["name"], f"set topic: {mqtt_set_topic}")
|
||||
@@ -93,36 +97,32 @@ def client_connect(client, device, mqtt_topic):
|
||||
|
||||
while True:
|
||||
try:
|
||||
print(now(), device["name"], f"connecting to {host}")
|
||||
ws = HCSocket(host, device["key"], device.get("iv",None))
|
||||
dev = HCDevice(ws, device.get("features", None), device["name"])
|
||||
dev[device["name"]] = HCDevice(ws, device.get("features", None), device["name"])
|
||||
|
||||
#ws.debug = True
|
||||
ws.reconnect()
|
||||
|
||||
while True:
|
||||
msg = dev.recv()
|
||||
msg = dev[device["name"]].recv()
|
||||
if msg is None:
|
||||
break
|
||||
if len(msg) > 0:
|
||||
print(now(), device["name"], msg)
|
||||
|
||||
update = False
|
||||
for topic in topics:
|
||||
for topic in device_topics:
|
||||
value = msg.get(topic, None)
|
||||
if value is None:
|
||||
continue
|
||||
|
||||
# Convert "On" to True, "Off" to False
|
||||
if value == "On":
|
||||
value = True
|
||||
elif value == "Off":
|
||||
value = False
|
||||
|
||||
new_topic = topics[topic]
|
||||
if new_topic == "remaining":
|
||||
state["remainingseconds"] = value
|
||||
value = "%d:%02d" % (value / 60 / 60, (value / 60) % 60)
|
||||
# new_topic = topics[topic]
|
||||
# if new_topic == "remaining":
|
||||
# state["remainingseconds"] = value
|
||||
# value = "%d:%02d" % (value / 60 / 60, (value / 60) % 60)
|
||||
|
||||
new_topic = device_topics[topic]
|
||||
state[new_topic] = value
|
||||
update = True
|
||||
|
||||
|
||||
Reference in New Issue
Block a user