Acties:
  • +18 Henk 'm!
Afbeeldingslocatie: https://tweakers.net/i/UEIxmuz-sp16v8oY2iif6QjPjBg=/800x/filters:strip_exif()/f/image/m0wMK22D1JwJig3Z24R6IERt.png?f=fotoalbum_large

Heb jij basis kennis van Home Assistant dan gaat je dit zeker lukken! Ben je nieuw in Home Assistant land, pas dan op! Voor je het weet wil je alles in Home Assistant. Dit topic bespreekt beide integraties, laat je creativiteit de vrije loop. Delen is altijd beter dan voor jezelf houden.

Aansturingsmogelijkheden

Zendure (Fireson) (cloud/lokaal)zenSDK (Gielz) (lokaal)zenSDK (zelfbouw) (lokaal)
Hyper 2000 (MQTT)
Solarflow 800 pro (zenSDK)Solarflow 800 proSolarflow 800 pro
Solarflow 2400 AC (zenSDK)Solarflow 2400 ACSolarflow 2400 AC

Draait het allemaal, geef dan even door wat je gebruikt; https://strawpoll.com/05ZdzxXvmn6
Afbeeldingslocatie: https://tweakers.net/i/vIznA5ZMDZVQr2uaiXThnJkGJfc=/fit-in/4920x3264/filters:max_bytes(3145728):no_upscale():strip_icc():strip_exif()/f/image/C7TrxSIqFWbOaK4UfmPkNCAt.jpg?f=user_large
*19-09-2025


Recente startpost aanpassingen

zenSDK gielz (lokaal)
2025-09-16 🔴‬ CHANGE - Automatisering Het uitgesteld laden zit nu niet meer in de automatisering. Dit omdat je dit tegenwoordig eenvoudig zelf kunt maken in een losse automatisering door de juiste modus te selecteren. Zet bijvoorbeeld 1 uur voor zonsopgang de modus naar "Alleen slim ontladen" daarna 1 uur na zonsopgang de modus naar "Nul op de meter". Hierdoor stel je het laden met 1 uur uit en vind er een nette reset plaats van het huidige vermogen.
2025-09-07 🔴‬ NEW - Nieuwe/gewijzigde sensoren 12 nieuwe sensoren zijn toegevoegd en alle data is nu realtime via de enkele API call.
‪‪2025-09-04 🔴‬ NEW - Nieuwe/gewijzigde sensoren De sensoren "Indicatie Beschikbare Energie", "Aantal Batterijen" zijn toegevoegd. "Resterende Ontlaad Tijd" is verbeterd en toont geen vreemde 999u tijden meer.
‪‪2025-08-27 🔴‬ NEW - zenSDK (Gielz) 2.0 Volledige TS is herzien om het allemaal weer een stuk makkelijker en vooral om een betere aansturing te krijgen van de NOM. De grootste aanpassing is eigenlijk het niet meer nodig hebben van een externe meting (bijv Homewizard Energysocket). Ook een aantal kleine aanpassingen zoals nog maar één automatisering en een strakkere NOM lijn.


zenSDK gielz (lokaal)

https://github.com/Zendure/zenSDK
Deze maakt gebruik van de ZenSDK van Zendure zelf. Hierbij maak je lokaal verbinding met je batterij.

code:
1
http://<IP-BATTERIJ>/properties/report
in je internet browser om te zien of je zenSDK data hebt via het juiste ip.
Afbeeldingslocatie: https://tweakers.net/i/C47_saBRngvlHQ-Eg5yheaDAdM4=/800x/filters:strip_exif()/f/image/d8rYj0ZwcJYzgpRe4u5TPQmQ.png?f=fotoalbum_large

(1/3) Sensoren aanmaken via configuration.yaml
Zorg eerst dat HEMS is uitgeschakeld in de app, 2 stuurlui is geen goed plan.

Daarna gaan wij alles aanmaken voor de restful integratie (zit standaard in HA). Hiervoor heb ik een bijna plug-n-play Configuration.yaml gemaakt waarbij je de volgende hardware nodig hebt; P1 van Homewizard (of een andere P1 met data per seconden) en een Solarflow 2400 AC. Heb je een Solarflow 800 pro dan zal je even alle namen moeten nalopen en veranderen.

Vul de volgende gegevens in;
<IP-BATTERIJ> (in de app te vinden bij device information)
<SERIAL-2400AC> (in de app te vinden bij device information of via je properties link in je internet browser)
<IP-HOMEWIZARD-P1> (zorg dat de lokale api aan staat in de app van homewizard)
<NORDPOOL> vul hier je Nordpool HACS entiteit met kwartier prijzen/kwh in deze is optioneel
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
# Laad standaard set van integraties. Niet verwijderen.
default_config:

# Laad frontend thema's uit de themes-map
frontend:
  themes: !include_dir_merge_named themes

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

input_select:
  zendure_2400_ac_modus_selecteren:
    name: Zendure 2400 AC Modus Selecteren
    icon: mdi:battery-charging-wireless
    options:
      - Standby
      - Handmatig
      - Nul op de meter
      - Alleen slim ontladen
      - Alleen slim opladen
      - Opladen met 2400 watt
      - Ontladen met 2400 watt

input_boolean:
  dynamisch_15_minuten:
    name: Dynamisch 15 Minuten
    icon: mdi:clock-time-three-outline

input_text:
  dynamisch_handmatige_periode:
    name: Dynamisch Handmatige Periode
    icon: mdi:view-grid
    max: 250
    mode: text

  dynamisch_handmatige_periode_morgen:
    name: Dynamisch Handmatige Periode Morgen
    icon: mdi:view-grid
    max: 250
    mode: text

input_number:
  zendure_2400_ac_handmatig_vermogen:
    name: Zendure 2400 AC Handmatig Vermogen
    min: -2400
    max: 2400
    step: 1
    mode: box
    unit_of_measurement: "W"

  dynamisch_minimale_spread:
    name: Dynamisch Minimale Spread
    icon: mdi:percent-box
    min: 0
    max: 100
    step: 1
    unit_of_measurement: '%'
    mode: box

  dynamisch_goedkoopste_x_periode:
    name: Dynamisch Goedkoopste X Periode
    icon: mdi:view-grid-plus
    min: 0
    max: 96
    step: 1
    mode: box

  dynamisch_duurste_x_periode:
    name: Dynamisch Duurste X Periode
    icon: mdi:view-grid-plus
    min: 0
    max: 96
    step: 1
    mode: box

  dynamisch_goedkoopste_x_periode_morgen:
    name: Dynamisch Goedkoopste X Periode Morgen
    icon: mdi:view-grid-plus
    min: 0
    max: 96
    step: 1
    mode: box

  dynamisch_duurste_x_periode_morgen:
    name: Dynamisch Duurste X Periode Morgen
    icon: mdi:view-grid-plus
    min: 0
    max: 96
    step: 1
    mode: box

sensor:
  - platform: statistics
    name: "Zendure 2400 AC Efficiëntie Import (24u gemiddelde)"
    unique_id: zendure_2400_ac_efficientie_import_24u
    entity_id: sensor.zendure_2400_ac_efficientie_import
    state_characteristic: mean
    sampling_size: 86400
    max_age:
      hours: 24

  - platform: statistics
    name: "Zendure 2400 AC Efficiëntie Export (24u gemiddelde)"
    unique_id: zendure_2400_ac_efficientie_export_24u
    entity_id: sensor.zendure_2400_ac_efficientie_export
    state_characteristic: mean
    sampling_size: 86400
    max_age:
      hours: 24

  - platform: integration
    name: "Zendure 2400 AC Energie Import"
    unique_id: zendure_2400_ac_energie_import
    source: sensor.zendure_2400_ac_vermogen_import
    unit_prefix: k
    round: 2
    method: trapezoidal

  - platform: integration
    name: "Zendure 2400 AC Energie Export"
    unique_id: zendure_2400_ac_energie_export
    source: sensor.zendure_2400_ac_vermogen_export
    unit_prefix: k
    round: 2
    method: trapezoidal

