Skip to content

Commit

Permalink
merging master
Browse files Browse the repository at this point in the history
  • Loading branch information
MalteSchm committed Mar 26, 2023
2 parents 0be5748 + a4c8e85 commit a476782
Show file tree
Hide file tree
Showing 32 changed files with 649 additions and 532 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ This project is still under development and adds following features:
[![OpenDTU Build](https://github.com/tbnobody/OpenDTU/actions/workflows/build.yml/badge.svg)](https://github.com/tbnobody/OpenDTU/actions/workflows/build.yml)
[![cpplint](https://github.com/tbnobody/OpenDTU/actions/workflows/cpplint.yml/badge.svg)](https://github.com/tbnobody/OpenDTU/actions/workflows/cpplint.yml)

## !! IMPORTANT UPGRADE NOTES !!

If you are upgrading from a version before 15.03.2023 you have to upgrade the partition table of the ESP32. Please follow the [this](docs/UpgradePartition.md) documentation!

## Background
This project was started from [this](https://www.mikrocontroller.net/topic/525778) discussion (Mikrocontroller.net).
It was the goal to replace the original Hoymiles DTU (Telemetry Gateway) with their cloud access. With a lot of reverse engineering the Hoymiles protocol was decrypted and analyzed.
Expand Down Expand Up @@ -235,6 +239,7 @@ Firmware version seems to play not a significant role and cannot be read from th
## Breaking changes
Generated using: `git log --date=short --pretty=format:"* %h%x09%ad%x09%s" | grep BREAKING`
```
* 318136d 2023-03-15 BREAKING CHANGE: Updated partition table: Make sure you have a configuration backup and completly reflash the device!
* 3b7aef6 2023-02-13 BREAKING CHANGE: Web API!
* d4c838a 2023-02-06 BREAKING CHANGE: Prometheus API!
* daf847e 2022-11-14 BREAKING CHANGE: Removed deprecated config parsing method
Expand Down
24 changes: 24 additions & 0 deletions docs/UpgradePartition.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Upgrade Partition

To be able to install further updates you have to update the partition table of the ESP32. Doing so will **erase** all configuration data. Over The Air update using the web interface is **NOT** possible!

**So make sure you export a backup of your configuration files before continuing.**

There are several possibilities to update the partition table:
- Using Visual Studio Code or PlatformIO CLI

If you have already used Visual Studio Code or the `platformio` command you can use it again to install the latest version. The partition table is upgraded automatically.

- Any kind of flash interface

If you like to use any kind of flash interface like `esptool.py`, Espressif Flash Download Tool, ESP_Flasher or esptool-js you have to make sure to upload **ALL** provided .bin files. It is important to enter the correct target addresses.

| Address | File |
| ---------| ---------------------- |
| 0x1000 | bootloader.bin |
| 0x8000 | partitions.bin |
| 0xe000 | boot_app0.bin |
| 0x10000 | opendtu-*.bin |


After upgrading the ESP32 will open the intergrated access point (AP) again. Just connect to it using the default password ("openDTU42"). If you are connected, just visit http://192.168.4.1 and enter the "Configuration Management". Recover the previously backuped config files.
11 changes: 6 additions & 5 deletions include/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,17 +101,18 @@ struct CONFIG_T {

bool PowerLimiter_Enabled;
bool PowerLimiter_SolarPassTroughEnabled;
uint8_t PowerLimiter_BatteryDrainStategy;
uint32_t PowerLimiter_Interval;
char PowerLimiter_MqttTopicPowerMeter1[MQTT_MAX_TOPIC_STRLEN + 1];
char PowerLimiter_MqttTopicPowerMeter2[MQTT_MAX_TOPIC_STRLEN + 1];
char PowerLimiter_MqttTopicPowerMeter3[MQTT_MAX_TOPIC_STRLEN + 1];
bool PowerLimiter_IsInverterBehindPowerMeter;
uint8_t PowerLimiter_InverterId;
uint8_t PowerLimiter_InverterChannelId;
uint32_t PowerLimiter_TargetPowerConsumption;
uint32_t PowerLimiter_TargetPowerConsumptionHysteresis;
uint32_t PowerLimiter_LowerPowerLimit;
uint32_t PowerLimiter_UpperPowerLimit;
int32_t PowerLimiter_TargetPowerConsumption;
int32_t PowerLimiter_TargetPowerConsumptionHysteresis;
int32_t PowerLimiter_LowerPowerLimit;
int32_t PowerLimiter_UpperPowerLimit;
uint32_t PowerLimiter_BatterySocStartThreshold;
uint32_t PowerLimiter_BatterySocStopThreshold;
float PowerLimiter_VoltageStartThreshold;
Expand All @@ -128,7 +129,7 @@ struct CONFIG_T {

bool Display_PowerSafe;
bool Display_ScreenSaver;
bool Display_ShowLogo;
uint8_t Display_Rotation;
uint8_t Display_Contrast;
};

Expand Down
11 changes: 8 additions & 3 deletions include/Display_Graphic.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#include "defaults.h"
#include <U8g2lib.h>

enum DisplayType_t {
Expand All @@ -17,25 +18,29 @@ class DisplayGraphicClass {

void init(DisplayType_t type, uint8_t data, uint8_t clk, uint8_t cs, uint8_t reset);
void loop();
void setContrast(uint8_t contrast);
void setOrientation(uint8_t rotation = DISPLAY_ROTATION);
void setStartupDisplay();

bool enablePowerSafe = true;
bool enableScreensaver = true;
bool showLogo = true;
uint8_t contrast = 60;

private:
void printText(const char* text, uint8_t line);
void calcLineHeights();
void setFont(uint8_t line);

U8G2* _display;

DisplayType_t _display_type = DisplayType_t::None;
uint8_t _mExtra;
uint16_t _dispY = 0;
uint16_t _period = 1000;
uint16_t _interval = 60000; // interval at which to power save (milliseconds)
uint32_t _lastDisplayUpdate = 0;
uint32_t _previousMillis = 0;
char _fmtText[32];
bool _isLarge = false;
uint8_t _lineOffsets[5];
};

extern DisplayGraphicClass Display;
2 changes: 1 addition & 1 deletion include/PinMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#pragma once

#include <Arduino.h>
#include <stdint.h>
#include <ETH.h>
#include <stdint.h>

#define PINMAPPING_FILENAME "/pin_mapping.json"

Expand Down
13 changes: 9 additions & 4 deletions include/PowerLimiter.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,26 @@ typedef enum {
STATE_CONSUME_SOLAR_POWER_ONLY,
STATE_NORMAL_OPERATION
} plStates;

typedef enum {
EMPTY_WHEN_FULL= 0,
EMPTY_AT_NIGTH
} batDrainStrategy;


class PowerLimiterClass {
public:
void init();
void loop();
plStates getPowerLimiterState();
uint16_t getLastRequestedPowewrLimit();
int32_t getLastRequestedPowewrLimit();
void onMqttMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total);

private:
uint32_t _lastCommandSent;
uint32_t _lastLoop;
uint32_t _lastPowerMeterUpdate;
uint16_t _lastRequestedPowerLimit;
int32_t _lastRequestedPowerLimit;
plStates _plState = STATE_DISCOVER;

float _powerMeter1Power;
Expand All @@ -36,8 +41,8 @@ class PowerLimiterClass {

bool canUseDirectSolarPower();
int32_t calcPowerLimit(std::shared_ptr<InverterAbstract> inverter, bool consumeSolarPowerOnly);
void setNewPowerLimit(std::shared_ptr<InverterAbstract> inverter, uint32_t newPowerLimit);
uint16_t getDirectSolarPower();
void setNewPowerLimit(std::shared_ptr<InverterAbstract> inverter, int32_t newPowerLimit);
int32_t getDirectSolarPower();
float getLoadCorrectedVoltage(std::shared_ptr<InverterAbstract> inverter);
bool isStartThresholdReached(std::shared_ptr<InverterAbstract> inverter);
bool isStopThresholdReached(std::shared_ptr<InverterAbstract> inverter);
Expand Down
2 changes: 2 additions & 0 deletions include/WebApi_prometheus.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class WebApiPrometheusClass {

void addField(AsyncResponseStream* stream, String& serial, uint8_t idx, std::shared_ptr<InverterAbstract> inv, ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId, const char* channelName = NULL);

void addPanelInfo(AsyncResponseStream* stream, String& serial, uint8_t idx, std::shared_ptr<InverterAbstract> inv, ChannelType_t type, ChannelNum_t channel);

AsyncWebServer* _server;

enum {
Expand Down
3 changes: 2 additions & 1 deletion include/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@

#define DISPLAY_POWERSAFE true
#define DISPLAY_SCREENSAVER true
#define DISPLAY_SHOWLOGO true
#define DISPLAY_ROTATION 2
#define DISPLAY_CONTRAST 60

#define VEDIRECT_ENABLED false
Expand All @@ -94,6 +94,7 @@

#define POWERLIMITER_ENABLED false
#define POWERLIMITER_SOLAR_PASSTROUGH_ENABLED true
#define POWERLIMITER_BATTERY_DRAIN_STRATEGY 0
#define POWERLIMITER_INTERVAL 10
#define POWERLIMITER_IS_INVERTER_BEHIND_POWER_METER true
#define POWERLIMITER_INVERTER_ID 0
Expand Down
8 changes: 4 additions & 4 deletions lib/VeDirectFrameHandler/VeDirectFrameHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ typedef struct {
uint8_t ERR; // error code
uint32_t OR; // off reason
uint8_t MPPT; // state of MPP tracker
uint16_t HSDS; // day sequence number 1...365
uint32_t HSDS; // day sequence number 1...365
double V; // battery voltage in V
double I; // battery current in A
double VPV; // panel voltage in V
uint16_t PPV; // panel power in W
int32_t PPV; // panel power in W
double H19; // yield total kWh
double H20; // yield today kWh
uint16_t H21; // maximum power today W
int32_t H21; // maximum power today W
double H22; // yield yesterday kWh
uint16_t H23; // maximum power yesterday W
int32_t H23; // maximum power yesterday W
} veStruct;

class VeDirectFrameHandler {
Expand Down
12 changes: 6 additions & 6 deletions partitions_custom.csv
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x180000,
app1, app, ota_1, 0x190000,0x180000,
spiffs, data, spiffs, ,0x50000
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x5000,
otadata, data, ota, 0xe000, 0x2000,
app0, app, ota_0, 0x10000, 0x1E0000,
app1, app, ota_1, 0x1F0000, 0x1E0000,
spiffs, data, spiffs, 0x3D0000, 0x30000,
4 changes: 2 additions & 2 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ build_flags =

lib_deps =
https://github.com/yubox-node-org/ESPAsyncWebServer
bblanchon/ArduinoJson @ ^6.20.1
https://github.com/bertmelis/espMqttClient.git#v1.3.3
bblanchon/ArduinoJson @ ^6.21.0
https://github.com/bertmelis/espMqttClient.git#v1.4.1
nrf24/RF24 @ ^1.4.5
olikraus/U8g2 @ ^2.34.13
buelowp/sunset @ ^1.1.7
Expand Down
6 changes: 4 additions & 2 deletions src/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ bool ConfigurationClass::write()
JsonObject display = device.createNestedObject("display");
display["powersafe"] = config.Display_PowerSafe;
display["screensaver"] = config.Display_ScreenSaver;
display["showlogo"] = config.Display_ShowLogo;
display["rotation"] = config.Display_Rotation;
display["contrast"] = config.Display_Contrast;

JsonArray inverters = doc.createNestedArray("inverters");
Expand Down Expand Up @@ -118,6 +118,7 @@ bool ConfigurationClass::write()
JsonObject powerlimiter = doc.createNestedObject("powerlimiter");
powerlimiter["enabled"] = config.PowerLimiter_Enabled;
powerlimiter["solar_passtrough_enabled"] = config.PowerLimiter_SolarPassTroughEnabled;
powerlimiter["battery_drain_strategy"] = config.PowerLimiter_BatteryDrainStategy;
powerlimiter["interval"] = config.PowerLimiter_Interval;
powerlimiter["mqtt_topic_powermeter_1"] = config.PowerLimiter_MqttTopicPowerMeter1;
powerlimiter["mqtt_topic_powermeter_2"] = config.PowerLimiter_MqttTopicPowerMeter2;
Expand Down Expand Up @@ -256,7 +257,7 @@ bool ConfigurationClass::read()
JsonObject display = device["display"];
config.Display_PowerSafe = display["powersafe"] | DISPLAY_POWERSAFE;
config.Display_ScreenSaver = display["screensaver"] | DISPLAY_SCREENSAVER;
config.Display_ShowLogo = display["showlogo"] | DISPLAY_SHOWLOGO;
config.Display_Rotation = display["rotation"] | DISPLAY_ROTATION;
config.Display_Contrast = display["contrast"] | DISPLAY_CONTRAST;

JsonArray inverters = doc["inverters"];
Expand Down Expand Up @@ -286,6 +287,7 @@ bool ConfigurationClass::read()
JsonObject powerlimiter = doc["powerlimiter"];
config.PowerLimiter_Enabled = powerlimiter["enabled"] | POWERLIMITER_ENABLED;
config.PowerLimiter_SolarPassTroughEnabled = powerlimiter["solar_passtrough_enabled"] | POWERLIMITER_SOLAR_PASSTROUGH_ENABLED;
config.PowerLimiter_BatteryDrainStategy = powerlimiter["battery_drain_strategy"] | POWERLIMITER_BATTERY_DRAIN_STRATEGY;
config.PowerLimiter_Interval = POWERLIMITER_INTERVAL;
strlcpy(config.PowerLimiter_MqttTopicPowerMeter1, powerlimiter["mqtt_topic_powermeter_1"] | "", sizeof(config.PowerLimiter_MqttTopicPowerMeter1));
strlcpy(config.PowerLimiter_MqttTopicPowerMeter2, powerlimiter["mqtt_topic_powermeter_2"] | "", sizeof(config.PowerLimiter_MqttTopicPowerMeter2));
Expand Down
Loading

0 comments on commit a476782

Please sign in to comment.