diff --git a/.DS_Store b/.DS_Store index 1f3c622..f9d812e 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/README.md b/README.md index a0f8286..dc9eeb3 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,9 @@ By remotely setting values via MQTT you can for example, change the power mode t The program is designed to be run in a Docker Container, and can be deployed on a lightweight SBC next to your Inverter (i.e. an Orange Pi Zero running Arabian), and read data via the RS232 or USB ports on the back of the Inverter. +![Example Lovelace Dashboard](images/lovelace-dashboard.jpg "Example Lovelace Dashboard") +_Example: My "Lovelace" dashboard using data collected from the Inverter._ + ---- **Docker Hub:** [`bushrangers/ha-voltronic-mqtt`](https://hub.docker.com/r/bushrangers/ha-voltronic-mqtt/) @@ -63,6 +66,8 @@ _(see [protocol manual](http://forums.aeva.asn.au/uploads/293/HS_MS_MSX_RS232_Pr ``` +DESCRIPTION: PAYLOAD: OPTIONS: +---------------------------------------------------------------- Set output source priority POP00 (Utility first) POP01 (Solar first) POP02 (SBU) @@ -77,4 +82,15 @@ Set other commands PEa / PDa (Enable/disable buzzer) PEj / PDj (Enable/disable power saving) PEu / PDu (Enable/disable overload restart); PEx / PDx (Enable/disable backlight) -``` \ No newline at end of file +``` + +### Bonus: Lovelace Dashboard Files + +_**Please refer to the screenshot above for an example of the dashboard.**_ + +I've included some Lovelace dashboard files in the `homeassistant/` directory, however you will need to need to adapt to your own Home Assistant configuration and/or name of the inverter if you have changed it in the `mqtt.json` config file. + +Note that in addition to merging the sample Yaml files with your Home Assistant, you will need the following custom Lovelace cards installed if you wish to use my templates: + + - [vertical-stack-in-card](https://github.com/custom-cards/vertical-stack-in-card) + - [circle-sensor-card](https://github.com/custom-cards/circle-sensor-card) diff --git a/homeassistant/configuration.yaml b/homeassistant/configuration.yaml new file mode 100644 index 0000000..05163b0 --- /dev/null +++ b/homeassistant/configuration.yaml @@ -0,0 +1,90 @@ +# You will need to merge with your own Home Assistant configuration.yml file... + +input_select: + solar_output_source_priority: + name: Solar Output Source Priority + options: + - POP00 (Utility first) + - POP01 (Solar first) + - POP02 (SBU) + + solar_charger_priority: + name: Solar Charger Priority Order + options: + - PCP00 (Utility first) + - PCP01 (Solar first) + - PCP02 (Solar and utility) + - PCP03 (Solar only) + + +# Automations of Solar PV Inverter (such as when to charge batteries off grid / from PV etc)... +# This will automatically fire off the event to the inverter when changed in the UI. +automation: +- id: 'set_solar_output_source' + alias: Solar Trigger Output Source Change + trigger: + platform: state + entity_id: input_select.solar_output_source_priority + action: + service: mqtt.publish + data_template: + topic: 'homeassistant/sensor/voltronic' + payload: > + {% if is_state("input_select.solar_output_source_priority", "POP00 (Utility first)") %} + POP00 + {% elif is_state("input_select.solar_output_source_priority", "POP01 (Solar first)") %} + POP01 + {% elif is_state("input_select.solar_output_source_priority", "POP02 (SBU)") %} + POP02 + {% endif %} + +- id: 'set_solar_charge_priority' + alias: Stolar Trigger Charge Priority Change + trigger: + platform: state + entity_id: input_select.solar_charger_priority + action: + service: mqtt.publish + data_template: + topic: 'homeassistant/sensor/voltronic' + payload: > + {% if is_state("input_select.solar_charger_priority", "PCP00 (Utility first)") %} + PCP00 + {% elif is_state("input_select.solar_charger_priority", "PCP01 (Solar first)") %} + PCP01 + {% elif is_state("input_select.solar_charger_priority", "PCP02 (Solar and utility)") %} + PCP02 + {% elif is_state("input_select.solar_charger_priority", "PCP03 (Solar only)") %} + PCP03 + {% endif %} + +# Auto Switch to 'Solar based charging ONLY at sunrise' (will not charge batteries from the Grid to save power...) +- id: 'switch_solar_only_charging_am' + alias: Auto switch to "Solar Only" charging at Sunrise + trigger: + - event: sunrise + platform: sun + offset: "00:15:00" + condition: [] + action: + - service: input_select.select_option + data: + entity_id: input_select.solar_charger_priority + option: "PCP01 (Solar first)" + - service: input_select.select_option + data: + entity_id: input_select.solar_output_source_priority + option: "POP01 (Solar first)" + +- id: 'switch_battery_late_evenings' + # Running on UPS mode seems to fuck up the 8 port tplink switch (it drops out from time to time) so it's best that we change mode after 2AM when less people are using Plex etc... + alias: Switch to battery preferred output late evenings + trigger: + - at: '02:00' + platform: time + condition: [] + action: + - service: input_select.select_option + data: + entity_id: input_select.solar_output_source_priority + option: "POP02 (SBU)" diff --git a/homeassistant/lovelace.yaml b/homeassistant/lovelace.yaml new file mode 100644 index 0000000..b796335 --- /dev/null +++ b/homeassistant/lovelace.yaml @@ -0,0 +1,152 @@ +resources: + - type: js + url: /local/vertical-stack-in-card.js?v=0.1.2 + - type: module + url: /local/circle-sensor-card.js?v=0 +title: Solar Dashboard + +views: + - badges: [] + cards: + - cards: + - type: conditional + conditions: + - entity: sensor.voltronic_inverter_mode + state: '1' + card: + type: picture + image: /local/inverter-modes/1.png + - type: conditional + conditions: + - entity: sensor.voltronic_inverter_mode + state: '2' + card: + type: picture + image: /local/inverter-modes/2.png + - type: conditional + conditions: + - entity: sensor.voltronic_inverter_mode + state: '3' + card: + type: picture + image: /local/inverter-modes/3.png + - type: conditional + conditions: + - entity: sensor.voltronic_inverter_mode + state: '4' + card: + type: picture + image: /local/inverter-modes/4.png + - type: conditional + conditions: + - entity: sensor.voltronic_inverter_mode + state: '5' + card: + type: picture + image: /local/inverter-modes/5.png + - type: conditional + conditions: + - entity: sensor.voltronic_inverter_mode + state: '6' + card: + type: picture + image: /local/inverter-modes/6.png + - content: | + --- + type: markdown + - type: entities + entities: + - entity: input_select.solar_output_source_priority + icon: 'mdi:battery' + - entity: input_select.solar_charger_priority + icon: 'mdi:format-list-numbered' + - entity: automation.auto_switch_to_solar_only_charging_at_sunrise + - entity: automation.switch_to_battery_preferred_output_late_evenings + show_header_toggle: false + title: null + type: 'custom:vertical-stack-in-card' + - cards: + - entities: + - entity: sensor.voltronic_pv_in_voltage + name: PV Voltage (V) + icon: 'mdi:grid' + type: sensor + - entity: sensor.voltronic_pv_in_watts + name: PV Watts (W) + icon: 'mdi:battery-charging-70' + type: sensor + type: glance + - entities: + - entity: sensor.voltronic_load_watt + name: Inverter Output Load + type: history-graph + - entities: + - entity: sensor.voltronic_ac_grid_frequency + icon: 'mdi:current-ac' + name: Grid Frequency + - entity: sensor.voltronic_ac_grid_voltage + icon: 'mdi:power-plug' + name: Grid Voltage + - entity: sensor.voltronic_ac_out_frequency + icon: 'mdi:current-ac' + name: Output Freq + - entity: sensor.voltronic_ac_out_voltage + icon: 'mdi:power-plug' + name: Output Voltage + type: glance + show_header_toggle: false + title: System Overview + type: 'custom:vertical-stack-in-card' + - cards: + - cards: + - color_stops: + '40': '#00dc10' + '60': '#ff0000' + '80': '#ffe400' + entity: sensor.voltronic_load_pct + font_style: + font-size: 1.5em + gradient: true + name: System Load (%) + stroke_width: 10 + type: 'custom:circle-sensor-card' + - color_stops: + '50': '#ff0000' + '75': '#ffe400' + '100': '#00dc10' + entity: sensor.voltronic_battery_capacity + font_style: + font-size: 1.5em + gradient: true + name: Battery Capacity + stroke_width: 10 + type: 'custom:circle-sensor-card' + type: horizontal-stack + - entities: + - entity: sensor.voltronic_battery_charge_current + name: Battery Charge Current (A) + - entity: sensor.voltronic_battery_discharge_current + name: Battery Discharge Current (A) + type: history-graph + - entities: + - entity: sensor.voltronic_battery_float_voltage + icon: 'mdi:battery-charging' + name: Float Point + - entity: sensor.voltronic_battery_recharge_voltage + icon: 'mdi:battery-negative' + name: Recharge Lvl + - entity: sensor.voltronic_battery_redischarge_voltage + icon: 'mdi:battery-plus' + name: Discharge Lvl + - entity: sensor.voltronic_battery_under_voltage + icon: 'mdi:battery-charging-wireless-outline' + name: Critical Cutoff + type: glance + - entity: sensor.voltronic_battery_voltage + name: Battery Voltage (V) + type: sensor + show_header_toggle: false + title: null + type: 'custom:vertical-stack-in-card' + icon: 'mdi:grid' + title: Solar Configuration diff --git a/homeassistant/www/inverter-modes/1.png b/homeassistant/www/inverter-modes/1.png new file mode 100644 index 0000000..7a9e399 Binary files /dev/null and b/homeassistant/www/inverter-modes/1.png differ diff --git a/homeassistant/www/inverter-modes/2.png b/homeassistant/www/inverter-modes/2.png new file mode 100644 index 0000000..17d18aa Binary files /dev/null and b/homeassistant/www/inverter-modes/2.png differ diff --git a/homeassistant/www/inverter-modes/3.png b/homeassistant/www/inverter-modes/3.png new file mode 100644 index 0000000..4c99164 Binary files /dev/null and b/homeassistant/www/inverter-modes/3.png differ diff --git a/homeassistant/www/inverter-modes/4.png b/homeassistant/www/inverter-modes/4.png new file mode 100644 index 0000000..c72de36 Binary files /dev/null and b/homeassistant/www/inverter-modes/4.png differ diff --git a/homeassistant/www/inverter-modes/5.png b/homeassistant/www/inverter-modes/5.png new file mode 100644 index 0000000..305c205 Binary files /dev/null and b/homeassistant/www/inverter-modes/5.png differ diff --git a/homeassistant/www/inverter-modes/6.png b/homeassistant/www/inverter-modes/6.png new file mode 100644 index 0000000..d9c6c46 Binary files /dev/null and b/homeassistant/www/inverter-modes/6.png differ diff --git a/homeassistant/www/inverter-modes/7.png b/homeassistant/www/inverter-modes/7.png new file mode 100644 index 0000000..424ee8a Binary files /dev/null and b/homeassistant/www/inverter-modes/7.png differ diff --git a/images/lovelace-dashboard.jpg b/images/lovelace-dashboard.jpg new file mode 100644 index 0000000..893ac79 Binary files /dev/null and b/images/lovelace-dashboard.jpg differ diff --git a/manual/HS_MS_MSX_RS232_Protocol_20140822_after_current_upgrade.pdf b/manual/HS_MS_MSX_RS232_Protocol_20140822_after_current_upgrade.pdf new file mode 100644 index 0000000..0a993ae Binary files /dev/null and b/manual/HS_MS_MSX_RS232_Protocol_20140822_after_current_upgrade.pdf differ diff --git a/sources/voltronic-mqtt/entrypoint.sh b/sources/voltronic-mqtt/entrypoint.sh index 0fb2d3a..5d7a2e5 100755 --- a/sources/voltronic-mqtt/entrypoint.sh +++ b/sources/voltronic-mqtt/entrypoint.sh @@ -1,11 +1,12 @@ #!/bin/bash export TERM=xterm -# Init the mqtt server for the first time... -bash /opt/voltronic-mqtt/mqtt-init.sh +# Init the mqtt server for the first time, then every 5 minutes +# This will re-create the auto-created topics in the MQTT server if HA is restarted... +watch -n 300 /opt/voltronic-mqtt/mqtt-init.sh > /dev/null 2>&1 & # Run the MQTT Subscriber process in the background (so that way we can change the configuration on the inverter from home assistant) /opt/voltronic-mqtt/mqtt-subscriber.sh & -# execute exactly ever minute... -watch -n 30 /opt/voltronic-mqtt/mqtt-push.sh # > /dev/null 2>&1 +# execute exactly every 30 seconds... +watch -n 30 /opt/voltronic-mqtt/mqtt-push.sh > /dev/null 2>&1 diff --git a/sources/voltronic-mqtt/mqtt-init.sh b/sources/voltronic-mqtt/mqtt-init.sh index 03135c8..2f48dcc 100755 --- a/sources/voltronic-mqtt/mqtt-init.sh +++ b/sources/voltronic-mqtt/mqtt-init.sh @@ -16,7 +16,8 @@ registerTopic () { \"name\": \""$MQTT_DEVICENAME"_$1\", \"unit_of_measurement\": \"$2\", \"state_topic\": \"$MQTT_TOPIC/sensor/"$MQTT_DEVICENAME"_$1\", - \"icon\": \"mdi:$3\" + \"icon\": \"mdi:$3\", + \"retain\": true }" } @@ -27,42 +28,43 @@ registerInverterRawCMD () { -t "$MQTT_TOPIC/sensor/$MQTT_DEVICENAME/config" \ -m "{ \"name\": \""$MQTT_DEVICENAME"\", - \"state_topic\": \"$MQTT_TOPIC/sensor/$MQTT_DEVICENAME\" + \"state_topic\": \"$MQTT_TOPIC/sensor/$MQTT_DEVICENAME\", + \"retain\": true }" } -registerTopic "Inverter_mode" "" "mdi-solar-power" # 1 = Power_On, 2 = Standby, 3 = Line, 4 = Battery, 5 = Fault, 6 = Power_Saving, 7 = Unknown -registerTopic "AC_grid_voltage" "V" "mdi-power-plug" -registerTopic "AC_grid_frequency" "Hz" "mdi-current-ac" -registerTopic "AC_out_voltage" "V" "mdi-power-plug" -registerTopic "AC_out_frequency" "Hz" "mdi-current-ac" -registerTopic "PV_in_voltage" "V" "mdi-solar-panel-large" -registerTopic "PV_in_current" "A" "mdi-solar-panel-large" -registerTopic "PV_in_watts" "W" "mdi-solar-panel-large" -registerTopic "PV_in_watthour" "Wh" "mdi-solar-panel-large" -registerTopic "SCC_voltage" "V" "mdi-current-dc" -registerTopic "Load_pct" "%" "mdi-brightness-percent" -registerTopic "Load_watt" "W" "mdi-chart-bell-curve" -registerTopic "Load_watthour" "Wh" "mdi-chart-bell-curve" -registerTopic "Load_va" "VA" "mdi-chart-bell-curve" -registerTopic "Bus_voltage" "V" "mdi-details" -registerTopic "Heatsink_temperature" "" "mdi-details" -registerTopic "Battery_capacity" "%" "mdi-battery-outline" -registerTopic "Battery_voltage" "V" "mdi-battery-outline" -registerTopic "Battery_charge_current" "A" "mdi-current-dc" -registerTopic "Battery_discharge_current" "A" "mdi-current-dc" -registerTopic "Load_status_on" "" "mdi-power" -registerTopic "SCC_charge_on" "" "mdi-power" -registerTopic "AC_charge_on" "" "mdi-power" -registerTopic "Battery_recharge_voltage" "V" "mdi-current-dc" -registerTopic "Battery_under_voltage" "V" "mdi-current-dc" -registerTopic "Battery_bulk_voltage" "V" "mdi-current-dc" -registerTopic "Battery_float_voltage" "V" "mdi-current-dc" -registerTopic "Max_grid_charge_current" "A" "mdi-current-ac" -registerTopic "Max_charge_current" "A" "mdi-current-ac" -registerTopic "Out_source_priority" "" "mdi-grid" -registerTopic "Charger_source_priority" "" "mdi-solar-power" -registerTopic "Battery_redischarge_voltage" "V" "mdi-battery-negative" +registerTopic "Inverter_mode" "" "solar-power" # 1 = Power_On, 2 = Standby, 3 = Line, 4 = Battery, 5 = Fault, 6 = Power_Saving, 7 = Unknown +registerTopic "AC_grid_voltage" "V" "power-plug" +registerTopic "AC_grid_frequency" "Hz" "current-ac" +registerTopic "AC_out_voltage" "V" "power-plug" +registerTopic "AC_out_frequency" "Hz" "current-ac" +registerTopic "PV_in_voltage" "V" "solar-panel-large" +registerTopic "PV_in_current" "A" "solar-panel-large" +registerTopic "PV_in_watts" "W" "solar-panel-large" +registerTopic "PV_in_watthour" "Wh" "solar-panel-large" +registerTopic "SCC_voltage" "V" "current-dc" +registerTopic "Load_pct" "%" "brightness-percent" +registerTopic "Load_watt" "W" "chart-bell-curve" +registerTopic "Load_watthour" "Wh" "chart-bell-curve" +registerTopic "Load_va" "VA" "chart-bell-curve" +registerTopic "Bus_voltage" "V" "details" +registerTopic "Heatsink_temperature" "" "details" +registerTopic "Battery_capacity" "%" "battery-outline" +registerTopic "Battery_voltage" "V" "battery-outline" +registerTopic "Battery_charge_current" "A" "current-dc" +registerTopic "Battery_discharge_current" "A" "current-dc" +registerTopic "Load_status_on" "" "power" +registerTopic "SCC_charge_on" "" "power" +registerTopic "AC_charge_on" "" "power" +registerTopic "Battery_recharge_voltage" "V" "current-dc" +registerTopic "Battery_under_voltage" "V" "current-dc" +registerTopic "Battery_bulk_voltage" "V" "current-dc" +registerTopic "Battery_float_voltage" "V" "current-dc" +registerTopic "Max_grid_charge_current" "A" "current-ac" +registerTopic "Max_charge_current" "A" "current-ac" +registerTopic "Out_source_priority" "" "grid" +registerTopic "Charger_source_priority" "" "solar-power" +registerTopic "Battery_redischarge_voltage" "V" "battery-negative" # Add in a separate topic so we can send raw commands from assistant back to the inverter via MQTT (such as changing power modes etc)... registerInverterRawCMD diff --git a/sources/voltronic-mqtt/mqtt-push.sh b/sources/voltronic-mqtt/mqtt-push.sh index f23a377..757b2c9 100755 --- a/sources/voltronic-mqtt/mqtt-push.sh +++ b/sources/voltronic-mqtt/mqtt-push.sh @@ -19,6 +19,9 @@ INVERTER_DATA=`timeout 10 /opt/voltronic-cli/bin/skymax` ##################################################################################### Inverter_mode=`echo $INVERTER_DATA | jq '.Inverter_mode' -r` + + # 1 = Power_On, 2 = Standby, 3 = Line, 4 = Battery, 5 = Fault, 6 = Power_Saving, 7 = Unknown + [ ! -z "$Inverter_mode" ] && pushMQTTData "Inverter_mode" "$Inverter_mode" AC_grid_voltage=`echo $INVERTER_DATA | jq '.AC_grid_voltage' -r`