template:
  - sensor:
      - name: "Dynamisch Nordpool"
        unique_id: dynamisch_nordpool
        icon: mdi:cash
        unit_of_measurement: "€/kWh"
        state: >-
          {% set nordpool = 'sensor.<NORDPOOL>' %}
          {% set use_15_min = is_state('input_boolean.dynamisch_15_minuten', 'on') %}
          {% if use_15_min %}
            {% set data = state_attr(nordpool, 'raw_today') or [] %}
            {% set nowts = as_timestamp(now()) %}
            {% set current = namespace(val=None) %}
            {% for p in data %}
              {% set s = as_timestamp(as_datetime(p.start)) %}
              {% set e = as_timestamp(as_datetime(p.end)) %}
              {% if nowts >= s and nowts < e %}
                {% set current.val = (p.value) | round(5) %}
              {% endif %}
            {% endfor %}
            {{ current.val if current.val is not none else 'unknown' }}
          {% else %}
            {% set raw = state_attr(nordpool, 'raw_today') %}
            {% set now = now() %}
            {% if raw %}
              {% set current_hour_values = raw 
                | selectattr('start', '>=', now.replace(minute=0, second=0, microsecond=0)) 
                | selectattr('start', '<', now.replace(minute=0, second=0, microsecond=0) + timedelta(hours=1)) 
                | map(attribute='value') 
                | list %}
              {% if current_hour_values %}
                {{ (current_hour_values | sum / current_hour_values | count) | round(5) }}
              {% else %}
                {{ states(nordpool) }}
              {% endif %}
            {% else %}
              {{ states(nordpool) }}
            {% endif %}
          {% endif %}
        attributes:
          raw_today: >-
            {% set nordpool = 'sensor.<NORDPOOL>' %}
            {% set use_15_min = is_state('input_boolean.dynamisch_15_minuten', 'on') %}
            {% set raw = state_attr(nordpool, 'raw_today') %}
            {% if raw %}
              [
              {% if use_15_min %}
                {% for item in raw %}
                  {
                    "start": "{{ item.start.isoformat() }}",
                    "end": "{{ item.end.isoformat() }}",
                    "value": {{ item.value }}
                  }{% if not loop.last %},{% endif %}
                {% endfor %}
              {% else %}
                {% set hourly = raw | groupby('start.hour') %}
                {% for hour_group in hourly %}
                  {% set values = hour_group.list | map(attribute='value') | list %}
                  {% set hour_start = hour_group.list[0].start.replace(minute=0, second=0, microsecond=0) %}
                  {% set hour_end = hour_start + timedelta(hours=1) %}
                  {
                    "start": "{{ hour_start.isoformat() }}",
                    "end": "{{ hour_end.isoformat() }}",
                    "value": {{ (values | sum / values | count) | round(5) }}
                  }{% if not loop.last %},{% endif %}
                {% endfor %}
              {% endif %}
              ]
            {% else %}
              []
            {% endif %}
          raw_tomorrow: >-
            {% set nordpool = 'sensor.<NORDPOOL>' %}
            {% set use_15_min = is_state('input_boolean.dynamisch_15_minuten', 'on') %}
            {% set raw = state_attr(nordpool, 'raw_tomorrow') %}
            {% if raw %}
              [
              {% if use_15_min %}
                {% for item in raw %}
                  {
                    "start": "{{ item.start.isoformat() }}",
                    "end": "{{ item.end.isoformat() }}",
                    "value": {{ item.value }}
                  }{% if not loop.last %},{% endif %}
                {% endfor %}
              {% else %}
                {% set hourly = raw | groupby('start.hour') %}
                {% for hour_group in hourly %}
                  {% set values = hour_group.list | map(attribute='value') | list %}
                  {% set hour_start = hour_group.list[0].start.replace(minute=0, second=0, microsecond=0) %}
                  {% set hour_end = hour_start + timedelta(hours=1) %}
                  {
                    "start": "{{ hour_start.isoformat() }}",
                    "end": "{{ hour_end.isoformat() }}",
                    "value": {{ (values | sum / values | count) | round(5) }}
                  }{% if not loop.last %},{% endif %}
                {% endfor %}
              {% endif %}
              ]
            {% else %}
              []
            {% endif %}

      - name: "Dynamisch Spread Indicatie"
        unique_id: dynamisch_spread_indicatie
        icon: mdi:percent-box
        unit_of_measurement: "%"
        state: >
          {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_today') %}
          {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode') | int %}
          {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode') | int %}
          {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
          
          {% if prijzen is iterable %}
            {% set ns = namespace(goedkoopste_uren=[], duurste_uren=[]) %}
            {% if handmatige | length > 0 %}
              {% for item in handmatige.split(';') %}
                {% set type = item[0] %}
                {% set tijd = item[1:] %}
                {% for uur in prijzen %}
                  {% set dt_start = uur.start | as_datetime %}
                  {% if dt_start.strftime('%H:%M') == tijd %}
                    {% if type == 'G' %}
                      {% set ns.goedkoopste_uren = ns.goedkoopste_uren + [uur] %}
                    {% elif type == 'D' %}
                      {% set ns.duurste_uren = ns.duurste_uren + [uur] %}
                    {% endif %}
                  {% endif %}
                {% endfor %}
              {% endfor %}
            {% else %}
              {% set prijzen_per_uur = prijzen | sort(attribute='value') %}
              {% set ns.goedkoopste_uren = prijzen_per_uur[:aantal_goedkoop] %}
              {% if aantal_duur > 0 %}
                {% set ns.duurste_uren = prijzen_per_uur[-aantal_duur:] %}
              {% else %}
                {% set goedkope_starttijden = ns.goedkoopste_uren | map(attribute='start') | list %}
                {% set ns.duurste_uren = prijzen | rejectattr('start', 'in', goedkope_starttijden) | list %}
              {% endif %}
            {% endif %}

            {% if ns.goedkoopste_uren | count > 0 and ns.duurste_uren | count > 0 %}
              {% set avg_goedkoop = ns.goedkoopste_uren | map(attribute='value') | sum / ns.goedkoopste_uren | count %}
              {% set avg_duur = ns.duurste_uren | map(attribute='value') | sum / ns.duurste_uren | count %}
              {% set spread_pct = ((avg_duur - avg_goedkoop) / avg_goedkoop) * 100 %}
              {{ spread_pct | round(1) }}
            {% else %}
              0
            {% endif %}
          {% else %}
            0
          {% endif %}
        attributes:
          handmatige_periode: >
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_today') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode') | int %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
            {% set ns = namespace(goedkoopste=[], duurste=[]) %}
            {% if prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% set type = item[0] %}
                  {% set tijd = item[1:] %}
                  {% for uur in prijzen %}
                    {% set dt_start = uur.start | as_datetime %}
                    {% if dt_start.strftime('%H:%M') == tijd %}
                      {% if type == 'G' %}
                        {% set ns.goedkoopste = ns.goedkoopste + [(type ~ dt_start.strftime('%H:%M'))] %}
                      {% elif type == 'D' %}
                        {% set ns.duurste = ns.duurste + [(type ~ dt_start.strftime('%H:%M'))] %}
                      {% endif %}
                    {% endif %}
                  {% endfor %}
                {% endfor %}
              {% else %}
                {% set prijzen_per_uur = prijzen | sort(attribute='value') %}
                {% set goedkoopste_uren = prijzen_per_uur[:aantal_goedkoop] %}
                {% set dure_uren = prijzen_per_uur[-aantal_duur:] if aantal_duur > 0 else prijzen | rejectattr('start', 'in', goedkoopste_uren | map(attribute='start') | list) | list %}
                {% for uur in goedkoopste_uren %}
                  {% set tijd = uur.start | as_datetime %}
                  {% set ns.goedkoopste = ns.goedkoopste + ['G' ~ tijd.strftime('%H:%M')] %}
                {% endfor %}
                {% for uur in dure_uren %}
                  {% set tijd = uur.start | as_datetime %}
                  {% set ns.duurste = ns.duurste + ['D' ~ tijd.strftime('%H:%M')] %}
                {% endfor %}
              {% endif %}
              {{ (ns.duurste + ns.goedkoopste) | join(';') }}
            {% else %}
              ""
            {% endif %}
          goedkoopste_periode: >
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_today') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
            {% set ns = namespace(uren=[]) %}
            {% if prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'G' %}
                    {% set tijd = item[1:] %}
                    {% for uur in prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set ns.uren = (prijzen | sort(attribute='value'))[:aantal_goedkoop] %}
              {% endif %}
              [
              {% for uur in ns.uren %}
                "{{ (uur.start | as_datetime).strftime('%H:%M') }} - €{{ '%.4f' | format(uur.value) }}"
                {% if not loop.last %}, {% endif %}
              {% endfor %}
              ]
            {% else %}
              []
            {% endif %}
          duurste_periode: >
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_today') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode') | int %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
            {% set ns = namespace(uren=[]) %}
            {% if prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'D' %}
                    {% set tijd = item[1:] %}
                    {% for uur in prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set prijzen_per_uur = prijzen | sort(attribute='value') %}
                {% set goedkope_starttijden = prijzen_per_uur[:aantal_goedkoop] | map(attribute='start') | list %}
                {% if aantal_duur > 0 %}
                  {% set ns.uren = prijzen_per_uur[-aantal_duur:] %}
                {% else %}
                  {% set ns.uren = prijzen | rejectattr('start', 'in', goedkope_starttijden) | list %}
                {% endif %}
              {% endif %}
              [
              {% for uur in ns.uren %}
                "{{ (uur.start | as_datetime).strftime('%H:%M') }} - €{{ '%.4f' | format(uur.value) }}"
                {% if not loop.last %}, {% endif %}
              {% endfor %}
              ]
            {% else %}
              []
            {% endif %}
          gemiddelde_goedkoop: >
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_today') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
            {% set ns = namespace(uren=[]) %}
            {% if prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'G' %}
                    {% set tijd = item[1:] %}
                    {% for uur in prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set ns.uren = (prijzen | sort(attribute='value'))[:aantal_goedkoop] %}
              {% endif %}
              {% if ns.uren | count > 0 %}
                {% set avg = ns.uren | map(attribute='value') | sum / ns.uren | count %}
                €{{ '%.4f' | format(avg) }}
              {% else %}
                n.v.t.
              {% endif %}
            {% else %}
              n.v.t.
            {% endif %}
          gemiddelde_duur: >
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_today') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode') | int %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
            {% set ns = namespace(uren=[]) %}
            {% if prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'D' %}
                    {% set tijd = item[1:] %}
                    {% for uur in prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set prijzen_per_uur = prijzen | sort(attribute='value') %}
                {% set goedkope_starttijden = prijzen_per_uur[:aantal_goedkoop] | map(attribute='start') | list %}
                {% if aantal_duur > 0 %}
                  {% set ns.uren = prijzen_per_uur[-aantal_duur:] %}
                {% else %}
                  {% set ns.uren = prijzen | rejectattr('start', 'in', goedkope_starttijden) | list %}
                {% endif %}
              {% endif %}
              {% if ns.uren | count > 0 %}
                {% set avg = ns.uren | map(attribute='value') | sum / ns.uren | count %}
                €{{ '%.4f' | format(avg) }}
              {% else %}
                n.v.t.
              {% endif %}
            {% else %}
              n.v.t.
            {% endif %}
          spread_berekening: >
            (gemiddeld duur - goedkoop) / goedkoop × 100

      - name: "Dynamisch Spread Indicatie NOM"
        unique_id: dynamisch_spread_indicatie_NOM
        icon: mdi:percent-box
        unit_of_measurement: "%"
        state: >
          {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_today') %}
          {% set duurste_prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'duurste_na_eerste_goedkope') %}
          {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode') | int %}
          {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode') | int %}
          {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
          {% set ns = namespace(goedkoopste_uren=[], duurste_uren=[]) %}

          {% if prijzen is iterable and duurste_prijzen is iterable %}
            {% if handmatige | length > 0 %}
              {% for item in handmatige.split(';') %}
                {% set type = item[0] %}
                {% set tijd = item[1:] %}
                {% if type == 'G' %}
                  {% for uur in prijzen %}
                    {% set dt_start = uur.start | as_datetime %}
                    {% if dt_start.strftime('%H:%M') == tijd %}
                      {% set ns.goedkoopste_uren = ns.goedkoopste_uren + [uur] %}
                    {% endif %}
                  {% endfor %}
                {% elif type == 'D' %}
                  {% for uur in duurste_prijzen %}
                    {% set dt_start = uur.start | as_datetime %}
                    {% if dt_start.strftime('%H:%M') == tijd %}
                      {% set ns.duurste_uren = ns.duurste_uren + [uur] %}
                    {% endif %}
                  {% endfor %}
                {% endif %}
              {% endfor %}
            {% else %}
              {% set ns.goedkoopste_uren = (prijzen | sort(attribute='value'))[:aantal_goedkoop] %}
              {% set duurste_sorted = duurste_prijzen | sort(attribute='value', reverse=true) %}
              {% if aantal_duur > 0 %}
                {% set ns.duurste_uren = duurste_sorted[:aantal_duur] %}
              {% else %}
                {% set ns.duurste_uren = duurste_sorted %}
              {% endif %}
            {% endif %}

            {% if ns.goedkoopste_uren | count > 0 and ns.duurste_uren | count > 0 %}
              {% set avg_goedkoop = ns.goedkoopste_uren | map(attribute='value') | sum / ns.goedkoopste_uren | count %}
              {% set avg_duur = ns.duurste_uren | map(attribute='value') | sum / ns.duurste_uren | count %}
              {% set spread_pct = ((avg_duur - avg_goedkoop) / avg_goedkoop) * 100 %}
              {{ spread_pct | round(1) }}
            {% else %}
              0
            {% endif %}
          {% else %}
            0
          {% endif %}
        attributes:
          goedkoopste_uren: >
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_today') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
            {% set ns = namespace(uren=[]) %}

            {% if prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'G' %}
                    {% set tijd = item[1:] %}
                    {% for uur in prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set ns.uren = (prijzen | sort(attribute='value'))[:aantal_goedkoop] %}
              {% endif %}
              [
              {% for uur in ns.uren %}
                "{{ (uur.start | as_datetime).strftime('%H:%M') }} - €{{ '%.4f' | format(uur.value) }}"
                {% if not loop.last %}, {% endif %}
              {% endfor %}
              ]
            {% else %}
              []
            {% endif %}
          duurste_uren: >
            {% set duurste_prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'duurste_na_eerste_goedkope') %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
            {% set ns = namespace(uren=[]) %}

            {% if duurste_prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'D' %}
                    {% set tijd = item[1:] %}
                    {% for uur in duurste_prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set ns.uren = duurste_prijzen | sort(attribute='value', reverse=true) %}
                {% if aantal_duur > 0 %}
                  {% set ns.uren = ns.uren[:aantal_duur] %}
                {% endif %}
              {% endif %}
              [
              {% for uur in ns.uren %}
                "{{ (uur.start | as_datetime).strftime('%H:%M') }} - €{{ '%.4f' | format(uur.value) }}"
                {% if not loop.last %}, {% endif %}
              {% endfor %}
              ]
            {% else %}
              []
            {% endif %}
          gemiddelde_goedkoop: >
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_today') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
            {% set ns = namespace(uren=[]) %}

            {% if prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'G' %}
                    {% set tijd = item[1:] %}
                    {% for uur in prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set ns.uren = (prijzen | sort(attribute='value'))[:aantal_goedkoop] %}
              {% endif %}
              {% if ns.uren | count > 0 %}
                {% set avg = ns.uren | map(attribute='value') | sum / ns.uren | count %}
                €{{ '%.4f' | format(avg) }}
              {% else %}
                n.v.t.
              {% endif %}
            {% else %}
              n.v.t.
            {% endif %}
          gemiddelde_duur: >
            {% set duurste_prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'duurste_na_eerste_goedkope') %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
            {% set ns = namespace(uren=[]) %}

            {% if duurste_prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'D' %}
                    {% set tijd = item[1:] %}
                    {% for uur in duurste_prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set ns.uren = duurste_prijzen | sort(attribute='value', reverse=true) %}
                {% if aantal_duur > 0 %}
                  {% set ns.uren = ns.uren[:aantal_duur] %}
                {% endif %}
              {% endif %}
              {% if ns.uren | count > 0 %}
                {% set avg = ns.uren | map(attribute='value') | sum / ns.uren | count %}
                €{{ '%.4f' | format(avg) }}
              {% else %}
                n.v.t.
              {% endif %}
            {% else %}
              n.v.t.
            {% endif %}
          spread_berekening: >
            (gemiddeld duur - goedkoop) / goedkoop × 100

      - name: "Dynamisch Spread Indicatie Morgen"
        unique_id: dynamisch_spread_indicatie_morgen
        icon: mdi:percent-box
        unit_of_measurement: "%"
        state: >
          {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_tomorrow') %}
          {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode_morgen') | int %}
          {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode_morgen') | int %}
          {% set handmatige = states('input_text.dynamisch_handmatige_periode_morgen') %}
          
          {% if prijzen is iterable %}
            {% set ns = namespace(goedkoopste_uren=[], duurste_uren=[]) %}
            {% if handmatige | length > 0 %}
              {% for item in handmatige.split(';') %}
                {% set type = item[0] %}
                {% set tijd = item[1:] %}
                {% for uur in prijzen %}
                  {% set dt_start = uur.start | as_datetime %}
                  {% if dt_start.strftime('%H:%M') == tijd %}
                    {% if type == 'G' %}
                      {% set ns.goedkoopste_uren = ns.goedkoopste_uren + [uur] %}
                    {% elif type == 'D' %}
                      {% set ns.duurste_uren = ns.duurste_uren + [uur] %}
                    {% endif %}
                  {% endif %}
                {% endfor %}
              {% endfor %}
            {% else %}
              {% set prijzen_per_uur = prijzen | sort(attribute='value') %}
              {% set ns.goedkoopste_uren = prijzen_per_uur[:aantal_goedkoop] %}
              {% if aantal_duur > 0 %}
                {% set ns.duurste_uren = prijzen_per_uur[-aantal_duur:] %}
              {% else %}
                {% set goedkope_starttijden = ns.goedkoopste_uren | map(attribute='start') | list %}
                {% set ns.duurste_uren = prijzen | rejectattr('start', 'in', goedkope_starttijden) | list %}
              {% endif %}
            {% endif %}
            {% if ns.goedkoopste_uren | count > 0 and ns.duurste_uren | count > 0 %}
              {% set avg_goedkoop = ns.goedkoopste_uren | map(attribute='value') | sum / ns.goedkoopste_uren | count %}
              {% set avg_duur = ns.duurste_uren | map(attribute='value') | sum / ns.duurste_uren | count %}
              {% set spread_pct = ((avg_duur - avg_goedkoop) / avg_goedkoop) * 100 %}
              {{ spread_pct | round(1) }}
            {% else %}
              0
            {% endif %}
          {% else %}
            0
          {% endif %}
        attributes:
          handmatige_periode: >
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_tomorrow') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode_morgen') | int %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode_morgen') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode_morgen') %}
            {% set ns = namespace(goedkoopste=[], duurste=[]) %}
            {% if prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% set type = item[0] %}
                  {% set tijd = item[1:] %}
                  {% for uur in prijzen %}
                    {% set dt_start = uur.start | as_datetime %}
                    {% if dt_start.strftime('%H:%M') == tijd %}
                      {% if type == 'G' %}
                        {% set ns.goedkoopste = ns.goedkoopste + ['G' ~ dt_start.strftime('%H:%M')] %}
                      {% elif type == 'D' %}
                        {% set ns.duurste = ns.duurste + ['D' ~ dt_start.strftime('%H:%M')] %}
                      {% endif %}
                    {% endif %}
                  {% endfor %}
                {% endfor %}
              {% else %}
                {% set prijzen_per_uur = prijzen | sort(attribute='value') %}
                {% set goedkoopste_uren = prijzen_per_uur[:aantal_goedkoop] %}
                {% set dure_uren = prijzen_per_uur[-aantal_duur:] if aantal_duur > 0 else prijzen | rejectattr('start', 'in', goedkoopste_uren | map(attribute='start') | list) | list %}
                {% for uur in goedkoopste_uren %}
                  {% set tijd = uur.start | as_datetime %}
                  {% set ns.goedkoopste = ns.goedkoopste + ['G' ~ tijd.strftime('%H:%M')] %}
                {% endfor %}
                {% for uur in dure_uren %}
                  {% set tijd = uur.start | as_datetime %}
                  {% set ns.duurste = ns.duurste + ['D' ~ tijd.strftime('%H:%M')] %}
                {% endfor %}
              {% endif %}
              {{ (ns.duurste + ns.goedkoopste) | join(';') }}
            {% else %}
              ""
            {% endif %}
          goedkoopste_periode: >
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_tomorrow') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode_morgen') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode_morgen') %}
            {% set ns = namespace(uren=[]) %}
            {% if prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'G' %}
                    {% set tijd = item[1:] %}
                    {% for uur in prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set ns.uren = (prijzen | sort(attribute='value'))[:aantal_goedkoop] %}
              {% endif %}
              [
              {% for uur in ns.uren %}
                "{{ (uur.start | as_datetime).strftime('%H:%M') }} - €{{ '%.4f' | format(uur.value) }}"
                {% if not loop.last %}, {% endif %}
              {% endfor %}
              ]
            {% else %}
              []
            {% endif %}
          duurste_periode: >
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_tomorrow') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode_morgen') | int %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode_morgen') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode_morgen') %}
            {% set ns = namespace(uren=[]) %}
            {% if prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'D' %}
                    {% set tijd = item[1:] %}
                    {% for uur in prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set prijzen_per_uur = prijzen | sort(attribute='value') %}
                {% set goedkope_starttijden = prijzen_per_uur[:aantal_goedkoop] | map(attribute='start') | list %}
                {% if aantal_duur > 0 %}
                  {% set ns.uren = prijzen_per_uur[-aantal_duur:] %}
                {% else %}
                  {% set ns.uren = prijzen | rejectattr('start', 'in', goedkope_starttijden) | list %}
                {% endif %}
              {% endif %}
              [
              {% for uur in ns.uren %}
                "{{ (uur.start | as_datetime).strftime('%H:%M') }} - €{{ '%.4f' | format(uur.value) }}"
                {% if not loop.last %}, {% endif %}
              {% endfor %}
              ]
            {% else %}
              []
            {% endif %}
          gemiddelde_goedkoop: >
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_tomorrow') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode_morgen') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode_morgen') %}
            {% set ns = namespace(uren=[]) %}
            {% if prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'G' %}
                    {% set tijd = item[1:] %}
                    {% for uur in prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set ns.uren = (prijzen | sort(attribute='value'))[:aantal_goedkoop] %}
              {% endif %}
              {% if ns.uren | count > 0 %}
                {% set avg = ns.uren | map(attribute='value') | sum / ns.uren | count %}
                €{{ '%.4f' | format(avg) }}
              {% else %}
                n.v.t.
              {% endif %}
            {% else %}
              n.v.t.
            {% endif %}
          gemiddelde_duur: >
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_tomorrow') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode_morgen') | int %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode_morgen') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode_morgen') %}
            {% set ns = namespace(uren=[]) %}
            {% if prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'D' %}
                    {% set tijd = item[1:] %}
                    {% for uur in prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set prijzen_per_uur = prijzen | sort(attribute='value') %}
                {% set goedkope_starttijden = prijzen_per_uur[:aantal_goedkoop] | map(attribute='start') | list %}
                {% if aantal_duur > 0 %}
                  {% set ns.uren = prijzen_per_uur[-aantal_duur:] %}
                {% else %}
                  {% set ns.uren = prijzen | rejectattr('start', 'in', goedkope_starttijden) | list %}
                {% endif %}
              {% endif %}
              {% if ns.uren | count > 0 %}
                {% set avg = ns.uren | map(attribute='value') | sum / ns.uren | count %}
                €{{ '%.4f' | format(avg) }}
              {% else %}
                n.v.t.
              {% endif %}
            {% else %}
              n.v.t.
            {% endif %}
          spread_berekening: >
            (gemiddeld duur - goedkoop) / goedkoop × 100

      - name: "Dynamisch Spread Indicatie NOM Morgen"
        unique_id: dynamisch_spread_indicatie_nom_morgen
        icon: mdi:percent-box
        unit_of_measurement: "%"
        state: >
          {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_tomorrow') %}
          {% set duurste_prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'duurste_na_eerste_goedkope_morgen') %}
          {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode_morgen') | int %}
          {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode_morgen') | int %}
          {% set handmatige = states('input_text.dynamisch_handmatige_periode_morgen') %}
          {% set ns = namespace(goedkoopste_uren=[], duurste_uren=[]) %}

          {% if prijzen is iterable and duurste_prijzen is iterable %}
            {% if handmatige | length > 0 %}
              {% for item in handmatige.split(';') %}
                {% set type = item[0] %}
                {% set tijd = item[1:] %}
                {% if type == 'G' %}
                  {% for uur in prijzen %}
                    {% set dt_start = uur.start | as_datetime %}
                    {% if dt_start.strftime('%H:%M') == tijd %}
                      {% set ns.goedkoopste_uren = ns.goedkoopste_uren + [uur] %}
                    {% endif %}
                  {% endfor %}
                {% elif type == 'D' %}
                  {% for uur in duurste_prijzen %}
                    {% set dt_start = uur.start | as_datetime %}
                    {% if dt_start.strftime('%H:%M') == tijd %}
                      {% set ns.duurste_uren = ns.duurste_uren + [uur] %}
                    {% endif %}
                  {% endfor %}
                {% endif %}
              {% endfor %}
            {% else %}
              {% set ns.goedkoopste_uren = (prijzen | sort(attribute='value'))[:aantal_goedkoop] %}
              {% set duurste_sorted = duurste_prijzen | sort(attribute='value', reverse=true) %}
              {% if aantal_duur > 0 %}
                {% set ns.duurste_uren = duurste_sorted[:aantal_duur] %}
              {% else %}
                {% set ns.duurste_uren = duurste_sorted %}
              {% endif %}
            {% endif %}

            {% if ns.goedkoopste_uren | count > 0 and ns.duurste_uren | count > 0 %}
              {% set avg_goedkoop = ns.goedkoopste_uren | map(attribute='value') | sum / ns.goedkoopste_uren | count %}
              {% set avg_duur = ns.duurste_uren | map(attribute='value') | sum / ns.duurste_uren | count %}
              {% set spread_pct = ((avg_duur - avg_goedkoop) / avg_goedkoop) * 100 %}
              {{ spread_pct | round(1) }}
            {% else %}
              0
            {% endif %}
          {% else %}
            0
          {% endif %}
        attributes:
          goedkoopste_periode: > 
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_tomorrow') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode_morgen') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode_morgen') %}
            {% set ns = namespace(uren=[]) %}
            {% if prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'G' %}
                    {% set tijd = item[1:] %}
                    {% for uur in prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set ns.uren = (prijzen | sort(attribute='value'))[:aantal_goedkoop] %}
              {% endif %}
              [
              {% for uur in ns.uren %}
                "{{ (uur.start | as_datetime).strftime('%H:%M') }} - €{{ '%.4f' | format(uur.value) }}"
                {% if not loop.last %}, {% endif %}
              {% endfor %}
              ]
            {% else %}
              []
            {% endif %}
          duurste_periode: > 
            {% set duurste_prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'duurste_na_eerste_goedkope_morgen') %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode_morgen') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode_morgen') %}
            {% set ns = namespace(uren=[]) %}
            {% if duurste_prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'D' %}
                    {% set tijd = item[1:] %}
                    {% for uur in duurste_prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set ns.uren = duurste_prijzen | sort(attribute='value', reverse=true) %}
                {% if aantal_duur > 0 %}
                  {% set ns.uren = ns.uren[:aantal_duur] %}
                {% endif %}
              {% endif %}
              [
              {% for uur in ns.uren %}
                "{{ (uur.start | as_datetime).strftime('%H:%M') }} - €{{ '%.4f' | format(uur.value) }}"
                {% if not loop.last %}, {% endif %}
              {% endfor %}
              ]
            {% else %}
              []
            {% endif %}
          gemiddelde_goedkoop: >
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_today') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
            {% set ns = namespace(uren=[]) %}
            {% if prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'G' %}
                    {% set tijd = item[1:] %}
                    {% for uur in prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set ns.uren = (prijzen | sort(attribute='value'))[:aantal_goedkoop] %}
              {% endif %}
              {% if ns.uren | count > 0 %}
                {% set avg = ns.uren | map(attribute='value') | sum / ns.uren | count %}
                €{{ '%.4f' | format(avg) }}
              {% else %}
                n.v.t.
              {% endif %}
            {% else %}
              n.v.t.
            {% endif %}
          gemiddelde_duur: > 
            {% set duurste_prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'duurste_na_eerste_goedkope_morgen') %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode_morgen') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode_morgen') %}
            {% set ns = namespace(uren=[]) %}
            {% if duurste_prijzen is iterable %}
              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% if item[0] == 'D' %}
                    {% set tijd = item[1:] %}
                    {% for uur in duurste_prijzen %}
                      {% set dt_start = uur.start | as_datetime %}
                      {% if dt_start.strftime('%H:%M') == tijd %}
                        {% set ns.uren = ns.uren + [uur] %}
                      {% endif %}
                    {% endfor %}
                  {% endif %}
                {% endfor %}
              {% else %}
                {% set ns.uren = duurste_prijzen | sort(attribute='value', reverse=true) %}
                {% if aantal_duur > 0 %}
                  {% set ns.uren = ns.uren[:aantal_duur] %}
                {% endif %}
              {% endif %}
              {% if ns.uren | count > 0 %}
                {% set avg = ns.uren | map(attribute='value') | sum / ns.uren | count %}
                €{{ '%.4f' | format(avg) }}
              {% else %}
                n.v.t.
              {% endif %}
            {% else %}
              n.v.t.
            {% endif %}
          spread_berekening: >
            (gemiddeld duur - goedkoop) / goedkoop × 100

      - name: "Dynamisch Duurste Periode"
        unique_id: dynamisch_duurste_periode
        icon: mdi:progress-clock
        state: >
          {% set prijzen = state_attr('sensor.dynamisch_nordpool', 'raw_today') %}
          {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode') | int %}
          {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
          {% if prijzen is iterable and aantal_duur > 0 %}
            {% set ns = namespace(dure_starttijden=[]) %}
            
            {% if handmatige | length > 0 %}
              {% for item in handmatige.split(';') %}
                {% set type = item[0] %}
                {% set tijd = item[1:] %}
                {% if type == 'D' %}
                  {% for uur in prijzen %}
                    {% set dt_start = uur.start | as_datetime %}
                    {% if dt_start.strftime('%H:%M') == tijd %}
                      {% set ns.dure_starttijden = ns.dure_starttijden + [uur.start] %}
                    {% endif %}
                  {% endfor %}
                {% endif %}
              {% endfor %}
            {% else %}
              {% set prijzen_sorted = prijzen | sort(attribute='value') %}
              {% set duurste_periodes = prijzen_sorted[-aantal_duur:] %}
              {% set ns.dure_starttijden = duurste_periodes | map(attribute='start') | list %}
            {% endif %}

            {% set nu = now().astimezone() %}
            {% set in_duur_blok = prijzen
              | selectattr('start', 'in', ns.dure_starttijden)
              | selectattr('start', 'le', nu.isoformat())
              | selectattr('end', 'gt', nu.isoformat())
              | list %}

            {% if in_duur_blok | length > 0 %}
              Ja
            {% else %}
              Nee
            {% endif %}
          {% else %}
            Onbekend
          {% endif %}
        attributes:
          raw_today: >
            {% set prijzen = state_attr('sensor.dynamisch_goedkoopste_periode', 'raw_today') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode') | int %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode') | int %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
            {% if prijzen is iterable %}
              {% set ns = namespace(goedkope_starttijden=[], dure_starttijden=[]) %}

              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% set type = item[0] %}
                  {% set tijd = item[1:] %}
                  {% for uur in prijzen %}
                    {% set dt_start = uur.start | as_datetime %}
                    {% if dt_start.strftime('%H:%M') == tijd %}
                      {% if type == 'G' %}
                        {% set ns.goedkope_starttijden = ns.goedkope_starttijden + [uur.start] %}
                      {% elif type == 'D' %}
                        {% set ns.dure_starttijden = ns.dure_starttijden + [uur.start] %}
                      {% endif %}
                    {% endif %}
                  {% endfor %}
                {% endfor %}
              {% else %}
                {% set prijzen_per_uur = prijzen | sort(attribute='value') %}
                {% set goedkoopste_uren = prijzen_per_uur[:aantal_goedkoop] %}
                {% set ns.goedkope_starttijden = goedkoopste_uren | map(attribute='start') | list %}

                {% if aantal_duur > 0 %}
                  {% set duurste_uren = prijzen_per_uur[-aantal_duur:] %}
                {% else %}
                  {% set duurste_uren = prijzen | rejectattr('start', 'in', ns.goedkope_starttijden) | list %}
                {% endif %}
                {% set ns.dure_starttijden = duurste_uren | map(attribute='start') | list %}
              {% endif %}

              [
              {% for uur in prijzen %}
                {
                  "start": "{{ uur.start }}",
                  "end": "{{ uur.end }}",
                  "value": {{ uur.value }},
                  "goedkoop": "{{ 'ja' if uur.start in ns.goedkope_starttijden else 'nee' }}",
                  "duur": "{{ 'ja' if uur.start in ns.dure_starttijden else 'nee' }}"
                }{% if not loop.last %},{% endif %}
              {% endfor %}
              ]
            {% else %}
              []
            {% endif %}

      - name: "Dynamisch Goedkoopste Periode"
        unique_id: dynamisch_goedkoopste_periode
        icon: mdi:progress-clock
        state: >
          {% set prijzen = state_attr('sensor.dynamisch_nordpool', 'raw_today') %}
          {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode') | int %}
          {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
          {% set nu = now().astimezone() %}

          {% if prijzen is iterable %}
            {% set ns = namespace(goedkope_starttijden=[]) %}

            {% if handmatige | length > 0 %}
              {% for item in handmatige.split(';') %}
                {% set type = item[0] %}
                {% set tijd = item[1:] %}
                {% if type == 'G' %}
                  {% for uur in prijzen %}
                    {% set dt_start = uur.start | as_datetime %}
                    {% if dt_start.strftime('%H:%M') == tijd %}
                      {% set ns.goedkope_starttijden = ns.goedkope_starttijden + [uur.start] %}
                    {% endif %}
                  {% endfor %}
                {% endif %}
              {% endfor %}
            {% else %}
              {% set prijzen_sorted = prijzen | sort(attribute='value') %}
              {% set goedkoopste_periodes = prijzen_sorted[:aantal_goedkoop] %}
              {% set ns.goedkope_starttijden = goedkoopste_periodes | map(attribute='start') | list %}
            {% endif %}

            {% set in_goedkoop_blok = prijzen 
              | selectattr('start', 'in', ns.goedkope_starttijden) 
              | selectattr('start', 'le', nu.isoformat()) 
              | selectattr('end', 'gt', nu.isoformat()) 
              | list %}

            {% if in_goedkoop_blok | length > 0 %}
              Ja
            {% else %}
              Nee
            {% endif %}
          {% else %}
            Onbekend
          {% endif %}
        attributes:
          raw_today: >
            {% set prijzen = state_attr('sensor.dynamisch_nordpool', 'raw_today') %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode') | int %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode') | int %}

            {% if prijzen is iterable %}
              {% set ns = namespace(goedkope_starttijden=[], dure_starttijden=[]) %}

              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% set type = item[0] %}
                  {% set tijd = item[1:] %}
                  {% for uur in prijzen %}
                    {% set dt_start = uur.start | as_datetime %}
                    {% if dt_start.strftime('%H:%M') == tijd %}
                      {% if type == 'G' %}
                        {% set ns.goedkope_starttijden = ns.goedkope_starttijden + [uur.start] %}
                      {% elif type == 'D' %}
                        {% set ns.dure_starttijden = ns.dure_starttijden + [uur.start] %}
                      {% endif %}
                    {% endif %}
                  {% endfor %}
                {% endfor %}
              {% else %}
                {% set prijzen_per_uur = prijzen | sort(attribute='value') %}
                {% set goedkoopste_uren = prijzen_per_uur[:aantal_goedkoop] %}
                {% set ns.goedkope_starttijden = goedkoopste_uren | map(attribute='start') | list %}
                {% if aantal_duur > 0 %}
                  {% set duurste_uren = prijzen_per_uur[-aantal_duur:] %}
                {% else %}
                  {% set duurste_uren = prijzen | rejectattr('start', 'in', ns.goedkope_starttijden) | list %}
                {% endif %}
                {% set ns.dure_starttijden = duurste_uren | map(attribute='start') | list %}
              {% endif %}

              [
              {% for uur in prijzen %}
                {
                  "start": "{{ uur.start }}",
                  "end": "{{ uur.end }}",
                  "value": {{ uur.value }},
                  "goedkoop": "{{ 'ja' if uur.start in ns.goedkope_starttijden else 'nee' }}",
                  "duur": "{{ 'ja' if uur.start in ns.dure_starttijden else 'nee' }}"
                }{% if not loop.last %},{% endif %}
              {% endfor %}
              ]
            {% else %}
              []
            {% endif %}

          raw_tomorrow: >
            {% set prijzen = state_attr('sensor.dynamisch_nordpool', 'raw_tomorrow') %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode_morgen') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode_morgen') | int %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode_morgen') | int %}

            {% if prijzen is iterable %}
              {% set ns = namespace(goedkope_starttijden=[], dure_starttijden=[]) %}

              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% set type = item[0] %}
                  {% set tijd = item[1:] %}
                  {% for uur in prijzen %}
                    {% set dt_start = uur.start | as_datetime %}
                    {% if dt_start.strftime('%H:%M') == tijd %}
                      {% if type == 'G' %}
                        {% set ns.goedkope_starttijden = ns.goedkope_starttijden + [uur.start] %}
                      {% elif type == 'D' %}
                        {% set ns.dure_starttijden = ns.dure_starttijden + [uur.start] %}
                      {% endif %}
                    {% endif %}
                  {% endfor %}
                {% endfor %}
              {% else %}
                {% set prijzen_per_uur = prijzen | sort(attribute='value') %}
                {% set goedkoopste_uren = prijzen_per_uur[:aantal_goedkoop] %}
                {% set ns.goedkope_starttijden = goedkoopste_uren | map(attribute='start') | list %}
                {% if aantal_duur > 0 %}
                  {% set duurste_uren = prijzen_per_uur[-aantal_duur:] %}
                {% else %}
                  {% set duurste_uren = prijzen | rejectattr('start', 'in', ns.goedkope_starttijden) | list %}
                {% endif %}
                {% set ns.dure_starttijden = duurste_uren | map(attribute='start') | list %}
              {% endif %}

              [
              {% for uur in prijzen %}
                {
                  "start": "{{ uur.start }}",
                  "end": "{{ uur.end }}",
                  "value": {{ uur.value }},
                  "goedkoop": "{{ 'ja' if uur.start in ns.goedkope_starttijden else 'nee' }}",
                  "duur": "{{ 'ja' if uur.start in ns.dure_starttijden else 'nee' }}"
                }{% if not loop.last %},{% endif %}
              {% endfor %}
              ]
            {% else %}
              []
            {% endif %}

          duurste_na_eerste_goedkope: >
            {% set prijzen = state_attr('sensor.dynamisch_nordpool', 'raw_today') %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode') | int %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode') | int %}

            {% if prijzen is iterable %}
              {% set ns = namespace(goedkope_starttijden=[], dure_starttijden=[]) %}

              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% set type = item[0] %}
                  {% set tijd = item[1:] %}
                  {% for uur in prijzen %}
                    {% set dt_start = uur.start | as_datetime %}
                    {% if dt_start.strftime('%H:%M') == tijd %}
                      {% if type == 'G' %}
                        {% set ns.goedkope_starttijden = ns.goedkope_starttijden + [uur.start] %}
                      {% elif type == 'D' %}
                        {% set ns.dure_starttijden = ns.dure_starttijden + [uur.start] %}
                      {% endif %}
                    {% endif %}
                  {% endfor %}
                {% endfor %}
              {% else %}
                {% set prijzen_per_uur = prijzen | sort(attribute='value') %}
                {% set goedkoopste_uren = prijzen_per_uur[:aantal_goedkoop] %}
                {% set ns.goedkope_starttijden = goedkoopste_uren | map(attribute='start') | list %}
                {% if aantal_duur > 0 %}
                  {% set duurste_uren = prijzen_per_uur[-aantal_duur:] %}
                {% else %}
                  {% set duurste_uren = prijzen | rejectattr('start', 'in', ns.goedkope_starttijden) | list %}
                {% endif %}
                {% set ns.dure_starttijden = duurste_uren | map(attribute='start') | list %}
              {% endif %}

              {% set eerste_goedkoop = ns.goedkope_starttijden | map('as_datetime') | sort | first %}

              [
              {% for uur in prijzen if uur.start in ns.dure_starttijden and (uur.start | as_datetime > eerste_goedkoop) %}
                {
                  "start": "{{ uur.start }}",
                  "end": "{{ uur.end }}",
                  "value": {{ uur.value }},
                  "goedkoop": "{{ 'ja' if uur.start in ns.goedkope_starttijden else 'nee' }}",
                  "duur": "ja"
                }{% if not loop.last %},{% endif %}
              {% endfor %}
              ]
            {% else %}
              []
            {% endif %}

          duurste_na_eerste_goedkope_morgen: >
            {% set prijzen = state_attr('sensor.dynamisch_nordpool', 'raw_tomorrow') %}
            {% set handmatige = states('input_text.dynamisch_handmatige_periode_morgen') %}
            {% set aantal_goedkoop = states('input_number.dynamisch_goedkoopste_x_periode_morgen') | int %}
            {% set aantal_duur = states('input_number.dynamisch_duurste_x_periode_morgen') | int %}

            {% if prijzen is iterable %}
              {% set ns = namespace(goedkope_starttijden=[], dure_starttijden=[]) %}

              {% if handmatige | length > 0 %}
                {% for item in handmatige.split(';') %}
                  {% set type = item[0] %}
                  {% set tijd = item[1:] %}
                  {% for uur in prijzen %}
                    {% set dt_start = uur.start | as_datetime %}
                    {% if dt_start.strftime('%H:%M') == tijd %}
                      {% if type == 'G' %}
                        {% set ns.goedkope_starttijden = ns.goedkope_starttijden + [uur.start] %}
                      {% elif type == 'D' %}
                        {% set ns.dure_starttijden = ns.dure_starttijden + [uur.start] %}
                      {% endif %}
                    {% endif %}
                  {% endfor %}
                {% endfor %}
              {% else %}
                {% set prijzen_per_uur = prijzen | sort(attribute='value') %}
                {% set goedkoopste_uren = prijzen_per_uur[:aantal_goedkoop] %}
                {% set ns.goedkope_starttijden = goedkoopste_uren | map(attribute='start') | list %}
                {% if aantal_duur > 0 %}
                  {% set duurste_uren = prijzen_per_uur[-aantal_duur:] %}
                {% else %}
                  {% set duurste_uren = prijzen | rejectattr('start', 'in', ns.goedkope_starttijden) | list %}
                {% endif %}
                {% set ns.dure_starttijden = duurste_uren | map(attribute='start') | list %}
              {% endif %}

              {% set eerste_goedkoop = ns.goedkope_starttijden | map('as_datetime') | sort | first %}

              [
              {% for uur in prijzen if uur.start in ns.dure_starttijden and (uur.start | as_datetime > eerste_goedkoop) %}
                {
                  "start": "{{ uur.start }}",
                  "end": "{{ uur.end }}",
                  "value": {{ uur.value }},
                  "goedkoop": "{{ 'ja' if uur.start in ns.goedkope_starttijden else 'nee' }}",
                  "duur": "ja"
                }{% if not loop.last %},{% endif %}
              {% endfor %}
              ]
            {% else %}
              []
            {% endif %}

      - name: "Zendure 2400 AC Efficiëntie Export"
        unique_id: zendure_2400_ac_efficientie_export
        unit_of_measurement: "%"
        state_class: measurement
        icon: mdi:percent-box
        state: >
          {% set ac = states('sensor.zendure_2400_ac_vermogen_export') | float(0) %}
          {% set dc = states('sensor.zendure_2400_ac_vermogen_export_dc') | float(0) %}
          {% if ac > 0 and dc > 0 %}
            {% set efficiency = (ac / dc) * 100 %}
            {{ [0, [efficiency, 100] | min] | max | round(1) }}
          {% else %}
            0
          {% endif %}

      - name: "Zendure 2400 AC Efficiëntie Import"
        unique_id: zendure_2400_ac_efficientie_import
        unit_of_measurement: "%"
        state_class: measurement
        icon: mdi:percent-box
        state: >
          {% set ac = states('sensor.zendure_2400_ac_vermogen_import') | float(0) %}
          {% set dc = states('sensor.zendure_2400_ac_vermogen_import_dc') | float(0) %}
          {% if ac > 0 and dc > 0 %}
            {% set efficiency = (dc / ac) * 100 %}
            {{ [0, [efficiency, 100] | min] | max | round(1) }}
          {% else %}
            0
          {% endif %}

      - name: "Zendure 2400 AC Indicatie Beschikbare Energie"
        unique_id: Zendure_2400_AC_Indicatie_Beschikbare_Energie
        unit_of_measurement: "kWh"
        state_class: measurement
        device_class: energy
        state: >
          {% set laad = states('sensor.zendure_2400_ac_laadpercentage') | float(0) %}
          {% set min_laad = states('sensor.zendure_2400_ac_minimale_laadpercentage') | float(0) %}
          {% set aantal_batterijen = states('sensor.zendure_2400_ac_aantal_batterijen') | float(1) %}
          {% set capaciteit_per_batterij = 2.88 %}
          {% set totale_capaciteit = aantal_batterijen * capaciteit_per_batterij %}
          {% set bruikbaar_percentage = laad - min_laad %}

          {% if bruikbaar_percentage < 0 %}
            0
          {% else %}
            {{ (bruikbaar_percentage / 100 * totale_capaciteit) | round(2) }}
          {% endif %}
        icon: mdi:lightning-bolt-circle

      - name: "Zendure 2400 AC RTE Totaal"
        unique_id: Zendure_2400_AC_RTE_Totaal
        unit_of_measurement: "%"
        state_class: measurement
        icon: mdi:percent-box
        state: >
          {% set energy_import = states('sensor.zendure_2400_ac_energie_import') | float(0) %}
          {% set energy_export = states('sensor.zendure_2400_ac_energie_export') | float(0) %}
          {% if energy_import > 0 %}
            {% set percentage = ((energy_export / energy_import) * 100) | round(2) %}
            {% if 0 <= percentage <= 100 %}
              {{ percentage }}
            {% else %}
              0
            {% endif %}
          {% else %}
            0
          {% endif %}

