mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-15 09:56:38 +02:00
Merge branch 'asyncWeb03' of https://github.com/grindylow/ahoy into asyncWeb03
This commit is contained in:
commit
c5fc9a6101
11 changed files with 264 additions and 74 deletions
|
@ -13,7 +13,7 @@ List of approaches
|
||||||
- [Others, C/C++](tools/nano/NRF24_SendRcv/)
|
- [Others, C/C++](tools/nano/NRF24_SendRcv/)
|
||||||
|
|
||||||
## Quick Start with ESP8266
|
## Quick Start with ESP8266
|
||||||
- [Go here ✨](https://github.com/grindylow/ahoy/blob/ahoy_v0.5.16/tools/esp8266/README.md#things-needed)
|
- [Go here ✨](tools/esp8266/README.md#things-needed)
|
||||||
|
|
||||||
|
|
||||||
## Success Stories
|
## Success Stories
|
||||||
|
|
|
@ -1,23 +1,30 @@
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Table of Contents](#table-of-contents)
|
||||||
- [Overview](#overview)
|
- [Overview](#overview)
|
||||||
- [Compatiblity](#compatiblity)
|
- [Compatiblity](#compatiblity)
|
||||||
- [Things needed](#things-needed)
|
- [Things needed](#things-needed)
|
||||||
+ [Faked Modules Warning](#there-are-fake-nrf24l01-modules-out-there)
|
- [There are fake NRF24L01+ Modules out there](#there-are-fake-nrf24l01-modules-out-there)
|
||||||
- [Wiring things up](#wiring-things-up)
|
- [Wiring things up](#wiring-things-up)
|
||||||
+ [ESP8266 wiring example](#esp8266-wiring-example)
|
- [ESP8266 wiring example](#esp8266-wiring-example)
|
||||||
|
- [Schematic](#schematic)
|
||||||
|
- [Symbolic view](#symbolic-view)
|
||||||
|
- [ESP32 wiring example](#esp32-wiring-example)
|
||||||
|
- [Schematic](#schematic-1)
|
||||||
|
- [Symbolic view](#symbolic-view-1)
|
||||||
|
- [ESP32 GPIO settings](#esp32-gpio-settings)
|
||||||
- [Flash the Firmware on your Ahoy DTU Hardware](#flash-the-firmware-on-your-ahoy-dtu-hardware)
|
- [Flash the Firmware on your Ahoy DTU Hardware](#flash-the-firmware-on-your-ahoy-dtu-hardware)
|
||||||
+ [Compiling your own Version (the geek way)](#compiling-your-own-version)
|
- [Compiling your own Version](#compiling-your-own-version)
|
||||||
- [Optional Configuration before compilation](#optional-configuration-before-compilation)
|
- [Optional Configuration before compilation](#optional-configuration-before-compilation)
|
||||||
+ [Using a ready-to-flash binary using nodemcu-pyflasher (the easy way)](#using-a-ready-to-flash-binary-using-nodemcu-pyflasher)
|
- [Using a ready-to-flash binary using nodemcu-pyflasher](#using-a-ready-to-flash-binary-using-nodemcu-pyflasher)
|
||||||
- [Connect to your Ahoy DTU](#connect-to-your-ahoy-dtu)
|
- [Connect to your Ahoy DTU](#connect-to-your-ahoy-dtu)
|
||||||
+ [Your Ahoy DTO is very verbose using the Serial Console](#your-ahoy-dto-is-very-verbose-using-the-serial-console)
|
- [Your Ahoy DTU is very verbose using the Serial Console](#your-ahoy-dtu-is-very-verbose-using-the-serial-console)
|
||||||
+ [Connect to the Ahoy DTU Webinterface using your Browser](#connect-to-the-ahoy-dtu-webinterface-using-your-browser)
|
- [Connect to the Ahoy DTU Webinterface using your Browser](#connect-to-the-ahoy-dtu-webinterface-using-your-browser)
|
||||||
- [HTTP based Pages](#http-based-pages)
|
- [HTTP based Pages](#http-based-pages)
|
||||||
- [MQTT command to set the DTU without webinterface](#mqtt-command-to-set-the-dtu-without-webinterface)
|
- [MQTT command to set the DTU without webinterface](#mqtt-command-to-set-the-dtu-without-webinterface)
|
||||||
- [Used Libraries](#used-libraries)
|
- [Used Libraries](#used-libraries)
|
||||||
- [Contact](#contact)
|
- [Contact](#contact)
|
||||||
- [ToDo's - remove when done](#todo)
|
- [ToDo](#todo)
|
||||||
|
|
||||||
***
|
***
|
||||||
|
|
||||||
|
@ -26,10 +33,14 @@
|
||||||
This page describes how the module of a Wemos D1 mini and ESP8266 is wired to the radio module and is flashed with the latest Firmware.<br/>
|
This page describes how the module of a Wemos D1 mini and ESP8266 is wired to the radio module and is flashed with the latest Firmware.<br/>
|
||||||
Further information will help you to communicate to the compatible inverters.
|
Further information will help you to communicate to the compatible inverters.
|
||||||
|
|
||||||
|
You find the full [User_Manual here](User_Manual.md)
|
||||||
|
|
||||||
## Compatiblity
|
## Compatiblity
|
||||||
|
|
||||||
For now the following Inverters should work out of the box:
|
For now the following Inverters should work out of the box:
|
||||||
|
|
||||||
Hoymiles Inverters
|
Hoymiles Inverters
|
||||||
|
|
||||||
- HM300
|
- HM300
|
||||||
- HM350
|
- HM350
|
||||||
- HM400
|
- HM400
|
||||||
|
@ -41,26 +52,46 @@ Hoymiles Inverters
|
||||||
- HM1500
|
- HM1500
|
||||||
|
|
||||||
TSun Inverters:
|
TSun Inverters:
|
||||||
|
|
||||||
- TSOL-350
|
- TSOL-350
|
||||||
- TSOL-400
|
- TSOL-400
|
||||||
- othery may work as well (need to be veryfied).
|
- others may work as well (need to be verified).
|
||||||
|
|
||||||
|
|
||||||
## Things needed
|
## Things needed
|
||||||
|
|
||||||
In order to build your own Ahoy DTU, you will need some things.<br/>
|
In order to build your own Ahoy DTU, you will need some things.<br/>
|
||||||
This list is not closing as the Maker Community offers more Boards than we could cover in this Readme.<br/><br/>
|
This list is not closing as the Maker Community offers more Boards than we could cover in this Readme.<br/><br/>
|
||||||
|
|
||||||
We suggest to use a WEMOS D1 mini Board as well as a NRF24L01+ Breakout Board.<br/>
|
We suggest to use a WEMOS D1 mini Board as well as a NRF24L01+ Breakout Board as a bare minimum.<br/>
|
||||||
Make sure it has the "+" in its name as we depend on some features provided with the plus-variant.<br/>
|
Any other ESP8266 Board with at least 4MBytes of ROM could work as well, depending on your skills and goals.<br/>
|
||||||
Any other ESP8266 Board with at least 4MBytes of ROM could work as well, depending on your skills.
|
Make sure the NRF24L01+ module has the "+" in its name as we depend on the 250kbps features provided only with the plus-variant.
|
||||||
|
|
||||||
|
| **Parts** | **Price** |
|
||||||
|
| --- | --- |
|
||||||
|
| D1 ESP8266 Mini WLAN Board Mikrokontroller | 4,40 Euro |
|
||||||
|
| NRF24L01+ SMD Modul 2,4 GHz Wi-Fi Funkmodul | 3,45 Euro |
|
||||||
|
| Jumper Wire Steckbrücken Steckbrett weiblich-weiblich | 2,49 Euro |
|
||||||
|
| **Total costs** | **10,34 Euro** |
|
||||||
|
|
||||||
|
To also run our sister project OpenDTU and be upwards compatible for the future we would recommend to spend some more money on an ESP32 board which has two CPU cores and a NRF24L01+ module with external antenna.
|
||||||
|
|
||||||
|
| **Parts** | **Price** |
|
||||||
|
| --- | --- |
|
||||||
|
| ESP32 Dev Board NodeMCU WROOM32 WiFi | 7,90 Euro |
|
||||||
|
| NRF24L01+ PA LNA SMA mit Antenne Long | 4,50 Euro |
|
||||||
|
| Jumper Wire Steckbrücken Steckbrett weiblich-weiblich | 2,49 Euro |
|
||||||
|
| **Total costs** | **14,89 Euro** |
|
||||||
|
|
||||||
#### There are fake NRF24L01+ Modules out there
|
#### There are fake NRF24L01+ Modules out there
|
||||||
Whatch out, there are some fake NRF24L01+ Modules out there that seem to use rebranded NRF24L01 Chips (without the +).<br/>
|
|
||||||
|
Watch out, there are some fake NRF24L01+ Modules out there that seem to use rebranded NRF24L01 Chips (without the +).<br/>
|
||||||
An example can be found in [Issue #230](https://github.com/grindylow/ahoy/issues/230).<br/>
|
An example can be found in [Issue #230](https://github.com/grindylow/ahoy/issues/230).<br/>
|
||||||
You are welcome to add more examples of faked chips. We will that information here.<br/>
|
You are welcome to add more examples of faked chips. We will add that information here.<br/>
|
||||||
|
|
||||||
## Wiring things up
|
## Wiring things up
|
||||||
|
|
||||||
The NRF24L01+ radio module is connected to the standard SPI pins:
|
The NRF24L01+ radio module is connected to the standard SPI pins:
|
||||||
|
|
||||||
- SCLK (Signal Clock),
|
- SCLK (Signal Clock),
|
||||||
- MISO (Master In Slave Out) and
|
- MISO (Master In Slave Out) and
|
||||||
- MOSI (Master Out Slave In)
|
- MOSI (Master Out Slave In)
|
||||||
|
@ -68,6 +99,7 @@ The NRF24L01+ radio module is connected to the standard SPI pins:
|
||||||
*These pins need to be configured in the config.h.*
|
*These pins need to be configured in the config.h.*
|
||||||
|
|
||||||
Additional, there are 3 pins, which can be set individual:
|
Additional, there are 3 pins, which can be set individual:
|
||||||
|
|
||||||
- CS (Chip Select),
|
- CS (Chip Select),
|
||||||
- CE (Chip Enable) and
|
- CE (Chip Enable) and
|
||||||
- IRQ (Interrupt)
|
- IRQ (Interrupt)
|
||||||
|
@ -75,23 +107,31 @@ Additional, there are 3 pins, which can be set individual:
|
||||||
*These pins can be changed from the /setup URL.*
|
*These pins can be changed from the /setup URL.*
|
||||||
|
|
||||||
#### ESP8266 wiring example
|
#### ESP8266 wiring example
|
||||||
|
|
||||||
This is an example wiring using a Wemos D1 mini.<br>
|
This is an example wiring using a Wemos D1 mini.<br>
|
||||||
|
|
||||||
##### Schematic
|
##### Schematic
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
##### Symbolic view
|
##### Symbolic view
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
#### ESP32 wiring example
|
#### ESP32 wiring example
|
||||||
|
|
||||||
Example wiring for a 38pin ESP32 module
|
Example wiring for a 38pin ESP32 module
|
||||||
|
|
||||||
##### Schematic
|
##### Schematic
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
##### Symbolic view
|
##### Symbolic view
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
##### ESP32 GPIO settings
|
##### ESP32 GPIO settings
|
||||||
|
|
||||||
For this wiring, set the 3 individual GPIOs under the /setup URL:
|
For this wiring, set the 3 individual GPIOs under the /setup URL:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -101,11 +141,12 @@ IRQ D0 (GPIO16 - no IRQ!)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Flash the Firmware on your Ahoy DTU Hardware
|
## Flash the Firmware on your Ahoy DTU Hardware
|
||||||
Once your Hardware is ready to run, you need to flash the Ahoy DTU Firmware to your Board.
|
|
||||||
You can either build your own using your own configuration or use one or our pre-compiled generic builds.
|
|
||||||
|
|
||||||
|
Once your Hardware is ready to run, you need to flash the Ahoy DTU Firmware to your Board.
|
||||||
|
You can either build your own using your own configuration or use one of our pre-compiled generic builds.
|
||||||
|
|
||||||
#### Compiling your own Version
|
#### Compiling your own Version
|
||||||
|
|
||||||
This information suits you if you want to configure and build your own firmware.
|
This information suits you if you want to configure and build your own firmware.
|
||||||
|
|
||||||
This code comes to you as a **PlatformIO** project and can be compiled using the **PlatformIO** Addon.<br/>
|
This code comes to you as a **PlatformIO** project and can be compiled using the **PlatformIO** Addon.<br/>
|
||||||
|
@ -116,75 +157,70 @@ If you do not want to compile your own build, you can use one of our ready-to-fl
|
||||||
|
|
||||||
- number of supported inverters (set to 3 by default) `config.h`
|
- number of supported inverters (set to 3 by default) `config.h`
|
||||||
- DTU radio id `config.h` (default = 1234567801)
|
- DTU radio id `config.h` (default = 1234567801)
|
||||||
- unformated list in webbrowser `/livedata` `config.h`, `LIVEDATA_VISUALIZED`
|
- unformatted list in webbrowser `/livedata` `config.h`, `LIVEDATA_VISUALIZED`
|
||||||
|
|
||||||
Alternativly, instead of modifying `config.h`, `config_override_example.h` can be copied to `config_override.h` and customized.
|
Alternativly, instead of modifying `config.h`, `config_override_example.h` can be copied to `config_override.h` and customized.
|
||||||
config_override.h is excluded from version control and stays local.
|
config_override.h is excluded from version control and stays local.
|
||||||
|
|
||||||
|
|
||||||
#### Using a ready-to-flash binary using nodemcu-pyflasher
|
#### Using a ready-to-flash binary using nodemcu-pyflasher
|
||||||
|
|
||||||
This information suits you if you just want to use an easy way.
|
This information suits you if you just want to use an easy way.
|
||||||
|
|
||||||
1. download the flash-tool [nodemcu-pyflasher](https://github.com/marcelstoer/nodemcu-pyflasher)
|
1. download the flash-tool [nodemcu-pyflasher](https://github.com/marcelstoer/nodemcu-pyflasher)
|
||||||
2. download latest release bin-file from [ahoy_](https://github.com/grindylow/ahoy/releases)
|
2. download latest release bin-file from [ahoy_](https://github.com/grindylow/ahoy/releases)
|
||||||
3. open flash-tool and connect the target device to your computer.
|
3. open flash-tool and connect the target device to your computer.
|
||||||
4. Set the correct serial port and select the correct *.bin file
|
4. Set the correct serial port and select the correct *.bin file
|
||||||
5. click on "Flash NodeMCU"
|
5. click on "Flash NodeMCU"
|
||||||
6. flash the ESP with the compiled firmware using the UART pins or
|
6. flash the ESP with the compiled firmware using the UART pins or
|
||||||
7. repower the ESP
|
7. repower the ESP
|
||||||
8. the ESP will start as access point (AP) if there is no network config stored in its eeprom
|
8. the ESP will start as access point (AP) if there is no network config stored in its eeprom
|
||||||
9. connect to the AP, you will be forwarded to the setup page
|
9. connect to the AP (password: `esp_8266`), you will be forwarded to the setup page
|
||||||
10. configure your WiFi settings, save, repower
|
10. configure your WiFi settings, save, repower
|
||||||
11. check your router or serial console for the IP address of the module. You can try ping the configured device name as well.
|
11. check your router or serial console for the IP address of the module. You can try ping the configured device name as well.
|
||||||
|
|
||||||
|
|
||||||
Once your Ahoy DTU is running, you can use the Over The Air (OTA) capabilities to update your firmware.
|
Once your Ahoy DTU is running, you can use the Over The Air (OTA) capabilities to update your firmware.
|
||||||
|
|
||||||
|
|
||||||
! ATTENTION: If you update from a very low version to the newest, please make sure to wipe all flash data!
|
! ATTENTION: If you update from a very low version to the newest, please make sure to wipe all flash data!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Connect to your Ahoy DTU
|
## Connect to your Ahoy DTU
|
||||||
|
|
||||||
When everything is wired up and the firmware is flashed, it is time to connect to your Ahoy DTU.
|
When everything is wired up and the firmware is flashed, it is time to connect to your Ahoy DTU.
|
||||||
|
|
||||||
|
|
||||||
#### Your Ahoy DTU is very verbose using the Serial Console
|
#### Your Ahoy DTU is very verbose using the Serial Console
|
||||||
|
|
||||||
When connected to your computer, you can open a Serial Console to obtain additional information.<br/>
|
When connected to your computer, you can open a Serial Console to obtain additional information.<br/>
|
||||||
This might be useful in case of any troubles that might occur as well as to simply<br/>
|
This might be useful in case of any troubles that might occur as well as to simply<br/>
|
||||||
obtain information about the converted values which were read out of the inverter(s).
|
obtain information about the converted values which were read out of the inverter(s).
|
||||||
|
|
||||||
|
|
||||||
#### Connect to the Ahoy DTU Webinterface using your Browser
|
#### Connect to the Ahoy DTU Webinterface using your Browser
|
||||||
|
|
||||||
After you have sucessfully flashed and powered your Ahoy DTU, you can access it via your Browser.<br/>
|
After you have sucessfully flashed and powered your Ahoy DTU, you can access it via your Browser.<br/>
|
||||||
If your Ahoy DTU was able to log into the configured WiFi Network, it will try to obtain an IP-Address<br/>
|
If your Ahoy DTU was able to log into the configured WiFi Network, it will try to obtain an IP-Address<br/>
|
||||||
from your local DHCP Server (in most cases thats your Router).<br/><br/>
|
from your local DHCP Server (in most cases thats your Router).<br/><br/>
|
||||||
In case it could not connect to your configured Network, it will provide its own WiFi Network that you can<br/>
|
In case it could not connect to your configured Network, it will provide its own WiFi Network that you can<br/>
|
||||||
connect to for furter configuration.<br/>
|
connect to for furter configuration.<br/>
|
||||||
The WiFi SSID *(the WiFi Name)* and Passwort is configured in the config.h and defaults to the SSID "AHOY-DTU" with the Passwort "esp_8266".<br/>
|
The WiFi SSID *(the WiFi Name)* and Passwort is configured in the config.h and defaults to the SSID "`AHOY-DTU`" with the Passwort "`esp_8266`".<br/>
|
||||||
The Ahoy DTU will keep that Network open for a certain amount of time (also configurable in the config.h and defaults to 60secs).<br/>
|
The Ahoy DTU will keep that Network open for a certain amount of time (also configurable in the config.h and defaults to 60secs).<br/>
|
||||||
If nothing connects to it and that time runs up, it will retry to connect to the configured network an so on.<br/>
|
If nothing connects to it and that time runs up, it will retry to connect to the configured network an so on.<br/>
|
||||||
<br/>
|
<br/>
|
||||||
If connected to your local Network, you just have to find out the used IP Address. In most cases your Router will give you a hint.<br/>
|
If connected to your local Network, you just have to find out the used IP Address or try the default name [http://ahoy-dtu/](http://ahoy-dtu/). In most cases your Router will give you a hint.<br/>
|
||||||
If you connect to the WiFi the Ahoy DTU opens in case it could not connect to any other Network, the IP-Address of your Ahoy DTU is 192.168.1.1.<br/>
|
If you connect to the WiFi the Ahoy DTU opens in case it could not connect to any other Network, the IP-Address of your Ahoy DTU is [http://192.168.1.1/](http://192.168.1.1/).<br/>
|
||||||
Just open the IP-Address in your browser.<br/>
|
Just open the IP-Address in your browser.<br/>
|
||||||
<br/>
|
<br/>
|
||||||
The webinterface has the following abilities:
|
The webinterface has the following abilities:
|
||||||
|
|
||||||
- OTA Update (Over The Air Update)
|
- OTA Update (Over The Air Update)
|
||||||
- Configuration (Wifi, inverter(s), NTP Server, Pinout, MQTT, Amplifier Power Level, Debug)
|
- Configuration (Wifi, inverter(s), NTP Server, Pinout, MQTT, Amplifier Power Level, Debug)
|
||||||
- visual display of the connected inverters / modules
|
- visual display of the connected inverters / modules
|
||||||
- some statistics about communication (debug)
|
- some statistics about communication (debug)
|
||||||
|
|
||||||
|
|
||||||
##### HTTP based Pages
|
##### HTTP based Pages
|
||||||
To take control of your Ahoy DTU, you can directly call one of the following sub-pages (e.g. http://192.168.1.1/setup ).<br/>
|
|
||||||
|
To take control of your Ahoy DTU, you can directly call one of the following sub-pages (e.g. [http://ahoy-dtu/setup](http://ahoy-dtu/setup) or [http://192.168.1.1/setup](http://192.168.1.1/setup) ).<br/>
|
||||||
|
|
||||||
| page | use | output |
|
| page | use | output |
|
||||||
| ---- | ------ | ------ |
|
| ---- | ------ | ------ |
|
||||||
| /uptime | displays the uptime uf your Ahoy DTU | 0 Days, 01:37:34; now: 2022-08-21 11:13:53 |
|
| /uptime | displays the uptime of your Ahoy DTU | 0 Days, 01:37:34; now: 2022-08-21 11:13:53 |
|
||||||
| /reboot | reboots the Ahoy DTU | |
|
| /reboot | reboots the Ahoy DTU | |
|
||||||
| /erase | erases the EEPROM | |
|
| /erase | erases the EEPROM | |
|
||||||
| /factory | resets to the factory defaults configured in config.h | |
|
| /factory | resets to the factory defaults configured in config.h | |
|
||||||
|
@ -196,14 +232,11 @@ When everything is wired up and the firmware is flashed, it is time to connect t
|
||||||
| /json | gets live-data in JSON format | json output from the livedata |
|
| /json | gets live-data in JSON format | json output from the livedata |
|
||||||
| /api | | |
|
| /api | | |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## MQTT command to set the DTU without webinterface
|
## MQTT command to set the DTU without webinterface
|
||||||
[Read here](https://github.com/grindylow/ahoy/blob/main/tools/esp8266/User_Manual.md)
|
|
||||||
|
|
||||||
|
[Read here](tools/esp8266/User_Manual.md)
|
||||||
|
|
||||||
|
## Used Libraries
|
||||||
## Used Libraries
|
|
||||||
|
|
||||||
| Name | version | License |
|
| Name | version | License |
|
||||||
| --------------------- | ------- | -------- |
|
| --------------------- | ------- | -------- |
|
||||||
|
@ -219,14 +252,12 @@ When everything is wired up and the firmware is flashed, it is time to connect t
|
||||||
| `PubSubClient` | 2.8 | MIT |
|
| `PubSubClient` | 2.8 | MIT |
|
||||||
| `ArduinoJson` | 6.19.4 | MIT |
|
| `ArduinoJson` | 6.19.4 | MIT |
|
||||||
|
|
||||||
|
|
||||||
## Contact
|
## Contact
|
||||||
|
|
||||||
We run a Discord Server that can be used to get in touch with the Developers and Users.
|
We run a Discord Server that can be used to get in touch with the Developers and Users.
|
||||||
|
|
||||||
https://discord.gg/WzhxEY62mB
|
<https://discord.gg/WzhxEY62mB>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## ToDo
|
## ToDo
|
||||||
|
|
||||||
[See this post](https://github.com/grindylow/ahoy/issues/142)
|
[See this post](https://github.com/lumapu/ahoy/issues/142)
|
||||||
|
|
|
@ -237,6 +237,8 @@ Gather user inverter information here to understand what differs between some in
|
||||||
| setje | HM-600 | | 1.0.08 | 2020 | 07-10 | 104 | | |
|
| setje | HM-600 | | 1.0.08 | 2020 | 07-10 | 104 | | |
|
||||||
| madmartin | HM-600 | 0.1.4 | 1.0.10 | 2021 | 11-01 | 104 | | |
|
| madmartin | HM-600 | 0.1.4 | 1.0.10 | 2021 | 11-01 | 104 | | |
|
||||||
| lumapu | HM-1200 | 0.1.0 | 1.0.12 | 2020 | 06-24 | | | |
|
| lumapu | HM-1200 | 0.1.0 | 1.0.12 | 2020 | 06-24 | | | |
|
||||||
|
| chehrlic | HM-600 | | 1.0.10 | 2021 | 11-01 | 104 | | |
|
||||||
|
| chehrlic | TSOL-M800de | | 1.0.10 | 2021 | 11-01 | 104 | | |
|
||||||
| | | | | | | | | |
|
| | | | | | | | | |
|
||||||
| | | | | | | | | |
|
| | | | | | | | | |
|
||||||
|
|
||||||
|
|
|
@ -390,7 +390,7 @@ void app::processPayload(bool retransmit) {
|
||||||
// MQTT send out
|
// MQTT send out
|
||||||
if(mMqttActive) {
|
if(mMqttActive) {
|
||||||
record_t<> *recRealtime = iv->getRecordStruct(RealTimeRunData_Debug);
|
record_t<> *recRealtime = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||||
char topic[30], val[10];
|
char topic[32 + MAX_NAME_LENGTH], val[32];
|
||||||
float total[4];
|
float total[4];
|
||||||
memset(total, 0, sizeof(float) * 4);
|
memset(total, 0, sizeof(float) * 4);
|
||||||
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
|
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
|
||||||
|
@ -398,7 +398,7 @@ void app::processPayload(bool retransmit) {
|
||||||
if (NULL != iv) {
|
if (NULL != iv) {
|
||||||
if (iv->isAvailable(mTimestamp, rec)) {
|
if (iv->isAvailable(mTimestamp, rec)) {
|
||||||
for (uint8_t i = 0; i < rec->length; i++) {
|
for (uint8_t i = 0; i < rec->length; i++) {
|
||||||
snprintf(topic, 30, "%s/ch%d/%s", iv->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]);
|
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]);
|
||||||
snprintf(val, 10, "%.3f", iv->getValue(i, rec));
|
snprintf(val, 10, "%.3f", iv->getValue(i, rec));
|
||||||
mMqtt.sendMsg(topic, val);
|
mMqtt.sendMsg(topic, val);
|
||||||
if(recRealtime == rec) {
|
if(recRealtime == rec) {
|
||||||
|
@ -411,10 +411,31 @@ void app::processPayload(bool retransmit) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(iv->isProducing(mTimestamp, rec)){
|
||||||
|
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available_text", iv->name);
|
||||||
|
snprintf(val, 32, DEF_MQTT_IV_MESSAGE_INVERTER_AVAIL_AND_PRODUCED);
|
||||||
|
mMqtt.sendMsg(topic, val);
|
||||||
|
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->name);
|
||||||
|
snprintf(val, 32, "2");
|
||||||
|
mMqtt.sendMsg(topic, val);
|
||||||
|
} else {
|
||||||
|
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available_text", iv->name);
|
||||||
|
snprintf(val, 32, DEF_MQTT_IV_MESSAGE_INVERTER_AVAIL_AND_NOT_PRODUCED);
|
||||||
|
mMqtt.sendMsg(topic, val);
|
||||||
|
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->name);
|
||||||
|
snprintf(val, 32, "1");
|
||||||
|
mMqtt.sendMsg(topic, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->name);
|
||||||
|
snprintf(val, 48, "%i", iv->getLastTs(rec) * 1000);
|
||||||
|
mMqtt.sendMsg(topic, val);
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// total values (sum of all inverters)
|
// total values (sum of all inverters)
|
||||||
|
@ -428,7 +449,7 @@ void app::processPayload(bool retransmit) {
|
||||||
case 2: fieldId = FLD_YD; break;
|
case 2: fieldId = FLD_YD; break;
|
||||||
case 3: fieldId = FLD_PDC; break;
|
case 3: fieldId = FLD_PDC; break;
|
||||||
}
|
}
|
||||||
snprintf(topic, 30, "total/%s", fields[fieldId]);
|
snprintf(topic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]);
|
||||||
snprintf(val, 10, "%.3f", total[i]);
|
snprintf(val, 10, "%.3f", total[i]);
|
||||||
mMqtt.sendMsg(topic, val);
|
mMqtt.sendMsg(topic, val);
|
||||||
}
|
}
|
||||||
|
@ -446,6 +467,20 @@ void app::processPayload(bool retransmit) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mMqttActive) {
|
||||||
|
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||||
|
char topic[32 + MAX_NAME_LENGTH], val[32];
|
||||||
|
if (!iv->isAvailable(mTimestamp, rec) && !iv->isProducing(mTimestamp, rec)){
|
||||||
|
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available_text", iv->name);
|
||||||
|
snprintf(val, 32, DEF_MQTT_IV_MESSAGE_NOT_AVAIL_AND_NOT_PRODUCED);
|
||||||
|
mMqtt.sendMsg(topic, val);
|
||||||
|
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->name);
|
||||||
|
snprintf(val, 32, "0");
|
||||||
|
mMqtt.sendMsg(topic, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,6 +108,11 @@
|
||||||
// default MQTT topic
|
// default MQTT topic
|
||||||
#define DEF_MQTT_TOPIC "inverter"
|
#define DEF_MQTT_TOPIC "inverter"
|
||||||
|
|
||||||
|
//default MQTT Message Inverter Status
|
||||||
|
#define DEF_MQTT_IV_MESSAGE_NOT_AVAIL_AND_NOT_PRODUCED "not available and not producing" // STATUS 0
|
||||||
|
#define DEF_MQTT_IV_MESSAGE_INVERTER_AVAIL_AND_NOT_PRODUCED "available and not producing" // STATUS 1
|
||||||
|
#define DEF_MQTT_IV_MESSAGE_INVERTER_AVAIL_AND_PRODUCED "available and producing" // STATUS 2
|
||||||
|
|
||||||
#if __has_include("config_override.h")
|
#if __has_include("config_override.h")
|
||||||
#include "config_override.h"
|
#include "config_override.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
9
tools/homeassistant/README.md
Normal file
9
tools/homeassistant/README.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# HomeAssistant Examples
|
||||||
|
|
||||||
|
Disclaimer: these are collected examples from https://www.mikrocontroller.net/topic/525778 (Page 12)
|
||||||
|
|
||||||
|
in manual.yaml you will find the setup for manual configuration, adapt your name (Terrasse) and the topic (inverter) to your needs and place it into configuration.yaml
|
||||||
|
|
||||||
|
in autodiscovery.yaml you will find the setup for automatic discovery of the inverter
|
||||||
|
|
||||||
|
Note: the config might need adaption to your system (mqtt, homeassistant etc)
|
4
tools/homeassistant/autodiscovery.yaml
Normal file
4
tools/homeassistant/autodiscovery.yaml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
mqtt:
|
||||||
|
broker: http://<IP des Brokers>
|
||||||
|
discovery: true
|
||||||
|
discovery_prefix: inverter
|
23
tools/homeassistant/manual.yaml
Normal file
23
tools/homeassistant/manual.yaml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
sensor:
|
||||||
|
- platform: mqtt
|
||||||
|
state_topic: "inverter/Terrasse/ch0/P_AC"
|
||||||
|
name: "Aktuelle Produktion HM-600"
|
||||||
|
device_class: energy
|
||||||
|
unit_of_measurement: "Watt"
|
||||||
|
value_template: >
|
||||||
|
{{value|round(2)}}
|
||||||
|
state_class: total_increasing
|
||||||
|
unique_id: "current_hm600"
|
||||||
|
last_reset_topic: "inverter/Terrasse/ch0/P_AC"
|
||||||
|
last_reset_value_template: "1970-01-01T00:00:00+00:00"
|
||||||
|
- platform: mqtt
|
||||||
|
state_topic: "inverter/Terrasse/ch0/YieldTotal"
|
||||||
|
name: "Gesamtproduktion HM-600"
|
||||||
|
device_class: energy
|
||||||
|
unit_of_measurement: "KW/H"
|
||||||
|
value_template: >
|
||||||
|
{{value|round(2)}}
|
||||||
|
state_class: total_increasing
|
||||||
|
unique_id: "total_hm600"
|
||||||
|
last_reset_topic: "inverter/Terrasse/ch0/YieldTotal"
|
||||||
|
last_reset_value_template: "1970-01-01T00:00:00+00:00"
|
|
@ -482,21 +482,24 @@ def compose_esb_packet(packet, mtu=17, **params):
|
||||||
fragment = compose_esb_fragment(packet[i:i+mtu], **params)
|
fragment = compose_esb_fragment(packet[i:i+mtu], **params)
|
||||||
yield fragment
|
yield fragment
|
||||||
|
|
||||||
def compose_set_time_payload(timestamp=None):
|
def compose_send_time_payload(cmdId, alarm_id=0):
|
||||||
"""
|
"""
|
||||||
Build set time request packet
|
Build set time request packet
|
||||||
|
|
||||||
:param timestamp: time to set (default: int(time.time()) )
|
:param cmd to request
|
||||||
:type timestamp: int
|
:type cmd: uint8
|
||||||
:return: payload
|
:return: payload
|
||||||
:rtype: bytes
|
:rtype: bytes
|
||||||
"""
|
"""
|
||||||
if not timestamp:
|
timestamp = int(time.time())
|
||||||
timestamp = int(time.time())
|
|
||||||
|
|
||||||
payload = b'\x0b\x00'
|
# indices from esp8266 hmRadio.h / sendTimePacket()
|
||||||
payload = payload + struct.pack('>L', timestamp) # big-endian: msb at low address
|
payload = struct.pack('>B', cmdId) # 10
|
||||||
payload = payload + b'\x00\x00\x00\x05\x00\x00\x00\x00'
|
payload = payload + b'\x00' # 11
|
||||||
|
payload = payload + struct.pack('>L', timestamp) # 12..15 big-endian: msb at low address
|
||||||
|
payload = payload + b'\x00\x00' # 16..17
|
||||||
|
payload = payload + struct.pack('>H', alarm_id) # 18..19
|
||||||
|
payload = payload + b'\x00\x00\x00\x00' # 20..23
|
||||||
|
|
||||||
return frame_payload(payload)
|
return frame_payload(payload)
|
||||||
|
|
||||||
|
@ -649,7 +652,7 @@ class InverterTransaction:
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
seq_last = max(frames, key=lambda frame:frame.seq).seq if len(frames) else 0
|
seq_last = max(frames, key=lambda frame:frame.seq).seq if len(frames) else 0
|
||||||
self.__retransmit_frame(seq_last + 1)
|
self.__retransmit_frame(seq_last + 1)
|
||||||
raise BufferError(f'Missing packet: Last packet {len(self.scratch)}')
|
raise BufferError(f'Missing packet: Last packet {seq_last + 1}')
|
||||||
|
|
||||||
# Rebuild payload from unordered frames
|
# Rebuild payload from unordered frames
|
||||||
payload = b''
|
payload = b''
|
||||||
|
|
|
@ -7,6 +7,7 @@ Hoymiles micro-inverters main application
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import struct
|
import struct
|
||||||
|
from enum import IntEnum
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
@ -16,7 +17,7 @@ from yaml.loader import SafeLoader
|
||||||
import paho.mqtt.client
|
import paho.mqtt.client
|
||||||
import hoymiles
|
import hoymiles
|
||||||
|
|
||||||
def main_loop():
|
def main_loop(do_init):
|
||||||
"""Main loop"""
|
"""Main loop"""
|
||||||
inverters = [
|
inverters = [
|
||||||
inverter for inverter in ahoy_config.get('inverters', [])
|
inverter for inverter in ahoy_config.get('inverters', [])
|
||||||
|
@ -25,9 +26,29 @@ def main_loop():
|
||||||
for inverter in inverters:
|
for inverter in inverters:
|
||||||
if hoymiles.HOYMILES_DEBUG_LOGGING:
|
if hoymiles.HOYMILES_DEBUG_LOGGING:
|
||||||
print(f'Poll inverter {inverter["serial"]}')
|
print(f'Poll inverter {inverter["serial"]}')
|
||||||
poll_inverter(inverter)
|
poll_inverter(inverter, do_init)
|
||||||
|
|
||||||
def poll_inverter(inverter, retries=4):
|
class InfoCommands(IntEnum):
|
||||||
|
InverterDevInform_Simple = 0 # 0x00
|
||||||
|
InverterDevInform_All = 1 # 0x01
|
||||||
|
GridOnProFilePara = 2 # 0x02
|
||||||
|
HardWareConfig = 3 # 0x03
|
||||||
|
SimpleCalibrationPara = 4 # 0x04
|
||||||
|
SystemConfigPara = 5 # 0x05
|
||||||
|
RealTimeRunData_Debug = 11 # 0x0b
|
||||||
|
RealTimeRunData_Reality = 12 # 0x0c
|
||||||
|
RealTimeRunData_A_Phase = 13 # 0x0d
|
||||||
|
RealTimeRunData_B_Phase = 14 # 0x0e
|
||||||
|
RealTimeRunData_C_Phase = 15 # 0x0f
|
||||||
|
AlarmData = 17 # 0x11, Alarm data - all unsent alarms
|
||||||
|
AlarmUpdate = 18 # 0x12, Alarm data - all pending alarms
|
||||||
|
RecordData = 19 # 0x13
|
||||||
|
InternalData = 20 # 0x14
|
||||||
|
GetLossRate = 21 # 0x15
|
||||||
|
GetSelfCheckState = 30 # 0x1e
|
||||||
|
InitDataState = 0xff
|
||||||
|
|
||||||
|
def poll_inverter(inverter, do_init, retries=4):
|
||||||
"""
|
"""
|
||||||
Send/Receive command_queue, initiate status poll on inverter
|
Send/Receive command_queue, initiate status poll on inverter
|
||||||
|
|
||||||
|
@ -39,11 +60,15 @@ def poll_inverter(inverter, retries=4):
|
||||||
dtu_ser = ahoy_config.get('dtu', {}).get('serial')
|
dtu_ser = ahoy_config.get('dtu', {}).get('serial')
|
||||||
|
|
||||||
# Queue at least status data request
|
# Queue at least status data request
|
||||||
command_queue[str(inverter_ser)].append(hoymiles.compose_set_time_payload())
|
inv_str = str(inverter_ser)
|
||||||
|
if do_init:
|
||||||
|
command_queue[inv_str].append(hoymiles.compose_send_time_payload(InfoCommands.InverterDevInform_All))
|
||||||
|
# command_queue[inv_str].append(hoymiles.compose_send_time_payload(InfoCommands.SystemConfigPara))
|
||||||
|
command_queue[inv_str].append(hoymiles.compose_send_time_payload(InfoCommands.RealTimeRunData_Debug))
|
||||||
|
|
||||||
# Putt all queued commands for current inverter on air
|
# Put all queued commands for current inverter on air
|
||||||
while len(command_queue[str(inverter_ser)]) > 0:
|
while len(command_queue[inv_str]) > 0:
|
||||||
payload = command_queue[str(inverter_ser)].pop(0)
|
payload = command_queue[inv_str].pop(0)
|
||||||
|
|
||||||
# Send payload {ttl}-times until we get at least one reponse
|
# Send payload {ttl}-times until we get at least one reponse
|
||||||
payload_ttl = retries
|
payload_ttl = retries
|
||||||
|
@ -95,6 +120,11 @@ def poll_inverter(inverter, retries=4):
|
||||||
string_id = string_id + 1
|
string_id = string_id + 1
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
if 'event_count' in data:
|
||||||
|
if event_message_index[inv_str] < data['event_count']:
|
||||||
|
event_message_index[inv_str] = data['event_count']
|
||||||
|
command_queue[inv_str].append(hoymiles.compose_send_time_payload(InfoCommands.AlarmData, alarm_id=event_message_index[inv_str]))
|
||||||
|
|
||||||
if mqtt_client:
|
if mqtt_client:
|
||||||
mqtt_send_status(mqtt_client, inverter_ser, data,
|
mqtt_send_status(mqtt_client, inverter_ser, data,
|
||||||
topic=inverter.get('mqtt', {}).get('topic', None))
|
topic=inverter.get('mqtt', {}).get('topic', None))
|
||||||
|
@ -219,6 +249,7 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
mqtt_client = None
|
mqtt_client = None
|
||||||
|
|
||||||
|
event_message_index = {}
|
||||||
command_queue = {}
|
command_queue = {}
|
||||||
mqtt_command_topic_subs = []
|
mqtt_command_topic_subs = []
|
||||||
|
|
||||||
|
@ -261,7 +292,9 @@ if __name__ == '__main__':
|
||||||
g_inverters = [g_inverter.get('serial') for g_inverter in ahoy_config.get('inverters', [])]
|
g_inverters = [g_inverter.get('serial') for g_inverter in ahoy_config.get('inverters', [])]
|
||||||
for g_inverter in ahoy_config.get('inverters', []):
|
for g_inverter in ahoy_config.get('inverters', []):
|
||||||
g_inverter_ser = g_inverter.get('serial')
|
g_inverter_ser = g_inverter.get('serial')
|
||||||
command_queue[str(g_inverter_ser)] = []
|
inv_str = str(g_inverter_ser)
|
||||||
|
command_queue[inv_str] = []
|
||||||
|
event_message_index[inv_str] = 0
|
||||||
|
|
||||||
#
|
#
|
||||||
# Enables and subscribe inverter to mqtt /command-Topic
|
# Enables and subscribe inverter to mqtt /command-Topic
|
||||||
|
@ -276,10 +309,13 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
loop_interval = ahoy_config.get('interval', 1)
|
loop_interval = ahoy_config.get('interval', 1)
|
||||||
try:
|
try:
|
||||||
|
do_init = True
|
||||||
while True:
|
while True:
|
||||||
t_loop_start = time.time()
|
t_loop_start = time.time()
|
||||||
|
|
||||||
main_loop()
|
main_loop(do_init)
|
||||||
|
|
||||||
|
do_init = False
|
||||||
|
|
||||||
print('', end='', flush=True)
|
print('', end='', flush=True)
|
||||||
|
|
||||||
|
|
|
@ -294,10 +294,12 @@ class EventsResponse(UnknownResponse):
|
||||||
|
|
||||||
crc_valid = self.validate_crc_m()
|
crc_valid = self.validate_crc_m()
|
||||||
if crc_valid:
|
if crc_valid:
|
||||||
print(' payload has valid modbus crc')
|
#print(' payload has valid modbus crc')
|
||||||
self.response = self.response[:-2]
|
self.response = self.response[:-2]
|
||||||
|
|
||||||
status = self.response[:2]
|
status = struct.unpack('>H', self.response[:2])[0]
|
||||||
|
a_text = self.alarm_codes.get(status, 'N/A')
|
||||||
|
print (f' Inverter status: {a_text} ({status})')
|
||||||
|
|
||||||
chunk_size = 12
|
chunk_size = 12
|
||||||
for i_chunk in range(2, len(self.response), chunk_size):
|
for i_chunk in range(2, len(self.response), chunk_size):
|
||||||
|
@ -314,6 +316,28 @@ class EventsResponse(UnknownResponse):
|
||||||
print(f' {fmt:7}: ' + str(struct.unpack('>' + fmt, chunk)))
|
print(f' {fmt:7}: ' + str(struct.unpack('>' + fmt, chunk)))
|
||||||
print(end='', flush=True)
|
print(end='', flush=True)
|
||||||
|
|
||||||
|
class HardwareInfoResponse(UnknownResponse):
|
||||||
|
def __init__(self, *args, **params):
|
||||||
|
super().__init__(*args, **params)
|
||||||
|
"""
|
||||||
|
const byteAssign_t InfoAssignment[] = {
|
||||||
|
{ FLD_FW_VERSION, UNIT_NONE, CH0, 0, 2, 1 },
|
||||||
|
{ FLD_FW_BUILD_YEAR, UNIT_NONE, CH0, 2, 2, 1 },
|
||||||
|
{ FLD_FW_BUILD_MONTH_DAY, UNIT_NONE, CH0, 4, 2, 1 },
|
||||||
|
{ FLD_HW_ID, UNIT_NONE, CH0, 8, 2, 1 }
|
||||||
|
};
|
||||||
|
self.response = bytes('\x27\x1a\x07\xe5\x04\x4d\x03\x4a\x00\x68\x00\x00\x00\x00\xe6\xfb', 'latin1')
|
||||||
|
"""
|
||||||
|
fw_version, fw_build_yyyy, fw_build_mmdd, unknown, hw_id = struct.unpack('>HHHHH', self.response[0:10])
|
||||||
|
|
||||||
|
fw_version_maj = int((fw_version / 10000))
|
||||||
|
fw_version_min = int((fw_version % 10000) / 100)
|
||||||
|
fw_version_pat = int((fw_version % 100))
|
||||||
|
fw_build_mm = int(fw_build_mmdd / 100)
|
||||||
|
fw_build_dd = int(fw_build_mmdd % 100)
|
||||||
|
print()
|
||||||
|
print(f'Firmware: {fw_version_maj}.{fw_version_min}.{fw_version_pat} build at {fw_build_dd}/{fw_build_mm}/{fw_build_yyyy}, HW revision {hw_id}')
|
||||||
|
|
||||||
class DebugDecodeAny(UnknownResponse):
|
class DebugDecodeAny(UnknownResponse):
|
||||||
"""Default decoder"""
|
"""Default decoder"""
|
||||||
|
|
||||||
|
@ -359,6 +383,9 @@ class DebugDecodeAny(UnknownResponse):
|
||||||
|
|
||||||
|
|
||||||
# 1121-Series Intervers, 1 MPPT, 1 Phase
|
# 1121-Series Intervers, 1 MPPT, 1 Phase
|
||||||
|
class Hm300Decode01(HardwareInfoResponse):
|
||||||
|
""" Firmware version / date """
|
||||||
|
|
||||||
class Hm300Decode02(EventsResponse):
|
class Hm300Decode02(EventsResponse):
|
||||||
""" Inverter generic events log """
|
""" Inverter generic events log """
|
||||||
|
|
||||||
|
@ -407,6 +434,9 @@ class Hm300Decode0B(StatusResponse):
|
||||||
""" Inverter temperature in °C """
|
""" Inverter temperature in °C """
|
||||||
return self.unpack('>H', 26)[0]/10
|
return self.unpack('>H', 26)[0]/10
|
||||||
|
|
||||||
|
class Hm300Decode0C(Hm300Decode0B):
|
||||||
|
""" 1121-series mirco-inverters status data """
|
||||||
|
|
||||||
class Hm300Decode11(EventsResponse):
|
class Hm300Decode11(EventsResponse):
|
||||||
""" Inverter generic events log """
|
""" Inverter generic events log """
|
||||||
|
|
||||||
|
@ -415,6 +445,9 @@ class Hm300Decode12(EventsResponse):
|
||||||
|
|
||||||
|
|
||||||
# 1141-Series Inverters, 2 MPPT, 1 Phase
|
# 1141-Series Inverters, 2 MPPT, 1 Phase
|
||||||
|
class Hm600Decode01(HardwareInfoResponse):
|
||||||
|
""" Firmware version / date """
|
||||||
|
|
||||||
class Hm600Decode02(EventsResponse):
|
class Hm600Decode02(EventsResponse):
|
||||||
""" Inverter generic events log """
|
""" Inverter generic events log """
|
||||||
|
|
||||||
|
@ -492,6 +525,9 @@ class Hm600Decode0B(StatusResponse):
|
||||||
""" Event counter """
|
""" Event counter """
|
||||||
return self.unpack('>H', 40)[0]
|
return self.unpack('>H', 40)[0]
|
||||||
|
|
||||||
|
class Hm600Decode0C(Hm600Decode0B):
|
||||||
|
""" 1141-series mirco-inverters status data """
|
||||||
|
|
||||||
class Hm600Decode11(EventsResponse):
|
class Hm600Decode11(EventsResponse):
|
||||||
""" Inverter generic events log """
|
""" Inverter generic events log """
|
||||||
|
|
||||||
|
@ -500,6 +536,9 @@ class Hm600Decode12(EventsResponse):
|
||||||
|
|
||||||
|
|
||||||
# 1161-Series Inverters, 2 MPPT, 1 Phase
|
# 1161-Series Inverters, 2 MPPT, 1 Phase
|
||||||
|
class Hm1200Decode01(HardwareInfoResponse):
|
||||||
|
""" Firmware version / date """
|
||||||
|
|
||||||
class Hm1200Decode02(EventsResponse):
|
class Hm1200Decode02(EventsResponse):
|
||||||
""" Inverter generic events log """
|
""" Inverter generic events log """
|
||||||
|
|
||||||
|
@ -619,6 +658,9 @@ class Hm1200Decode0B(StatusResponse):
|
||||||
""" Event counter """
|
""" Event counter """
|
||||||
return self.unpack('>H', 60)[0]
|
return self.unpack('>H', 60)[0]
|
||||||
|
|
||||||
|
class Hm1200Decode0C(Hm1200Decode0B):
|
||||||
|
""" 1161-series mirco-inverters status data """
|
||||||
|
|
||||||
class Hm1200Decode11(EventsResponse):
|
class Hm1200Decode11(EventsResponse):
|
||||||
""" Inverter generic events log """
|
""" Inverter generic events log """
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue