Skip to content

Commit 69db08d

Browse files
authored
Merge pull request #25 from ohAnd/develop
Develop
2 parents e96b217 + 4f4ac08 commit 69db08d

File tree

11 files changed

+937
-93
lines changed

11 files changed

+937
-93
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: feature - build image and push
2+
# This workflow builds and pushes a Docker image to GitHub Container Registry.
3+
# It is triggered on pushes to branches other than "main" and "develop", and can also be triggered manually.
4+
# The image is tagged with the branch name of the push event.
5+
# The workflow uses the GITHUB_TOKEN secret for authentication with GitHub Container Registry.
6+
7+
on:
8+
push:
9+
branches-ignore:
10+
- "main"
11+
- "develop"
12+
workflow_dispatch: # allows manual triggering of the workflow
13+
14+
jobs:
15+
publish_image:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
21+
- name: Convert repository owner to lowercase
22+
run: echo "owner=$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
23+
24+
- name: Build image
25+
run: docker build -t ghcr.io/${{ env.owner }}/eos_connect:feature .
26+
27+
# Only run tagging and pushing tasks for "push" events
28+
- name: Log in to GitHub Container Registry
29+
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
30+
31+
- name: Tag image with develop version
32+
run: docker tag ghcr.io/${{ env.owner }}/eos_connect:feature ghcr.io/${{ env.owner }}/eos_connect:feature_dev_${{ github.ref_name }}
33+
34+
- name: Push Docker image to GitHub Container Registry
35+
run: |
36+
docker push ghcr.io/${{ env.owner }}/eos_connect:feature_dev_${{ github.ref_name }}

src/CONFIG_README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,44 @@ pv_forecast:
175175

176176
---
177177

178+
### **MQTT Configuration**
179+
180+
The `mqtt` section allows you to configure the MQTT broker and Home Assistant MQTT Auto Discovery settings.
181+
182+
#### **Parameters**
183+
184+
- **`mqtt.enabled`**:
185+
Enable or disable MQTT functionality.
186+
- `true`: Enable MQTT.
187+
- `false`: Disable MQTT.
188+
189+
- **`mqtt.broker`**:
190+
The address of the MQTT broker (e.g., `localhost` or `192.168.1.10`).
191+
192+
- **`mqtt.port`**:
193+
The port of the MQTT broker. Default: `1883`.
194+
195+
- **`mqtt.user`**:
196+
The username for authenticating with the MQTT broker (optional).
197+
198+
- **`mqtt.password`**:
199+
The password for authenticating with the MQTT broker (optional).
200+
201+
- **`mqtt.tls`**:
202+
Enable or disable TLS for secure MQTT connections.
203+
- `true`: Use TLS for secure connections.
204+
- `false`: Do not use TLS.
205+
206+
- **`mqtt.ha_mqtt_auto_discovery`**:
207+
Enable or disable Home Assistant MQTT Auto Discovery.
208+
- `true`: Enable Auto Discovery.
209+
- `false`: Disable Auto Discovery.
210+
211+
- **`mqtt.ha_mqtt_auto_discovery_prefix`**:
212+
The prefix for Home Assistant MQTT Auto Discovery topics. Default: `homeassistant`.
213+
214+
---
215+
178216
### **Other Configuration Settings**
179217

180218
- **`refresh_time`**:
@@ -253,6 +291,15 @@ inverter:
253291
# EVCC configuration
254292
evcc:
255293
url: http://yourEVCCserver:7070 # URL for EVCC server - default: http://yourEVCCserver:7070
294+
mqtt:
295+
enabled: false # Enable MQTT - default: false
296+
broker: localhost # URL for MQTT server - default: mqtt://yourMQTTserver
297+
port: 1883 # Port for MQTT server - default: 1883
298+
user: mqtt_user # Username for MQTT server - default: mqtt
299+
password: mqtt_password # Password for MQTT server - default: mqtt
300+
tls: false # Use TLS for MQTT server - default: false
301+
ha_mqtt_auto_discovery: true # Enable Home Assistant MQTT auto discovery - default: true
302+
ha_mqtt_auto_discovery_prefix: homeassistant # Prefix for Home Assistant MQTT auto discovery - default: homeassistant
256303
refresh_time: 3 # Default refresh time of EOS connect in minutes - default: 3
257304
time_zone: Europe/Berlin # Default time zone - default: Europe/Berlin
258305
eos_connect_web_port: 8081 # Default port for EOS connect server - default: 8081

src/config.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,21 @@ def create_default_config(self):
110110
"url": "http://yourEVCCserver:7070", # URL for EVCC server
111111
}
112112
),
113+
"mqtt": CommentedMap(
114+
{
115+
"enabled": False, # Enable MQTT - default: false
116+
# URL for MQTT server - default: mqtt://yourMQTTserver
117+
"broker": "homeassistant",
118+
"port": 1883, # Port for MQTT server - default: 1883
119+
"user": "username", # Username for MQTT server - default: mqtt
120+
"password": "password", # Password for MQTT server - default: mqtt
121+
"tls": False, # Use TLS for MQTT server - default: false
122+
# Enable Home Assistant MQTT auto discovery - default: true
123+
"ha_mqtt_auto_discovery": True,
124+
# Prefix for Home Assistant MQTT auto discovery - default: homeassistant
125+
"ha_mqtt_auto_discovery_prefix": "homeassistant",
126+
}
127+
),
113128
"refresh_time": 3, # Default refresh time in minutes
114129
"time_zone": "Europe/Berlin", # Add default time zone
115130
"eos_connect_web_port": 8081, # Default port for EOS connect server
@@ -268,6 +283,37 @@ def create_default_config(self):
268283
"URL for EVCC server - default: http://yourEVCCserver:7070",
269284
"url",
270285
)
286+
# mqtt configuration
287+
config.yaml_set_comment_before_after_key(
288+
"mqtt", before="MQTT configuration"
289+
)
290+
config["mqtt"].yaml_add_eol_comment(
291+
"Enable MQTT - default: false", "enabled"
292+
)
293+
config["mqtt"].yaml_add_eol_comment(
294+
"URL for MQTT server - default: mqtt://yourMQTTserver", "broker"
295+
)
296+
config["mqtt"].yaml_add_eol_comment(
297+
"Port for MQTT server - default: 1883", "port"
298+
)
299+
config["mqtt"].yaml_add_eol_comment(
300+
"Username for MQTT server - default: mqtt", "user"
301+
)
302+
config["mqtt"].yaml_add_eol_comment(
303+
"Password for MQTT server - default: mqtt", "password"
304+
)
305+
config["mqtt"].yaml_add_eol_comment(
306+
"Use TLS for MQTT server - default: false", "tls"
307+
)
308+
config["mqtt"].yaml_add_eol_comment(
309+
"Enable Home Assistant MQTT auto discovery - default: true",
310+
"ha_mqtt_auto_discovery",
311+
)
312+
config["mqtt"].yaml_add_eol_comment(
313+
"Prefix for Home Assistant MQTT auto discovery - default: homeassistant",
314+
"ha_mqtt_auto_discovery_prefix",
315+
)
316+
271317
# refresh time configuration
272318
config.yaml_add_eol_comment(
273319
"Default refresh time of EOS connect in minutes - default: 3",

src/eos_connect.py

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from interfaces.evcc_interface import EvccInterface
2323
from interfaces.eos_interface import EosInterface
2424
from interfaces.price_interface import PriceInterface
25+
from interfaces.mqtt_interface import MqttInterface
2526

2627
EOS_TGT_DURATION = 48
2728
EOS_API_GET_PV_FORECAST = "https://api.akkudoktor.net/forecast"
@@ -119,6 +120,10 @@ def charging_state_callback(new_state):
119120
change_control_state()
120121

121122

123+
mqtt_interface = MqttInterface(
124+
config_manager.config["mqtt"]
125+
)
126+
122127
evcc_interface = EvccInterface(
123128
url=config_manager.config["evcc"]["url"],
124129
update_interval=10,
@@ -140,7 +145,7 @@ def charging_state_callback(new_state):
140145
config_manager.config.get("battery", {}).get("url", ""),
141146
config_manager.config.get("battery", {}).get("soc_sensor", ""),
142147
config_manager.config.get("battery", {}).get("access_token", ""),
143-
config_manager.config.get("battery", {})
148+
config_manager.config.get("battery", {}),
144149
)
145150

146151
price_interface = PriceInterface(
@@ -300,9 +305,7 @@ def get_pv_akku_data():
300305
"max_charge_power_w": config_manager.config["battery"][
301306
"max_charge_power_w"
302307
],
303-
"initial_soc_percentage": round(
304-
battery_interface.get_current_soc()
305-
),
308+
"initial_soc_percentage": round(battery_interface.get_current_soc()),
306309
"min_soc_percentage": config_manager.config["battery"][
307310
"min_soc_percentage"
308311
],
@@ -525,6 +528,13 @@ def run_optimization(self):
525528
) as file:
526529
json.dump(json_optimize_input, file, indent=4)
527530

531+
mqtt_interface.update_publish_topics(
532+
{
533+
"optimization/state": {
534+
"value": self.get_current_state()["request_state"]
535+
}
536+
}
537+
)
528538
optimized_response = eos_interface.eos_set_optimize_request(
529539
json_optimize_input, config_manager.config["eos"]["timeout"]
530540
)
@@ -560,6 +570,14 @@ def run_optimization(self):
560570
sleeptime = (next_eval - loop_now).total_seconds()
561571
minutes, seconds = divmod(sleeptime, 60)
562572
self.__set_state_next_run(next_eval.astimezone(time_zone).isoformat())
573+
mqtt_interface.update_publish_topics(
574+
{
575+
"optimization/last_run": {
576+
"value": self.get_current_state()["last_response_timestamp"]},
577+
"optimization/next_run": {
578+
"value": self.get_current_state()["next_run"]},
579+
}
580+
)
563581
logger.info(
564582
"[Main] Next optimization at %s. Sleeping for %d min %.0f seconds\n",
565583
next_eval.strftime("%H:%M:%S"),
@@ -585,6 +603,19 @@ def setting_control_data(ac_charge_demand_rel, dc_charge_demand_rel, discharge_a
585603
base_control.set_current_ac_charge_demand(ac_charge_demand_rel)
586604
base_control.set_current_dc_charge_demand(dc_charge_demand_rel)
587605
base_control.set_current_discharge_allowed(bool(discharge_allowed))
606+
mqtt_interface.update_publish_topics(
607+
{
608+
"control/eos_ac_charge_demand": {
609+
"value": base_control.get_current_ac_charge_demand()
610+
},
611+
"control/eos_dc_charge_demand": {
612+
"value": base_control.get_current_dc_charge_demand()
613+
},
614+
"control/eos_discharge_allowed": {
615+
"value": base_control.get_current_discharge_allowed()
616+
}
617+
}
618+
)
588619
# set the current battery state of charge
589620
base_control.set_current_battery_soc(battery_interface.get_current_soc())
590621
# getting the current charging state from evcc
@@ -616,6 +647,23 @@ def change_control_state():
616647
current_overall_state = base_control.get_current_overall_state_number()
617648
current_overall_state_text = base_control.get_current_overall_state()
618649

650+
mqtt_interface.update_publish_topics(
651+
{
652+
"control/overall_state": {
653+
"value": base_control.get_current_overall_state_number()
654+
},
655+
"optimization/state": {
656+
"value": optimization_scheduler.get_current_state()["request_state"]
657+
},
658+
"control/override_remain_time": { "value": "01:00" },
659+
"battery/soc": {"value": battery_interface.get_current_soc()},
660+
"battery/remaining_energy": {
661+
"value": battery_interface.get_current_usable_capacity()
662+
},
663+
"status": {"value": "online"},
664+
}
665+
)
666+
619667
# Check if the overall state of the inverter was changed recently
620668
if base_control.was_overall_state_changed_recently(180):
621669
logger.debug("[Main] Overall state changed recently")
@@ -761,6 +809,7 @@ def get_controls():
761809
"evcc": {
762810
"charging_state": base_control.get_current_evcc_charging_state(),
763811
"charging_mode": base_control.get_current_evcc_charging_mode(),
812+
"current_session": evcc_interface.get_current_detail_data(),
764813
},
765814
"battery": {
766815
"soc": current_battery_soc,
@@ -799,6 +848,7 @@ def get_controls():
799848
and inverter_interface is not None
800849
):
801850
inverter_interface.shutdown()
851+
mqtt_interface.shutdown()
802852
evcc_interface.shutdown()
803853
battery_interface.shutdown()
804854
logger.info("[Main] Server stopped")

src/interfaces/base_control.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def was_overall_state_changed_recently(self, time_window_seconds):
7272

7373
def get_current_ac_charge_demand(self):
7474
"""
75-
Returns the current AC charge demand.
75+
Returns the current AC charge demand calculated based on maximum battery charge power.
7676
"""
7777
return self.current_ac_charge_demand
7878

0 commit comments

Comments
 (0)