rest:
  - resource: http://<IP-BATTERIJ>/properties/report
    scan_interval: 1
    sensor:
      - name: "Zendure 2400 AC Vermogen Import (DC)"
        unique_id: Zendure_2400_AC_Vermogen_Import_(DC)
        value_template: >
         {% set ns = namespace(total=0) %}
         {% for pack in value_json.packData %}
          {% if pack.state == 1 %}
          {% set ns.total = ns.total + (pack.power | int) %}
         {% endif %}
         {% endfor %}
         {{ ns.total }}
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power

      - name: "Zendure 2400 AC Vermogen Export (DC)"
        unique_id: Zendure_2400_AC_Vermogen_Export_(DC)
        value_template: >
         {% set ns = namespace(total=0) %}
         {% for pack in value_json.packData %}
          {% if pack.state == 2 %}
          {% set ns.total = ns.total + (pack.power | int) %}
         {% endif %}
         {% endfor %}
         {{ ns.total }}
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power

      - name: "Zendure 2400 AC Vermogen Export"
        value_template: "{{ value_json['properties']['packInputPower'] | int }}"
        unique_id: Zendure_2400_AC_Vermogen_Export
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power

      - name: "Zendure 2400 AC Vermogen Import"
        value_template: "{{ (value_json['properties']['outputPackPower'] | int) }}"
        unique_id: Zendure_2400_AC_Vermogen_Import
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power

      - name: "Zendure 2400 AC Signaalsterkte"
        value_template: >
          {% set rssi = value_json['properties']['rssi'] | int(-100) %}
          {% if rssi >= -60 %}
            Uitstekend
          {% elif rssi >= -70 %}
            Goed
          {% elif rssi >= -80 %}
            Zwak
          {% else %}
            Slecht
          {% endif %}
        unique_id: Zendure_2400_AC_Signaalsterkte
        icon: mdi:wifi

      - name: "Zendure 2400 AC Batterij 1 Temperatuur"
        value_template: >
          {% set maxTemp = value_json['packData'][0]['maxTemp'] | int %}
          {{ (maxTemp - 2731) / 10.0 }}
        unique_id: Zendure_2400_AC_Batterij_1_Temperatuur
        unit_of_measurement: "°C"
        state_class: measurement
        device_class: temperature
        icon: mdi:thermometer

      - name: "Zendure 2400 AC Batterij 2 Temperatuur"
        value_template: >
          {% set maxTemp = value_json['packData'][1]['maxTemp'] | int %}
          {{ (maxTemp - 2731) / 10.0 }}
        unique_id: Zendure_2400_AC_Batterij_2_Temperatuur
        unit_of_measurement: "°C"
        state_class: measurement
        device_class: temperature
        icon: mdi:thermometer

      - name: "Zendure 2400 AC Batterij 3 Temperatuur"
        value_template: >
          {% set maxTemp = value_json['packData'][2]['maxTemp'] | int %}
          {{ (maxTemp - 2731) / 10.0 }}
        unique_id: Zendure_2400_AC_Batterij_3_Temperatuur
        unit_of_measurement: "°C"
        state_class: measurement
        device_class: temperature
        icon: mdi:thermometer

      - name: "Zendure 2400 AC Batterij 4 Temperatuur"
        value_template: >
          {% set maxTemp = value_json['packData'][3]['maxTemp'] | int %}
          {{ (maxTemp - 2731) / 10.0 }}
        unique_id: Zendure_2400_AC_Batterij_4_Temperatuur
        unit_of_measurement: "°C"
        state_class: measurement
        device_class: temperature
        icon: mdi:thermometer

      - name: "Zendure 2400 AC Batterij 5 Temperatuur"
        value_template: >
          {% set maxTemp = value_json['packData'][4]['maxTemp'] | int %}
          {{ (maxTemp - 2731) / 10.0 }}
        unique_id: Zendure_2400_AC_Batterij_5_Temperatuur
        unit_of_measurement: "°C"
        state_class: measurement
        device_class: temperature
        icon: mdi:thermometer

      - name: "Zendure 2400 AC Batterij 6 Temperatuur"
        value_template: >
          {% set maxTemp = value_json['packData'][5]['maxTemp'] | int %}
          {{ (maxTemp - 2731) / 10.0 }}
        unique_id: Zendure_2400_AC_Batterij_6_Temperatuur
        unit_of_measurement: "°C"
        state_class: measurement
        device_class: temperature
        icon: mdi:thermometer

      - name: "Zendure 2400 AC Vermogen Aansturing"
        value_template: >
          {% set opladen = value_json['properties']['outputPackPower'] | int %}
          {% set ontladen = - (value_json['properties']['packInputPower'] | int) %}
          {% if opladen != 0 %}
            {{ opladen }}
          {% else %}
            {{ ontladen }}
          {% endif %}
        unique_id: Zendure_2400_AC_Vermogen_Aansturing
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power

      - name: "Zendure 2400 AC Aantal Batterijen"
        value_template: "{{ value_json['properties']['packNum'] }}"
        unique_id: Zendure_2400_AC_Aantal_Batterijen
        icon: mdi:battery

      - name: "Zendure 2400 AC Opslagmodus"
        value_template: >
          {% set states = {1: "Opslaan in RAM", 0: "Opslaan in Flash"} %}
          {% set packState = value_json['properties']['smartMode'] | int %}
          {{ states.get(packState, "Onbekend") }}
        unique_id: Zendure_2400_AC_Opslagmodus
        icon: mdi:floppy

      - name: "Zendure 2400 AC Batterijspanning"
        value_template: "{{ (value_json['properties']['BatVolt'] | float / 100) | round(2) }}"
        unique_id: Zendure_2400_AC_Batterijspanning
        unit_of_measurement: "V"
        state_class: measurement
        device_class: voltage
        icon: mdi:sine-wave

      - name: "Zendure 2400 AC Resterende Ontlaad Tijd"
        value_template: >
         {% set vermogen_aansturing = states('sensor.zendure_2400_ac_vermogen_aansturing') | float(0) %}
         {% if vermogen_aansturing < 0 %}
         {% set total_minutes = value_json['properties']['remainOutTime'] | float(0) %}
         {% set hours = (total_minutes // 60) | int %}
         {% set minutes = (total_minutes % 60) | int %}
          {{ hours }}u {{ minutes }}m
         {% else %}
          Niet aan het ontladen
         {% endif %}
        icon: mdi:clock-time-eight-outline
        unique_id: zendure_2400_ac_resterende_ontlaad_tijd

      - name: "Zendure 2400 AC Omvormer Temperatuur"
        value_template: >
          {% set maxTemp = value_json['properties']['hyperTmp'] | int %}
          {{ (maxTemp - 2731) / 10.0 }}
        unique_id: Zendure_2400_AC_Omvormer_Temperatuur
        unit_of_measurement: "°C"
        state_class: measurement
        device_class: temperature
        icon: mdi:thermometer

      - name: "Zendure 2400 AC Laadpercentage"
        value_template: "{{ value_json['properties']['electricLevel'] }}"
        device_class: battery
        unit_of_measurement: "%"
        state_class: measurement
        unique_id: Zendure_2400_AC_Laadpercentage

      - name: "Zendure 2400 AC Minimale Laadpercentage"
        value_template: "{{ (value_json['properties']['minSoc'] | int / 10) | int }}"
        device_class: battery
        unit_of_measurement: "%"
        state_class: measurement
        unique_id: Zendure_2400_AC_Minimale_Laadpercentage
        icon: mdi:battery-high

      - name: "Zendure 2400 AC Maximale Laadpercentage"
        value_template: "{{ (value_json['properties']['socSet'] | int / 10) | int }}"
        device_class: battery
        unit_of_measurement: "%"
        state_class: measurement
        unique_id: Zendure_2400_AC_Maximale_Laadpercentage
        icon: mdi:battery-high

      - name: "Zendure 2400 AC Modus"
        value_template: >
          {% set states = {1: "Opladen", 2: "Ontladen"} %}
          {% set packState = value_json['properties']['acMode'] | int %}
          {{ states.get(packState, "Onbekend") }}
        unique_id: Zendure_2400_AC_Modus
        icon: mdi:battery-charging-wireless

      - name: "Zendure 2400 AC Error"
        value_template: >
          {% set states = {0: "Geen meldingen", 1: "Zie Zendure APP"} %}
          {% set packState = value_json['properties']['is_error'] | int %}
          {{ states.get(packState, "Onbekend") }}
        unique_id: Zendure_2400_AC_Error
        icon: mdi:battery-alert

      - name: "Zendure 2400 AC SOC Status"
        value_template: >
          {% set states = {0: "Goed", 1: "Kalibreren"} %}
          {% set packState = value_json['properties']['socStatus'] | int %}
          {{ states.get(packState, "Onbekend") }}
        unique_id: Zendure_2400_AC_SOC_Status
        icon: mdi:battery-heart-variant

      - name: "Zendure 2400 AC Ingesteld Ontlaadvermogen"
        value_template: "{{ value_json['properties']['outputLimit'] }}"
        unique_id: Zendure_2400_AC_Ingesteld_Ontlaadvermogen
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power

      - name: "Zendure 2400 AC Ingesteld Oplaadvermogen"
        value_template: "{{ value_json['properties']['inputLimit'] }}"
        unique_id: Zendure_2400_AC_Ingesteld_Oplaadvermogen
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power
    
  - resource: http://<IP-HOMEWIZARD-P1>/api/v1/data   # IP-adres van je Homewizard P1 voor V1 API
    scan_interval: 1
    sensor:
      - name: "P1 Aansturing API v1"
        value_template: "{{ value_json.active_power_w | float }}"
        unique_id: P1_Aansturing_API_V1
        unit_of_measurement: "W"
        device_class: power
 
rest_command:
  zendure_opslaan_in_ram:
    url: http://<IP-BATTERIJ>/properties/write
    method: POST
    payload: '{"sn":"<SERIAL-2400AC>","properties":{"smartMode": 1 }}'

  zendure_snel_laden:
    url: http://<IP-BATTERIJ>/properties/write
    method: POST
    payload: '{"sn":"<SERIAL-2400AC>","properties":{"acMode": 1, "inputLimit": 2400 }}'

  zendure_stop_met_laden:
    url: http://<IP-BATTERIJ>/properties/write
    method: POST
    payload: '{"sn":"<SERIAL-2400AC>","properties":{"acMode": 1, "inputLimit": 0 }}'

  zendure_x_laden:
    url: http://<IP-BATTERIJ>/properties/write
    method: POST
    payload: '{"sn":"<SERIAL-2400AC>","properties":{"acMode": 1, "inputLimit": {{inputLimit}} }}'

  zendure_x_laden_balanceren:
    url: http://<IP-BATTERIJ>/properties/write
    method: POST
    payload: '{"sn":"<SERIAL-2400AC>","properties":{"inputLimit": {{inputLimit}} }}'

  zendure_x_ontladen:
    url: http://<IP-BATTERIJ>/properties/write
    method: POST
    payload: '{"sn":"<SERIAL-2400AC>","properties":{"acMode": 2, "outputLimit": {{outputLimit}} }}'

  zendure_x_ontladen_balanceren:
    url: http://<IP-BATTERIJ>/properties/write
    method: POST
    payload: '{"sn":"<SERIAL-2400AC>","properties":{"outputLimit": {{outputLimit}} }}'

  zendure_snel_ontladen:
    url: http://<IP-BATTERIJ>/properties/write
    method: POST
    payload: '{"sn":"<SERIAL-2400AC>","properties":{"acMode": 2, "outputLimit": 2400 }}'

  zendure_stop_met_ontladen:
    url: http://<IP-BATTERIJ>/properties/write
    method: POST
    payload: '{"sn":"<SERIAL-2400AC>","properties":{"acMode": 2, "outputLimit": 0 }}'

  zendure_stop_met_alles:
    url: http://<IP-BATTERIJ>/properties/write
    method: POST
    payload: '{"sn":"<SERIAL-2400AC>","properties":{"outputLimit": 0, "inputLimit": 0 }}'

  zendure_standby:
    url: http://<IP-BATTERIJ>/properties/write
    method: POST
    payload: '{"sn":"<SERIAL-2400AC>","properties":{"smartMode": 0, "outputLimit": 0, "inputLimit": 0 }}'
Maak eerst een backup van je huidige configuration.yaml. Daarna pas je je huidige aan of je gebruikt direct de bovenstaande als je nooit iets met de configuration.yaml gedaan hebt. Hierna herstart je Home Assistant. En krijg je het onderstaande te zien tussen je integraties;

Afbeeldingslocatie: https://tweakers.net/i/E7bxQrCWwNpk4ZDFy1JQ9ITlLVE=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/UXu36CdUJ1KpqALNx5mSgJcP.png?f=user_large

*beschikbare entiteiten
Afbeeldingslocatie: https://tweakers.net/i/0wQt4Oea6YSVe5ku7Ipu4Ll1i-o=/800x/filters:strip_exif()/f/image/OlDVSsfncqLWEOegbQdlqMsy.png?f=fotoalbum_large

Je hebt nu lokaal verbinding met je 2400 AC. Om het nu even te testen kun je naar je Ontwikkelhulpmiddelen gaan en onder acties Zendure opzoeken. Probeer hier even de optie Snel ontladen (LET OP! DIT IS 2400 WATT, Hij hanteert wel je ingestelde limieten in de app) uit te voeren en kijk of je 2400 AC reageert en daarna Stop met alles. Zie je deze rest_commands niet maar had je wel je sensoren gezien dan kan het zijn dat Home Assistant de configuration.yaml niet goed heeft ingeladen. Helaas is dit een bug en moet je vaak een aantal keer herstarten. Hierna raakt hij ze nooit meer kwijt na een herstart.

Afbeeldingslocatie: https://tweakers.net/i/JxXs0t_MueIsdCrf_szwqhRYaHw=/800x/filters:strip_exif()/f/image/8Eh4Sb8T2h2sj23qvkg3NOHx.png?f=fotoalbum_large

(2/3) Zendure zenSDK (Gielz) automatisering
De motor van alles. Deze zal slim opladen en slim ontladen en samen dansen tot één geheel. Er zit ook standaard uitgesteld laden in die 1 uur na zonsopgang aan de slag gaat van april t/m september. En 1 uur voor zonsondergang niet meer gaat hamsteren. Heb je bij het bovenstaande geen namen aangepast dan is het een kwestie van een nieuwe automatisering aanmaken en rechtsboven op bewerken in YAML aan te klikken. Copy en paste en opslaan met deze naam en start daarna de automatisering;
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
alias: Zendure zenSDK (Gielz)
description: Versie 20251004
triggers:
  - at: "00:00:00"
    trigger: time
    id: middernacht_trigger
  - seconds: /4
    trigger: time_pattern
  - entity_id:
      - input_number.zendure_2400_ac_handmatig_vermogen
    trigger: state
  - entity_id:
      - input_select.zendure_2400_ac_modus_selecteren
    id: modus_trigger
    trigger: state
conditions: []
actions:
  - alias: Modus
    choose:
      - conditions:
          - condition: trigger
            id: modus_trigger
          - condition: state
            entity_id: input_select.zendure_2400_ac_modus_selecteren
            state: Standby
        sequence:
          - action: rest_command.zendure_standby
            data: {}
        alias: Standby
      - conditions:
          - condition: trigger
            id: modus_trigger
          - condition: state
            entity_id: input_select.zendure_2400_ac_modus_selecteren
            state: Handmatig
        sequence:
          - action: rest_command.zendure_stop_met_alles
            data: {}
        alias: Handmatig
      - conditions:
          - condition: trigger
            id: modus_trigger
          - condition: state
            entity_id: input_select.zendure_2400_ac_modus_selecteren
            state: Nul op de meter
        sequence:
          - action: rest_command.zendure_stop_met_alles
            data: {}
        alias: Nul op de meter
      - conditions:
          - condition: trigger
            id: modus_trigger
          - condition: or
            conditions:
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Alleen slim ontladen
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Alleen slim opladen
        sequence:
          - action: rest_command.zendure_stop_met_alles
            data: {}
        alias: Alleen slim opladen/ontladen
      - conditions:
          - condition: trigger
            id: modus_trigger
          - condition: state
            entity_id: input_select.zendure_2400_ac_modus_selecteren
            state: Ontladen met 2400 watt
        sequence:
          - action: rest_command.zendure_snel_ontladen
            data: {}
        alias: Ontladen met 2400 watt
      - conditions:
          - condition: trigger
            id: modus_trigger
          - condition: state
            entity_id: input_select.zendure_2400_ac_modus_selecteren
            state: Opladen met 2400 watt
        sequence:
          - action: rest_command.zendure_snel_laden
            data: {}
        alias: Opladen met 2400 watt
  - alias: Aansturing
    choose:
      - conditions:
          - condition: state
            entity_id: sensor.zendure_2400_ac_opslagmodus
            state: Opslaan in Flash
          - condition: or
            conditions:
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Nul op de meter
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Alleen slim opladen
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Alleen slim ontladen
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Handmatig
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Opladen met 2400 watt
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Ontladen met 2400 watt
        sequence:
          - action: rest_command.zendure_opslaan_in_ram
            data: {}
        alias: Wanneer opslag modus op Flash staat deze op RAM instellen
      - conditions:
          - condition: trigger
            id: middernacht_trigger
        sequence:
          - alias: Zet goedkoopste periode van morgen naar vandaag
            target:
              entity_id: input_number.dynamisch_goedkoopste_x_periode
            data:
              value: >-
                {{ states('input_number.dynamisch_goedkoopste_x_periode_morgen')
                | float }}
            action: input_number.set_value
          - alias: Zet duurste periode van morgen naar vandaag
            target:
              entity_id: input_number.dynamisch_duurste_x_periode
            data:
              value: >-
                {{ states('input_number.dynamisch_duurste_x_periode_morgen') |
                float }}
            action: input_number.set_value
          - alias: Zet handmatige periode van morgen naar vandaag
            target:
              entity_id: input_text.dynamisch_handmatige_periode
            data:
              value: "{{ states('input_text.dynamisch_handmatige_periode_morgen') }}"
            action: input_text.set_value
          - alias: Reset handmatige periode van morgen
            target:
              entity_id: input_text.dynamisch_handmatige_periode_morgen
            data:
              value: ""
            action: input_text.set_value
        alias: Dynamisch omzetten van morgen naar vandaag
      - conditions:
          - condition: numeric_state
            entity_id: sensor.p1_aansturing_api_v1
            above: 100
          - condition: template
            value_template: |
              {{ states('sensor.zendure_2400_ac_laadpercentage') | float >
               states('sensor.zendure_2400_ac_minimale_laadpercentage') | float }}
          - condition: numeric_state
            entity_id: sensor.zendure_2400_ac_vermogen_aansturing
            above: -30
            below: 75
          - condition: or
            conditions:
              - condition: state
                entity_id: sensor.zendure_2400_ac_modus
                state: Opladen
                for: "00:00:09"
              - condition: state
                entity_id: sensor.zendure_2400_ac_modus
                state: Ontladen
          - condition: or
            conditions:
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Nul op de meter
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Alleen slim ontladen
        sequence:
          - data:
              outputLimit: >-
                {% set factor = 0.75 %} {% set cap = 2400 %} {% set correctie =
                -2 %} {% set p1 = states('sensor.p1_aansturing_api_v1') |
                float(0) %} {% set zendure =
                states('sensor.zendure_2400_ac_vermogen_aansturing') | float(0)
                %} {% set totaal = (p1 - zendure - correctie) * factor %} {% set
                beperkt = [ [totaal, 0] | max, cap ] | min %} {{ beperkt | int
                }}
            action: rest_command.zendure_x_ontladen
        alias: Start met ontladen bij +100 watt (75% van de vraag)
      - conditions:
          - condition: template
            value_template: |
              {{ states('sensor.zendure_2400_ac_laadpercentage') | float >
               states('sensor.zendure_2400_ac_minimale_laadpercentage') | float }}
          - condition: template
            value_template: >-
              {% set factor = 1.00 %} {% set cap = 2400 %} {% set correctie = -2
              %} {% set p1 = states('sensor.p1_aansturing_api_v1') | float(0) %}
              {% set zendure =
              states('sensor.zendure_2400_ac_vermogen_aansturing') | float(0) %}
              {% set totaal = (p1 - zendure - correctie) * factor %} {% set
              beperkt = [ [totaal, 0] | max, cap ] | min %} {% set target =
              beperkt | int %} {% set huidig =
              states('sensor.zendure_2400_ac_ingesteld_ontlaadvermogen') |
              int(0) %} {{ huidig != target }}
          - condition: numeric_state
            entity_id: sensor.zendure_2400_ac_vermogen_aansturing
            below: 0
          - condition: or
            conditions:
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Nul op de meter
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Alleen slim ontladen
        sequence:
          - data:
              outputLimit: >-
                {% set factor = 1.00 %} {% set cap = 2400 %} {% set correctie =
                -2 %} {% set p1 = states('sensor.p1_aansturing_api_v1') |
                float(0) %} {% set zendure =
                states('sensor.zendure_2400_ac_vermogen_aansturing') | float(0)
                %} {% set totaal = (p1 - zendure - correctie) * factor %} {% set
                beperkt = [ [totaal, 0] | max, cap ] | min %} {{ beperkt | int
                }}
            action: rest_command.zendure_x_ontladen_balanceren
        alias: Tijdens ontladen balanceren naar 0 watt (100% van de vraag)
      - conditions:
          - condition: numeric_state
            entity_id: sensor.p1_aansturing_api_v1
            below: -100
          - condition: numeric_state
            entity_id: sensor.zendure_2400_ac_laadpercentage
            below: 100
          - condition: numeric_state
            entity_id: sensor.zendure_2400_ac_vermogen_aansturing
            above: -30
            below: 30
          - condition: not
            conditions:
              - condition: state
                entity_id: sensor.zendure_2400_ac_modus
                state: ontladen
                for: "00:00:15"
          - condition: or
            conditions:
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Nul op de meter
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Alleen slim opladen
        sequence:
          - data:
              inputLimit: >-
                {% set factor = 0.75 %} {% set cap = 2400 %} {% set
                correctie_export = 40 %} {% set p1 =
                states('sensor.p1_aansturing_api_v1') | float(0) %} {% set
                zendure = states('sensor.zendure_2400_ac_vermogen_aansturing') |
                float(0) %} {% set verschil = zendure - p1 - correctie_export %}
                {% set beperkt = verschil * factor if verschil > 0 else 0 %} {%
                set beperkt = beperkt if beperkt < cap else cap %} {{ beperkt |
                int }}
            action: rest_command.zendure_x_laden
        alias: Start met opladen bij -100 watt (75% van aanbod)
      - conditions:
          - condition: template
            value_template: >-
              {% set factor = 1.00 %} {% set cap = 2400 %} {% set
              correctie_export = 40 %} {% set p1 =
              states('sensor.p1_aansturing_api_v1') | float(0) %} {% set zendure
              = states('sensor.zendure_2400_ac_vermogen_aansturing') | float(0)
              %} {% set verschil = (zendure - p1 - correctie_export) * factor %}
              {% set beperkt = [ [verschil, 0] | max, cap ] | min %} {% set
              target = beperkt | int %} {% set huidig =
              states('sensor.zendure_2400_ac_ingesteld_oplaadvermogen') | int(0)
              %} {{ huidig != target }}
          - condition: numeric_state
            entity_id: sensor.zendure_2400_ac_laadpercentage
            below: 100
          - condition: numeric_state
            entity_id: sensor.zendure_2400_ac_vermogen_aansturing
            above: 0
          - condition: not
            conditions:
              - condition: state
                entity_id: sensor.zendure_2400_ac_modus
                state: ontladen
                for: "00:00:15"
          - condition: or
            conditions:
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Nul op de meter
              - condition: state
                entity_id: input_select.zendure_2400_ac_modus_selecteren
                state: Alleen slim opladen
        sequence:
          - data:
              inputLimit: >-
                {% set factor = 1.00 %} {% set cap = 2400 %} {% set
                correctie_export = 40 %} {% set p1 =
                states('sensor.p1_aansturing_api_v1') | float(0) %} {% set
                zendure = states('sensor.zendure_2400_ac_vermogen_aansturing') |
                float(0) %} {% set verschil = zendure - p1 - correctie_export %}
                {% set beperkt = verschil * factor if verschil > 0 else 0 %} {%
                set beperkt = beperkt if beperkt < cap else cap %} {{ beperkt |
                int }}
            action: rest_command.zendure_x_laden_balanceren
        alias: Tijdens opladen balanceren naar -40 watt (100% van aanbod)
      - conditions:
          - condition: state
            entity_id: input_select.zendure_2400_ac_modus_selecteren
            state: Handmatig
          - condition: numeric_state
            entity_id: input_number.zendure_2400_ac_handmatig_vermogen
            below: 0
        sequence:
          - data:
              outputLimit: >-
                {{ states('input_number.zendure_2400_ac_handmatig_vermogen') |
                int | abs }}
            action: rest_command.zendure_x_ontladen
        alias: Handmatig ontladen
      - conditions:
          - condition: state
            entity_id: input_select.zendure_2400_ac_modus_selecteren
            state: Handmatig
          - condition: numeric_state
            entity_id: input_number.zendure_2400_ac_handmatig_vermogen
            above: -1
        sequence:
          - data:
              inputLimit: >-
                {{ states('input_number.zendure_2400_ac_handmatig_vermogen') |
                int | abs }}
            action: rest_command.zendure_x_laden
        alias: Handmatig laden
mode: single
Afbeeldingslocatie: https://tweakers.net/i/F-dvszA2QdjtySFwv3rAm20xvd0=/fit-in/4000x4000/filters:no_upscale():gifsicle():strip_exif()/f/image/ZF93jbv5ikiiTuPZKsqsSEV6.gif?f=user_large

Afbeeldingslocatie: https://tweakers.net/i/hRtKK9MCuWRSIuUkqL5PRGJO_DI=/fit-in/4000x4000/filters:no_upscale():gifsicle():strip_exif()/f/image/gmx1eNhHPdIqSwq1nPkADwFu.gif?f=user_large

(3/3) Batterij laten werken
Voeg nu de entiteit Zendure 2400 AC Modus Selecteren toe aan je dashboard en wellicht nog andere entiteiten die je hebt aangemaakt via de configuration.yaml. Zendure 2400 AC Modus Selecteren zal op Standby staan kies hier je gewenste modus om de Zendure zenSDK (Gielz) automatisering te laten gaan werken.

Afbeeldingslocatie: https://tweakers.net/i/qp3pTkMDVDrqciMpc5TqW-KagyA=/fit-in/4000x4000/filters:no_upscale():gifsicle():strip_exif()/f/image/HOzuofE1B3xQ16mIOEOVPTPu.gif?f=user_large

(OPTIONEEL) Nordpool
Wanneer je ook het Dynamisch Nordpool gedeelte in gebruik gaat nemen moet je voor dat je deze in gebruik neemt bij beide handmatige periodes even unknown weghalen. Hierna zal het dynamisch gedeelte werken. Alles wat in de forecast gezet word zal overgenomen worden om 00:00 via de automatisering.

Dynamisch Goedkoopste Periode en Dynamisch Duurste Periode geven JA en NEE aan. deze kun je vervolgens in je eigen automatisering gebruiken waarmee je de modus van de batterij veranderd.

Apexcharts voor dynamisch vandaag en morgen
Afbeeldingslocatie: https://tweakers.net/i/pZs6hiQmuExPgseEYn4fXVnB-WY=/800x/filters:strip_exif()/f/image/lrvE8bAcP8jbdStml1tUpe4t.png?f=fotoalbum_large

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
type: custom:apexcharts-card
stacked: true
header:
  show: true
  title: Vandaag
experimental:
  color_threshold: true
graph_span: 24h
apex_config:
  noData:
    text: Vanaf 14:00 zijn de prijzen van morgen bekend.
  plotOptions:
    bar:
      columnWidth: 90%
  tooltip:
    enabledOnSeries:
      - 0
    followCursor: true
    shared: true
    intersect: false
    enabled: true
    x:
      format: HH:mm
      show: false
  grid:
    show: true
    borderColor: "#332f2c"
    strokeDashArray: 0
  chart:
    height: 200px
  yaxis:
    - title:
        text: ""
      decimalsInFloat: 2
      min: 0
      max: 1
      tickAmount: 5
      forceNiceScale: false
      labels:
        style:
          colors: "#7b7c83"
  xaxis:
    labels:
      show: false
    axisTicks:
      show: false
    axisBorder:
      color: "#616269"
  legend:
    show: false
span:
  start: day
series:
  - entity: sensor.dynamisch_nordpool
    yaxis_id: Prijs
    type: column
    color: "#ebebeb"
    float_precision: 3
    color_threshold:
      - value: 0
        color: "#186ddc"
      - value: 0.155
        color: "#04822e"
      - value: 0.2
        color: "#12A141"
      - value: 0.25
        color: "#79B92C"
      - value: 0.3
        color: "#C4D81D"
      - value: 0.35
        color: "#F3DC0C"
      - value: 0.4
        color: "#EFA51E"
      - value: 0.45
        color: "#E76821"
      - value: 0.5
        color: "#DC182F"
    name: Vandaag
    show:
      in_header: false
      legend_value: false
      extremas: true
    data_generator: |
      return entity.attributes.raw_today.map((start, index) => {
        return [new Date(start["start"]).getTime(), entity.attributes.raw_today[index]["value"]];
      });
  - entity: sensor.dynamisch_goedkoopste_periode
    yaxis_id: Goedkoop
    color: green
    curve: stepline
    opacity: 0.2
    type: column
    name: Goedkoop
    data_generator: |
      const data = entity.attributes["raw_today"];
      if (!data) return [];

      return data.map(item => {
        const tijd = new Date(item.start).getTime();
        const waarde = item.goedkoop === "ja" ? 1 : 0;
        return [tijd, waarde];
      });
  - entity: sensor.dynamisch_goedkoopste_periode
    yaxis_id: Goedkoop
    color: red
    curve: stepline
    opacity: 0.2
    type: column
    name: Duur
    data_generator: |
      const data = entity.attributes["raw_today"];
      if (!data) return [];

      return data.map(item => {
        const tijd = new Date(item.start).getTime();
        const waarde = item.duur === "ja" ? 1 : 0;
        return [tijd, waarde];
      });
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
type: custom:apexcharts-card
stacked: true
header:
  show: true
  title: Morgen
experimental:
  color_threshold: true
graph_span: 24h
apex_config:
  noData:
    text: Vanaf 14:00 zijn de prijzen van morgen bekend.
  plotOptions:
    bar:
      columnWidth: 90%
  tooltip:
    enabledOnSeries:
      - 0
    followCursor: true
    shared: true
    intersect: false
    enabled: true
    x:
      format: HH:mm
      show: false
  grid:
    show: true
    borderColor: "#332f2c"
    strokeDashArray: 0
  chart:
    height: 200px
  yaxis:
    - title:
        text: ""
      decimalsInFloat: 2
      min: 0
      max: 1
      tickAmount: 5
      forceNiceScale: false
      labels:
        style:
          colors: "#7b7c83"
  xaxis:
    labels:
      show: false
    axisTicks:
      show: false
    axisBorder:
      color: "#616269"
  legend:
    show: false
span:
  start: day
  offset: +1d
series:
  - entity: sensor.dynamisch_nordpool
    yaxis_id: Prijs
    type: column
    color: "#ebebeb"
    float_precision: 3
    color_threshold:
      - value: 0
        color: "#186ddc"
      - value: 0.155
        color: "#04822e"
      - value: 0.2
        color: "#12A141"
      - value: 0.25
        color: "#79B92C"
      - value: 0.3
        color: "#C4D81D"
      - value: 0.35
        color: "#F3DC0C"
      - value: 0.4
        color: "#EFA51E"
      - value: 0.45
        color: "#E76821"
      - value: 0.5
        color: "#DC182F"
    name: Morgen
    show:
      in_header: false
      legend_value: false
      extremas: true
    data_generator: |
      return entity.attributes.raw_tomorrow.map((start, index) => {
        return [new Date(start["start"]).getTime(), entity.attributes.raw_tomorrow[index]["value"]];
      });
  - entity: sensor.dynamisch_goedkoopste_periode
    yaxis_id: Goedkoop
    color: green
    curve: stepline
    opacity: 0.2
    type: column
    name: Goedkoop
    data_generator: |
      const data = entity.attributes["raw_tomorrow"];
      if (!data) return [];

      return data.map(item => {
        const tijd = new Date(item.start).getTime();
        const waarde = item.goedkoop === "ja" ? 1 : 0;
        return [tijd, waarde];
      });
  - entity: sensor.dynamisch_goedkoopste_periode
    yaxis_id: Goedkoop
    color: red
    curve: stepline
    opacity: 0.2
    type: column
    name: Duur
    data_generator: |
      const data = entity.attributes["raw_tomorrow"];
      if (!data) return [];

      return data.map(item => {
        const tijd = new Date(item.start).getTime();
        const waarde = item.duur === "ja" ? 1 : 0;
        return [tijd, waarde];
      });




FAQ zenSDK gielz (lokaal)
🔴 Hoe zou mijn NOM er moeten uitzien als alles goed geconfigureerd is?
Is het niet zoals onderstaande grafiek dan is de fout 9/10 keer dat je P1 geen 1 seconden data heeft of überhaupt geen data genereert. Ook wanneer je eigen sensoren gebruikt moet je die goed vervangen in de Zendure zenSDK (Gielz) (het liefst via kladblok vervangen). Mocht het hierna nog niet helemaal vlak zijn pas dan een correctie toe en kijk naar je apparaten die korte piekvermogens hebben (bijv een kokend waterkraan).
Afbeeldingslocatie: https://tweakers.net/i/jDP1lWZG4f5gyDLLCYIDj-N8mVI=/800x/filters:gifsicle():strip_exif()/f/image/DxTMeVgQx6zyqosDKGEYoX6q.gif?f=fotoalbum_large

🔴 Ik wil juist meer/minder opladen of ontladen en dus een correctie toepassen.
In de Zendure zenSDK (Gielz) automatisering heb je als eind actie bij iedere optie een template. En ook 2 voorwaarde bij optie 3 en 5 om het ingestelde vermogen niet te overschrijven wanneer de doelwaarde het zelfde is. Hier staat {% set correctie = -2 %} bij ontladen en bij laden {% set correctie_export = 40 %} en deze kun je bij ontladen een min waarde bijvoorbeeld -50 geven dan is het doel -50 watt. Kijk gewoon even in de nacht of je vind dat er 5 of 10 watt af moet en speel een beetje met deze waarde. Heb je grotere afwijkingen dan 50 watt bij ontladen dan is dit niet de oplossing maar is de configuratie fout.

🔴 Ik wil niet op 2400 maximaal opladen of ontladen. Wat nu?.
In de Zendure zenSDK (Gielz) automatisering heb je als eind actie bij iedere optie een template. En ook 2 voorwaarde bij optie 3 en 5 om het ingestelde vermogen niet te overschrijven wanneer de doelwaarde het zelfde is. Hier staat {% set cap = 2400 %} en deze kun je aanpassen naar wat jij wilt. Hij zal nooit meer kunnen ontladen en opladen dan wat jij in de app als maximum hebt ingesteld.

Werkt deze API via het Flashgeheugen of het RAM geheugen?
Hij kijkt elke 4 seconden of hij niet toevallig naar het Flashgeheugen gaat wegschrijven. Als dit het geval is zet de Zendure zenSDK (Gielz) automatisering dit goed tenzij je in de Standby modus staat. In de Standby modus moet smartmode uit staan om te voorkomen dat hij permanent 15-30 watt gaat terugleveren.
Zendure support:
For the device, each time the output mode is switched, it will be written to the flash. Why is it written? It is designed to ensure that the device can maintain the last state after power failure. For the new 2025 products, you can find a property called smartMode. Once the value is 1, the ac mode setting will no longer be written to the flash, so the flash life will be much longer.
Therefore, for linkage in ct mode, smartmode will be 1, and acmode can be set repeatedly to achieve a balance in overall household energy input and output.

Kan ik nu mijn 2400 AC blokkeren van het internet.
Ja zeker het draait 100% lokaal en jij bent de baas
Afbeeldingslocatie: https://tweakers.net/i/MC0HELIJ7pSSSQlSHWY6DgnZflo=/800x/filters:strip_icc():strip_exif()/f/image/MQYUSieP3Yf5jSfqXqNNP1jh.jpg?f=fotoalbum_large

Zendure zenSDK (Gielz) staat op 1-4 seconden kan deze ook naar 1-3 seconden?
Optimale is hier op dit moment 1-4 seconden maar wees vrij om dit aan te passen. Wat je zult zien dat het vermogen van de batterij en de P1 out of sync gaan lopen en het een golfbeweging gaat worden op je P1. Bij bijvoorbeeld de Homewizard PiB hanteren ze standaard 2-4 seconden.

Ik heb geen Homewizard P1 of überhaupt geen P1
Zolang je de meterstanden maar zo nauwkeurig mogelijk en per seconden beschikbaar zijn is dit geen probleem. Dit kan bijvoorbeeld ook met een Zendure P1, Zendure 3CT, Shelly CT of Homewizard KWH meter na je hoofdschakelaar. Gaat niet zelf in je meterkast rotzooien als je alleen weet waar je meterkast zit. Vergeet niet in de Zendure zenSDK (Gielz) automatisering de sensor naar je eigen sensor aan te passen. Kladblok vervangen is je vriend.

De sensoren zijn soms allemaal niet beschikbaar. API lijkt offline
Dit kan 2 oorzaken hebben. Of de signaalsterke sensor geeft zwak of slecht aan en je zal het WIFI signaal moeten verbeteren. Of je gebruikt meerdere API calls door bijvoorbeeld de ZenSDK te draaien + de Zendure HA (Fireson).

Hoe werkt handmatige periode bij dynamisch
Je kunt hier zelf aangeven in de forecast wat je wilt ontladen in het onderstaande format. Deze worden vervolgens om 00:00 overgezet naar vandaag en zal dan eenmalig uitgevoerd worden.
G11:00;G12:00;G13:00;D19:00;D20:00;D21:00
*G is goedkoop, D is duur.

Voer je hier iets anders in dan de gebruikelijke commandline (bijv Geen) dan zal hij helemaal niet ontladen of laden die dag.

[ Voor 255% gewijzigd door gielz op 04-10-2025 19:46 ]

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • 0 Henk 'm!

  • jordyc
  • Registratie: Oktober 2014
  • Laatst online: 20:45
Eventjes een wat meer algemene vraag. Zijn er hier al mensen die hebben nagedacht over de combinatie thuisbatterij en een EV? Wat voor slimmigheden hebben jullie al gebouwd om er voor te zorgen dat ze elkaar niet in de weg zitten?

Op dit moment heb ik in HA het volgende gebouwd met de fireson integratie en een aantal extra sensors van Bikkelreal:
Indien smart discharge actief en auto is aan het laden --> naar off mode
Indien smart mode en EV laden --> dan op smart charge.

Daarnaast laad ik de batterij altijd normaal laden in de goedkoopste uren, idee hierachter is dat de batterij juist voor de komende 24 uur is en duurdere afname moet voorkomen. De EV kan eventueel ook minder vol geladen als door load balancing de EV minder vol wordt geladen en de prijzen te hoog worden.

Acties:
  • 0 Henk 'm!

  • JanHenk
  • Registratie: September 2008
  • Niet online
@gielz Mooi werk, is te volgen! Begrijp ik het nu goed dat je als het ware je eigen 'matching' (NOM) script hebt geschreven, dat iedere vier seconden wordt gedraaid om het vermogen van de batterij aan te passen?

Is het niet mogelijk om de NOM aansturing bij Zendure te laten en alleen te overschrijven als je 'iets anders' wil? Of werkt de NOM-aansturing van Zendure niet lokaal?

Werkt dit ook met meerdere batterijen? Of beter gezegd; omvormers?

skoda enyaq 80 | holtkamper aero | fiscalist én techneut


Acties:
  • +1 Henk 'm!
Klopt het is de mijn eigen NOM met 1 automatisering. Elke 4 seconden gaat hij starten of balanceren in de huidige modus. De NOM aansturing van Zendure was ik niet tevreden over omdat ik het liever in eigen beheer heb en lokaal. Bij het testen van de 3CT als het internet weg was deed hij ook niets meer. De restful API aansturing ziet er dan zo uit vandaag (afgerond is het, maar het is 0,06kwh);

Afbeeldingslocatie: https://tweakers.net/i/bcePwSfHrv8CjCLT-csWkJjTuVY=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/jpCPdHKSFH2K55KRAVQhzq2J.png?f=user_large

Hij is nu geschreven voor 1 omvormer. Maar hij is in theorie eenvoudig aan te passen naar 2 of meerdere omdat bij iedere optie/uitkomst hij aan de api gaat doorgeven wat nodig is. Stel je hebt dan 2 omvormers dan heb je uiteindelijk 2 acties waarbij je bijvoorbeeld set factor = 1.00 kun aanpassen naar de helft per omvormer.

Ik zal adviseren om ze gewoon alle 3 één voor één te proberen en daarna een eigen keuze te maken; (volgorde van hoeveel werk) Zendure, Fireson en Restful API. Wil je 100% lokaal dan is de keuze beperkter.
JanHenk schreef op dinsdag 17 juni 2025 @ 13:56:
@gielz Mooi werk, is te volgen! Begrijp ik het nu goed dat je als het ware je eigen 'matching' (NOM) script hebt geschreven, dat iedere vier seconden wordt gedraaid om het vermogen van de batterij aan te passen?

Is het niet mogelijk om de NOM aansturing bij Zendure te laten en alleen te overschrijven als je 'iets anders' wil? Of werkt de NOM-aansturing van Zendure niet lokaal?

Werkt dit ook met meerdere batterijen? Of beter gezegd; omvormers?

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • +1 Henk 'm!

  • Sander
  • Registratie: Juni 2004
  • Niet online
jordyc schreef op dinsdag 17 juni 2025 @ 07:38:
Eventjes een wat meer algemene vraag. Zijn er hier al mensen die hebben nagedacht over de combinatie thuisbatterij en een EV? Wat voor slimmigheden hebben jullie al gebouwd om er voor te zorgen dat ze elkaar niet in de weg zitten?

Op dit moment heb ik in HA het volgende gebouwd met de fireson integratie en een aantal extra sensors van Bikkelreal:
Indien smart discharge actief en auto is aan het laden --> naar off mode
Indien smart mode en EV laden --> dan op smart charge.

Daarnaast laad ik de batterij altijd normaal laden in de goedkoopste uren, idee hierachter is dat de batterij juist voor de komende 24 uur is en duurdere afname moet voorkomen. De EV kan eventueel ook minder vol geladen als door load balancing de EV minder vol wordt geladen en de prijzen te hoog worden.
Ik heb dit draaien en ik moet eerlijk zeggen dat het vooral zo min mogelijk doen is... kleine crosspost uit eigen werk van uit Sander in "Evcc slim laden met de zon en dynamische tarieven" topic:

EVCC pakt in mijn geval (tesla) alleen maar volle amperes omhoog of omlaag dus regelt niet erg fijnmazig. Dit gebeurd ook nog eens met een redelijke wachtperiode tussen schakelmomenten (omhoog/omlaag en aan/uit). Doordat de batterij sneller en fijnmaziger reageert (in tijd en afname/teruggifte) heeft die eigenlijk altijd al zijn vermogen 'geclaimd' voordat EVCC gaat beginnen en die past zich dan aan.

Gaat er kortstondig een wolk voor de zon dan begint evcc eerst met 'terugtellen' voor hij afschakelt en dan springt de batterij kortstondig bij en voorkomt netafname. Gaat de wolk weer weg, pakt de batterij eerst weer vermogen terug voor EVCC schakelt.

Battery-boost werkt op dezelfde manier automatisch: als er te weinig zon is en ik zet de auto op 'snel' laden dan gaat de energiemeter positieve waarden laten zien en springt de batterij ook weer bij.


In aanvulling hierop heb ik wel een paar slimme modes gedefineerd waarmee ik de batterij manipuleer:
- Alleen laden (= verbruiksmeter geef 0 door bij verbruik)
- Alleen ontladen (= verbruiksmeter geeft 0 door bij overschot).

Maar in de praktijk raak ik het eigenlijk niet aan. De essentie is dat mijn lader trager reageert dan de batterij en daarmee zit het elkaar niet in de weg. Behalve dat de batterij soms dus prioriteit neemt bij het opladen (want dan is hij sneller met beschikbaar overschot oppakken dan de TWC)

[ Voor 5% gewijzigd door Sander op 17-06-2025 17:03 ]


Acties:
  • 0 Henk 'm!

  • wautah91
  • Registratie: April 2010
  • Laatst online: 03-10 13:22
Mooie startport @gielz! Bij de Fireson integratie zou je nog een link naar mijn blogpost kunnen toevoegen, waar ik uitgebreid in ga op het toevoegen van de Hyper2000 in Home Assistant. Ook heb ik het artikel inmiddels geupdatet met een paragraaf over de lokale MQTT aansturing.
https://www.twoenter.nl/b...ratie-met-home-assistant/

Mijn smarthome blog artikelen over: Thuisaccu | Dynamische energieprijzen | Watermeter


Acties:
  • 0 Henk 'm!

  • zeegerd
  • Registratie: Juli 2010
  • Laatst online: 03-10 16:33
Mooi gedaan, goede (her)start zo! :)

Bij de nieuwere types (+API) is er hierboven al aandacht voor werken met RAM ipv flash, maar hoe zit dit bij de @FireSon-integratie? Daar zullen gebruikers vermoedelijk ook liever kiezen om flashgeheugen niet onnodig te belasten. Dit mis ik nog, lijkt me nuttig om toe te voegen.

Misschien ook al elders te vinden, bijv in een handleiding, dan kan ernaar verwezen worden uiteraard. Kan aan mij liggen maar ik heb het zo snel niet gevonden.

There's nothing moister than an oyster.


Acties:
  • 0 Henk 'm!
zeegerd schreef op woensdag 18 juni 2025 @ 09:45:
Mooi gedaan, goede (her)start zo! :)

Bij de nieuwere types (+API) is er hierboven al aandacht voor werken met RAM ipv flash, maar hoe zit dit bij de @FireSon-integratie? Daar zullen gebruikers vermoedelijk ook liever kiezen om flashgeheugen niet onnodig te belasten. Dit mis ik nog, lijkt me nuttig om toe te voegen.

Misschien ook al elders te vinden, bijv in een handleiding, dan kan ernaar verwezen worden uiteraard. Kan aan mij liggen maar ik heb het zo snel niet gevonden.
De Fireson integratie werkt met MQTT, de omvormers lezen de waardes af van een MQTT server en schrijven die waarde dus niet lokaal weg.

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • 0 Henk 'm!
Weet je dat heel zeker? Want via postman zie je op de 2400 AC dat er wel data wegschreven word maar uiteraard dan wel in het RAM geheugen als de NOM modus aan staat.
Taro schreef op woensdag 18 juni 2025 @ 17:50:
[...]

De Fireson integratie werkt met MQTT, de omvormers lezen de waardes af van een MQTT server en schrijven die waarde dus niet lokaal weg.

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • +1 Henk 'm!
gielz schreef op woensdag 18 juni 2025 @ 18:49:
Weet je dat heel zeker? Want via postman zie je op de 2400 AC dat er wel data wegschreven word maar uiteraard dan wel in het RAM geheugen als de NOM modus aan staat.


[...]
Misschien moeten we onze @FireSon even taggen, om uitsluitsel te geven.

Humans don’t need an opportunity to be wicked. They’ve been doing it for free since the beginning.


Acties:
  • 0 Henk 'm!
gielz schreef op woensdag 18 juni 2025 @ 18:49:
Weet je dat heel zeker? Want via postman zie je op de 2400 AC dat er wel data wegschreven word maar uiteraard dan wel in het RAM geheugen als de NOM modus aan staat.


[...]
@FireSon Naar mijn weten worden de waardes naar de Zendure of locale MQTT server gestuurd, waar de Hypers/2400AC/SF800Pro ze van ophalen en uitvoeren, correct? Komen daar Flash/RAM writes bij kijken op bijv. het eenmalig aanpassen van een AC-mode na?

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • +1 Henk 'm!
Mooie guide/blog. Ik zal zeker een linkje verwerken in de TS.
wautah91 schreef op woensdag 18 juni 2025 @ 09:26:
Mooie startport @gielz! Bij de Fireson integratie zou je nog een link naar mijn blogpost kunnen toevoegen, waar ik uitgebreid in ga op het toevoegen van de Hyper2000 in Home Assistant. Ook heb ik het artikel inmiddels geupdatet met een paragraaf over de lokale MQTT aansturing.
https://www.twoenter.nl/b...ratie-met-home-assistant/

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • 0 Henk 'm!
Taro schreef op woensdag 18 juni 2025 @ 18:52:
[...]

@FireSon Naar mijn weten worden de waardes naar de Zendure of locale MQTT server gestuurd, waar de Hypers/2400AC/SF800Pro ze van ophalen en uitvoeren, correct? Komen daar Flash/RAM writes bij kijken op bijv. het eenmalig aanpassen van een AC-mode na?
Als ik het goed begrijp is het schrijven naar de flash nodig, zodat het apparaat verder gaat waar het gebleven is bij een onderbreking?
Kan je het dan niet testen? Een commando sturen, de ac2400 van de accu afhalen, en dan van de stroom, terug in het stopcontact en direct terug op de accu, en dan kijken wat hij doet?

