Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mpepping/solarman-mqtt
Send Solarman Smart PV inverter metrics to MQTT
https://github.com/mpepping/solarman-mqtt
home-assistant mqtt pvoutput solarman solarmanpv trannergy
Last synced: about 21 hours ago
JSON representation
Send Solarman Smart PV inverter metrics to MQTT
- Host: GitHub
- URL: https://github.com/mpepping/solarman-mqtt
- Owner: mpepping
- License: apache-2.0
- Created: 2021-09-21T18:17:29.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2024-03-15T17:10:35.000Z (11 months ago)
- Last Synced: 2024-05-01T12:57:40.979Z (9 months ago)
- Topics: home-assistant, mqtt, pvoutput, solarman, solarmanpv, trannergy
- Language: Python
- Homepage:
- Size: 718 KB
- Stars: 58
- Watchers: 10
- Forks: 22
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# solarman-mqtt
Script to retrieve current Solar PV data from the Solarman API, and send Power (W) and Energy (kWh) metrics to a MQTT broker, for further use in home automation. Several PV vendors use the Solarman Smart platform for statistics. One example is the Trannergy PV converter.
```bash
usage: run.py [-h] [-d] [-s] [-i INTERVAL] [-f FILE] [--validate] [--create-passhash CREATE_PASSHASH] [-v]Collect data from Trannergy / Solarman API
optional arguments:
-h, --help show this help message and exit
-d, --daemon run as a service
-s, --single single run and exit
-i INTERVAL, --interval INTERVAL
run interval in seconds (default 300 sec.)
-f FILE, --file FILE config file (default ./config.json)
--validate validate config file and exit
--create-passhash CREATE_PASSHASH
create passhash from provided passwordand exit
```## Usage
You can run this script as a Docker container or in Python 3. Either way, a configuration file is required. Use the sample [config.sample.json](config.sample.json) file in this repository for reference. Also, a Solarman API appid+secret is required, which can be requested via [[email protected]](mailto:[email protected]?subject=SolarmanPV%20API%20key%20Request).
## How to get all required input for the config file
Create a new config file by copying the [sample config file](config.sample.json) and filling in the required information.
The first part covers your SolarmanPV account:
```json
{
"name": "Trannergy",
"url": "globalapi.solarmanpv.com",
"appid": "",
"secret": "",
"username": "",
"passhash": "",
[..]
}
```* **name**: is free text to identify the platform.
* **url**: is the base URL of the API.
* **appid**: is the appid for the API (See Usage).
* **secret**: is the secret for the API (See Usage).
* **username**: is the username for the API (emailadres).
* **passhash**: is a sha256 hash of your password. This can be generated via `--create-passhash`.The second part covers the PV inverter and logger ID's. These can be retrieved via the Solarman API.
```json
{
[..]
"stationId": 123,
"inverterId": 456,
"loggerId": 789
[..]
}
```* **stationId**: is the ID of the station. This is the value of `stationList[0].id`.
```bash
curl --location --request POST 'https://globalapi.solarmanpv.com/station/v1.0/list?language=en' \
--header 'Content-Type: application/json' \
--header 'Authorization: bearer TOKEN' \
--data-raw '{"size":20,"page":1}'
```* **inverterId**: is the SN of the inverter. This is the value of `deviceListItems[0].deviceSn`.
* For Bosswerk MI300 and MI600 use "MICRO_INVERTER" instead of "INVERTER".```bash
curl --location --request POST 'https://globalapi.solarmanpv.com/station/v1.0/device?language=en' \
--header 'Content-Type: application/json' \
--header 'Authorization: bearer TOKEN' \
--data-raw '{"size":10,"page":1,"stationId":1234567,"deviceType":"INVERTER"}'
```* **loggerId**: is the SN of the logger. This is the value of `deviceListItems[0].deviceSn`.
```bash
curl --location --request POST 'https://globalapi.solarmanpv.com/station/v1.0/device?language=en' \
--header 'Content-Type: application/json' \
--header 'Authorization: bearer TOKEN' \
--data-raw '{"size":10,"page":1,"stationId":1234567,"deviceType":"COLLECTOR"}'
```* **meterId** (optional): If you have a DTSD422 meter as part of your PV system, you can add the meter serialnumber to the config file.
```json
{
[..]
"meterId": 123
[..]
}
```A bearer TOKEN to use in the requests above can be retrieved by adding your APPID, APPSECRET, USERNAME, PASSHASH in this request:
```bash
curl --location --request POST 'https://globalapi.solarmanpv.com/account/v1.0/token?appId=APPID&language=en' \
--header 'Content-Type: application/json' \
--data-raw '{
"appSecret": "APPSECRET",
"email": "USERNAME",
"password": "PASSHASH"
}'
```**Note:** If there is an error with `AUTH_INVALID_USERNAME_OR_PASSWORD` as code it might be that your password is too long or contains special characters. Try something shorter and A-Z, a-z and 0-9 only.
The final section covers the MQTT broker, to where the metrics will be published.
```json
{
[..]
"broker": "mqtt.example.com",
"port": 1883,
"topic": "solarman",
"username": "",
"password": ""
}
```## MQTT topics
The following topics are published to the MQTT broker. Topics and fields may differ between PV system types. The example output below use `solarmanpv` as the topic, configured in the config file.
### Station (Plant)
Information about the plant, current power and last update time.
```text
solarmanpv/station/batteryPower
solarmanpv/station/batterySoc
solarmanpv/station/chargePower
solarmanpv/station/dischargePower
solarmanpv/station/generationPower
solarmanpv/station/gridPower
solarmanpv/station/irradiateIntensity
solarmanpv/station/lastUpdateTime
solarmanpv/station/purchasePower
solarmanpv/station/usePower
solarmanpv/station/wirePower
```### Inverter
Inverter information.
```text
solarmanpv/inverter/deviceId
solarmanpv/inverter/deviceSn
solarmanpv/inverter/deviceState
solarmanpv/inverter/deviceType
solarmanpv/inverter/attributes
```The `attributes` field contains all inverter datalist entries as a JSON object. An expample set of attributes is shown below:
```text
SN: XXXXXXXXXX
Device_Type: 4
Production_Compliance_Type: 0
Rated_Power: 300.00
Year: 48
Month: 0
Day: 0
Hour: 0
Minute: 0
Seconds: 0
Communication_Protocol_Version: V0.2.0.1
Control_Board_Firmware_Version: V0.1.1.2
Communication_Board_Firmware_Version: V0.2.0.7
DC_Voltage_PV1: 0.00
DC_Voltage_PV2: 0.00
DC_Voltage_PV3: 0.00
DC_Voltage_PV4: 0.00
DC_Current_PV1: 0.00
DC_Current_PV2: 0.00
DC_Current_PV3: 0.00
DC_Current_PV4: 0.00
DC_Power_PV1: 0.00
DC_Power_PV2: 0.00
DC_Power_PV3: 0.00
DC_Power_PV4: 0.00
AC_Voltage_1: 0.00
AC_Current_1: 0.00
Total_AC_Output_Power(Active): 0
AC_Output_Frequency_1: 0.00
Total_Production(Active): 2.50
Total_Production_1: 2.50
Total_Production_2: 0.00
Total_Production_3: 0.00
Total_Production_4: 0.00
Daily_Production(Active): 0.70
Daily_Production_1: 0.70
Daily_Production_2: 0.00
Daily_Production_3: 0.00
Daily_Production_4: 0.00
AC_Radiator_Temp: -10.00
Micro_Inverter_Port_1: XXXXXXXXXX-1
Micro_Inverter_Port_2: XXXXXXXXXX-2
Micro_Inverter_Port_3: XXXXXXXXXX-3
Micro_Inverter_Port_4: XXXXXXXXXX-4
Number_Of_MPPT_Paths: 1
Number_Of_Phases: 1
Running_Status: 4
Overfrequency_And_Load_Reduction_Starting_Point: 50.20
Islanding Protection Enabled: Enable
Overfrequency_And_Load_Reduction_Percentage: 44
GFDI Enabled: Disable
Grid-connected Standard: 0
Grid Voltage_Upper_Limit: 275.00
Grid Voltage_Lower_Limit: 180.00
Grid Frequency_Upper_Limit: 52.00
Grid Frequency_Lower_Limit: 47.50
Start-up Self-checking Time: 60
```### Logger (Collector)
```text
solarmanpv/logger/deviceId
solarmanpv/logger/deviceSn
solarmanpv/logger/deviceState
solarmanpv/logger/deviceType
solarmanpv/logger/attributes
```The `attributes` field contains all inverter datalist entries as a JSON object. Some devices may send an empty object for this field.
An example set of attributes is shown below:```bash
Embedded_Device_SN: XXXXXXXXXX
Module_Version_No: MW3_15_5406_1.35
Extended_System_Version: V1.1.00.07
Total_running_time: 1
Offset_time: 1634486607
Data_Uploading_Period: 5
Data_Acquisition_Period: 60
Max._No._of_Connected_Devices: 1
Signal_Strength: 100
Heart_Rate: 120
IV_Curve_Supported: 1
Batch_Command_Supported: 1
Support_Reporting_Upgrading_Progress: 0
AT+UPGRADE_Command_Supported: 255
Method_Of_Protocol_Upgrade: 255
```## Running multiple inverter stations
If you have multiple inverter stations, you can add them to the config file as a list. Make sure to publish to separate MQTT topics per inverter instance, and configure the Home Assistant MQTT sensors accordingly.
```json
[
{
"name": "Trannergy-1",
"stationId": 987,
"inverterId": 654,
"loggerId": 321,
"mqtt": {
"topic": "inverter1"
}
},
{
"name": "Trannergy-2",
"stationId": 123,
"inverterId": 456,
"loggerId": 789,
"mqtt": {
"topic": "inverter2"
}
}
]
```*Minimized example config; see `config.sample.json` for all fields.*
## Home Assistant
```yaml
mqtt:
sensor:
- name: "solarmanpv_station_generationPower"
state_topic: "solarmanpv/station/generationPower"
unique_id: "generatedPower"
unit_of_measurement: "Wh"
device_class: energy
state_class: measurement
```Repeat for every station topic needed.
```yaml
- name: "solarmanpv_inverter"
unique_id: "solarmanpv_inverter"
state_topic: "solarmanpv/inverter/deviceState"
json_attributes_topic: "solarmanpv/inverter/attributes"- name: "solarmanpv_logger"
unique_id: "solarmanpv_logger"
state_topic: "solarmanpv/logger/deviceState"
json_attributes_topic: "solarmanpv/logger/attributes"sensor:
- platform: template
sensors:
solarmanpv_inverter_device_state:
unique_id: "inverter_device_state"
value_template: >-
{% set mapper = {
'1' : 'Online',
'2' : 'Failure',
'3' : 'Offline'} %}
{% set state = states.sensor.solarmanpv_inverter.state %}
{{ mapper[state] if state in mapper else 'Unknown' }}- platform: template
sensors:
solarmanpv_logger_device_state:
unique_id: "logger_device_state"
value_template: >-
{% set mapper = {
'1' : 'Online',
'2' : 'Failure',
'3' : 'Offline'} %}
{% set state = states.sensor.solarmanpv_logger.state %}
{{ mapper[state] if state in mapper else 'Unknown' }}
```### Templates
```yaml
template:- sensor:
- name: "Solarman energy daily"
unique_id: "solarman_energy_daily"
unit_of_measurement: 'kWh'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'Daily_Production_(Active)') }}"
device_class: energy
state_class: measurement
attributes:
last_reset: '1970-01-01T00:00:00+00:00'- sensor:
- name: solarmanpv_inverter_dc_voltage_pv1
unique_id: "solarmanpv_inverter_dc_voltage_pv1"
unit_of_measurement: 'V'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'DC_Voltage_PV1') }}"
state_class: measurement- sensor:
- name: solarmanpv_inverter_dc_current_pv1
unique_id: "solarmanpv_inverter_dc_current_pv1"
unit_of_measurement: 'A'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'DC_Current_PV1') }}"
state_class: measurement- sensor:
- name: solarmanpv_inverter_dc_voltage_testing
unique_id: "solarmanpv_inverter_dc_current_testing"
unit_of_measurement: 'V'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'DC_Voltage_PV1') }}"
state_class: measurement
unit_of_measurement: 'A'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'DC_Current_PV1') }}"
state_class: measurement- sensor:
- name: solarmanpv_inverter_dc_voltage_pv2
unique_id: " solarmanpv_inverter_dc_voltage_pv2"
unit_of_measurement: 'V'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'DC_Voltage_PV2') }}"
state_class: measurement- sensor:
- name: solarmanpv_inverter_dc_current_pv2
unique_id: "solarmanpv_inverter_dc_current_pv2"
unit_of_measurement: 'A'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'DC_Current_PV2') }}"
state_class: measurement- sensor:
- name: solarmanpv_inverter_dc_power_pv1
unique_id: "solarmanpv_inverter_dc_power_pv1"
unit_of_measurement: 'W'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'DC_Power_PV1') }}"
state_class: measurement- sensor:
- name: solarmanpv_inverter_dc_power_pv2
unique_id: "solarmanpv_inverter_dc_power_pv2"
unit_of_measurement: 'W'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'DC_Power_PV2') }}"
state_class: measurement- sensor:
- name: solarmanpv_inverter_total_production
unique_id: "solarmanpv_inverter_total_production"
unit_of_measurement: 'kWh'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'Cumulative_Production_(Active)') }}"
state_class: total_increasing- sensor:
- name: solarmanpv_inverter_daily_production
unique_id: "solarmanpv_inverter_daily_production"
unit_of_measurement: 'kWh'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'Daily_Production_(Active)') }}"
state_class: total_increasing- sensor:
- name: solarmanpv_inverter_ac_radiator_temp
unique_id: "solarmanpv_inverter_ac_radiator_temp"
unit_of_measurement: '°C'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'Temperature-_Inverter') }}"
state_class: measurement- sensor:
- name: solarmanpv_inverter_ac_voltage_1
unique_id: "solarmanpv_inverter_ac_voltage_1"
unit_of_measurement: 'V'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'AC_Voltage_R/U/A') }}"
state_class: measurement- sensor:
- name: solarmanpv_inverter_ac_current_1
unique_id: "solarmanpv_inverter_ac_current_1"
unit_of_measurement: 'A'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'AC_Current_R/U/A') }}"
state_class: measurement- sensor:
- name: solarmanpv_inverter_ac_voltage_2
unique_id: "solarmanpv_inverter_ac_volgage_2"
unit_of_measurement: 'V'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'AC_Voltage_S/V/B') }}"
state_class: measurement- sensor:
- name: solarmanpv_inverter_ac_current_2
unique_id: "solarmanpv_inverter_ac_current_2"
unit_of_measurement: 'A'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'AC_Current_S/V/B') }}"
state_class: measurement- sensor:
- name: solarmanpv_inverter_ac_voltage_3
unique_id: "solarmanpv_inverter_ac_voltage_3"
unit_of_measurement: 'V'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'AC_Voltage_T/W/C') }}"
state_class: measurement- sensor:
- name: solarmanpv_inverter_ac_current_3
unique_id: "solarmanpv_inverter_ac_current_3"
unit_of_measurement: 'A'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'AC_Current_T/W/C') }}"
state_class: measurement- sensor:
- name: solarmanpv_inverter_ac_output_frequency
unique_id: "solarmanpv_inverter_ac_output_frequency"
unit_of_measurement: 'Hz'
state: "{{ state_attr('sensor.solarmanpv_inverter', 'AC_Output_Frequency_R') }}"
state_class: measurement
```### Screenshot
![Screenshot](https://github.com/mpepping/solarman-mqtt/raw/main/doc/images/screenshot.png "Screenshot")
![Screenshot](https://github.com/mpepping/solarman-mqtt/raw/main/doc/images/screenshot_haenergy.png "Screenshot")## Running
The easiest way to run is via a container. Current version is available at
### Using Docker
Docker example to run this script every 5 minutes and providing a config file:
```bash
cd /opt
git clone https://github.com/mpepping/solarman-mqtt
cd solarman-mqtt
mv config.sample.json config.json # setup your config
sudo docker run --name solarman-mqtt -d --restart unless-stopped -v /opt/solarman-mqtt:/opt/app-root/src ghcr.io/mpepping/solarman-mqtt:latest
```### Using docker-compose
This `docker-compose.yml` example can be used with docker-compose or podman-compose
```yaml
version: '3'services:
solarman-mqtt:
image: ghcr.io/mpepping/solarman-mqtt:latest
container_name: "solarman-mqtt"
environment:
- TZ=Europe/Berlin
volumes:
- /opt/solarman-mqtt/config.json:/opt/app-root/src/config.json # or mount your complete config directory
restart: unless-stopped
```### Using Python
Run `pip install -r requirements.txt` and start `python3 run.py`.