Browse Source

Merge branch 'development03' into asyncWeb03

pull/283/head
lumapu 2 years ago
parent
commit
bd93622d8f
  1. 39
      README.md
  2. BIN
      doc/Wiring_ESP32_Schematic.png
  3. BIN
      doc/Wiring_ESP32_Symbol.png
  4. 22
      tools/esp8266/README.md
  5. 2
      tools/rpi/ahoy.yml.example
  6. 2
      tools/rpi/hoymiles/__init__.py
  7. 54
      tools/rpi/hoymiles/outputs.py

39
README.md

@ -1,28 +1,35 @@
![actions/workflows/compile_esp8266.yml](../../actions/workflows/compile_esp8266.yml/badge.svg) ![actions/workflows/compile_development.yml](../../actions/workflows/compile_development.yml/badge.svg)
# 🖐 Ahoy!
![Logo](https://github.com/grindylow/ahoy/blob/main/doc/logo1_small.png?raw=true)
# ahoy
Ahoy is a project to bypass the original Hoymiles cloud solution.
In order to use this project, it is important what the area of ​​​​application looks like.
With each version it is necessary to have an NRF24L01+.
**Communicate with Hoymiles inverters via radio**. Get actual values like power, current, daily energy and set parameters like the power limit via web interface or MQTT. In this repository you will find different approaches means Hardware / Software to realize the described functionalities.
Click on the link below you are interested in.
There you will find further explanations on how to proceed. (*Note: It is still under construction!*)
List of approaches
##### Most updated section
- [ESP8266](tools/esp8266/) that includes an web interface
- [ESP8266/ESP32, C++](tools/esp8266/) 👈 the most effort is spent here
- [Arduino Nano, C++](tools/nano/NRF24_SendRcv/)
- [Raspberry Pi, Python](tools/rpi/)
- [Others, C/C++](tools/nano/NRF24_SendRcv/)
##### will be updated as needed
- [Arduino Nano](tools/nano/NRF24_SendRcv/)
- [Raspberry Pi](tools/rpi/)
- [others](tools/nano/NRF24_SendRcv/)
## Quick Start with ESP8266
- [Go here ✨](https://github.com/grindylow/ahoy/blob/ahoy_v0.5.16/tools/esp8266/README.md#things-needed)
If errors occur or you have suggestions for ideas, please feel free to contact us [here](https://github.com/grindylow/ahoy/issues).
## Contact
We run a Discord Server that can be used to get in touch with the Developers and Users.
## Success Stories
- [Getting the data into influxDB and visualize them in a Grafana Dashboard](https://grafana.com/grafana/dashboards/16850-pv-power-ahoy/) (thx @Carl)
https://discord.gg/WzhxEY62mB
## Support, Feedback, Information and Discussion
- [Discord Server (~ 300 Users)](https://discord.gg/WzhxEY62mB)
- [The root of development](https://www.mikrocontroller.net/topic/525778)
### Development
If you encounter issues use the issues here on github.
Please try to describe your issues as precise as possible and think about if this is a issue with the software here in the repository or other software components.
**Contributors are always welcome!**
### Related Projects
- [OpenDTU](https://github.com/tbnobody/OpenDTU)
- [DTU Simulator](https://github.com/Ziyatoe/DTUsimMI1x00-Hoymiles)

BIN
doc/Wiring_ESP32_Schematic.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
doc/Wiring_ESP32_Symbol.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

22
tools/esp8266/README.md

@ -76,11 +76,29 @@ Additional, there are 3 pins, which can be set individual:
#### ESP8266 wiring example
This is an example wiring using a Wemos D1 mini.<br>
<img src="https://github.com/grindylow/ahoy/blob/main/doc/AhoyWemos_Steckplatine.jpg" width="300">
<img src="https://github.com/grindylow/ahoy/blob/main/doc/AhoyWemos_Schaltplan.jpg" width="300">
##### Schematic
![Schematic](../../doc/AhoyWemos_Schaltplan.jpg)
##### Symbolic view
![Symbolic](../../doc/AhoyWemos_Steckplatine.jpg)
#### ESP32 wiring example
Example wiring for a 38pin ESP32 module
##### Schematic
![Schematic](../../doc/Wiring_ESP32_Schematic.png)
##### Symbolic view
![Symbolic](../../doc/Wiring_ESP32_Symbol.png)
##### ESP32 GPIO settings
For this wiring, set the 3 individual GPIOs under the /setup URL:
```
CS D1 (GPIO5)
CE D2 (GPIO4)
IRQ D0 (GPIO16 - no IRQ!)
```
## 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.

2
tools/rpi/ahoy.yml.example

@ -30,6 +30,8 @@ ahoy:
volkszaehler:
disabled: true
inverters:
- serial: 114172220003
url: 'http://localhost/middleware/'
channels:
- type: 'temperature'

2
tools/rpi/hoymiles/__init__.py

@ -647,7 +647,7 @@ class InverterTransaction:
self.time_rx = end_frame.time_rx
tr_len = end_frame.seq - 0x80
except StopIteration:
seq_last = max(frames, key=lambda frame:frame.seq).seq
seq_last = max(frames, key=lambda frame:frame.seq).seq if len(frames) else 0
self.__retransmit_frame(seq_last + 1)
raise BufferError(f'Missing packet: Last packet {len(self.scratch)}')

54
tools/rpi/hoymiles/outputs.py

@ -208,14 +208,10 @@ try:
except ModuleNotFoundError:
pass
class VolkszaehlerOutputPlugin(OutputPluginFactory):
def __init__(self, config, **params):
"""
Initialize VolkszaehlerOutputPlugin
"""
super().__init__(**params)
self.session = requests.Session()
class VzInverterOutput:
def __init__(self, config, session):
self.session = session
self.serial = config.get('serial')
self.baseurl = config.get('url', 'http://localhost/middleware/')
self.channels = dict()
for channel in config.get('channels', []):
@ -224,7 +220,7 @@ class VolkszaehlerOutputPlugin(OutputPluginFactory):
if uid and ctype:
self.channels[ctype] = uid
def store_status(self, response, **params):
def store_status(self, data, session):
"""
Publish StatusResponse object
@ -232,15 +228,9 @@ class VolkszaehlerOutputPlugin(OutputPluginFactory):
:raises ValueError: when response is not instance of StatusResponse
"""
if not isinstance(response, StatusResponse):
raise ValueError('Data needs to be instance of StatusResponse')
if len(self.channels) == 0:
return
data = response.__dict__()
ts = int(round(data['time'].timestamp() * 1000))
# AC Data
@ -277,3 +267,37 @@ class VolkszaehlerOutputPlugin(OutputPluginFactory):
raise ValueError('Could not send request (%s)' % url)
except ConnectionError as e:
raise ValueError('Could not send request (%s)' % e)
class VolkszaehlerOutputPlugin(OutputPluginFactory):
def __init__(self, config, **params):
"""
Initialize VolkszaehlerOutputPlugin
"""
super().__init__(**params)
self.session = requests.Session()
self.inverters = dict()
for inverterconfig in config.get('inverters', []):
serial = inverterconfig.get('serial')
output = VzInverterOutput(inverterconfig, self.session)
self.inverters[serial] = output
def store_status(self, response, **params):
"""
Publish StatusResponse object
:param hoymiles.decoders.StatusResponse response: StatusResponse object
:raises ValueError: when response is not instance of StatusResponse
"""
if not isinstance(response, StatusResponse):
raise ValueError('Data needs to be instance of StatusResponse')
if len(self.inverters) == 0:
return
data = response.__dict__()
serial = data["inverter_ser"]
if serial in self.inverters:
output = self.inverters[serial]
output.store_status(data, self.session)

Loading…
Cancel
Save