Humans don’t need an opportunity to be wicked. They’ve been doing it for free since the beginning.


Acties:
  • +1 Henk 'm!
geert1992 schreef op woensdag 18 juni 2025 @ 19:05:
[...]


Als ik het goed begrijp is het schrijven naar de flash nodig, zodat het apparaat verder gaat waar het gebleven is bij een onderbreking?
Ja, voor een handmatige AC-Mode instelling wel ja. Maar als hij dat via MQTT ophaalt in een slimme mode kan die dat vanaf de MQTT server halen en daarmee verder gaan, dan is schrijven/lezen uit RAM niet nodig volgens mij.
Kan je het dan niet testen? Een commando sturen, de ac2400 van de accu afhalen, en dan van de stroom, terug in het stopcontact en direct terug op de accu, en dan kijken wat hij doet?
Laat ik graag even aan anderen over :)

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • +1 Henk 'm!
Heb ik getest bij de 2400 AC met smartmode = 1. Hierbij word de ACmode niet meer in het flashgeheugen geschreven zoals Zendure heeft aangegeven. De aansturing is dan exact zoals de 3CT en P1. Fireson Integratie (las ik in deel1) en de Restful API doen dit op dezelfde manier voor NOM. Voor de Restful API heb ik dit getest daarbij werd inderdaad de ACmode niet onthouden bij het uitzetten van de omvormer.

Hoe dit bij de Hyper is heb ik geen idee van maar wat ik uit de tekst van Zendure op maak is dat dit gewoon Flash is voor de ACmode.
For the device, each time the output mode is switched, it will be written to the flash. Why is it written? It is designed to ensure that the device can maintain the last state after power failure. For the new 2025 products, you can find a property called smartMode. Once the value is 1, the ac mode setting will no longer be written to the flash, so the flash life will be much longer.
Therefore, for linkage in ct mode, smartmode will be 1, and acmode can be set repeatedly to achieve a balance in overall household energy input and output.
Afbeeldingslocatie: https://tweakers.net/i/efH81b62zzPMwTzSseMDd_JtLF4=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/r0KVCHaKO6MCIJGoty0iHXlt.png?f=user_large

Met 10 jaar garantie op beide producten moet het wel goed komen verwacht ik.
geert1992 schreef op woensdag 18 juni 2025 @ 19:05:
[...]


Als ik het goed begrijp is het schrijven naar de flash nodig, zodat het apparaat verder gaat waar het gebleven is bij een onderbreking?
Kan je het dan niet testen? Een commando sturen, de ac2400 van de accu afhalen, en dan van de stroom, terug in het stopcontact en direct terug op de accu, en dan kijken wat hij doet?

[ Voor 19% gewijzigd door gielz op 18-06-2025 20:16 ]

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • +5 Henk 'm!

  • FireSon
  • Registratie: Januari 2014
  • Laatst online: 03-10 12:33
Taro schreef op woensdag 18 juni 2025 @ 18:52:
[...]
@FireSon Naar mijn weten worden de waardes naar de Zendure of locale MQTT server gestuurd, waar de Hypers/2400AC/SF800Pro ze van ophalen en uitvoeren, correct? Komen daar Flash/RAM writes bij kijken op bijv. het eenmalig aanpassen van een AC-mode na?
Dat is correct. Het schrijven van properties zoals AC mode gaan waarschijnlijk wel naar de flash. De NOM commando's van de Smart mode niet. Ik heb het niet voor niets uitgezocht ;)

Acties:
  • 0 Henk 'm!
Thanks, ik neem dit ook even op in de FAQ om te voorkomen dat hier over een tijdje weer vragen over komen.
FireSon schreef op donderdag 19 juni 2025 @ 08:29:
[...]

Dat is correct. Het schrijven van properties zoals AC mode gaan waarschijnlijk wel naar de flash. De NOM commando's van de Smart mode niet. Ik heb het niet voor niets uitgezocht ;)

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • +1 Henk 'm!

  • Mediacj
  • Registratie: Augustus 2002
  • Laatst online: 17:18
FireSon schreef op donderdag 19 juni 2025 @ 08:29:
[...]

Dat is correct. Het schrijven van properties zoals AC mode gaan waarschijnlijk wel naar de flash. De NOM commando's van de Smart mode niet. Ik heb het niet voor niets uitgezocht ;)
Geldt dit ook als je in de manual-stand waarden invult bij het veld “Zendure Manager handmatig vermogen”?

[ Voor 11% gewijzigd door Mediacj op 19-06-2025 09:46 ]


Acties:
  • 0 Henk 'm!

  • zeegerd
  • Registratie: Juli 2010
  • Laatst online: 03-10 16:33
Mediacj schreef op donderdag 19 juni 2025 @ 09:46:
[...]

Geldt dit ook als je in de manual-stand waarden invult bij het veld “Zendure Manager handmatig vermogen”?
Goeie, vroeg het me ook al af. Die lijkt op de native modi voor (ont)laden met vast vermogen, althans door mijn ogen. ;)

There's nothing moister than an oyster.


Acties:
  • 0 Henk 'm!

  • c0mplex1
  • Registratie: Juni 2025
  • Laatst online: 22-09 16:32
Dit is mijn eerste post hier op Tweakers, dus als ik iets niet goed doet alvast mijn excuses hiervoor.

Half juli hoop ik mijn SF2400AC + 2*AB3000X te mogen ontvangen.
Ervaring met een thuisbatterij heb ik nog niet.

Met veel interesse volg ik dan ook dit topic (en deel 1), met name de automatisering van @gielz, waar ik dan ook enkele vragen over heb.
Ik zal dan gelijk maar de koe bij de horens vatten:

Sensoren aanmaken:
Wat is het verschil tussen de rest commando's op regel 196 (zendure_x_laden) en regel 201 (zendure_x_laden_balanceren)
Waarom staat bij het ene commando de property "acMode":1 er bij en bij het andere commando niet?
Dit geldt ook zo bij de regels 206 en 211 ("acMode":2).
Kun je dan gewoon niet de property "acMode":x weg laten?

Waarom definieer je zoveel rest commando's als je er maar enkele(4) gebruikt?

Zendure NOM 1.00:
Regels 81, 199: waar verwijst de sensor.xxxx_2 naar toe?
Deze kom ik niet tegen in de sensoren lijst.
Regels 136-139: zijn deze niet overbodig, omdat je dit al met regels 131-133 onderzocht heb?
Regels 174, 195, 254: hier mis ik de "factor" correctie.
De kreten "enabled: true" die je her en der in de automatisering tegen komt zijn m.i. overbodig omdat je niets meer hoeft te testen.

Als ik de batterijen ontvangen heb en je automatisering gaat gebruiken, zullen er waarschijnlijk nog meer vragen bij mij op poppen.

PV 4340 Wp OW | SF2400AC + 4*AB3000X | EV 65kWh | Dynamisch contract | HA OS op RPi5


Acties:
  • 0 Henk 'm!
Goed dat je zo naar de code kijkt. Hier werkt het allemaal prima maar er zal zeker wat spaghetti code in zitten wat beter kan. Ik heb even je punten 1 voor 1 bekeken en de antwoorden erbij gezet.
c0mplex1 schreef op donderdag 19 juni 2025 @ 12:18:
Wat is het verschil tussen de rest commando's op regel 196 (zendure_x_laden) en regel 201 (zendure_x_laden_balanceren)
Waarom staat bij het ene commando de property "acMode":1 er bij en bij het andere commando niet?
Dit geldt ook zo bij de regels 206 en 211 ("acMode":2).
Kun je dan gewoon niet de property "acMode":x weg laten?
Bij het starten zet hij de juiste ACmode, hierna gaat hij dit niet nogmaals via de API versturen. Tijdens het testen zag ik namelijk dat hij anders de ACmode weer opnieuw gaat opslaan wat een beetje overbodig is.
Waarom definieer je zoveel rest commando's als je er maar enkele(4) gebruikt?
Ze worden allemaal gebruikt, buiten de zendure_opslaan_in_flash. De NOM gebruikt er 5, de overige worden gebruikt in de selectielijst.
Zendure NOM 1.00:
Regels 81, 199: waar verwijst de sensor.xxxx_2 naar toe?
Deze kom ik niet tegen in de sensoren lijst.
verwijst naar unique_id: Zendure_2400_AC_Ingesteld_Oplaadvermogen en Zendure_2400_AC_Ingesteld_Ontlaadvermogen. Ik zal vanavond even kijken waarom hij hier _2 van gemaakt heeft want er is er maar 1.
Regels 136-139: zijn deze niet overbodig, omdat je dit al met regels 131-133 onderzocht heb?
Nee dit zijn 2 aparte onderdelen. Buiten het opwekseizoen geen gebruik maken van uitgesteld laden en binnen het opwekseizoen wel. Deze regels kunnen ook verwijderd worden maar dan gaat hij in de ochtend en avond hamsteren bij het opladen wat niet optimaal voor je RTE is.
Regels 174, 195, 254: hier mis ik de "factor" correctie.
Bij ontladen heet deze correctie en bij laden heet deze correctie_export. Dit zal ik even in de FAQ aanpassen.
De kreten "enabled: true" die je her en der in de automatisering tegen komt zijn m.i. overbodig omdat je niets meer hoeft te testen.
Stukje spaghetti code ;)

Hopelijk zijn je batterijen er snel! Echt een mooi product.

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • +1 Henk 'm!
Binnen de startpost kun je nu direct bovenaan de aanpassingen zien in de startpost. Dit om te voorkomen dat er iets gemist word wat wel relevant kan zijn voor de werking van de batterij.


Startpost aanpassingen

Algemeen
2025-06-19 - Startpost aanpassingen gesplitst per onderdeel.

Fireson integratie
2025-06-18 - FAQ toegevoegd met website waar meer uitleg gegeven word over over de integratie en leuke extra onderdelen.
2025-06-17 - FAQ toegevoegd met betrekking tot bluetooth proxy.

Restful API zenSDK
‪‪2025-06-19 ❤︎‬ CHANGE - Zendure NOM 1.00 Automatisering Tikfout gevonden in optie 5. Hier werd verwezen naar Zendure_2400_AC_Ingesteld_Oplaadvermogen_2 maar dit moet Zendure_2400_AC_Ingesteld_Oplaadvermogen zijn. De NOM werkwijze is en blijft hetzelfde, hij zal alleen nu geen API bericht meer versturen als het ingestelde vermogen gelijk is aan het gewenste vermogen. Dit komt bij opladen vaak voor als hij op de cap zit van 1200 watt en het is in het opwekseizoen.
2025-06-19 - FAQ update over correctie factor bij laden.

[ Voor 4% gewijzigd door gielz op 19-06-2025 14:43 ]

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • +2 Henk 'm!

  • c0mplex1
  • Registratie: Juni 2025
  • Laatst online: 22-09 16:32
@gielz Volgens mij zitten we niet helemaal op dezelfde golflengte.
Ik heb jouw rest template en automatisering aangepast en (voor mij) leesbaarder gemaakt.
Ook heb ik links en rechts wat foutjes eruit gehaald.
Het geheel (rest template en automatisering) is 100% ongetest op zijn werking.
Ik krijg (nog) geen foutmeldingen in HA, dus de syntax is goed, denk ik.
Hieronder wat ik nu heb:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
rest: #------------------------------------------------------------------------
  # HomeWizard Energy Socket
  - resource: http://192.168.0.xxx/api/v1/data
    scan_interval: 1
    sensor:
      - name: "HomeWizard Active Power"
        unique_id: d546d4e4-8bc5-427e-9c7a-ab894d5f2271
        value_template: "{{ value_json.active_power_w }}"
        unit_of_measurement: "W"
        device_class: power
        state_class: measurement

  - resource: http://192.168.0.xxx/properties/report
    sensor:
    # Maximum Battery Temperature
      - name: "AB3000X-1 - Batterij Temperatuur"
        unique_id: 7d35f15c-d7fe-4945-80b6-9d1d4ad20252
        value_template: >
          {% set maxTemp = value_json['packData'][0]['maxTemp'] %}
          {{ ((maxTemp - 2731) / 10) | round(1) }} # Kelvin to Celsius
        unit_of_measurement: "°C"
        device_class: temperature
        icon: mdi:thermometer

    # Maximum Battery temperature
      - name: "AB3000X-2 - Batterij Temperatuur"
        unique_id: 2020e295-324a-4dd0-a640-e99ddb13c107
        value_template: >
          {% set maxTemp = value_json['packData'][1]['maxTemp'] %}
          {{ ((maxTemp - 2731) / 10) | round(1) }}
        unit_of_measurement: "°C"
        device_class: temperature
        icon: mdi:thermometer

    # Enclosure Temperature
      - name: "SolarFlow 2400 AC - Omvormer Temperatuur"
        unique_id: f77762b4-ca34-4732-99ba-cddbd7b18e57
        value_template: >
          {% set maxTemp = value_json['properties']['hyperTmp'] %}
          {{ ((maxTemp - 2731) / 10) | round(1) }}
        unit_of_measurement: "°C"
        device_class: temperature
        state_class: measurement
        icon: mdi:thermometer

    # Remaining Charge Time  (Resterende Oplaadtijd)
      - name: "SolarFlow 2400 AC - Resterende Oplaadtijd"
        unique_id: 49c24f72-d4a7-46f1-9a31-ff0603df2e4d
        value_template: >
          {% set total_minutes = value_json['properties']['remainInputTime'] %}
          {% set hours = (total_minutes // 60) %}
          {% set minutes = (total_minutes % 60) %}
          {{ hours }}u {{ minutes }}m

    # Remaining Discharge Time  (Resterende Ontlaadtijd)
      - name: "SolarFlow 2400 AC - Resterende Ontlaadtijd"
        unique_id: 84ded5b7-d876-41d6-b8bb-999533b156d0
        value_template: >
          {% set total_minutes = value_json['properties']['remainOutTime'] %}
          {% set hours = (total_minutes // 60) %}
          {% set minutes = (total_minutes % 60) %}
          {% if hours == 999 and minutes == 0 %}
            Niet bekend
          {% else %}
            {{ hours }}u {{ minutes }}m
          {% endif %}
        icon: mdi:clock-time-eight-outline

    # Battery Level  (Batterij)
      - name: "SolarFlow 2400 AC - Laadpercentage"
        unique_id: 6909394d-c240-4867-940d-aef46d25d835
        value_template: "{{ value_json['properties']['electricLevel'] }}"
        unit_of_measurement: "%"
        device_class: battery

    # SOC Minimaal
      - name: "SolarFlow 2400 AC - Minimale Laadpercentage"
        unique_id: 12f078b1-efcf-4dd3-83b4-f3b0a2a8426a
        value_template: "{{ value_json['properties']['minSoc'] / 10 }}"
        unit_of_measurement: "%"
        device_class: battery
        icon: mdi:battery-high

    # SOC Maximaal
      - name: "SolarFlow 2400 AC - Maximale Laadpercentage"
        unique_id: 408f88e3-2b74-4a6a-922f-2b4d650274a4
        value_template: "{{ value_json['properties']['socSet'] / 10 }}"
        unit_of_measurement: "%"
        device_class: battery
        icon: mdi:battery-high

    # AC Charging Power Limit  (Limiet Opladen)
      - name: "SolarFlow 2400 AC - Ingesteld Oplaadvermogen"
        unique_id: 5d1747d3-fb00-4995-ba2b-1ebf651b5509
        value_template: "{{ value_json['properties']['inputLimit'] }}"
        unit_of_measurement: "W"
        device_class: power

    # Home Output Power Limit  (Limiet Ontladen)
      - name: "SolarFlow 2400 AC - Ingesteld Ontlaadvermogen"
        unique_id: 3017561d-1262-4997-9848-ee4f791e8e85
        value_template: "{{ value_json['properties']['outputLimit'] }}"
        unit_of_measurement: "W"
        device_class: power

    # Output Power To Battery Pack (charging)  (Batterij Opladen)
      - name: "SolarFlow 2400 AC - Vermogen (opladen)"
        unique_id: a6178d62-24b1-426a-9cb6-8f070d572d79
        value_template: "{{ value_json['properties']['outputPackPower'] }}"
        unit_of_measurement: "W"
        device_class: power
        state_class: measurement

    # Battery Pack Input Power (discharging)  (Batterij Ontladen)
      - name: "SolarFlow 2400 AC - Vermogen (ontladen)"
        unique_id: 639a4f52-c6cc-4275-9a51-e87907850fde
        value_template: "{{ - (value_json['properties']['packInputPower']) }}"
        unit_of_measurement: "W"
        device_class: power
        state_class: measurement

      - name: "SolarFlow 2400 AC - Vermogen (gecombineerd)"
        unique_id: 70f1cc7b-c278-4113-a779-26168f76515a
        value_template: >
          {% set opladen = value_json['properties']['outputPackPower'] %}
          {% set ontladen = - (value_json['properties']['packInputPower']) %}
          {% if opladen != 0 %}
            {{ opladen }}
          {% else %}
            {{ ontladen }}
          {% endif %}
        unit_of_measurement: "W"
        device_class: power
        state_class: measurement

      - name: "SolarFlow 2400 AC - SOC Status"
        unique_id: 4274e3f6-dc19-42bc-9c3d-622947026555
        value_template: >
          {% set packState = value_json['properties']['socStatus'] %}
          {% set states = {0: "Goed", 1: "Kalibreren"} %}
          {{ states.get(packState, "Onbekend") }}
        icon: mdi:battery-heart-variant

    # AC Mode, 1: Input, 2: Output
      - name: "SolarFlow 2400 AC - Modes"
        unique_id: 754cf3a8-7983-46ec-b55b-8be6fb327369
        value_template: >
          {% set packState = value_json['properties']['acMode'] %}
          {% set states = {1: "Opladen", 2: "Ontladen"} %}
          {{ states.get(packState, "Onbekend") }}
        icon: mdi:battery-charging-wireless

      - name: "SolarFlow 2400 AC - Restapi Rate"
        unique_id: 43459046-75ef-48f2-a9c2-b6538238217c
        value_template: "{{ value_json['messageId'] }}"
        state_class: measurement
        icon: mdi:api

      - name: "SolarFlow 2400 AC - Opslagmodus"
        unique_id: f2e2066c-e658-4b6d-bb2e-04f2dd8bb128
        value_template: >
          {% set packState = value_json['properties']['smartMode'] %}
          {% set states = {1: "RAM", 0: "Flash"} %}
          {{ states.get(packState, "Onbekend") }}
        icon: mdi:floppy

      - name: "SolarFlow 2400 AC - Error"
        unique_id: a67d790a-87f1-42f3-aa08-b42f1b43311b
        value_template: >
          {% set packState = value_json['properties']['is_error'] %}
          {% set states = {0: "Geen", 1: "Zie Zendure APP"} %}
          {{ states.get(packState, "Onbekend") }}
        icon: mdi:battery-alert

rest_command: #----------------------------------------------------------------

  solarflow_2400_ac_x_opladen:
    url: "http://{{ ip }}/properties/write"
    method: POST
    payload: '{"sn":"{{ sn }}", "properties":{"acMode": 1, "inputLimit": {{inputLimit}} }}'

  solarflow_2400_ac_x_ontladen:
    url: "http://{{ ip }}/properties/write"
    method: POST
    payload: '{"sn":"{{ sn }}", "properties":{"acMode": 2, "outputLimit": {{outputLimit}} }}'

  solarflow_2400_ac_x_opladen_balanceren:
    url: http://{{ ip }}/properties/write
    method: POST
    payload: '{"sn":"{{ sn }}","properties":{"inputLimit": {{inputLimit}} }}'

  solarflow_2400_ac_x_ontladen_balanceren:
    url: http://{{ ip }}/properties/write
    method: POST
    payload: '{"sn":"{{ sn }}","properties":{"outputLimit": {{outputLimit}} }}'

  solarflow_2400_ac_stop_met_alles:
    url: "http://{{ ip }}/properties/write"
    method: POST
    payload: '{"sn":"{{ sn }}", "properties":{"inputLimit": 0, "outputLimit": 0 }}'

  solarflow_2400_ac_opslaan_in_ram:
    url: http://{{ ip }}/properties/write
    method: POST
    payload: '{"sn":"{{ sn }}","properties":{"smartMode": 1 }}'

# Riemann sum integral sensor t.b.v. vertonen in energy display ---------------

sensor:
  # Calculate the Power flowing into the battery in kWh
  - platform: integration
    name: "Energy to SolarFlow 2400 AC (gridInputPower)"
    unique_id: 575c7ded-b92c-4320-8ade-7615f604ea8e
    source: sensor.solarflow_2400_ac_vermogen_opladen
    unit_prefix: k
    round: 2
    max_sub_interval:
      minutes: 5

  # Calculate the Power feeding back to the home/grid in kWh
  - platform: integration
    name: "Energy from SolarFlow 2400 AC (outputHomePower)"
    unique_id: 51b8262f-f060-4bd4-8b07-be7919e7c3ee
    source: sensor.solarflow_2400_ac_vermogen_ontladen
    unit_prefix: k
    round: 2
    max_sub_interval:
      minutes: 5

input_select: #----------------------------------------------------------------

  solarflow_2400_ac_mode_select:
    name: SolarFlow 2400 AC - Mode Select
    options:
      - Nul op de meter
      - Alleen slim opladen
      - Alleen slim ontladen
      - Standby
      - Opladen met 800 Watt
      - Ontladen met 800 Watt
    initial: Nul op de meter
    icon: mdi:battery-charging-wireless

automation: #------------------------------------------------------------------

  - id: a3c54ca0-0b39-4fde-b8de-e3c19df00393
    alias: SolarFlow 2400 AC - NOM v1.01
    description: ""

    triggers:
      - trigger: time_pattern
        seconds: /4

    actions:
      - variables:
          p1mtr: "{{ states('sensor.p1_meter_power') | float(0) }}"
          hwpwr: "{{ states('sensor.homewizard_active_power') | float(0) }}"
          ipadd: 192.168.0.xxx
          serno: 123456789

      - choose:
          - alias: "Wanneer de opslagmodus op Flash of Onbekend staat deze op RAM instellen"
            conditions:
              - "{{ states('sensor.solarflow_2400_ac_opslagmodus') in ['Flash', 'Onbekend'] }}"
            sequence:
              - action: rest_command.solarflow_2400_ac_opslaan_in_ram
                data:
                  ip: "{{ ipadd }}"
                  sn: "{{ serno }}"

          - alias: "Start met ontladen bij +100 Watt (75% van de vraag)"
            conditions:
              - "{{ p1mtr > 100 }}"
              - "{{ -1 < hwpwr < 75 }}"
              - "{{ states('input_select.solarflow_2400_ac_mode_select') in ['Nul op de meter', 'Alleen slim ontladen'] }}"
              - or:
                  - "{{ is_state('sensor.solarflow_2400_ac_modus', 'Ontladen') }}"
                  - condition: state
                    entity_id: sensor.solarflow_2400_ac_modes
                    state: Opladen
                    for:
                      hours: 0
                      minutes: 0
                      seconds: 9
            sequence:
              - action: rest_command.solarflow_2400_ac_x_ontladen
                data:
                  ip: "{{ ipadd }}"
                  sn: "{{ serno }}"
                  outputLimit: >-
                    {% set cap = 800 %}     # Max. vermogen
                    {% set factor = 0.75 %}
                    {% set corr = 0 %}
                    {% set total = (p1mtr - hwpwr - corr) * factor %}
                    {{ ([max([total, 0]), cap] | min) | int }}

          - alias: "Tijdens ontladen balanceren naar 0 Watt (100% van de vraag)"
            conditions:
              - condition: template
                value_template: >-
                  {% set cap = 800 %}
                  {% set factor = 1.00 %}
                  {% set corr = 0 %}
                  {% set total = (p1mtr - hwpwr - corr) * factor %}
                  {% set target = ([max([total, 0]), cap] | min) | int %}
                  {% set current = states('sensor.zendure_2400_ac_ingesteld_ontlaadvermogen') | int(0) %}
                  {{ current != target }}
              - "{{ hwpwr < 0 }}"
              - "{{ states('input_select.solarflow_2400_ac_mode_select') in ['Nul op de meter', 'Alleen slim ontladen'] }}"
            sequence:
              - action: rest_command.solarflow_2400_ac_x_ontladen_balanceren
                data:
                  ip: "{{ ipadd }}"
                  sn: "{{ serno }}"
                  outputLimit: >-
                    {% set cap = 800 %}
                    {% set factor = 1.00 %}
                    {% set corr = 0 %}
                    {% set total = (p1mtr - hwpwr - corr) * factor %}
                    {{ ([max([total, 0]), cap] | min) | int }}

          - alias: "Start met opladen bij -100 Watt (alleen tussen 2u na ☀︎ en 1u voor ☾) (75% van aanbod)"
            conditions:
              - "{{ p1mtr < -100 }}"
              - "{{ -10 < hwpwr < 15 }}"
              - "{{ states('sensor.solarflow_2400_ac_laadpercentage') < 99 }}"
              - "{{ states('input_select.solarflow_2400_ac_mode_select') in ['Nul op de meter', 'Alleen slim opladen'] }}"
              - or:
                  - "{{ not (4 <= now().month <= 9) }}" # niet van april t/m september
                  - condition: sun
                    after: sunrise
                    before: sunset
                    after_offset: "+02:00:00"
                    before_offset: "-01:00:00"
              - not:
                  - condition: state
                    entity_id: sensor.solarflow_2400_ac_modus
                    state: Ontladen
                    for:
                      hours: 0
                      minutes: 0
                      seconds: 15
            sequence:
              - action: rest_command.solarflow_2400_ac_x_opladen
                data:
                  ip: "{{ ipadd }}"
                  sn: "{{ serno }}"
                  inputLimit: >-
                    {% set cap = 800 %}
                    {% set factor = 0.75 %}
                    {% set corr = 80 %}
                    {% set total = hwpwr - p1mtr - corr %}
                    {% set limited = total if total > 0 else 0 %}
                    {{ (limited if limited < cap else cap) | int }}

          - alias: "Tijdens opladen balanceren naar -80 Watt (alleen tussen 2u na ☀︎ en 1u voor ☾) (100% van aanbod)"
            conditions:
              - condition: template
                value_template: >-
                  {% set cap = 800 %}
                  {% set factor = 1.00 %}
                  {% set corr = 80 %}
                  {% set total = hwpwr - p1mtr - corr %}
                  {% set limited = total if total > 0 else 0 %}
                  {% set target = (limited if limited < cap else cap) | int %}
                  {% set current = states('sensor.zendure_2400_ac_ingesteld_oplaadvermogen') | int(0) %}
                  {{ current != target }}
              - "{{ hwpwr > 0 }}"
              - "{{ states('sensor.solarflow_2400_ac_laadpercentage') < 99 }}"
              - "{{ states('input_select.solarflow_2400_ac_mode_select') in ['Nul op de meter', 'Alleen slim opladen'] }}"
              - or:
                  - "{{ not (4 <= now().month <= 9) }}"
                  - condition: sun
                    after: sunrise
                    before: sunset
                    after_offset: "+02:00:00"
                    before_offset: "-01:00:00"
              - not:
                  - condition: state
                    entity_id: sensor.solarflow_2400_ac_modus
                    state: Ontladen
                    for:
                      hours: 0
                      minutes: 0
                      seconds: 15
            sequence:
              - action: rest_command.solarflow_2400_ac_x_opladen_balanceren
                data:
                  ip: "{{ ipadd }}"
                  sn: "{{ serno }}"
                  inputLimit: >-
                    {% set cap = 800 %}
                    {% set factor = 1.00 %}
                    {% set corr = 80 %}
                    {% set total = hwpwr - p1mtr - corr %}
                    {% set limited = total if total > 0 else 0 %}
                    {{ (limited if limited < cap else cap) | int }}

PV 4340 Wp OW | SF2400AC + 4*AB3000X | EV 65kWh | Dynamisch contract | HA OS op RPi5


Acties:
  • 0 Henk 'm!

  • avdwerf
  • Registratie: Maart 2007
  • Nu online
Heb de entities aangemaakt via de ZenSDK. Werkt allemaal prima. Iemand die al een leuke fancy kaart heeft gemaakt voor op het dashboard? Ik blijf voorlopig alleen uitlezen, aansturen doe ik nog even in Zendure app zelf.

Acties:
  • 0 Henk 'm!
Geen idee of dit binnen je eigen dashboard past maar hier gebruiken wij deze. De onderste grafiek is gemakkelijk over te nemen maar dan zonder de opkomst en ondergang lijn.

- Apexcharts
- 1 Sensor om P1 en de batterij te combineren.

Afbeeldingslocatie: https://tweakers.net/i/MIWV8swNqC9NKHSt_zphSyexIf8=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/b7kEb2pJSs5nOpB6a7KvDxfS.png?f=user_large
avdwerf schreef op donderdag 19 juni 2025 @ 16:10:
Heb de entities aangemaakt via de ZenSDK. Werkt allemaal prima. Iemand die al een leuke fancy kaart heeft gemaakt voor op het dashboard? Ik blijf voorlopig alleen uitlezen, aansturen doe ik nog even in Zendure app zelf.

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • 0 Henk 'm!

  • c0mplex1
  • Registratie: Juni 2025
  • Laatst online: 22-09 16:32
@gielz Zou je de code van de onderste grafiek willen delen?
Dit bespaart om niet opnieuw het wiel te hoeven uitvinden. :)

PV 4340 Wp OW | SF2400AC + 4*AB3000X | EV 65kWh | Dynamisch contract | HA OS op RPi5


Acties:
  • +3 Henk 'm!
Hierbij de grafiek, ik heb het config-template-card gedeelte er even uitgehaald voor de zonsopkomst en ondergang. In de header heb ik 2 dagelijkse nutsmeters die ik ook elders gebruik maar die kan je eventueel ook weghalen.

Voor het P1 vermogen inclusief batterij hanteer ik de onderstaande template sensor;

code:
1
2
3
4
{{
            (states('sensor.p1_meter_power') | float +
            (states('sensor.zendure_2400_ac_vermogen') | float * -1)) | round(0)
          }}


Afbeeldingslocatie: https://tweakers.net/i/xx95KKWWoIUKo6D4iVQckQy4s18=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/ZgnHjs8A8O2qVo5rtsKLXfKU.png?f=user_large
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
type: custom:apexcharts-card
cache: true
update_interval: 5min
stacked: true
header:
  show: true
  show_states: true
  title: ""
graph_span: 24h
span:
  start: day
series:
  - entity: sensor.zendure_2400_ac_vermogen
    name: Batterij
    group_by:
      func: avg
      duration: 15min
    type: area
    transform: return -x;
    stroke_width: 0
    opacity: 1
    extend_to: now
    color: "#f1b605"
    float_precision: 0
    yaxis_id: energy
    show:
      in_header: false
  - entity: sensor.p1_vermogen_met_batterij
    name: P1 met batterij
    group_by:
      func: avg
      duration: 15min
    type: area
    stroke_width: 0
    opacity: 1
    extend_to: now
    color: "#46474c"
    float_precision: 0
    yaxis_id: energy
    show:
      in_header: false
  - entity: sensor.zendure_2400_ac_laadpercentage
    name: Laadpercentage
    type: line
    color: "#fff"
    opacity: 0
    stroke_width: 2
    extend_to: now
    curve: straight
    group_by:
      func: min
      duration: 15min
    show:
      in_header: false
  - entity: sensor.zendure_2400_ac_import_dagelijks
    yaxis_id: header_only
    name: Vandaag (geladen)
    show:
      in_header: true
      in_chart: false
  - entity: sensor.zendure_2400_ac_export_dagelijks
    yaxis_id: header_only
    name: Vandaag (ontladen)
    show:
      in_header: true
      in_chart: false
  - entity: sensor.zendure_2400_ac_laadpercentage
    yaxis_id: header_only
    name: SOC
    show:
      in_header: true
      in_chart: false
apex_config:
  tooltip:
    x:
      format: HH:mm
      show: false
  xaxis:
    labels:
      show: false
      style:
        colors: grey
    axisTicks:
      show: false
    axisBorder:
      color: "#616269"
  yaxis:
    - title:
        text: ""
      decimalsInFloat: 0
      labels:
        style:
          colors: "#7b7c83"
  grid:
    strokeDashArray: 0
    borderColor: rgb(52,52,52)
    show: true
  chart:
    height: 270px
  legend:
    show: false
  markers:
    size: 0
    hover:
      size: 0
c0mplex1 schreef op dinsdag 24 juni 2025 @ 13:04:
@gielz Zou je de code van de onderste grafiek willen delen?
Dit bespaart om niet opnieuw het wiel te hoeven uitvinden. :)

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • 0 Henk 'm!

  • jordyc
  • Registratie: Oktober 2014
  • Laatst online: 20:45
@Taro ik heb de sensors gefixed en getest. De sensoren doen nu ook wat ik verwacht.

Wat is er anders:
- De wallbox gaf in kWh het vermogen, dit wordt nu maal 1000 gedaan om naar watts om te rekenen
- De input boolean op "off" betekent dat de auto NIET met de batterij opgeladen moet worden. Dit voelt iets intuitiever.

Negatieve sensor
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{% set vermogen = states('<sensor.p1_meter_vermogen>') | float(0) %}
{% set ev_vermogen = states('<sensor.EV_laadvermogen>')| float(0) * 1000 %}
{% set batterij_input = states('sensor.battery_input_total') | float(0) %}
{% set include_ev = is_state('<input_boolean.ev_laden_met_batterij_stroom>', 'off') %}

{% set netto_vermogen = vermogen - (ev_vermogen if include_ev else 0) %}

{% if netto_vermogen < 0 %}
  {{ netto_vermogen + 1 }}
{% elif netto_vermogen >0 and batterij_input != 0 %}
  {{ netto_vermogen + 1 }}
{% elif netto_vermogen > 0 and batterij_input == 0 %}
  {{ [netto_vermogen, 0] | max }}
{% else %}
  0
{% endif %}


Positieve sensor
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{% set vermogen = states('<sensor.p1_meter_vermogen>') | float(0) %}
{% set ev_vermogen = states('<sensor.EV_laadvermogen>') | float(0) * 1000 %}
{% set batterij_output = states('sensor.battery_output_total') | float(0) %}
{% set include_ev = is_state('<input_boolean.ev_laden_met_batterij_stroom>', 'off') %}

{% set netto_vermogen = vermogen - (ev_vermogen if include_ev else 0) %}

{% if netto_vermogen > 0 %}
  {{ netto_vermogen + 1 }}
{% elif netto_vermogen < 0 and batterij_output != 0 %}
  {{ netto_vermogen + 1 }}
{% elif netto_vermogen < 0 and batterij_output == 0 %}
  {{ [netto_vermogen, 0] | max }}
{% else %}
  0
{% endif %}


negative and positive sensor
code:
1
2
3
4
5
{% set vermogen = states('<sensor.p1_meter_vermogen>') | float(0) %}
{% set ev_vermogen = states('<sensor.EV_laadvermogen>') | float(0) * 1000 %}
{% set include_ev = is_state('<input_boolean.ev_laden_met_batterij_stroom>', 'off') %}

{{ (vermogen - (ev_vermogen if include_ev else 0)) + 1 }}

[ Voor 4% gewijzigd door jordyc op 24-06-2025 19:58 ]


Acties:
  • 0 Henk 'm!

  • pfwolbers
  • Registratie: September 2003
  • Laatst online: 30-09 22:42
Ik wil binnenkort zonnepanelen gaan aansluiten op de hyper. Nu heb ik de hyper via de integratie van @FireSon werkend op home assistant.
Echter hoe krijg ik de zonne opbrengst goed in het energy dashboard zonder dat dit dubbel geteld wordt?
Er is een "totaal zonne energie" maar als ik de energie gebruik welke ik heb opgewekt dan komt deze ook terug bij "totaal geleverd". Of klopt dit niet?

Acties:
  • 0 Henk 'm!
pfwolbers schreef op dinsdag 24 juni 2025 @ 21:25:
Ik wil binnenkort zonnepanelen gaan aansluiten op de hyper. Nu heb ik de hyper via de integratie van @FireSon werkend op home assistant.
Echter hoe krijg ik de zonne opbrengst goed in het energy dashboard zonder dat dit dubbel geteld wordt?
Er is een "totaal zonne energie" maar als ik de energie gebruik welke ik heb opgewekt dan komt deze ook terug bij "totaal geleverd". Of klopt dit niet?
Je kunt hiervoor ook een Riemann helper op de DC/PV ingang waarde zetten en dat optellen. Zo heb ik het volgende overzichtje gemaakt:

Afbeeldingslocatie: https://tweakers.net/i/Rp6BWjA3NFQzJVmDWesj8j99rpQ=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/D7fzHQ5kqNmxcA91j3FaV5Fz.png?f=user_large

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • 0 Henk 'm!

  • pfwolbers
  • Registratie: September 2003
  • Laatst online: 30-09 22:42
Ja, dat kan. Maar in het dashboard gaat dat volgens mij niet goed. De panelen op de hyper worden dan wel goed weergegeven, echter deze energie komt ook nog uit de batterij in het dashboard. Gaat dat dan wel goed met het totaal huis verbruik in het dashboard?
Dat is voor zover ik weet een berekening van zonne opbrengst + batterij uitvoer + net invoer. En dat totaal klopt dan niet meer aangezien de opbrengst van de zonnepanelen dubbel geteld wordt.

Acties:
  • 0 Henk 'm!

  • Bra-Jo
  • Registratie: Mei 2002
  • Niet online

Bra-Jo

DILLIGAF

Ik had alles goed aan het draaien, dankzij een BT proxy. Nu heb ik mijn systeem uitgebreidmet een tweede Hyper en accu, en sindsdien heb ik weer freezes en moet ik Ha in zijn geheel herstarten om alles weer op de rit te krijgen. Nog niet echt onderzocht wat en hoe, doe ik binnenkort wanneer leven weer onder de 30 graden geleefd kan worden. :)

Wat ik me afvraag: hoe kan ik de maximale laadsnelheid begrenzen? Ivm veiligheid en C-waarde wil ik die op 500, maar krijg het niet voor elkaar. Input-limit lijkt niks te doen, maakt niet uit wat ik er instel. Ik kan het type cluster instellen, 800/1200/2400 enz. Dat lijkt ook niets te doen, heb ze nu beiden op 800 maar er wordt geladen op 900-1000. Wat doe ik verkeerd?

Nomen nescio


Acties:
  • 0 Henk 'm!

  • Dolf_Tweakers
  • Registratie: Januari 2025
  • Laatst online: 20-09 09:03
Zijn er hier al Belgen die de Hyper met zonnepanelen i.s.m. HA en NodeRed gebruiken?
Wil er namelijk al wat tijd in steken om het een beetje onder de knie te krijgen.
Uiteraard zoveel als mogelijk zelf opgewekte zonnestroom gebruiken maar ook peak-shaving toepassen om capaciteitstarief net onder 2500W te houden.
Zal ook i.s.m. Marstek 5.12 zijn die via RS485 Modbus zal aangestuurd worden.
Wordt dus een hele uitdaging.

B | VW ID.7 Tourer (77kWh) | SolarEdge SE3500H-BE 3.5kW - 4.86 Wp (18 Boviet BVM6610P-270 + Optimizers) 171° | Home Assistant | Marstek 5.12 uitgeleend | Zendure Hyper + 2 AB2000S


Acties:
  • +1 Henk 'm!
Bra-Jo schreef op zondag 29 juni 2025 @ 12:34:
Ik had alles goed aan het draaien, dankzij een BT proxy. Nu heb ik mijn systeem uitgebreidmet een tweede Hyper en accu, en sindsdien heb ik weer freezes en moet ik Ha in zijn geheel herstarten om alles weer op de rit te krijgen. Nog niet echt onderzocht wat en hoe, doe ik binnenkort wanneer leven weer onder de 30 graden geleefd kan worden. :)

Wat ik me afvraag: hoe kan ik de maximale laadsnelheid begrenzen? Ivm veiligheid en C-waarde wil ik die op 500, maar krijg het niet voor elkaar. Input-limit lijkt niks te doen, maakt niet uit wat ik er instel. Ik kan het type cluster instellen, 800/1200/2400 enz. Dat lijkt ook niets te doen, heb ze nu beiden op 800 maar er wordt geladen op 900-1000. Wat doe ik verkeerd?
Wat gebruik je, de FireSon integratie of als toevoeging daarop nog de "Fake meter" variant van @Bikkelreal ?

Je kunt zowel manual charging qua limiet instellen, als smart mode begrenzen. Hier werkt het nu al weken stabiel met een combinatie van beide en 3 Hypers via local MQTT en BT.

Dus: FireSon integratie altijd op Smart Mode, een fake P1-meter maken die qua waarde verandert. En daar kan je dan het vermogen voor laden/ontladen mee sturen. Zoals je hieronder ook ziet: Een 2400AC en Hyper op 1 groep samen doen 2800 Watt, terwijl ze samen 3600 Watt zouden kunnen doen.

Hierbij zie je mooi hoe dat werkt, de fake meter is -0.1 Watt, maar er wordt op dit moment wel 7910 Watt ontladen :)
Afbeeldingslocatie: https://tweakers.net/i/he6epIwH6Uyn7KIH1HGKB0Wh6i0=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/MCqtZtvsRiDbDtTqgff9Zm8W.png?f=user_large

[ Voor 4% gewijzigd door Taro op 29-06-2025 20:35 ]

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • 0 Henk 'm!

  • Bra-Jo
  • Registratie: Mei 2002
  • Niet online

Bra-Jo

DILLIGAF

Taro schreef op zondag 29 juni 2025 @ 20:29:
[...]

Wat gebruik je, de FireSon integratie of als toevoeging daarop nog de "Fake meter" variant van @Bikkelreal ?

Je kunt zowel manual charging qua limiet instellen, als smart mode begrenzen. Hier werkt het nu al weken stabiel met een combinatie van beide en 3 Hypers via local MQTT en BT.

Dus: FireSon integratie altijd op Smart Mode, een fake P1-meter maken die qua waarde verandert. En daar kan je dan het vermogen voor laden/ontladen mee sturen. Zoals je hieronder ook ziet: Een 2400AC en Hyper op 1 groep samen doen 2800 Watt, terwijl ze samen 3600 Watt zouden kunnen doen.

Hierbij zie je mooi hoe dat werkt, de fake meter is -0.1 Watt, maar er wordt op dit moment wel 7910 Watt ontladen :)
[Afbeelding]
Alleen de Fireson-integratie, met de P1-meter van Homewizard als "bron". De meter van Bikkelreal heb ik blijkbaar gemist, ga ik me even over inlezen.
Ik had verwacht dat het zou werken met de limiet instellen, dat heb ik ook in een automation meegenomen (set max input load to 500) maar dat (b)lijkt dus niet zo te zijn. Ik dacht even dat de automations misschien het probleem waren, maar zelfs wanneer die niet getriggerd worden, verliest HA af en toe de verbinding en moet ik heel HA herstarten om weer iets van actie te krijgen.

Misschien maar weer eens helemaal terug naar 0, zorgen dat communicatie blijft werken en da kijken wat er gebeurt met m'n aansturing. :/

Nomen nescio


Acties:
  • +1 Henk 'm!

  • wautah91
  • Registratie: April 2010
  • Laatst online: 03-10 13:22
Bra-Jo schreef op maandag 30 juni 2025 @ 06:46:
[...]
Misschien maar weer eens helemaal terug naar 0, zorgen dat communicatie blijft werken en da kijken wat er gebeurt met m'n aansturing. :/
Dat denk ik ook. Want op de manier hoe jij aanstuurt doe ik het ook. Gewoon een automation die het output limit op 270W zet 's nachts, ongeveer gelijk aan mijn sluipverbruik.

Afbeeldingslocatie: https://tweakers.net/i/p_TytSCBN2sqVq2Q7imXfpi5yAU=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/QHYbFPPm3FUnPqJHvVYXViy1.png?f=user_large


ik heb scripts aangemaakt die door de automation worden uitgevoerd.

Opladen met 1200 Watt, maar je kunt zelf de waarde kiezen.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
sequence:
  - action: select.select_option
    metadata: {}
    data:
      option: input
    target:
      entity_id: select.hyper2000_ac_mode
    alias: AC mode input
  - action: number.set_value
    metadata: {}
    data:
      value: "0"
    target:
      entity_id: number.hyper2000_output_limit
  - action: number.set_value
    metadata: {}
    data:
      value: "1200"
    target:
      entity_id: number.hyper2000_input_limit
  - action: select.select_option
    metadata: {}
    data:
      option: "off"
    target:
      entity_id: select.zendure_manager_operation
  - action: input_text.set_value
    metadata: {}
    data:
      value: Volle snelheid opladen
    target:
      entity_id: input_text.gekozen_accustrategie
  - action: automation.turn_off
    metadata: {}
    data:
      stop_actions: true
    target:
      entity_id: automation.handmatige_nom_2
alias: "Thuisaccu: volle snelheid opladen"
description: ""

[ Voor 60% gewijzigd door wautah91 op 30-06-2025 08:16 . Reden: plaatje toegevoegd ]

Mijn smarthome blog artikelen over: Thuisaccu | Dynamische energieprijzen | Watermeter


Acties:
  • 0 Henk 'm!

  • Bra-Jo
  • Registratie: Mei 2002
  • Niet online

Bra-Jo

DILLIGAF

wautah91 schreef op maandag 30 juni 2025 @ 08:12:
[...]


Dat denk ik ook. Want op de manier hoe jij aanstuurt doe ik het ook. Gewoon een automation die het output limit op 270W zet 's nachts, ongeveer gelijk aan mijn sluipverbruik.

[Afbeelding]


ik heb scripts aangemaakt die door de automation worden uitgevoerd.

Opladen met 1200 Watt, maar je kunt zelf de waarde kiezen.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
sequence:
  - action: select.select_option
    metadata: {}
    data:
      option: input
    target:
      entity_id: select.hyper2000_ac_mode
    alias: AC mode input
  - action: number.set_value
    metadata: {}
    data:
      value: "0"
    target:
      entity_id: number.hyper2000_output_limit
  - action: number.set_value
    metadata: {}
    data:
      value: "1200"
    target:
      entity_id: number.hyper2000_input_limit
  - action: select.select_option
    metadata: {}
    data:
      option: "off"
    target:
      entity_id: select.zendure_manager_operation
  - action: input_text.set_value
    metadata: {}
    data:
      value: Volle snelheid opladen
    target:
      entity_id: input_text.gekozen_accustrategie
  - action: automation.turn_off
    metadata: {}
    data:
      stop_actions: true
    target:
      entity_id: automation.handmatige_nom_2
alias: "Thuisaccu: volle snelheid opladen"
description: ""
Tnx, dat bevestigt dat mijn gedachtengang in ieder geval niet heel verkeerd was. :) Vanavond na werk maar weer eens puzzelen.

Nomen nescio


Acties:
  • +1 Henk 'm!

  • Sander
  • Registratie: Juni 2004
  • Niet online
Bra-Jo schreef op maandag 30 juni 2025 @ 08:39:
[...]

Tnx, dat bevestigt dat mijn gedachtengang in ieder geval niet heel verkeerd was. :) Vanavond na werk maar weer eens puzzelen.
Zodra je de output limit zet gaat de hyper automatisch over naar die fixed limit output stand en stopt hij dus met smart matching modus van FireSon. Die switches (en dat vaak doen) gaven in eerdere releases vaker freezes etc.

Ik doe het dus ook met een input_select waarin ik de modus kies (of laat kiezen door de dynamische prijzen etc) En dan een template die op basis daarvan de powermeter die FireSon integratie oppakt weer manipuleert:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{% set grid_power = (states("sensor.dsmr_reading_electricity_currently_delivered") | float(0) - states("sensor.dsmr_reading_electricity_currently_returned") | float(0)) * 1000 %}
{% set battery_power = ( states("sensor.hyper_2000_power_flow") | float(0)) %}
{% set charge_mode = states("input_select.thuisbatterij_modus") %}
{% if charge_mode == 'Geforceerd laden' %}
  -1250
{% elif charge_mode == 'Geforceerd ontladen' %}
  1000
{% elif charge_mode == 'Alleen Slim Laden' %}
  {% if grid_power > 0 %}
    {{ -battery_power }}
  {% else %}
    {{ min(0, grid_power) }}
  {% endif %}
{% elif charge_mode == 'Alleen Slim Ontladen' %}
  {% if grid_power < 0 %}
    {{ -battery_power }}
  {% else %}
    {{ max(0, grid_power) }}
  {% endif %}
{% else %} {# Default or any other state #}
  {{ grid_power }}
{% endif %}


Op deze manier zorg je er op een makkelijke manier voor dat je op ieder momnet gewoon de integratie hebt draaien maar zelf kan bijsturen wat er wel en niet mag gebeuren.

Acties:
  • 0 Henk 'm!

  • Bra-Jo
  • Registratie: Mei 2002
  • Niet online

Bra-Jo

DILLIGAF

Sander schreef op maandag 30 juni 2025 @ 10:58:
[...]


Zodra je de output limit zet gaat de hyper automatisch over naar die fixed limit output stand en stopt hij dus met smart matching modus van FireSon. Die switches (en dat vaak doen) gaven in eerdere releases vaker freezes etc.
Ah dat zou in mijn geval veel verklaren, tnx!
Ik ben nog niet heel erg thuis in het gebruik van scripts, mijn automatiseringen zijn allemaal vrij simpel op basis van de gui. Tijd om me daar in te gaan verdiepen lijkt me. Bedankt allen!

Nomen nescio


Acties:
  • +1 Henk 'm!

  • wautah91
  • Registratie: April 2010
  • Laatst online: 03-10 13:22
Bra-Jo schreef op dinsdag 1 juli 2025 @ 06:54:
[...]

Ah dat zou in mijn geval veel verklaren, tnx!
Ik ben nog niet heel erg thuis in het gebruik van scripts, mijn automatiseringen zijn allemaal vrij simpel op basis van de gui. Tijd om me daar in te gaan verdiepen lijkt me. Bedankt allen!
Je kunt de yaml code van de automatisering kopiëren en plakken in je automatisering door te kiezen voor 'Bewerken in yaml' in het menu. Daarna kun je terugswitchen naar de Visuele editor.

Mijn smarthome blog artikelen over: Thuisaccu | Dynamische energieprijzen | Watermeter


Acties:
  • +3 Henk 'm!

  • TiBoD
  • Registratie: Augustus 2004
  • Laatst online: 07:56
Ik heb wat zitten vibe coden en een Home Assistant integration gemaakt die de lokale API gebruikt. (Voor nu alleen reads; writes zijn nog TODO).

https://github.com/TimSoethout/home-assistant-zendure_local

Klik om via HACS te installeren:
https://my.home-assistant...ocal&category=integration

Wat vinden jullie er van? Nog doorontwikkelen? Ik weet niet of @FireSon de lokale API ook nog op de planning had staan, want dan voeg ik het liever samen natuurlijk. :)

Afbeeldingslocatie: https://tweakers.net/i/W5sCZ5ggLJna8MZorpPs6GoP8Q8=/800x/filters:strip_exif()/f/image/11iwlkOPgxD4ZxvbjCWFtZM5.png?f=fotoalbum_large

Acties:
  • 0 Henk 'm!
Ik liep er hier vaak tegen aan dat je in de homewizard app niet makkelijk bijvoorbeeld even de laatste 15minuten kunt tonen met 5 seconden interval en daarbij aangeeft wat de import en export is en hoe deze aansluit op het huisvermogen (grijs gekleurd). Ik gebruik daarom nu de onderstaande Home Assistant apexchart.

Zijn hier nog andere tweakers met mooie dashboards om inspiratie op te doen?

Afbeeldingslocatie: https://tweakers.net/i/yRYtADFxHdtB7bBEY5l5bZi6z4Y=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/bcOBoetyOTZYuhuKmYHh0Kcy.png?f=user_large

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • +1 Henk 'm!
Ziet er leuk uit! Maar denk wel dat de gebruikers vooral zoeken naar write opties en gewoon een te selecteren modus. Dit omdat sensoren vrij makkelijk zelf aan te maken zijn. Als dit zo doorgaat heeft iedereen wel een hoop te kiezen voor de aansturing en dat is zeker mooi!

