Skip to content

About

Java service that bridges a Schneider Combox and Brultech Dashbox to MQTT and calculates solar power available for EV charging.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

23 Commits

Folders and files

Repository files navigation

SolarServer

A Java service that bridges a home solar installation to MQTT. It polls two data sources, computes how much solar power is safely available for EV charging, and publishes everything to one or more MQTT brokers.

  • Schneider Conext Combox (Modbus TCP) – inverter/charger, battery and PV data
  • Brultech Dashbox (HTTP) – per-circuit power monitoring, including the EV charger
  • Solar analyzer – derives availableSolarPower, the number of watts the EV charger can draw without discharging the house battery

Note: This app is very specific to my own solar setup (a Schneider Combox, a Brultech Dashbox, and a particular EV charger and battery bank). It could easily be modified to support a different system by changing the register map in Combox.json, the circuit mapping in BrultechDevice.java, and the constants in SolarAnalyzer.java.

The MQTT data it publishes is consumed by the mobile app in eric-vickery/solar-monitor.

How it works

SolarServer starts independent timers and then blocks until shutdown:

Timer Default period Job
Combox 2000 ms Reads Modbus registers defined in src/main/resources/Combox.json
Dashbox 2000 ms Fetches circuit wattages from /index.php/pages/search/getWattVals
Analyzer 1500 ms Pulls the latest values from the other providers and updates the available-solar figure
MQTT publisher (one per broker) 5000 ms Publishes every field from all providers, whether or not it changed

Analyzer behavior

The target is MAX_SOLAR_WATTS (9200) − house load − battery charge allowance, clamped to 0–7200 W (the EV charger maximum). The published value ramps toward it (up 250 W every 3 s, down 500 W every 2 s). Safeguards:

  • Gate – output drops to 0 unless the charger is in Bulk/Absorb/Float/Equalize and battery voltage is above a threshold.
  • Equilibrium hold – ramp-up stops once the battery surplus falls below a threshold (smaller in Float).
  • Slight-negative nudge – if the battery is mildly negative, step down once and wait 20 s before another step.
  • Discharge delay – sustained discharge beyond −175 W for 3 minutes triggers a ramp to 0.
  • Backoff – after ramping to 0, hold for 10 minutes. After 3 backoffs the analyzer gives up for the day.
  • Full-charge rule – once the battery has reached full charge, a drop in SOC below 97.8% gives up for the day.
  • Midnight reset – all state is cleared at midnight.

Tuning constants live at the top of SolarAnalyzer.java.

MQTT topics

Topics are retained. Combox topics are defined per register in Combox.json (e.g. combox/lastPublishedTime).

  • combox/… – Combox registers
  • dashbox/… – circuit power (main, evCharger, wellPump, dryer, …) and solarRoomTempF / solarRoomTempC
  • solarAnalyzer/availableSolarPower, inDischargeDelay, inDischargeBackoff, numberOfBackoffs, houseBatteryHitFullCharge, givenUpForDay

Configuration

All configuration is via environment variables, kept in SolarServer.env. That file contains sensitive information (broker credentials) and is git-ignored, so never commit it.

Variable Default Description
COMBOX_ADDRESS required Combox IP address
COMBOX_PORT 502 Modbus TCP port
DASHBOX_HOST required Dashbox hostname
COMBOX_POLLING_FREQ 2000 Combox poll interval (ms)
DASHBOX_POLLING_FREQ 2000 Dashbox poll interval (ms)
ANALYZER_CALCULATION_FREQ 1500 Analyzer interval (ms)
MQTT_CONSOLE_MODE false Print payloads to stdout instead of connecting to a broker
MQTT_BROKER – Primary broker URL, e.g. tcp://host:1883 or ssl://host:8883
MQTT_BROKER_NAME – Label used in logs
MQTT_USERNAME / MQTT_PASSWORD – Optional credentials
MQTT_PUBLISHING_FREQ 5000 Publish interval (ms)

Additional brokers

Add more brokers by suffixing the MQTT variables with _2, _3, … (MQTT_BROKER_2, MQTT_BROKER_NAME_2, MQTT_USERNAME_2, MQTT_PASSWORD_2, MQTT_PUBLISHING_FREQ_2). Each broker publishes on its own timer. Numbering must be contiguous; the first missing MQTT_BROKER_N ends the search. If MQTT_PUBLISHING_FREQ_N is omitted it falls back to MQTT_PUBLISHING_FREQ.

Building and running

Requires JDK 24 and Maven.

EasyModbusJavaClient.jar is not on Maven Central, so install it from lib/ once:

mvn install:install-file -Dfile=lib/EasyModbusJavaClient.jar -DgroupId=de.re.easymodbus -DartifactId=EasyModbus -Dversion=2.8.0 -Dpackaging=jar

Then build a shaded jar and run it:

mvn package
set -a; source SolarServer.env; set +a; java -jar target/SolarServer-1.0-SNAPSHOT.jar

Set MQTT_CONSOLE_MODE=true to try it without a broker.

Docker

The Dockerfile does a multi-stage build (Maven + Temurin 24) and runs on eclipse-temurin:24-jre. docker-compose.yml builds for linux/amd64 and linux/arm64, reads SolarServer.env, and uses host networking so the container can reach the Combox on the local network.

docker compose up -d --build

License

Released under the MIT License.

Project layout

src/main/java/com/fiedlervickery/
├── SolarServer.java      entry point, timers, shutdown hook
├── combox/               Modbus client and register definitions
├── brultech/             Dashbox HTTP client
├── analyzer/             SolarAnalyzer – available-solar logic
└── mqtt/                 publishers (broker / console), fields and payloads
src/main/resources/Combox.json   register map and MQTT topics

About

Java service that bridges a Schneider Combox and Brultech Dashbox to MQTT and calculates solar power available for EV charging.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages