Repository navigation
Expand file tree
/
Copy pathconfig.ini.example
More file actions
622 lines (585 loc) · 28.4 KB
/
Copy pathconfig.ini.example
File metadata and controls
622 lines (585 loc) · 28.4 KB
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
[GENERAL]
# Use ct002/ct003 for multiple storage devices; use shelly* types otherwise.
# Comma-separated list of device types to emulate (ct002, ct003, shellypro3em, shellyemg3, shellyproem50)
DEVICE_TYPE = shellypro3em
# Comma-separated list of device IDs (optional, auto-generated if not set)
# DEVICE_IDS = shellypro3em-c59b15461a21
# Skip initial powermeter test on startup
SKIP_POWERMETER_TEST = False
# The web-based configuration editor at http://<host>:<port>/config. Left
# unset it follows DASHBOARD_ENABLED below, whose Configuration tab is that
# editor. Set it to True to serve the editor with no dashboard, or to False
# to refuse it even with one — False also takes the dashboard's Configuration
# tab away, and is the way to keep an unauthenticated port from editing this
# file at all.
# WEB_CONFIG_ENABLED = False
# The live status dashboard at http://<host>:<port>/ (default True).
# Shows grid power, every battery's target and reported power, power-source
# health and the balancer's internal state. Set this to False to serve only
# the health check (and /config, if WEB_CONFIG_ENABLED above is on). Ignored
# by the Home Assistant add-on, where the dashboard always runs and opens from
# the sidebar.
# DASHBOARD_ENABLED = True
# Let the dashboard change this file and control batteries (default True).
# There is NO authentication on this port, so anyone who can reach it can use
# those controls; set this to False for a read-only page.
# DASHBOARD_ALLOW_WRITE = True
# Only relevant when this file is used BY the Home Assistant add-on: there the
# dashboard opens from the sidebar and port 52500 is refused unless you opt in
# here. Running AstraMeter yourself (Docker or Python), the port is the only
# way in and the dashboard is already served there.
# DASHBOARD_DIRECT_ACCESS = False
# Extra host names the web port answers under, comma-separated. IP addresses,
# localhost, .local and .home.arpa names always work, so most setups need
# nothing here. Add a name if you reach the dashboard through one that
# resolves via a nameserver — a reverse proxy, a private DNS entry, or a
# router-assigned name such as astrameter.fritz.box. Names are refused by
# default because a name is the one part of the address another website can
# aim at this port from your browser (DNS rebinding), and this port has no
# login to fall back on.
# DASHBOARD_ALLOWED_HOSTS = astrameter.example.lan, proxy.example.lan
# Port for the embedded web server (health check + dashboard + config editor). Default: 52500
# WEB_SERVER_PORT = 52500
# Global throttling configuration (in seconds) - applies to all powermeters unless overridden
# Enforces minimum time between power meter readings by waiting when called too frequently
# This helps prevent instability or oscillation for slower data sources
# Set to 0 to disable throttling (default)
# Recommended values: 1-3 seconds for slower data sources
# Can be overridden per powermeter section
THROTTLE_INTERVAL = 0
# Wait briefly (up to 2s) for a fresh push from event-driven powermeters
# (MQTT, Home Assistant, HomeWizard, SMA energy meter, ...) before responding
# to the battery. Keeps battery control loops on the freshest data.
# Set to false to skip the wait entirely and always serve the last-known
# value — recommended for sources that update slower than 2s (e.g. a P1 smart
# meter behind Home Assistant) or whenever you'd rather have an instant
# response than a fresh one. Defaults to true.
# Can be overridden per powermeter section.
# WAIT_FOR_NEXT_MESSAGE = true
# Ignore repeated requests from the same emulator client within this window
# (seconds). Applies to CT002/CT003 (keyed by consumer id) and Shelly (keyed
# by battery IP). Can be overridden in the [CT002]/[CT003] section. 0 disables.
# A suppressed request is left UNANSWERED, so a battery's answered rate can only
# fall to a whole fraction of its own poll rate (half, a third, ...) — the value
# is honoured exactly, but its effect changes in steps, not smoothly.
# DEDUPE_TIME_WINDOW = 0
# [CT002]
## CT type is derived from the emulated device (ct002 -> HME-4, ct003 -> HME-3).
## Note: CT003 can optionally use its own [CT003] section with the same keys.
## CT MAC (12 hex digits, from Marstek app).
## If empty, the emulator accepts any request CT MAC and echoes the request's
## CT MAC in responses. If set, the emulator responds only to the configured MAC.
# CT_MAC = 001122334455
## UDP port to bind for CT002/CT003 (default 12345).
# UDP_PORT = 12345
## WiFi RSSI reported to the storage system
# WIFI_RSSI = -50
## Ignore repeated requests from the same consumer within this window (seconds).
## Overrides the [GENERAL] DEDUPE_TIME_WINDOW for this section.
# DEDUPE_TIME_WINDOW = 0
## Forget consumers after this many seconds without updates (multi-consumer support).
## Unset (default): adaptive — a battery is dropped after missing ~2 of its own
## poll cycles (min 5s), like the real CT. Set a number for a fixed window.
# CONSUMER_TTL = 120
## Log concise status (phase consumption + consumer charge/discharge) on each request when enabled
# DEBUG_STATUS = False
## --- HTTP cloud reporting (opt-in, experimental) ---
## Mimic what a real CT does: periodically GET hamedata.com's setCtReporting with
## live grid power, the charge/discharge buckets, RSSI, slave count and link
## flags (the HME-4/HME-3 field layout follows the emulated device type). Plain
## HTTP, no TLS. OFF by default. See docs/marstek-mqtt-http.md (§6) for the field
## meanings and the open unknowns (cadence, energy/V-I values, account binding).
# CLOUD_REPORTING = False
## Host to report to (default eu.hamedata.com; other regions swap the host).
# CLOUD_REPORTING_HOST = eu.hamedata.com
## The id sent as `id`/`uid` is the CT MAC: the device AstraMeter registers in
## your Marstek account (the [MARSTEK] section) if available, otherwise CT_MAC.
## The cloud accepts reports only for a device id it already knows. (The model
## and firmware version are sent automatically as part of the handshake.)
## Seconds between reports. The real cadence isn't documented — measure it from a
## device and set it here (default 60).
# CLOUD_REPORTING_INTERVAL = 60
## --- Active control ---
## When True (default), the emulator smooths the grid reading, splits the target
## across batteries, and balances their load. When False, raw meter values are
## relayed and batteries decide on their own.
# ACTIVE_CONTROL = True
## --- Fair distribution (multi-battery balancing) ---
## Adjust each battery's target so they share the load evenly.
## Only matters with 2+ batteries.
# FAIR_DISTRIBUTION = True
## How aggressively to correct imbalance between batteries.
## 0 = no correction (equal split only); 0.3-0.5 = faster rebalancing.
# BALANCE_GAIN = 0.2
## Ignore imbalance smaller than this (W). Prevents micro-corrections. Kept
## above the battery firmware's own +-20 W input deadband so corrections the
## battery would ignore are never sent.
# BALANCE_DEADBAND = 25
## Cap on the per-cycle balance correction (W). Limits how fast a single
## battery's target can deviate from its fair share.
# MAX_CORRECTION_PER_STEP = 80
## When imbalance exceeds ERROR_BOOST_THRESHOLD (W), the balance gain is
## multiplied by up to (1 + ERROR_BOOST_MAX). For example with the defaults
## (gain=0.2, threshold=150, max=0.5): at 150 W imbalance the effective gain
## is 0.2 * 1.5 = 0.3; below the threshold gain stays at 0.2.
# ERROR_BOOST_THRESHOLD = 150
# ERROR_BOOST_MAX = 0.5
## Below this imbalance (W), the gain is scaled down proportionally for
## gentler corrections as batteries approach equilibrium.
# ERROR_REDUCE_THRESHOLD = 20
## Hard clamp on target change relative to current battery output (W). 0 disables.
# MAX_TARGET_STEP = 0
## Ramp pacing: cap each battery's per-poll command delta. The cap starts at
## PACE_BASE_STEP (matching the battery firmware ramp's first step) and
## grows toward PACE_MAX_STEP only while the battery demonstrably follows the
## command; it resets when the direction reverses. Keeps the firmware's
## accelerating ramp from overshooting on meter latency. 0 disables pacing.
# PACE_BASE_STEP = 30
# PACE_MAX_STEP = 100
## Steady-import trim (W): every Marstek firmware parks the grid a few watts to
## the import side of zero in steady state (its input deadband won't chase a
## small residual), leaving real load to be imported at the retail tariff. Once
## the grid has held steady inside a small import band for a few polls (never
## during a load step, so no added overshoot) this nudges the batteries to cover
## it, recovering that self-consumption. Stays clear of a full/empty pack. 0
## disables.
# IMPORT_TRIM_W = 15
## --- DC battery keep-alive ---
## Applies per battery (independent of balancing — also relevant with a single
## battery). Minimum discharge (W) to keep a DC battery (e.g. Marstek B2500) from
## switching its inverter off at 0 W and falling asleep under high PV surplus.
## Only affects DC-only batteries that have no inverter of their own (Venus and
## Jupiter are unaffected); 0 disables (default). Can also be set per battery from
## Home Assistant. Recommended >= 20.
# MIN_DC_OUTPUT = 0
## --- Saturation detection (full/empty battery handling) ---
## Track how well each battery follows its target. When a battery can't deliver
## (full or empty), its share is reduced and redistributed to others.
# SATURATION_DETECTION = True
## EMA factor for the saturation score. Lower = slower to declare saturated.
# SATURATION_ALPHA = 0.15
## Ignore saturation tracking when target is below this (W).
# MIN_TARGET_FOR_SATURATION = 20
## --- Efficiency optimization (opt-in low-demand power concentration + probe handoff) ---
## At low total demand, concentrates power on fewer batteries to avoid
## inefficient low-power operation. Each active battery gets at least this
## many watts. 0 disables (default). Batteries rotate for fairness, and newly
## promoted batteries are probed before the previous active battery fades out.
## Example: 2 batteries, 200W demand, threshold 150 → one gets 200W, other 0W.
# MIN_EFFICIENT_POWER = 0
## Seconds between rotating which battery has priority (minimum 10).
# EFFICIENCY_ROTATION_INTERVAL = 900
## Minimum target (W) sent when probing a newly promoted battery.
## Batteries that ignore tiny commands need a higher floor (default 80).
# PROBE_MIN_POWER = 80
## How quickly the old battery fades out after a successful probe
## (0.01=very slow, 1.0=instant).
# EFFICIENCY_FADE_ALPHA = 0.15
## Force-rotate when a battery can't follow its target (e.g. externally limited
## to 0 W or fully discharged). After a probe succeeds, this still swaps out an
## active battery within a few seconds instead of waiting for the full rotation
## interval. 0 disables. The saturation EMA is time-weighted, so slow
## powermeters (>10 s updates) accumulate saturation faster per sample; raise
## this value (e.g. 0.8) if you see unnecessary swaps with a slow meter.
# EFFICIENCY_SATURATION_THRESHOLD = 0.4
## Smooths the household-demand estimate that decides how many batteries stay
## active, so meter noise can't flip a battery in and out of the active pool
## every few readings (which wears the setpoints with no benefit — a battery
## can't track noise anyway). Lower = smoother/slower to react to a sustained
## load change; 1.0 disables the smoothing (react to every reading). Only
## relevant with MIN_EFFICIENT_POWER set and two or more batteries.
# EFFICIENCY_DEMAND_ALPHA = 0.1
## How quickly a swapped-out battery becomes eligible again. Applied each cycle
## while the battery has no target. 1.0 = never recover, lower = faster recovery.
# SATURATION_DECAY_FACTOR = 0.995
## Probe window for a newly promoted battery. During this time the previous
## active battery stays online as backup and covers the residual shortfall until
## the promoted battery shows meaningful real output.
# SATURATION_GRACE_SECONDS = 90
## Stall escape for non-probe grace cases such as batteries rejoining auto mode.
## Probe handoffs use the probe window above as the primary timer.
# SATURATION_STALL_TIMEOUT_SECONDS = 60
# [MARSTEK]
## Optional: auto-register managed fake CT devices in Marstek cloud on startup.
# ENABLE = False
# BASE_URL = https://eu.hamedata.com
# MAILBOX = your@email.example
# PASSWORD = your_password
## Prefix is fixed to 02b250 (locally administered MAC space) for managed fake devices.
## Used for add-device request
# TIMEZONE = Europe/Berlin
## Optional: live grid in the Marstek mobile app over MQTT uses [MQTT_INSIGHTS]
## on the same broker as hame-relay (https://github.com/tomquist/hame-relay) >= 1.3.5
## (HA discovery does not depend on this).
# [SHELLY]
# TYPE = 1PM #PLUS1PM #EM #3EM #3EMPRO
# IP = 192.168.1.100
# USER = username
# PASS = password
# METER_INDEX = meter1
## Per-powermeter throttling override (optional)
## Shelly devices are typically fast, so throttling may not be needed
# THROTTLE_INTERVAL = 0
## Per-powermeter smoothing (optional, defaults come from [GENERAL])
## EMA alpha (0.0-1.0). Higher = tracks faster; lower = filters noise.
## 0.9 works well at >= 1 Hz; reduce toward 0.3 for slower powermeters.
# SMOOTH_TARGET_ALPHA = 0.9
## Return zeros when |grid total| < DEADBAND (W). 10-30 W sensible; 0 disables.
# DEADBAND = 20
## Max watts the smoothed target may change per cycle (slew-rate limit). 0 disables.
# MAX_SMOOTH_STEP = 0
# [TASMOTA]
# IP = 192.168.1.101
# USER = tasmota_user
# PASS = tasmota_pass
# JSON_STATUS = StatusSNS
# JSON_PAYLOAD_MQTT_PREFIX = SML
# JSON_POWER_MQTT_LABEL = Power
## For 3-phase meters, use comma-separated labels:
# JSON_POWER_MQTT_LABEL = Power_L1,Power_L2,Power_L3
# JSON_POWER_INPUT_MQTT_LABEL = Power1
# JSON_POWER_OUTPUT_MQTT_LABEL = Power2
# JSON_POWER_CALCULATE = True
## Per-powermeter throttling override (optional)
# THROTTLE_INTERVAL = 1
# [SHRDZM]
# IP = 192.168.1.102
# USER = shrdzm_user
# PASS = shrdzm_pass
## Per-powermeter throttling override (optional)
# THROTTLE_INTERVAL = 1
# [EMLOG]
# IP = 192.168.1.103
# METER_INDEX = 0
# JSON_POWER_CALCULATE = True
## Per-powermeter throttling override (optional)
# THROTTLE_INTERVAL = 1
# [IOBROKER]
# IP = 192.168.1.104
# PORT = 8087
# CURRENT_POWER_ALIAS = Alias.0.power
# POWER_CALCULATE = True
# POWER_INPUT_ALIAS = Alias.0.power_in
# POWER_OUTPUT_ALIAS = Alias.0.power_out
## Per-powermeter throttling override (optional)
# THROTTLE_INTERVAL = 1
# [HOMEASSISTANT]
# IP = 192.168.1.105
# PORT = 8123
# HTTPS = True
# ACCESSTOKEN = YOUR_ACCESS_TOKEN
## Single sensor mode - comma-separated list for multiple phases
# CURRENT_POWER_ENTITY = sensor.phase1_power, sensor.phase2_power, sensor.phase3_power
## Or for separate input/output sensors (use entity IDs)
# POWER_CALCULATE = True
# POWER_INPUT_ALIAS = sensor.phase1_input, sensor.phase2_input, sensor.phase3_input
# POWER_OUTPUT_ALIAS = sensor.phase1_output, sensor.phase2_output, sensor.phase3_output
## Per-powermeter throttling override (optional)
## HomeAssistant typically needs 2-3 seconds due to network latency
# THROTTLE_INTERVAL = 2
## Skip the up-to-2s wait for a fresh push from this powermeter and always
## serve the last-known value. Useful when the underlying sensor (e.g. P1
## smart meter) updates slower than 2s, so the wait would always time out
## and the cached value would be served anyway. Defaults to the global
## [GENERAL] WAIT_FOR_NEXT_MESSAGE setting (true).
# WAIT_FOR_NEXT_MESSAGE = false
# [VZLOGGER]
# IP = 192.168.1.106
# PORT = 8080
# UUID = your-uuid
## For 3-phase meters, use comma-separated UUIDs (one per phase):
# UUID = uuid-l1, uuid-l2, uuid-l3
## Per-powermeter throttling override (optional)
# THROTTLE_INTERVAL = 1
# [ESPHOME]
# IP = 192.168.1.107
# PORT = 6052
# DOMAIN = your_domain
# ID = your_id
## Per-powermeter throttling override (optional)
# THROTTLE_INTERVAL = 1
# [ESPHOMENATIVE]
# ADDRESS = powermeter.local
# PORT = 6053
# API_KEY = 5BqtR16i91/+rwUl+QrJewKFOnyS/whHc3v9ySSKpb8=
# OBJECT_ID = grid_power
## Connection Info string (optional)
# CLIENT_INFO = AstraMeter
# [AMIS_READER]
# IP = 192.168.1.108
## Per-powermeter throttling override (optional)
# THROTTLE_INTERVAL = 1
# [MODBUS]
# HOST = 192.168.1.100
# PORT = 502
# UNIT_ID = 1
# ADDRESS = 0
# COUNT = 1
# DATA_TYPE = UINT16
# BYTE_ORDER = BIG
# WORD_ORDER = BIG
# REGISTER_TYPE = HOLDING
## Transport: TCP (default) or UDP
# TRANSPORT = TCP
## Per-powermeter throttling override (optional)
# THROTTLE_INTERVAL = 1
# [MQTT]
# BROKER = broker.example.com
# PORT = 1883
## Optional: enable TLS to connect over mqtts:// (default false)
# TLS = false
## Alternatively, provide a single MQTT URI in place of BROKER/PORT/USERNAME/PASSWORD/TLS:
## mqtt://user:pass@broker.example.com:1883
## mqtts://user:pass@broker.example.com:8883
# URI = mqtt://user:pass@broker.example.com:1883
# TOPIC = home/powermeter
# JSON_PATH = path.to.value (Optional)
# USERNAME = mqtt_user (Optional)
# PASSWORD = mqtt_pass (Optional)
## Per-powermeter throttling override (optional)
## MQTT can have variable latency depending on broker and network
# THROTTLE_INTERVAL = 1
## Multi-phase: replace the [MQTT] section above with one of these alternatives
## Option 1: one topic per phase (comma-separated)
# [MQTT]
# BROKER = broker.example.com
# TOPICS = home/power/l1, home/power/l2, home/power/l3
## Option 2: single topic with multiple JSON paths
# [MQTT]
# BROKER = broker.example.com
# TOPIC = home/powermeter
# JSON_PATHS = $.phases[0].power, $.phases[1].power, $.phases[2].power
# [JSON_HTTP]
# URL = http://example.com/api
# JSON_PATHS = $.power
## JSON_PATHS supports jsonpath-ng extensions; strip a unit suffix like
## "331.74 W" with `split` or `sub`:
##JSON_PATHS = $.state.`split( , 0, -1)`
##JSON_PATHS = $.state.`sub(/[^0-9.\-]+$/, )`
# USERNAME = user
# PASSWORD = pass
# HEADERS = Authorization: Bearer token
# [TQ_EM]
# IP = 192.168.1.100
# PASSWORD = secret (Optional)
# TIMEOUT = 5.0 (Optional)
# THROTTLE_INTERVAL = 1
# [HOMEWIZARD]
## HomeWizard P1 Meter via WebSocket API (v2)
## Connects over WSS and subscribes to real-time measurement updates
## Token must be obtained once via POST /api/user while pressing the device button
## See: https://api-documentation.homewizard.com/docs/v2/
# IP = 192.168.1.110
# TOKEN = YOUR_32_CHAR_HEX_TOKEN
# SERIAL = your_device_serial
## Verify server TLS using the bundled HomeWizard CA (default True).
## Set False only if you get certificate errors on a trusted LAN (insecure).
# VERIFY_SSL = True
## Per-powermeter throttling override (optional)
# THROTTLE_INTERVAL = 0
# [ENVOY]
## Enphase IQ Gateway (Envoy) via local HTTPS API
## Reads grid power from /production.json?details=1 (net-consumption).
## Auto-detects single- vs three-phase from the response.
# HOST = 192.168.1.120
## Option A: long-lived JWT token from https://entrez.enphaseenergy.com/
# TOKEN = eyJ...
## Option B: let AstraMeter obtain a token via the Enphase Enlighten cloud
## (auto-refreshes on 401; not compatible with MFA-enabled Enlighten accounts)
# USERNAME = you@example.com
# PASSWORD = your-enphase-password
# SERIAL = 123456789012
## Envoy uses a self-signed certificate; verification is disabled by default.
## Affects only the local Envoy connection — cloud requests always verify TLS.
# VERIFY_SSL = False
# [SMA_ENERGY_METER]
## SMA Energy Meter / Sunny Home Manager via Speedwire multicast
## Listens for UDP multicast broadcasts and reports per-phase power (L1, L2, L3)
# MULTICAST_GROUP = 239.12.255.254
# PORT = 9522
## Serial number of the meter (0 = auto-detect first meter found)
# SERIAL_NUMBER = 0
## Network interface IP to bind to (optional, leave empty for all interfaces)
# INTERFACE =
## Per-powermeter throttling override (optional)
# THROTTLE_INTERVAL = 0
# [FRITZ]
## AVM FRITZ!Smart Energy 250 smart-meter read head, via the FRITZ!Box
## AHA-HTTP-Interface (getdevicelistinfos). The read head pairs with the
## FRITZ!Box over DECT; AstraMeter polls the box for its current power.
# HOST = fritz.box
## A FRITZ!Box user with Smart Home permission (Home Network > FRITZ!Box Users).
# USER = smarthome
# PASSWORD = your-fritzbox-password
## AIN of the read head as shown under Home Network > SmartHome (with or without
## the blank). The signed grid-import (-1) branch is read by default; append
## -1 (Strombezug) or -2 (Einspeisung) explicitly to pick a branch.
# AIN = 12345 0123456
## Reach the FRITZ!Box over HTTPS (default False = http). Self-signed certs are
## common, so set VERIFY_SSL = False if HTTPS fails verification.
# HTTPS = False
# VERIFY_SSL = True
# TIMEOUT = 10.0
## IMPORTANT: power the read head over USB. On battery it only refreshes every
## ~2 min — too slow for AstraMeter's ~1 s control loop, so battery balancing
## won't work. USB raises the update rate to ~10 s; this throttle matches that
## so AstraMeter doesn't hammer the box between fresh readings.
# THROTTLE_INTERVAL = 10
# [FRONIUS]
## Fronius Smart Meter via a Fronius inverter's local Solar API.
## Reads the signed PowerReal_P_Sum (positive = grid import, negative = feed-in)
## from GetMeterRealtimeData.cgi. No token/login needed on the local network.
# IP = 192.168.1.130
## Solar API meter device id; 0 is the first/only meter (default).
# DEVICE_ID = 0
## Report per-phase power (PowerReal_P_Phase_1..3) as L1/L2/L3 instead of the
## aggregate sum. Only enable if your meter reports SIGNED per-phase power;
## some firmwares report it unsigned, which breaks export readings.
# PER_PHASE = True
## If readings are reversed, flip the sign:
# POWER_MULTIPLIER = -1
# [REFOSS]
## Refoss / Meross energy monitor (EM01P, EM06P, EM16P) via local Open API.
## Polls Em.Status.Get and reads signed channel power (W): positive = import,
## negative = feed-in. [MEROSS] is an alias for the same driver.
## The device API is cleartext HTTP — use only on a trusted local network.
# IP = 192.168.1.150
## CT channel id(s). One id for single-phase; three for L1/L2/L3 (e.g. 1,2,3).
# CHANNELS = 1
## Prefer a numeric IP in Docker — *.local mDNS often does not resolve in bridge mode.
# POWER_MULTIPLIER = -1
# [TIBBER_PULSE]
## Tibber Pulse read locally via the Pulse Bridge (no Tibber cloud). Takes each
## SML telegram live as the bridge pushes it (ws://<bridge>/ws), polling
## /node_data.json (/data.json on older firmware) wherever push isn't available.
## Enable the bridge's local webserver first: params page >
## webserver-force-enable = true > Store params.
# IP = 192.168.1.140
## Username is always "admin"; password is the nine-character code printed on the
## bridge (with the dash), e.g. AD56-54BA.
# PASSWORD = AD56-54BA
## Optional: node id (see http://<bridge>/nodes/), defaults to 1.
# NODE_ID = 1
## Optional: override the Basic-auth user (defaults to "admin").
# USER = admin
## Optional: request timeout in seconds (default 5). The bridge's webserver can
## be slow to respond — raise this if readings drop with connection timeouts.
# TIMEOUT = 5.0
## Optional: poll over HTTP instead of using push (default False). Push already
## falls back to polling on its own when the bridge can't push.
# FORCE_POLLING = False
## Optional OBIS overrides (12 hex digits; omit to use eHZ-style defaults)
# OBIS_POWER_CURRENT = 0100100700ff
# OBIS_POWER_L1 = 0100240700ff
# OBIS_POWER_L2 = 0100380700ff
# OBIS_POWER_L3 = 01004c0700ff
## When polling, throttle to avoid hammering the bridge's slow webserver.
# THROTTLE_INTERVAL = 2
## If readings are reversed, flip the sign:
# POWER_MULTIPLIER = -1
# [SCRIPT]
# COMMAND = /path/to/your/script.sh
## Per-powermeter throttling override (optional)
# THROTTLE_INTERVAL = 1
# [SML]
# SERIAL = /dev/ttyUSB0
# Required: device path to the serial interface.
## Optional OBIS overrides (12 hex digits; omit to use eHZ-style defaults)
# OBIS_POWER_CURRENT = 0100100700ff
# OBIS_POWER_L1 = 0100240700ff
# OBIS_POWER_L2 = 0100380700ff
# OBIS_POWER_L3 = 01004c0700ff
## --- PID controller (grid-balance feedback loop) ---
## When PID_KP > 0, a Proportional-Integral-Derivative controller is layered
## on top of the configured powermeter. It uses the measured grid power as its
## process variable and steers the reported value toward zero (net-zero grid).
##
## Recommended starting point (P-only, bias mode):
## PID_KP = 0.5 # gain; 0.5 is a safe start for one storage device
## PID_KI = 0 # integral — usually not needed; risks windup
## PID_KD = 0 # derivative — noisy on real meters; leave at 0
## PID_OUTPUT_MAX = 800 # cap the PID output at ± 800 W
## PID_MODE = bias # add PID output to raw reading (alternative: replace)
##
## In bias mode the PID and the storage device's own closed-loop controller
## act together; the system is stable for 0 < Kp < 1.
## In replace mode the PID output replaces the raw reading entirely.
##
## To keep a small import safety buffer (prevent accidental export), combine
## with a negative POWER_OFFSET applied before the PID:
## POWER_OFFSET = -20 # bias 20 W toward import
##
## Parameters can be set globally in [GENERAL] or per powermeter section.
## Per-section values override the global ones.
# PID_KP = 0.5
# PID_KI = 0
# PID_KD = 0
# PID_OUTPUT_MAX = 800
# PID_MODE = bias
## --- Hampel outlier filter (optional) ---
## Stateful rolling-median rejection of wild samples (e.g. MQTT/WiFi glitches).
## Outliers are replaced with the window median; normal samples pass through
## unchanged. Disabled by default.
##
## When HAMPEL_WINDOW > 0, the wrapper is inserted after throttling and before
## EMA smoothing. This is orthogonal to the EMA: Hampel rejects impulse noise,
## the EMA smooths the cleaned signal.
##
## A *sustained* change (solar arriving, an oven switching on) is held back
## for about half a window before it is adopted — it is indistinguishable
## from a spike until enough samples agree. A bigger window rejects noise
## better and adopts real changes more slowly; that is the whole trade.
##
## Recommended starting point for flaky HTTP/MQTT sources:
## HAMPEL_WINDOW = 5 # odd sizes recommended; 5–7 works well
## HAMPEL_N_SIGMA = 3.0 # reject beyond ~3σ (MAD-derived)
## HAMPEL_MIN_THRESHOLD = 50 # watts; floor for constant-signal (MAD=0) case
##
## Parameters can be set globally in [GENERAL] or per powermeter section.
## Per-section values override the global ones.
# HAMPEL_WINDOW = 5
# HAMPEL_N_SIGMA = 3.0
# HAMPEL_MIN_THRESHOLD = 50
## --- MQTT Insights (optional) ---
## Mainly for Home Assistant: publishes internal state (grid power, targets,
## saturation, consumer topology) to MQTT with HA Device Discovery.
## When running as a Home Assistant app with Mosquitto, this is auto-configured.
## With HA Discovery on, each battery also exposes config entities you set live
## from Home Assistant — Manual Target, Auto Target, Active, and a per-battery
## Distribution Weight (default 1.0) that biases the load split across batteries
## (e.g. 1.5 vs 1.0 for ~60:40). No extra keys needed; these persist across
## restarts via retained MQTT.
## Optional add-on: Marstek app poll replies use the same broker (see MARSTEK_* below).
# [MQTT_INSIGHTS]
# BROKER = 192.168.1.100
# PORT = 1883
# USERNAME = mqtt_user
# PASSWORD = mqtt_pass
## Enable TLS (default: false)
# TLS = false
## Alternatively, provide a single MQTT URI in place of BROKER/PORT/USERNAME/PASSWORD/TLS:
## mqtt://user:pass@broker.example.com:1883
## mqtts://user:pass@broker.example.com:8883
# URI = mqtt://user:pass@192.168.1.100:1883
## Base topic for all MQTT Insights messages (default: astrameter)
# BASE_TOPIC = astrameter
## Enable Home Assistant MQTT Device Discovery (default: true)
# HA_DISCOVERY = true
## HA discovery prefix (default: homeassistant)
# HA_DISCOVERY_PREFIX = homeassistant
## Optional Marstek mobile app: answer CT002/CT003 MQTT polls on this broker (default: true).
## Live readings in the app need hame-relay (https://github.com/tomquist/hame-relay) >= 1.3.5
## on the same broker; older relays may not forward poll/replies. Requires [MARSTEK] so the
## topic MAC matches the managed fake device. Set false for HA MQTT Insights only.
# MARSTEK_MQTT_ENABLED = true
## Seconds between optional Marstek aggregate (cd=1) broadcasts when the app is quiet; 0 = polls only.
# MARSTEK_MQTT_INTERVAL = 300
## Smallest gap between two state publishes for the same battery (seconds); 0 = every poll (default).
## A battery polls about once a second, so without this its state topic goes out at that rate and
## every subscriber pays to parse it. Raising it trades resolution in Home Assistant's history for a
## quieter broker. Availability, removals, discovery and commands are never throttled.
# STATE_THROTTLE_INTERVAL = 0
## Seconds between per-powermeter "Online" diagnostic sensor updates (default: 30); 0 disables it.
## Each configured powermeter section gets an "AstraMeter Powermeter <section>" device with an
## Online binary sensor that flips off when the source stops delivering fresh/usable readings.
# POWERMETER_HEALTH_INTERVAL = 30