Herkenbare rest_commands staan er al wel in zo te zien. ;)
TiBoD schreef op donderdag 3 juli 2025 @ 15:15:
Ik heb wat zitten vibe coden en een Home Assistant integration gemaakt die de lokale API gebruikt. (Voor nu alleen reads; writes zijn nog TODO).

https://github.com/TimSoethout/home-assistant-zendure_local

Klik om via HACS te installeren:
https://my.home-assistant...ocal&category=integration

Wat vinden jullie er van? Nog doorontwikkelen? Ik weet niet of @FireSon de lokale API ook nog op de planning had staan, want dan voeg ik het liever samen natuurlijk. :)

[Afbeelding]

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • 0 Henk 'm!

  • avdwerf
  • Registratie: Maart 2007
  • Nu online
Iemand dit dit voor me kan verduidelijken. Ik heb 2 (of eigenlijk 4, hetzelfde voor ontladen) waardes waartussen ik het verschil niet weet. Werk met de ZenSDK uit de openingspost.
Uit de json properties
inputLimit -> Zendure_2400_AC_Ingesteld_Oplaadvermogen

Afbeeldingslocatie: https://tweakers.net/i/q554ndLPlRnL7BdT0JdBwHGzZc8=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/XAXyF8t9l1cruWYeTbT2Hyku.png?f=user_large

En
outputPackPower -> Vermogen (opladen)
Afbeeldingslocatie: https://tweakers.net/i/N4CPR0FuRnEVZVuwnxs3tsQk1t8=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/sXzs3c9f2BidpEEHcHcx0c0P.png?f=user_large

Zou verwachten dat die laatste het actuele vermogen toont en die eerst een vaste waarde is, maar beiden veranderen tijdens het opladen zoals te zien in de screenshots.

Acties:
  • 0 Henk 'm!
Bij grafiek 1 geef je aan via de restapi wat je wilt dat hij gaat laden. Vervolgens bij grafiek 2 wat hij daadwerkelijk van dit laden overneemt en met een cap van 2400 watt.

Lijkt mij op zich duidelijk omdat het ingesteld oplaadvermogen variabel is (grafiek 1) gaat de batterij ook variabel opladen (grafiek 2)

Afbeeldingslocatie: https://tweakers.net/i/eKO0SncWxOpE0BvpgXmQFkpI5p4=/800x/filters:strip_exif()/f/image/zMixTcuZjDEuVicgOqM8gyco.png?f=fotoalbum_large

Afbeeldingslocatie: https://tweakers.net/i/25un44roAZqY14vZdhtQEo982QY=/800x/filters:strip_exif()/f/image/5f145L5ZR8W96XECva0gQaVE.png?f=fotoalbum_large
avdwerf schreef op vrijdag 4 juli 2025 @ 09:54:
Iemand dit dit voor me kan verduidelijken. Ik heb 2 (of eigenlijk 4, hetzelfde voor ontladen) waardes waartussen ik het verschil niet weet. Werk met de ZenSDK uit de openingspost.
Uit de json properties
inputLimit -> Zendure_2400_AC_Ingesteld_Oplaadvermogen

[Afbeelding]

En
outputPackPower -> Vermogen (opladen)
[Afbeelding]

Zou verwachten dat die laatste het actuele vermogen toont en die eerst een vaste waarde is, maar beiden veranderen tijdens het opladen zoals te zien in de screenshots.

[ Voor 20% gewijzigd door gielz op 04-07-2025 10:17 ]

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • 0 Henk 'm!

  • avdwerf
  • Registratie: Maart 2007
  • Nu online
gielz schreef op vrijdag 4 juli 2025 @ 10:13:
Bij grafiek 1 geef je aan via de restapi wat je wilt dat hij gaat laden. Vervolgens bij grafiek 2 wat hij daadwerkelijk van dit laden overneemt en met een cap van 2400 watt.

Lijkt mij op zich duidelijk omdat het ingesteld oplaadvermogen variabel is (grafiek 1) gaat de batterij ook variabel opladen (grafiek 2)

[Afbeelding]

[Afbeelding]


[...]
Aah oke. Ik heb de aansturing volledig in HEMS zelf zitten, gebruik HA alleen om uit te lezen. HEMS past dat dus continu aan op basis van de vraag/aanbod in mijn meterkast?

Acties:
  • 0 Henk 'm!
Ben niet echt bekend met HEMS, maar als het goed is stel je daar in hoe hij met je batterij om gaat. Heb je bijvoorbeeld een Shelly of een Ecotracker dan kun je daar naar kijken. Maar je zou nog even advies kunnen vragen in het algemene topic over HEMS en je huidige instellingen.
avdwerf schreef op vrijdag 4 juli 2025 @ 10:44:
[...]


Aah oke. Ik heb de aansturing volledig in HEMS zelf zitten, gebruik HA alleen om uit te lezen. HEMS past dat dus continu aan op basis van de vraag/aanbod in mijn meterkast?

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • 0 Henk 'm!

  • TiBoD
  • Registratie: Augustus 2004
  • Laatst online: 07:56
gielz schreef op vrijdag 4 juli 2025 @ 09:14:
Ziet er leuk uit! Maar denk wel dat de gebruikers vooral zoeken naar write opties en gewoon een te selecteren modus. Dit omdat sensoren vrij makkelijk zelf aan te maken zijn. Als dit zo doorgaat heeft iedereen wel een hoop te kiezen voor de aansturing en dat is zeker mooi!

Herkenbare rest_commands staan er al wel in zo te zien. ;)


[...]
Klopt, writes zijn wel echt nodig om het echt nuttig te maken.
Het is inderdaad geïnspireerd op jouw eerdere snippets. Zal je nog ergens credits geven. ;)
Ik heb ook de discussie gevolgd over persistent writes, dus wou dat ook goed toevoegen.

Ik kan me wel voorstellen dat de Cloud/Fireson integratie dit uiteindelijk ook gaat ondersteunen, zeker aangezien hij samen met Zendure (gaat) samenwerken.

Acties:
  • 0 Henk 'm!
@gielz Zou jij misschien een link in de TS willen delen naar de Homey integratie? Welke nu beschikbaar is gekomen. Of zou er in de toekomst een eigen topic gestart moeten worden bij meer interesse?

https://homey.app/nl-nl/app/com.zendure.flow/Zendure/

Het is natuurlijk een beetje grijs gebied om dit in het Home Assistant-integratietopic te vragen.

[ Voor 16% gewijzigd door geert1992 op 04-07-2025 12:49 ]

Humans don’t need an opportunity to be wicked. They’ve been doing it for free since the beginning.


Acties:
  • +1 Henk 'm!
Zodra er meer Homey's zich hier melden zal ik een stukje opnemen naar deze nieuwe integratie. Apart topic kan denk ik ook wel maar ook wel fijn om alle aparte aansturingen onder 1 dak te hebben.
geert1992 schreef op vrijdag 4 juli 2025 @ 12:47:
@gielz Zou jij misschien een link in de TS willen delen naar de Homey integratie? Welke nu beschikbaar is gekomen. Of zou er in de toekomst een eigen topic gestart moeten worden bij meer interesse?

https://homey.app/nl-nl/app/com.zendure.flow/Zendure/

Het is natuurlijk een beetje grijs gebied om dit in het Home Assistant-integratietopic te vragen.

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • +1 Henk 'm!
gielz schreef op vrijdag 4 juli 2025 @ 20:18:
Zodra er meer Homey's zich hier melden zal ik een stukje opnemen naar deze nieuwe integratie. Apart topic kan denk ik ook wel maar ook wel fijn om alle aparte aansturingen onder 1 dak te hebben.


[...]
Ja, graag allemaal hier. Mochten het nou 30 pagina's per dag worden kunnen we altijd verder kijken naar aparte topics.

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • 0 Henk 'm!
Benieuwd: De nieuwe pre-release doet volgens mij iets met 2400 AC's, Bluetooth en local MQTT. Iemand daarmee een 2400 AC lokaal in gebruik?

Ik wil als ik terug ben van vakantie een keer van Zendure account wisselen in HA en 3x 2400AC ipv 3x Hyper gaan inzetten. Als dat namelijk goed werkt kan ik de Hypers verkopen en daarvoor extra AB3000X opslag halen. Van 6 naar 3 devices ruimt hier lekker op...

Of 3x 2400 AC lokaal aansturen, maar volgens mij zijn er nog geen scripts die de load over 2 of meerdere devices lokaal aansturen?

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • 0 Henk 'm!
Voor de gene die nu een energy socket gebruiken en naar iets anders willen voor metingen buiten een KWH meter om. Ik ben nu de Shelly PM Mini Gen3 aan het testen;

https://www.bol.com/nl/nl...hAhA.4_13.14.ProductImage

Afbeeldingslocatie: https://tweakers.net/i/67-bRVCOFdo7ax07SqUqgRzLHLw=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/KWYZt53zxnUWFlwdNue9tq6m.png?f=user_large


code:
1
2
3
4
5
6
7
8
  - resource: http://192.168.0.227/rpc/PM1.GetStatus?id=0   # IP-adres van je Shelly PM Mini Gen3 voor API
    scan_interval: 1
    sensor:
      - name: "Shelly Zendure 2400 AC Vermogen Aansturing API"
        value_template: "{{ value_json.apower | float }}"
        unique_id: Shelly_Zendure_2400_AC_Vermogen_Aansturing_API
        unit_of_measurement: "W"
        device_class: power

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • 0 Henk 'm!

  • Dolf_Tweakers
  • Registratie: Januari 2025
  • Laatst online: 20-09 09:03
gielz schreef op zaterdag 5 juli 2025 @ 09:46:
Voor de gene die nu een energy socket gebruiken en naar iets anders willen voor metingen buiten een KWH meter om. Ik ben nu de Shelly PM Mini Gen3 aan het testen;

https://www.bol.com/nl/nl...hAhA.4_13.14.ProductImage

[Afbeelding]


code:
1
2
3
4
5
6
7
8
  - resource: http://192.168.0.227/rpc/PM1.GetStatus?id=0   # IP-adres van je Shelly PM Mini Gen3 voor API
    scan_interval: 1
    sensor:
      - name: "Shelly Zendure 2400 AC Vermogen Aansturing API"
        value_template: "{{ value_json.apower | float }}"
        unique_id: Shelly_Zendure_2400_AC_Vermogen_Aansturing_API
        unit_of_measurement: "W"
        device_class: power
Meet die bi-directioneel?
*edit* Was domme vraag, de foto was duidelijk

B | VW ID.7 Tourer (77kWh) | SolarEdge SE3500H-BE 3.5kW - 4.86 Wp (18 Boviet BVM6610P-270 + Optimizers) 171° | Home Assistant | Marstek 5.12 uitgeleend | Zendure Hyper + 2 AB2000S


Acties:
  • 0 Henk 'm!
Was ik ook benieuwd naar, en ja dat doet hij. Alleen voor de KWH import data heb je alleen een import+export en export. De import moet je even oplossen met een simpele template sensor.

Afbeeldingslocatie: https://tweakers.net/i/oAvnKNE--ppN0fA6bHeIrqHsVk8=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/SZEzPOMf38YVPhQ5Fls5snbx.png?f=user_large


Heb nu alles omgebouwd en zal deze week het doortesten.

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • 0 Henk 'm!

  • c0mplex1
  • Registratie: Juni 2025
  • Laatst online: 22-09 16:32
@gielz Ik heb wat vragen betreffende de timing van de automatisering en hardware.

Dat je om de 4 seconden de automatisering (Zendure NOM 1.00) start snap ik, want bij een kortere tijd bevriest de 2400AC en bij een langere tijd gaat de automatisering te ver uit de pas lopen.

Maar waarom lees je (met REST) de 2400AC om de 30 seconden uit en niet om de 4 seconden, want als je geen scan_interval definieer is de interval tijd standaard 30 sec.
Moet dit dan ook niet eens in de 4 seconden zijn, dus gelijk aan de automatisering?

Waarom lees je de HWE-P1 en HWE-SKT iedere seconde uit en niet eens in de 4 seconden.
Je gooit 3 samples weg, die gebruik je toch niet, omdat de automatiseering er niets mee doet, want die werkt maar 1x per 4 seconden. Dus ook hier de HWE-P1 en HWE-SKT 1x per 4 seconden uitlezen lijkt mij logischer.

PV 4340 Wp OW | SF2400AC + 4*AB3000X | EV 65kWh | Dynamisch contract | HA OS op RPi5


Acties:
  • 0 Henk 'm!
@c0mplex1 Er zal ook een volgordelijkheid én stukje timing in zitten. Je stelt de 2400 AC het liefst in met de laatst bekende waarde van maximaal 1 seconde geleden en niet bijv. de waarde van 3-4 seconden geleden.

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • 0 Henk 'm!
Dat was ook eerst hier het idee, waarom niet op een 4 seconden interval. Maar wanneer hij om de 4 seconden gaat kijken wat er moet gebeuren dan kan het zijn dat de P1 net nog zijn data moet verversen en je dus met oude data gaat werken. Hier ziet het er trouwens nu zo uit (laatste 30 minuten), dik tevreden;

*Batterij vermogen is omgedraaid in het dashboard - is laden + ontladen om gelijk te lopen met de P1.
Afbeeldingslocatie: https://tweakers.net/i/HoFR8S88kp0OairOtGxDeZpMrBE=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/QrNVAAHIf3yRl17KR1qspaf8.png?f=user_large

De overige sensoren meer uitlezen doe ik zelf voorlopig niet omdat de batterij dan zal bevriezen. Dit is standaard 15 seconden bij de overige sensoren. Ik heb nog wel een vraag open staan wat de rate limiter is van de API.

Mocht je zelf tot iets komen wat beter werkt in de praktijk deel het vooral hier! *O*
c0mplex1 schreef op zaterdag 5 juli 2025 @ 13:47:
@gielz Ik heb wat vragen betreffende de timing van de automatisering en hardware.

Dat je om de 4 seconden de automatisering (Zendure NOM 1.00) start snap ik, want bij een kortere tijd bevriest de 2400AC en bij een langere tijd gaat de automatisering te ver uit de pas lopen.

Maar waarom lees je (met REST) de 2400AC om de 30 seconden uit en niet om de 4 seconden, want als je geen scan_interval definieer is de interval tijd standaard 30 sec.
Moet dit dan ook niet eens in de 4 seconden zijn, dus gelijk aan de automatisering?

Waarom lees je de HWE-P1 en HWE-SKT iedere seconde uit en niet eens in de 4 seconden.
Je gooit 3 samples weg, die gebruik je toch niet, omdat de automatiseering er niets mee doet, want die werkt maar 1x per 4 seconden. Dus ook hier de HWE-P1 en HWE-SKT 1x per 4 seconden uitlezen lijkt mij logischer.

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • 0 Henk 'm!

  • c0mplex1
  • Registratie: Juni 2025
  • Laatst online: 22-09 16:32
Snap ik.
Wat ik niet snap is waarom de automatisering maar 1x per 4 seconde, en de aangeleverde data 1x per seconde.
Als alles via HA aangestuurd wordt zijn de start momenten, of het 1x per seconde of 1x per 4 seconden, gelijk.
b.v. om de 4 P1 triggers is gelijk aan elke automatisering trigger. HA gebruikt maar 1 klok, toch?

PV 4340 Wp OW | SF2400AC + 4*AB3000X | EV 65kWh | Dynamisch contract | HA OS op RPi5


Acties:
  • 0 Henk 'm!

  • c0mplex1
  • Registratie: Juni 2025
  • Laatst online: 22-09 16:32
@gielz We hebben gelijktijdig op de reageer knop gedrukt. Mijn antwoord was aan @Taro gericht.

Begrijp ik je goed dat als je de sensoren met een interval van 4 seconden uitleest, dat de 2400AC dan ook bevriest?
Waar baseer je die 15 seconden uitleestijd op? Die instelling kom ik nergens tegen.

PV 4340 Wp OW | SF2400AC + 4*AB3000X | EV 65kWh | Dynamisch contract | HA OS op RPi5


Acties:
  • 0 Henk 'm!
c0mplex1 schreef op zaterdag 5 juli 2025 @ 14:22:
Snap ik.
Wat ik niet snap is waarom de automatisering maar 1x per 4 seconde, en de aangeleverde data 1x per seconde.
Als alles via HA aangestuurd wordt zijn de start momenten, of het 1x per seconde of 1x per 4 seconden, gelijk.
b.v. om de 4 P1 triggers is gelijk aan elke automatisering trigger. HA gebruikt maar 1 klok, toch?
HA zal taken serieel uitvoeren, niet parallel vermoed ik. Dus iedere 4 seconden betekent niet exact in dezelfde milliseconde. En het kan zijn dat het ophalen van de data net wat meer tijd kost dan het schrijven van de data naar een ander device en je dus een oude waarde gebruikt.

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • 0 Henk 'm!
Ja de batterij zal dan bevriezen en dan moet je hem loskoppelen en van de batterijen aftillen. Ik zie bij de overige sensoren en eigenlijk alle standaard sensoren in HA altijd 15 seconden.

Maar waar loop je nu exact tegen aan in de praktijk? Gaat er iets niet goed?
c0mplex1 schreef op zaterdag 5 juli 2025 @ 14:32:
@gielz We hebben gelijktijdig op de reageer knop gedrukt. Mijn antwoord was aan @Taro gericht.

Begrijp ik je goed dat als je de sensoren met een interval van 4 seconden uitleest, dat de 2400AC dan ook bevriest?
Waar baseer je die 15 seconden uitleestijd op? Die instelling kom ik nergens tegen.

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • 0 Henk 'm!

  • c0mplex1
  • Registratie: Juni 2025
  • Laatst online: 22-09 16:32
De standaard (rest) scan_interval tijd heb ik hier vandaan.
Als je die op 15 seconden wilt hebben, zul je die parameter moeten invullen... denk ik.

Ik ben me aan het inleven hoe je de automatisering, met wat alles er bij hoort, tot stand hebt gebracht.
Tegen praktische problemen ben ik nog niet aangelopen, omdat ik nog wacht op de volledige levering van Zendure.

Ik ben wel bezig om jouw automatisering in één yaml bestand onder te brengen (rest, rest_command, input_select, Integral sensoren, etc.), zodat alles bij elkaar zit.
Ook dat deel waarmee je de automatisering uitschakelt ben ik aan het aanpassen.

PV 4340 Wp OW | SF2400AC + 4*AB3000X | EV 65kWh | Dynamisch contract | HA OS op RPi5


Acties:
  • 0 Henk 'm!
Leuke hobby!

Hier heel specifiek alles gescheiden. Restful gaat via de configuration.yaml. Al het overige direct via de UI. Omdat het hele huis via HA draait moet herstarten echt tot het minimum beperkt worden.

Laat vooral weten hoe het allemaal draait zodra het binnen is en of je nog verbeteringen hebt doorgevoerd.
c0mplex1 schreef op zaterdag 5 juli 2025 @ 15:21:
De standaard (rest) scan_interval tijd heb ik hier vandaan.
Als je die op 15 seconden wilt hebben, zul je die parameter moeten invullen... denk ik.

Ik ben me aan het inleven hoe je de automatisering, met wat alles er bij hoort, tot stand hebt gebracht.
Tegen praktische problemen ben ik nog niet aangelopen, omdat ik nog wacht op de volledige levering van Zendure.

Ik ben wel bezig om jouw automatisering in één yaml bestand onder te brengen (rest, rest_command, input_select, Integral sensoren, etc.), zodat alles bij elkaar zit.
Ook dat deel waarmee je de automatisering uitschakelt ben ik aan het aanpassen.

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • 0 Henk 'm!

  • bert pit
  • Registratie: Oktober 2012
  • Laatst online: 20:18

bert pit

asdasd

Mag ik hier ook een noob vraag stellen?
Ik heb geen ervaring met HA en wil er naar kijken om mijn twee Hypers ermee aan te sturen. Dus heb ik een oud laptopje voorzien van ubuntu en heb daar HA op gezet HA werkte op zich prima, maar het blijkt dat je daar geen HACS mee kan draaien dus ben ik overgestapt naar Debian. Op Debian loop ik vast in het besturingssysteem en krijg dat waarschijnlijk met veel gepruts/tijd wel voor elkaar. Maar het lijkt een beetje op het trekken aan een dood paard.

Mijn vraag aan de experts hier is wat voor een noob als mezelf de makkelijkste weg is om HA met HACS draaiend te krijgen. Is dat een HA green/yellow? Of loop ik daar tegen dezelfde problemen aan?

[ Voor 4% gewijzigd door bert pit op 05-07-2025 18:41 ]

Tijdens het lezen van deze zin, wordt wereldwijd circa 1.000.000 liter olie verstookt. Dus niet 2X lezen hè.


Acties:
  • +1 Henk 'm!

  • DaWizza
  • Registratie: Augustus 2001
  • Niet online
@bert pit je vraag past wss beter in Home Assistant: Open source Python3 home automation - deel 5

Dan zou ik daar wel uitleggen waarom HACS installeren niet lukt, dat moet gewoon werken op een x86/64 systeem.

SUZ-SWM80VA & ERSD-VM2D, 200L SWW, 5330Wp O 45°, 2870Wp W 45°, 820Wp Z 10°, Zendure 2400AC 8,64kWh thuisbatterij, Fresh-r on the wall compac WTW


Acties:
  • +3 Henk 'm!

  • jordyc
  • Registratie: Oktober 2014
  • Laatst online: 20:45
bert pit schreef op zaterdag 5 juli 2025 @ 18:39:
Mag ik hier ook een noob vraag stellen?
Ik heb geen ervaring met HA en wil er naar kijken om mijn twee Hypers ermee aan te sturen. Dus heb ik een oud laptopje voorzien van ubuntu en heb daar HA op gezet HA werkte op zich prima, maar het blijkt dat je daar geen HACS mee kan draaien dus ben ik overgestapt naar Debian. Op Debian loop ik vast in het besturingssysteem en krijg dat waarschijnlijk met veel gepruts/tijd wel voor elkaar. Maar het lijkt een beetje op het trekken aan een dood paard.

Mijn vraag aan de experts hier is wat voor een noob als mezelf de makkelijkste weg is om HA met HACS draaiend te krijgen. Is dat een HA green/yellow? Of loop ik daar tegen dezelfde problemen aan?
Ik draai HA op een HA green en dat werkt perfect. Ideaal om laagdrempelig te starten.

Acties:
  • +2 Henk 'm!

  • klump4u
  • Registratie: Februari 2008
  • Niet online

klump4u

Full electric in Zuid-Limburg

bert pit schreef op zaterdag 5 juli 2025 @ 18:39:
Mag ik hier ook een noob vraag stellen?
Ik heb geen ervaring met HA en wil er naar kijken om mijn twee Hypers ermee aan te sturen. Dus heb ik een oud laptopje voorzien van ubuntu en heb daar HA op gezet HA werkte op zich prima, maar het blijkt dat je daar geen HACS mee kan draaien dus ben ik overgestapt naar Debian. Op Debian loop ik vast in het besturingssysteem en krijg dat waarschijnlijk met veel gepruts/tijd wel voor elkaar. Maar het lijkt een beetje op het trekken aan een dood paard.

Mijn vraag aan de experts hier is wat voor een noob als mezelf de makkelijkste weg is om HA met HACS draaiend te krijgen. Is dat een HA green/yellow? Of loop ik daar tegen dezelfde problemen aan?
Ik heb op MP een Intel NUC gekocht met ssd, hier draait HA OS op en draait als een zonnetje, ook HACS

18950Wp🌞, Atlantic 270V3💧, Pana 5J🔥. Zendure 2400AC 11,5kWh🔋,Hyundai Kona 64kWh 🚗, Peblar Home ⛽


Acties:
  • +1 Henk 'm!

  • c0mplex1
  • Registratie: Juni 2025
  • Laatst online: 22-09 16:32
Raspberry Pi 5 Model B - 8GB
Transcend 128GB microSD UHS-I U3 A2 Ultra performance 160/90 MB/s
Behuizing Argon Neo 5 BRED voor RPi 5 (Zwart/Rood)
Raspberry Pi 27W USB-C Power Supply - Wit

Kiwi Electronics +/- € 150,00

Mijn hele huis draait er op. (incl. EV, zonnepanelen, nog geen PiB)

[ Voor 13% gewijzigd door c0mplex1 op 05-07-2025 19:27 ]

PV 4340 Wp OW | SF2400AC + 4*AB3000X | EV 65kWh | Dynamisch contract | HA OS op RPi5


Acties:
  • 0 Henk 'm!
Hier na ooit een RPI4 en daarna RPI5 te hebben gebruikt, inmiddels een Intel NUC i3 met 16 GB RAM en 256 GB SSD in gebruik voor Home Assistant. Via HA OS kan je ook Add-ons gebruiken en heb je dus alle mogelijkheden.

Wil je er veel mee doen en ben je er op een gegeven moment zelfs "afhankelijk" van? Ga dan niet voor een SD-kaart - die levensduur is beperkt en maak dus vooral dagelijks backups - maar ga voor een SSD en echte zuinige PC. De performance is echt stukken beter, helemaal als je in sommige gevallen heel HA regelmatig opnieuw moet opstarten zoals bij het debuggen van sommige nieuwe integraties weleens het geval is ;)

[ Voor 5% gewijzigd door Taro op 05-07-2025 20:37 ]

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • +1 Henk 'm!
Kijk ook vooral in huis wat je al hebt als je beginner bent. Heb je bijvoorbeeld een Synology NAS dan kun je daar ook gewoon Home Assistant OS erbij draaien. Hij staat al aan dus win-win.

Een collega die niets van Home Assistant wist heeft laatst een Home Assistant Green gekocht. Volgens hem de beste aankoop voor zijn smarthome hobby ooit.

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • +1 Henk 'm!
gielz schreef op zaterdag 5 juli 2025 @ 20:49:
Kijk ook vooral in huis wat je al hebt als je beginner bent. Heb je bijvoorbeeld een Synology NAS dan kun je daar ook gewoon Home Assistant OS erbij draaien. Hij staat al aan dus win-win.

