Modern Python driver for Morningstar TriStar MPPT solar charge controllers
β Production-ready - Tested on Venus OS v3.67 β Zero compilation - Pure Python, just copy and run β No QML required - Configure via D-Bus command line β 100% compatible - Same data as original C++ driver β WAN-ready - Works over internet with optimized timeouts β Advanced features - Voltage override, tail current detection, 31-day history
In my off-grid system the Morningstar Tristar MPPT 60 is used to charge a 7.7kWh Lithium battery with top charge voltage of 28.7V. As lithium batteries doe not like to stand top-charged over time, I normally charge to 28.36V and only top charge, using this driver, every month to ballance the cells or if I need more capacity for my next visit to the cottage
My Venus OS is connected to Home Assistant where I expose all the extra features in this driver.
π Complete Documentation - All D-Bus paths, logic, and advanced features
β Charge Profile Management - Switch between summer/winter/custom profiles with safe EEPROM programming β Automatic Voltage Scaling - Auto-detect 12V/24V/48V systems for precise EEPROM writes β Voltage Override System - Battery top-charging with automatic tail current detection β 31-Day History - Daily max/min tracking with state persistence β EEPROM Counters - Lifetime kWh from TriStar's internal registers
# 1. Copy files to Venus OS
scp dbus_tristar.py install.sh root@<venus-ip>:/tmp/
# 2. SSH to Venus OS
ssh root@<venus-ip>
# 3. Install (creates service and starts driver)
cd /tmp
chmod +x install.sh
./install.shThat's it! The driver is now running as a service.
Settings are configured via D-Bus command line (no GUI menu in Venus OS v3.67):
# Set IP address (REQUIRED)
dbus -y com.victronenergy.settings /Settings/TristarMPPT/IPAddress SetValue "192.168.1.100"
# Optional settings (with defaults shown)
dbus -y com.victronenergy.settings /Settings/TristarMPPT/PortNumber SetValue 502
dbus -y com.victronenergy.settings /Settings/TristarMPPT/Interval SetValue 5000
dbus -y com.victronenergy.settings /Settings/TristarMPPT/SlaveID SetValue 1
dbus -y com.victronenergy.settings /Settings/TristarMPPT/DeviceInstance SetValue 0
# Restart driver to apply changes
svc -t /service/dbus-tristarThe driver supports advanced battery top-charging with automatic tail current detection:
# Enable voltage override to 28.7V for top-charging
dbus -y com.victronenergy.solarcharger.tristar_0 /Control/VoltageOverride SetValue 28.7
# Monitor progress
dbus -y com.victronenergy.solarcharger.tristar_0 /Custom/VoltageOverride/TimeAtTargetVoltage GetValue
dbus -y com.victronenergy.solarcharger.tristar_0 /Custom/VoltageOverride/TailCurrentTimer GetValue
# Check status
dbus -y com.victronenergy.solarcharger.tristar_0 /Custom/VoltageOverride/Active GetValue
dbus -y com.victronenergy.solarcharger.tristar_0 /Custom/VoltageOverride/StopReason GetValue
# Disable when done (or let automatic tail current detection stop it)
dbus -y com.victronenergy.solarcharger.tristar_0 /Control/VoltageOverride SetValue 0Automatic stopping conditions:
- Battery full (tail current < 2.0A for 5 minutes)
- Time limit reached (max 2 hours/day)
- Nightly reset (03:00 local time)
Configure thresholds:
# Set tail current threshold to 1.5A
dbus -y com.victronenergy.settings /Settings/TristarMPPT/BatteryFullCurrent SetValue 1.5
# Set max voltage to 28.95V
dbus -y com.victronenergy.settings /Settings/TristarMPPT/MaxVoltageOverrideVoltage SetValue 28.95π Full documentation: DRIVER_DOCUMENTATION.md - Complete guide with all settings, D-Bus paths, and logic
Switch between seasonal charging profiles with safe EEPROM programming:
# Apply summer profile (lower voltage, shorter absorption)
dbus -y com.victronenergy.solarcharger.tristar_0 /Control/ApplyChargeProfile SetValue "summer"
# Apply winter profile (higher voltage, longer absorption)
dbus -y com.victronenergy.solarcharger.tristar_0 /Control/ApplyChargeProfile SetValue "winter"
# Monitor progress
dbus -y com.victronenergy.solarcharger.tristar_0 /Custom/ChargeProfile/ApplyStatus GetValue
dbus -y com.victronenergy.solarcharger.tristar_0 /Custom/ChargeProfile/ProgressPercent GetValue
# Check active EEPROM values
dbus -y com.victronenergy.solarcharger.tristar_0 /Custom/EEPROM/AbsorptionVoltage GetValue
dbus -y com.victronenergy.solarcharger.tristar_0 /Custom/EEPROM/FloatVoltage GetValueDefault profiles:
- Summer: 28.4V absorption, 27.2V float, 7200s (2h) absorption time
- Winter: 28.8V absorption, 27.6V float, 9000s (2.5h) absorption time
- Custom: 28.6V absorption, 27.4V float, 8400s (2.3h) absorption time (user-configurable)
Customize profiles via D-Bus Settings:
# Configure custom profile for your specific battery
dbus -y com.victronenergy.settings /Settings/TristarMPPT/ChargeProfiles/Custom/AbsorptionVoltage SetValue 28.8
dbus -y com.victronenergy.settings /Settings/TristarMPPT/ChargeProfiles/Custom/FloatVoltage SetValue 27.6
dbus -y com.victronenergy.settings /Settings/TristarMPPT/ChargeProfiles/Custom/AbsorptionTime SetValue 9000
dbus -y com.victronenergy.settings /Settings/TristarMPPT/ChargeProfiles/Custom/FloatCancelVoltage SetValue 26.4
# Apply the customized profile
dbus -y com.victronenergy.solarcharger.tristar_0 /Control/ApplyChargeProfile SetValue "custom"Safety features:
- Automatic DISCONNECT before EEPROM writes
- Backup creation before changes (saved to
/data/dbus-tristar/eeprom_backups/) - Verification after every write (0.1V tolerance)
- Automatic controller reset
- Thread-safe operation (main loop paused during writes)
- Automatic voltage scaling for 12V/24V/48V systems
π Full documentation: DRIVER_DOCUMENTATION.md - Complete charge profile reference
# Check service is running
svstat /service/dbus-tristar
# Check logs
tail -f /var/log/dbus-tristar/current
# Check D-Bus registration
dbus -y com.victronenergy.solarcharger.tristar_0 /ProductName GetValue
# Check current values
dbus -y com.victronenergy.solarcharger.tristar_0 /Dc/0/Voltage GetValue
dbus -y com.victronenergy.solarcharger.tristar_0 /Yield/Power GetValueYour TriStar MPPT will appear as a Solar Charger in:
- Venus OS main screen
- VRM Portal dashboard
- Remote Console
- β Full Modbus TCP communication (connect-read-close pattern)
- β All TriStar registers: voltage, current, power, yield, temperature
- β Target regulation voltage (charge setpoint)
- β Daily history: kWh, max values, time in absorption/bulk/float
- β Total yield tracking
- β Full VRM Portal integration
- β Charge profile management - Switch between summer/winter/custom profiles with safe EEPROM programming
- β Voltage override - Top-charge to configurable voltage (e.g., 28.7V)
- β Automatic battery full detection - Tail current monitoring with configurable thresholds
- β Mode control - Enable/disable charging via D-Bus
- β Equalize trigger (read/write coil with verification)
- β Charger disconnect (read/write coil with verification)
- β Controller reset (momentary button)
- β Comm server reset (momentary button)
- β Automatic nightly reset at configurable hour (default: 03:00)
- β Connection statistics (/Custom/Stats/SuccessfulReads)
- β Failure tracking (/Custom/Stats/FailedReads)
- β Consecutive failure counter (/Custom/Stats/ConsecutiveFailures)
- β Last success timestamp (/Custom/Stats/LastSuccessTime)
- β Backoff factor (/Custom/Stats/BackoffFactor)
- β Remote debugging via VRM Portal or dbus-spy
- β Automatic reconnection on network loss
- β Settings change callback (auto-reconnect when IP/port changes)
- β WAN-optimized: 1-second timeout with 5 retries
- β Connection watchdog (3-minute timeout detection)
- β Exponential backoff on persistent failures (1x β 2x β 4x interval)
- β Graceful shutdown handlers (SIGTERM/SIGINT)
- β Data validation (sanity checks on voltage/current/power)
- β Critical coil verification (read-after-write for EQUALIZE/DISCONNECT)
- β Statistics paths for remote diagnostics (/Custom/Stats/*)
- β MQTT integration via Venus OS broker
- Morningstar TriStar MPPT 30
- Morningstar TriStar MPPT 45
- Morningstar TriStar MPPT 60
Requirements:
- TriStar with Modbus TCP enabled
- Network connectivity between Venus OS and TriStar
- Venus OS v3.4+ (tested on v3.67)
dbus-tsmppt/
βββ dbus_tristar.py # Main driver (v2.26)
βββ install.sh # Installation script
βββ README.md # This file (overview)
βββ DRIVER_DOCUMENTATION.md # Complete technical reference (π READ THIS!)
βββ QUICKSTART.md # Quick start guide
βββ test_connection.py # Connection testing tool
βββ dbus_tristar_mock.py # Mock driver for testing
βββ docs/ # Technical docs and PDFs
βββ Reference Cplusplus code for dbus_tsmppt/ # Legacy C++/QML code
- DRIVER_DOCUMENTATION.md - π COMPLETE REFERENCE - All D-Bus paths, voltage override system, tail current detection, settings, troubleshooting
- QUICKSTART.md - 3-minute installation guide
- test_connection.py - Test Modbus connection to your TriStar
- docs/TECHNICAL-DETAILS.md - C++ compatibility analysis and technical details
Can't connect to TriStar?
# Test connection
python3 test_connection.py <tristar-ip> 502 1
# Check network
ping <tristar-ip>
# Review logs
tail -f /var/log/dbus-tristar/current
# Check connection statistics
dbus -y com.victronenergy.solarcharger.tristar_0 /Custom/Stats/ConsecutiveFailures GetValue
dbus -y com.victronenergy.solarcharger.tristar_0 /Custom/Stats/LastSuccessTime GetValueConnection drops frequently?
- Check
/Custom/Stats/FailedReadsand/Custom/Stats/SuccessfulReads - High failure rate indicates network instability
- Check if backoff is active:
/Custom/Stats/BackoffFactor(should be 1 normally) - Exponential backoff will activate after 10 consecutive failures
Unrealistic values showing?
- Driver has built-in sanity checks for voltage/current/power
- Check logs for warnings: "Unrealistic battery voltage" or similar
- Indicates possible Modbus packet corruption over WAN
- Corrupted values are automatically rejected and old values retained
No data showing?
- Verify IP address is correct in settings
- Check TriStar has Modbus TCP enabled (usually port 502)
- Check slave ID matches your device (usually 1)
- Review logs for connection errors
- Check
/Connectedpath:dbus -y com.victronenergy.solarcharger.tristar_0 /Connected GetValue
Settings menu doesn't appear in GUI?
- Expected behavior in Venus OS v3.67
- Use D-Bus command line instead (see Configuration section)
- Settings are fully functional via D-Bus
MQTT write not working?
- CRITICAL: Venus OS MQTT requires JSON format:
{"value": 1}not just1 - MQTT topics use device instance (e.g.,
solarcharger/0), not service name (e.g.,tristar_0) - Test D-Bus write first to verify driver is working:
dbus -y com.victronenergy.solarcharger.tristar_0 /Control/EqualizeTriggered SetValue 1
- Example MQTT write command:
mosquitto_pub -h <venus-ip> -t "W/<portal-id>/solarcharger/0/Control/EqualizeTriggered" -m '{"value": 1}'
- Check logs after MQTT write to see if driver received the command:
tail -f /var/log/dbus-tristar/current | grep "Coil write"
Architecture:
- Pure Python using Venus OS
SettingsDeviceAPI - Connect-read-close Modbus pattern (matches TriStar hardware)
- pymodbus v2.x/v3.x compatible with auto-detection
- GLib main loop with exponential backoff on failures
- WAN-optimized: 1-second timeout, data validation, smart retry logging
D-Bus Service:
- Service name:
com.victronenergy.solarcharger.tristar_{instance}(configurable) - 50+ D-Bus paths: Standard Victron + Custom monitoring/control
- Full settings integration:
/Settings/TristarMPPT/* - State persistence: 31-day history in
/data/dbus-tristar/state.json
For complete technical details, D-Bus path reference, Modbus registers, and troubleshooting: π See DRIVER_DOCUMENTATION.md
Venus OS has a built-in MQTT broker that automatically publishes all D-Bus paths. This makes integration with Home Assistant simple and native.
Read coil status:
N/<portal-id>/solarcharger/tristar_0/Control/EqualizeTriggered
N/<portal-id>/solarcharger/tristar_0/Control/ChargerDisconnect
Write to coils:
W/<portal-id>/solarcharger/tristar_0/Control/EqualizeTriggered {"value": 1}
W/<portal-id>/solarcharger/tristar_0/Control/ResetController {"value": 1}
IMPORTANT: Venus OS MQTT write requires JSON format. Use {"value": 1} not just 1.
Note:
- Replace
<portal-id>with your Venus OS VRM Portal ID (found in Settings β VRM Portal) - Replace
tristar_0with0if using default device instance (MQTT uses device instance, not service name) - Example:
W/b827ebe38b8c/solarcharger/0/Control/EqualizeTriggered {"value": 1}
mqtt:
switch:
- unique_id: tristar_equalize
name: "TriStar Equalize Charge"
state_topic: "N/<portal-id>/solarcharger/tristar_0/Control/EqualizeTriggered"
command_topic: "W/<portal-id>/solarcharger/tristar_0/Control/EqualizeTriggered"
payload_on: '{"value": 1}'
payload_off: '{"value": 0}'
- unique_id: tristar_disconnect
name: "TriStar Charger Disconnect"
state_topic: "N/<portal-id>/solarcharger/tristar_0/Control/ChargerDisconnect"
command_topic: "W/<portal-id>/solarcharger/tristar_0/Control/ChargerDisconnect"
payload_on: '{"value": 1}'
payload_off: '{"value": 0}'
button:
- unique_id: tristar_reset_controller
name: "TriStar Reset Controller"
command_topic: "W/<portal-id>/solarcharger/tristar_0/Control/ResetController"
payload_press: '{"value": 1}'Note: Replace <portal-id> with your Venus OS VRM Portal ID (found in Settings β VRM Portal).
The original C++ driver and legacy Python versions are preserved in:
Reference Cplusplus code for dbus_tsmppt/
Contents:
software/- Original Qt/C++ driver (Venus OS v2.30 and older)qml/- QML files for Venus OS v2.80-v3.3dbus-tsmppt.py- Legacy Python driver- Old installation scripts and documentation
These are kept for reference only. Use dbus_tristar.py for all new installations.
MIT License - See LICENSE
- Original C++ driver: Ole André Sæther (2018-2019)
- Python rewrite: 2024 - Modern Venus OS v3.4+ compatible
- Architecture: Based on Victron Energy Venus OS and velib_python
- https://github.com/mr-manuel/venus-os_dbus-mqtt-solar-charger
Enjoy your TriStar MPPT on Venus OS! βοΈπ
Questions? Check the logs: tail -f /var/log/dbus-tristar/current
TO DO LIST:
- Check modbus parameters to be used for I and V. Now it is a mix of fast and slow.
- Remove/change excess power estimation as this is not working properly
- Add monthly top charging in driver with indircation for discharging afterwards