Een collega die niets van Home Assistant wist heeft laatst een Home Assistant Green gekocht. Volgens hem de beste aankoop voor zijn smarthome hobby ooit.
Idd, gewoon gratis beginnen. Ik had hiervoor Domoticz, vond Home Assistant een enorme drempel en achteraf dacht ik: Had ik jaren eerder moeten doen.

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • 0 Henk 'm!

  • remcoXP
  • Registratie: Februari 2002
  • Laatst online: 08:51
klopt het overigens dat als je voor de FireSon methode kiest je geen integral helpers hoeft aan te maken zoals in de wiki staat?
ik kon op het energie dashboard kiezen voor total geladen en total geleverd. dat is toch correct?

Gadget-freakz.com. Feedback en tips zijn welkom.


Acties:
  • 0 Henk 'm!
remcoXP schreef op zondag 6 juli 2025 @ 07:15:
klopt het overigens dat als je voor de FireSon methode kiest je geen integral helpers hoeft aan te maken zoals in de wiki staat?
ik kon op het energie dashboard kiezen voor total geladen en total geleverd. dat is toch correct?
Klopt, Fireson is een integratie waar alles voor je klaar gezet word. Is ook een apart onderdeel in de TS. 😉

6320wp | Zendure 2400 AC (14.4 kwh) | Bambu A1 | 2x Hisense 2AMW-42U4RRA | Daikin RXM/FTXM35R | AQMOS BMX | Home Assistant OS op DS224+


Acties:
  • 0 Henk 'm!

  • remcoXP
  • Registratie: Februari 2002
  • Laatst online: 08:51
dat klopt maar zijn github en de https://www.twoenter.nl/ blog schrijven er nog wel over, vandaar mijn verwarring

Gadget-freakz.com. Feedback en tips zijn welkom.


Acties:
  • +1 Henk 'm!
Ik wil graag NOM gaan draaien met 3x 2400 AC in Home Assistant en dus het verdelen van de load over 3x 2400 AC ipv 3x Hyper en 3x 2400 AC. Daarom zou ik graag het lokale NOM gebeuren van @gielz vertalen van 1 naar 2, 3 of meer devices via REST API of MQTT aansturing.

De FireSon integratie doet dat al netjes, die neemt omvormervermogen, SoC, etc. mee en berekent dan de input/output per device. Nadeel is dat ik dit nog niet stabiel werkend heb gekregen voor meerdere 2400 AC's. Ik zal eerlijk zijn, ik zit er niet op te wachten dit helemaal zelf te gaan scripten.

Heeft iemand al een script of automatisering die op basis van 2 of meer Zendure 2400AC devices icm lokale aansturing NOM bereikt?

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • 0 Henk 'm!
Taro schreef op zondag 6 juli 2025 @ 18:40:
Ik wil graag NOM gaan draaien met 3x 2400 AC in Home Assistant en dus het verdelen van de load over 3x 2400 AC ipv 3x Hyper en 3x 2400 AC. Daarom zou ik graag het lokale NOM gebeuren van @gielz vertalen van 1 naar 2, 3 of meer devices via REST API of MQTT aansturing.

De FireSon integratie doet dat al netjes, die neemt omvormervermogen, SoC, etc. mee en berekent dan de input/output per device. Nadeel is dat ik dit nog niet stabiel werkend heb gekregen voor meerdere 2400 AC's. Ik zal eerlijk zijn, ik zit er niet op te wachten dit helemaal zelf te gaan scripten.

Heeft iemand al een script of automatisering die op basis van 2 of meer Zendure 2400AC devices icm lokale aansturing NOM bereikt?
Ik gebruik een NOM waarbij ik een 2400 AC en een SF 800 Pro combineer. De NOM is gecodeerd via node red.

Bij SoC werkt die zo dat wanneer 1 van de 2 soc hoger is dan ontlaadt die zoveel als mogelijk met de hoogste soc en restant met soc 2.

Daarnaast ook tot 250w wordt het beperkt tot 1 device (om onnodige kleine loads te krijgen).

Het een en ander is ook makkelijk uit te breiden. En dat ga ik ook nog doen (met 1 hyper fireson erbij), maar dat heb ik nu nog niet nodig. Komt van de winter wel

Als je die wil gebruiken laat maar weten dan dm ik die wel even.

energienerds.nl | gasloos| 11,5kWp | 20 kWh accu | EV | Atlantic WPB


Acties:
  • 0 Henk 'm!

  • Aziraphale
  • Registratie: September 2013
  • Nu online
Naar aanleiding van een DM wisseling met @Taro hier verder met mijn zoektocht naar hoe ik de Hyper goed kan laten werken met dynamische prijzen. In het algemene Zendure topic was er al code door Taro gedeeld en ik heb ook een handleiding online gevonden, maar die is nog niet genoeg "voor Dummies" om mij het te laten begrijpen.

Ik heb inmiddels zowel de Cheapest Energy Hours van The Fez als AIO Energy Management en Nord Pool geïnstalleerd, dus daarmee kan ik werken. Vervolgens moet ik templates aanmaken en dat kan ik ook, maar welke sensoren moet ik dan gebruiken? De handleiding die ik heb geeft het volgende:

code:
1
2
{% from 'cheapest_energy_hours.jinja' import cheapest_energy_hours %}
{{ cheapest_energy_hours('sensor.nordpool_kwh_nl_eur_4_09_021', attr_today='Today', hours=6, split=true, lowest=True, mode='is_now', value_key='price', time_key='time') }}


Maar de sensor die hierin genoemd wordt heb ik zelf niet. En ook in de gedeelde YAML in het andere topic zal ik zaken aan moeten passen voor mijn apparatuur, maar wat? Er is ook sprake van een visuele IFTT editor en dat zou me al een hoop helpen, want ik kon vroeger in Domoticz wel redelijk overweg met Blockly.

Mijn PV is niet rechtstreeks aangesloten op het Hyper, dus hij zal bij invoeding van PV naar het net moeten laden en als er geen PV overschot is op de goedkope uren vanuit het net. Verder streef ik dan naar NOM en daarna naar ontladen op dure uren. Dat laatste is nu nog niet echt van toepassing omdat ik nu de accu's aardig leeg trek gedurende de avond/nacht. Ik ben echter al aan het nadenken over uitbreiding en dan wordt dat waarschijnlijk wel interessant.

3120WP Solax, 4825WP SolarEdge, Nibe S2125-8 met een VVMS320, 11,52 kWh Zendure 2400AC


Acties:
  • 0 Henk 'm!
@Aziraphale Welke Nord Pool sensor je hebt hangt af van of je deze bijv. incl. of excl. BTW hebt aangemaakt. Heb je een andere dan kan je die prima gebruiken.

Als je mijn code hergebruikt heb je veel sensoren/entiteiten die inderdaad niet bekend zijn. Maar, als dat aangepast/hersteld is ziet het er in de WYSIWIG editor zo uit (2 bovenste delen, de rest herhaalt dit principe):
Afbeeldingslocatie: https://tweakers.net/i/7hj-bYKvATGFn636oNZItbNK_fc=/x800/filters:strip_exif()/f/image/oDuD7cqiKq1SA0fVsEkGdp0P.png?f=fotoalbum_large

Afbeeldingslocatie: https://tweakers.net/i/csbIwWdFhHilCrYK675MstR-T0Q=/x800/filters:strip_exif()/f/image/HY90jzCvXPDvdX07q54sjcS6.png?f=fotoalbum_large

Waarbij dan de IF checkt in de 1e stap op:
Afbeeldingslocatie: https://tweakers.net/i/yve0bXiF7jgdIjO7MDSCQLUoiBs=/x800/filters:strip_exif()/f/image/v2dKrXrX7VmVhKleCFCHZD87.png?f=fotoalbum_large

En voor de 2e stap op:
Afbeeldingslocatie: https://tweakers.net/i/hbzxVupoi59ZQk70E4wyMIlO1Ck=/x800/filters:strip_exif()/f/image/SgAncMA72ytyIbQJB5IeQohB.png?f=fotoalbum_large

Hopelijk helpt dat in het begrijpelijk maken?

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • +2 Henk 'm!

  • robkds
  • Registratie: Januari 2004
  • Laatst online: 05:52
Voor degenen (zoals ik) die met de restful API een Solarflow 800 Pro gebruiken, met deze code in je configuration.yaml kan je de PV inputs uitlezen:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#begin PV input
      - name: "Zendure 2400 AC solarInputPower"
        value_template: "{{ value_json['properties']['solarInputPower'] }}"
        unique_id: Zendure_2400_AC_solarInputPower
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power
      - name: "Zendure 2400 AC PV1"
        value_template: "{{ value_json['properties']['solarPower1'] }}"
        unique_id: Zendure_2400_AC_PV1
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power
      - name: "Zendure 2400 AC PV2"
        value_template: "{{ value_json['properties']['solarPower2'] }}"
        unique_id: Zendure_2400_AC_PV2
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power
      - name: "Zendure 2400 AC PV3"
        value_template: "{{ value_json['properties']['solarPower3'] }}"
        unique_id: Zendure_2400_AC_PV3
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power
      - name: "Zendure 2400 AC PV4"
        value_template: "{{ value_json['properties']['solarPower4'] }}"
        unique_id: Zendure_2400_AC_PV4
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power
#einde PV input

Dit moet je dus bij het stuk met de sensors toevoegen.

Goed man!


Acties:
  • 0 Henk 'm!

  • Aziraphale
  • Registratie: September 2013
  • Nu online
@Taro Hier kan ik al een stuk meer uit halen, thanks! De Nord Pool integratie heb ik gewoon geïnstalleerd en volgens mij heb ik daar verder niets bij aan kunnen geven qua btw. Niet dat dat veel uit zal maken voor de goedkope en dure uren, lijkt me?

3120WP Solax, 4825WP SolarEdge, Nibe S2125-8 met een VVMS320, 11,52 kWh Zendure 2400AC


Acties:
  • 0 Henk 'm!
Aziraphale schreef op zondag 6 juli 2025 @ 20:26:
@Taro Hier kan ik al een stuk meer uit halen, thanks! De Nord Pool integratie heb ik gewoon geïnstalleerd en volgens mij heb ik daar verder niets bij aan kunnen geven qua btw. Niet dat dat veel uit zal maken voor de goedkope en dure uren, lijkt me?
Ik heb in de configuration.yaml nog het volgende staan om de Nord Pool tarieven gelijk te krijgen aan de Zonneplan tarieven:
YAML:
1
2
3
4
5
6
7
8
9
10
11
12
13
  - platform: nordpool
    VAT: False
    currency: "EUR"
    price_in_cents: false
    low_price_cutoff: 0.9
    region: "NL"
    precision: 3
    price_type: kWh
    additional_costs: >
      {% set VAT = 0.21 %}
      {% set tax_kWh = 0.10154 %}
      {% set opslag = 0.0165 %}
      {{ (current_price * VAT ) + (tax_kWh + opslag) * (1 + VAT)|float }}


Als je Nord Pool tarieven nu al correct zijn, dan moet je gewoon de huidige beschikbare sensor gebruiken.

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • 0 Henk 'm!

  • Aziraphale
  • Registratie: September 2013
  • Nu online
Taro schreef op zondag 6 juli 2025 @ 20:28:
[...]

Ik heb in de configuration.yaml nog het volgende staan om de Nord Pool tarieven gelijk te krijgen aan de Zonneplan tarieven:
YAML:
1
2
3
4
5
6
7
8
9
10
11
12
13
  - platform: nordpool
    VAT: False
    currency: "EUR"
    price_in_cents: false
    low_price_cutoff: 0.9
    region: "NL"
    precision: 3
    price_type: kWh
    additional_costs: >
      {% set VAT = 0.21 %}
      {% set tax_kWh = 0.10154 %}
      {% set opslag = 0.0165 %}
      {{ (current_price * VAT ) + (tax_kWh + opslag) * (1 + VAT)|float }}


Als je Nord Pool tarieven nu al correct zijn, dan moet je gewoon de huidige beschikbare sensor gebruiken.
Die zijn bij mij absoluut niet correct, dus dit stukje is voor mij zeker interessant. Heb je dit zoals het hier staan in de configuration.yaml staan of onder een bepaald kopje?

3120WP Solax, 4825WP SolarEdge, Nibe S2125-8 met een VVMS320, 11,52 kWh Zendure 2400AC


Acties:
  • 0 Henk 'm!
Aziraphale schreef op zondag 6 juli 2025 @ 22:45:
[...]


Die zijn bij mij absoluut niet correct, dus dit stukje is voor mij zeker interessant. Heb je dit zoals het hier staan in de configuration.yaml staan of onder een bepaald kopje?
In de configuration.yaml.

Iemand wees hier laatst op de optie om een mapje te maken, met bijv. daarin:

zendure.yaml
nordpool.yaml
ecotracker.yaml
etc.

En dan het mapje te includen via de configuration.yaml, maar daarna werkte er helaas niets meer. Dus heb nu alles wederom in 1 bestand staan.

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • 0 Henk 'm!

  • Aziraphale
  • Registratie: September 2013
  • Nu online
Taro schreef op zondag 6 juli 2025 @ 22:47:
[...]

In de configuration.yaml.

Iemand wees hier laatst op de optie om een mapje te maken, met bijv. daarin:

zendure.yaml
nordpool.yaml
ecotracker.yaml
etc.

En dan het mapje te includen via de configuration.yaml, maar daarna werkte er helaas niets meer. Dus heb nu alles wederom in 1 bestand staan.
Ik heb ook alles daarin staan, maar dat staat dan gegroepeerd onder kopjes als 'template', 'sensor' etc. Dat hoeft hierbij dus niet?

3120WP Solax, 4825WP SolarEdge, Nibe S2125-8 met een VVMS320, 11,52 kWh Zendure 2400AC


Acties:
  • +1 Henk 'm!
@Aziraphale De Nord Pool config heb ik inderdaad bij het "sensor" onderdeel staan. Dus:

sensor:
- platform: nordpool

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • 0 Henk 'm!

  • remcoXP
  • Registratie: Februari 2002
  • Laatst online: 08:51
vandaag de pre versie uit hacs geinstalleerd omdat ik toch maar lokal MQTT, BLE wilde gebruiken.

ik gebruik: EMQX als broker en daarin heb ik de user aangemaakt met alle rechten die in de debuglog van fireson staat.
Echter ben ik nu bijna alle devices kwijt en blijft de status BLE zijn. Heb ik nu wat gemist of moet ik nog wat proberen?

Gadget-freakz.com. Feedback en tips zijn welkom.


Acties:
  • +1 Henk 'm!
remcoXP schreef op maandag 7 juli 2025 @ 08:47:
vandaag de pre versie uit hacs geinstalleerd omdat ik toch maar lokal MQTT, BLE wilde gebruiken.

ik gebruik: EMQX als broker en daarin heb ik de user aangemaakt met alle rechten die in de debuglog van fireson staat.
Echter ben ik nu bijna alle devices kwijt en blijft de status BLE zijn. Heb ik nu wat gemist of moet ik nog wat proberen?
Dan kun je het beste de mqtt reset proberen en als dat niet werkt HA nog een keer opnieuw opstarten

energienerds.nl | gasloos| 11,5kWp | 20 kWh accu | EV | Atlantic WPB


Acties:
  • 0 Henk 'm!

  • remcoXP
  • Registratie: Februari 2002
  • Laatst online: 08:51
gedaan maar helaas, debugging log geeft ook niets raars aan behalve dat hij een getall doet en dat lijkt te werken. geen connection errors of deny oid.
zou niet aan het feit mogen liggen dat ik een andere broker gebruik.

als ik met de user en pass die in de logs staat probeer in te loggen in mqtt explorer zie en kan ik alles :P

nu weet mqtt lokal uitgezet en alle devices werken weer :)

Gadget-freakz.com. Feedback en tips zijn welkom.


Acties:
  • +1 Henk 'm!
remcoXP schreef op maandag 7 juli 2025 @ 09:23:
gedaan maar helaas, debugging log geeft ook niets raars aan behalve dat hij een getall doet en dat lijkt te werken. geen connection errors of deny oid.
zou niet aan het feit mogen liggen dat ik een andere broker gebruik.

als ik met de user en pass die in de logs staat probeer in te loggen in mqtt explorer zie en kan ik alles :P

nu weet mqtt lokal uitgezet en alle devices werken weer :)
Ja dat heb ik ook tijdje gehad, dat als ik de mqtt lokal uit zet dat die het dan weer goed deed. Maar sinds laatste versie doet de local het ook prima (wel paar keer oflline enz, maar dat heb ik nu gerepareerd door elke nacht sowieso een reset te doen en bericht als meer dan 30sec geen wijziging.). Waar dit dan precies aan ligt weet ik niet. Paar keer herstarten wordt ook wel eens geadviseerd. Of je mqtt gebruiker verwijderen, integratie verwijderen en weer opnieuw proberen.

Ik moet ook zeggen dat de rest api variant bij mij veel stabieler is dan de fireseon. Maar is ook work in progress en uiteindelijk wel samenwerking met zendure. Dus even afwachten hoe het verder gaat.

[ Voor 9% gewijzigd door mrme12345 op 07-07-2025 09:38 ]

energienerds.nl | gasloos| 11,5kWp | 20 kWh accu | EV | Atlantic WPB


Acties:
  • 0 Henk 'm!

  • Aziraphale
  • Registratie: September 2013
  • Nu online
@Taro Ik ben er mee aan het stoeien en begin het wat te doorgronden (en ik zal het aan de gang krijgen, al is het alleen maar om het te snappen :Y ), maar ik vroeg me nog wel af wat het verschil is tussen de manier via HA en de Electricity Price Mode in HEMS. Komt die twee niet eigenlijk op hetzelfde neer?

3120WP Solax, 4825WP SolarEdge, Nibe S2125-8 met een VVMS320, 11,52 kWh Zendure 2400AC


Acties:
  • +1 Henk 'm!
robkds schreef op zondag 6 juli 2025 @ 20:20:
Voor degenen (zoals ik) die met de restful API een Solarflow 800 Pro gebruiken, met deze code in je configuration.yaml kan je de PV inputs uitlezen:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#begin PV input
      - name: "Zendure 2400 AC solarInputPower"
        value_template: "{{ value_json['properties']['solarInputPower'] }}"
        unique_id: Zendure_2400_AC_solarInputPower
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power
      - name: "Zendure 2400 AC PV1"
        value_template: "{{ value_json['properties']['solarPower1'] }}"
        unique_id: Zendure_2400_AC_PV1
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power
      - name: "Zendure 2400 AC PV2"
        value_template: "{{ value_json['properties']['solarPower2'] }}"
        unique_id: Zendure_2400_AC_PV2
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power
      - name: "Zendure 2400 AC PV3"
        value_template: "{{ value_json['properties']['solarPower3'] }}"
        unique_id: Zendure_2400_AC_PV3
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power
      - name: "Zendure 2400 AC PV4"
        value_template: "{{ value_json['properties']['solarPower4'] }}"
        unique_id: Zendure_2400_AC_PV4
        unit_of_measurement: "W"
        state_class: measurement
        device_class: power
#einde PV input

Dit moet je dus bij het stuk met de sensors toevoegen.
Is er een reden waarom je die 2400 AC noemt ondanks dat het over de 4 pv inputs van de sf 800 pro gaat?

energienerds.nl | gasloos| 11,5kWp | 20 kWh accu | EV | Atlantic WPB


Acties:
  • 0 Henk 'm!

  • robkds
  • Registratie: Januari 2004
  • Laatst online: 05:52
mrme12345 schreef op maandag 7 juli 2025 @ 10:12:
[...]

Is er een reden waarom je die 2400 AC noemt ondanks dat het over de 4 pv inputs van de sf 800 pro gaat?
Ja, zo kon ik het script van @gielz gewoon gebruiken zonder zoek-en-vervang acties. Pure luiheid dus 8)

Goed man!


Acties:
  • 0 Henk 'm!
robkds schreef op maandag 7 juli 2025 @ 11:18:
[...]

Ja, zo kon ik het script van @gielz gewoon gebruiken zonder zoek-en-vervang acties. Pure luiheid dus 8)
Ok dan snap ik het weer ;).

energienerds.nl | gasloos| 11,5kWp | 20 kWh accu | EV | Atlantic WPB


Acties:
  • 0 Henk 'm!
Aziraphale schreef op maandag 7 juli 2025 @ 10:02:
@Taro Ik ben er mee aan het stoeien en begin het wat te doorgronden (en ik zal het aan de gang krijgen, al is het alleen maar om het te snappen :Y ), maar ik vroeg me nog wel af wat het verschil is tussen de manier via HA en de Electricity Price Mode in HEMS. Komt die twee niet eigenlijk op hetzelfde neer?
Mijn automatisering vs HEMS bedoel je?

Heb 5 knoppen (booleans) gemaakt die te combineren zijn:
  • Onder de 20 cent laden
  • Goedkoopste 5 uren laden (op zondag: 6 ivm 100%)
  • Duur ontladen
  • EV laden uit de accu's
  • NOM
En mijn automatisering houdt daar dan rekening mee. Bijv.:
  • 5 duurste uren onder de 35 cent: Gemiddeld ontladen
  • 5 duurste uren boven de 35 cent: Maximaal ontladen
  • 5 goedkoopste uren: Maximaal laden
  • Onder de 20 cent, maar niet de goedkoopste uren: Smart charging
  • Boven de 20 cent, maar niet de duurste uren: Smart discharging
  • Anders: NOM.
Waarbij 5 duurste uren betekent: 3 duurste in de avond en 2 duurste in de ochtend. Gemiddeld gezien zijn dat de duurste 5 van de dag én je zorgt ervoor dat je accu's de rest van de tijd voldoende kWh's hebben voor NOM én dat ze volledig leeg zijn voordat het laden begint.

Vandaag einde ochtend duur ontladen uitgezet, goedkoop inkopen uit, onder de 20 cent laden aan en draait nu NOM t/m morgen 13:00 als er weer een paar uur geladen gaat worden.
Afbeeldingslocatie: https://tweakers.net/i/HHbzkxY6nNF6cFJ8_OChjW55ROc=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/PAjQxnqHEkUMTJRNtSn5zELq.png?f=user_large

Paar dagen gelezen had ik wel goedkoop inkopen en duur ontladen aan (Y-as begint bij -7000 Watt):
Afbeeldingslocatie: https://tweakers.net/i/DgJd8F1x-aPh0mPLlYNfHMQd3Lk=/fit-in/4000x4000/filters:no_upscale():strip_exif()/f/image/jOYas5Xug6Q0BUSCnLOyV2ov.png?f=user_large

Dus nee, niet (exact) hetzelfde als HEMS. Heb Zendure wel uitgebreide feedback gegeven over HEMS, dus hopelijk is dit spoedig ook native mogelijk :)

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • +1 Henk 'm!

  • Aziraphale
  • Registratie: September 2013
  • Nu online
@Taro Ik geloof dat ik eens ga kijken naar de Claude Code addon om me hiermee te helpen. Het ziet er allemaal prachtig uit, maar ik vrees dat me dit niet gaat lukken zonder stapsgewijze handleiding met alle sensoren die ik nodig heb en moet maken. Ik zie namelijk al sensoren voorbij komen die ik bij mij niet kan vinden en dus zal moeten maken. Wat dat betreft is HA toch wel een lastiger systeem dan Homey, wat @geert1992 met net heeft gedemonstreerd.

3120WP Solax, 4825WP SolarEdge, Nibe S2125-8 met een VVMS320, 11,52 kWh Zendure 2400AC


Acties:
  • 0 Henk 'm!
Aziraphale schreef op maandag 7 juli 2025 @ 21:21:
@Taro Ik geloof dat ik eens ga kijken naar de Claude Code addon om me hiermee te helpen. Het ziet er allemaal prachtig uit, maar ik vrees dat me dit niet gaat lukken zonder stapsgewijze handleiding met alle sensoren die ik nodig heb en moet maken. Ik zie namelijk al sensoren voorbij komen die ik bij mij niet kan vinden en dus zal moeten maken. Wat dat betreft is HA toch wel een lastiger systeem dan Homey, wat @geert1992 met net heeft gedemonstreerd.
Bedankt voor de koffie! Gezellig om een mede tweaker te ontmoeten!

Humans don’t need an opportunity to be wicked. They’ve been doing it for free since the beginning.


Acties:
  • +1 Henk 'm!

  • Aziraphale
  • Registratie: September 2013
  • Nu online
geert1992 schreef op maandag 7 juli 2025 @ 21:51:
[...]


Bedankt voor de koffie! Gezellig om een mede tweaker te ontmoeten!
Insgelijks!

3120WP Solax, 4825WP SolarEdge, Nibe S2125-8 met een VVMS320, 11,52 kWh Zendure 2400AC


Acties:
  • 0 Henk 'm!
@geert1992 Welke koffie is lekkerder? ;)

[ Voor 3% gewijzigd door Taro op 07-07-2025 22:47 ]

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV


Acties:
  • +1 Henk 'm!
Aziraphale schreef op maandag 7 juli 2025 @ 21:21:
@Taro Ik geloof dat ik eens ga kijken naar de Claude Code addon om me hiermee te helpen. Het ziet er allemaal prachtig uit, maar ik vrees dat me dit niet gaat lukken zonder stapsgewijze handleiding met alle sensoren die ik nodig heb en moet maken. Ik zie namelijk al sensoren voorbij komen die ik bij mij niet kan vinden en dus zal moeten maken. Wat dat betreft is HA toch wel een lastiger systeem dan Homey, wat @geert1992 met net heeft gedemonstreerd.
Dat is inderdaad wel een ding, als je die code overneemt krijg je allemaal unknown devices en sensoren.

Misschien op te lossen door ze allemaal een fixed ID te geven. Zal er in de toekomst eens naar kijken.

Maar wat je ook kunt doen is gewoon heel simpel beginnen en de automatisering steeds verder uitbouwen. Een Homey Pro is verder ook wel toegankelijk, heb ook een keer met Geert meegekeken en zeker een mooie optie.

Ik zie een Zendure meet-up dag aankomen ;)

Kennis delen > DM | Replace fear of the unknown with curiosity | 54 kWh thuisaccu's | Tesla Model Y LR & Model 3 SR+ | 10.660 Wp PV

Pagina: 1 2 ... 12 Laatste