this new class uses the newly introduced HttpRequestConfig and performs
HTTP requests using this config. it will be reused for other power
meters (SML over HTTP(S)) and may be reused by other features in the
future (battery provider, solar power provider, etc.).
the extractUrlComponents method did extract username and password
from the URL and encoded it for basic authentication. however, the
respective result string was never used. we only perform basic
authentication if the auth type is "basic" and if username and
password were supplied through the respective inputs.
the parameters to peform an HTTP request by the HTTP(S)+JSON power meter
have been generalized by introducing a new config struct. this is now
used for all values which the HTTP(S)+JSON power meter can retrieve, and
also used by the HTTP+SML power meter implementation. we anticipate that
other feature will use this config as well.
generalizing also allows to share serialization and deserialization
methods in the configuration handler and the web API handler, leading to
de-duplication of code and reduced flash memory usage.
a new web UI component is implemented to manage a set of HTTP request
settings.
avoid additional conversions and avoid double for the fact that
calculations on type double are implemented in software, whereas
float is handled in hardware on ESP32.
this new class handles SML data. it uses the SML lib to decode values
and manages those. this de-duplicates code as the class is applicable
to all power meters that collect SML data.
this setting was not used. the baud rate for the SDM is set to 9600 in
the source code. until the baud rate being customizable is actually
required by somebody, we remove the setting altogether.
"powertotal" is always published and it is published by the base class
directly. other values are still published by the derived classes, but
use a base class method, which takes care that a common base topic is
used in particular.
instead of iterating a map with subscriptions, we now bind the target
variable to the callback, which is executed once a message is arrived.
this way, the target variable is already linked to the respective topic
when the callback is executed.
lock the mutex when writing the variable, as the MQTT callback is
executed in a different context (MQTT task) than the main loop task,
which otherwise accesses the variables.
it is important to separate the capabilities of each power meter
provider into their own class/source file, as the providers work
fundamentally different and their implementations must not be
intermangled, which made maintenance and improvements a nightmare
in the past.
this only changes line endings. inspect this commit with command `git
show <commit-sha> --ignore-space-at-eol` and it will tell you that the
commit appears to be "empty" (since all changes are whitespace changes
near the end of a line, which are ignored in that git show command).
the files to be changed were found and updated using this command:
find lib src include webapp/src -type f | \
xargs grep --binary-files=without-match --files-with-matches \
$(printf '\r\n') | xargs dos2unix
the following files were restored afterwards, as they are using CRLF
line endings in the upstream as well:
- lib/CMT2300a/cmt2300a_defs.h
- lib/README
- include/README
the "serial console" over USB would be garbled badly after switching to
"platform = espressif32@6.7.0". this did not happen to the upstream
version of MessageOutput. we used Serial.flush(), which seemed to be
good in the respective context. however, the changes in
github.com/espressif/arduino-esp32/pull/9462
made flush() detrimental. we remove the use of flush(), as it seems not
to be required (in particular, the upstream project does not use it).
broke in be41e6b9. was unusable as the complete type of DummySerial has
to be available in the JK BMS controller header when defining the
unique_ptr managing the dummy instance. this problem is solved by moving
the whole dummy class into its own header.
instead of hard-coding the use of hardware UART 2, the SDM power meter
instance now asks for a free hardware serial port to use and
instanciates the respective HardwareSerial object using said port.
get rid of particular compile-time designations by UART index. just hand
out the next free index of hardware UARTs, or indicate that none is
available any more.
use names as keys to register and free UARTs.
only on ESP32-S3-USB. this fiddles with the available hardware UARTs to
make it possible to use a third Victron MPPT. if three MPPTs are defined
int the pin mapping, you will not be able to use the SmartShunt and JK
BMS battery interfaces.
note that using a second MPPT will also conflict with the SDM power
meter, and that conflict is not detected, yet.
this implements accessing array members in an ArduinoJSON object
following the FirebaseJson syntax. the FirebaseJson lib was previously
removed to save flash memory, and logic was implemented to find a JSON
node using the FirebaseJson path syntax, restoring the functionality.
however, array access was not implemented.
this change also addresses leading and trailing and double forward
slashes in the path expression.
moreover, much more expressive error messages are now generated in case
the path could not be resolved.
mbedtls is already integral part of the firmware. use it in favor of
rweather/Crypto library to calculate a sha256 checksum of a string, as
used in the HTTP power meter implementation.
we used this library solely to interpret the answer of an HTTP web
server as JSON and find a particular value using a path expression in
the HTTP power meter implementation.
since we ran out of flash memory on non-S3 ESP32, we need to cut some
corners. removing FirebaseJson is the last low-hanging fruit that we
currently know of. we can get rid of it by using ArduinoJson (which is
already integral part of the firmware) and implementing a custom logic
to extract a value based on a path expression.
other than the FirebaseJson path "finder", the new implementation
only knows how to access sub-keys delimited by a forward slash. in
particular, accessing array members is not supported any more. I am
hoping that this is simply not an issue. if so, we will have users
complaining and we can add this functionality in a later release.
merge upstream tag v24.4.12, resolve conflicts (helgeerbe), fix eslint errors (schlimmchen) and adopt new web api method to save code duplication (schlimmchen).
this allows to use two VE.Direct interfaces, as there is no conflict
regarding HW serial port 2 after making the battery interfaces use
serial port 0 on devices with USB CDC. on those chips HW serial 0 is
free to be used since serial messages are written through the USB
interface directly.
we found that the inverter sometimes stops responding to commands,
especially to the "start producing" command. we now count the number of
consecutive timeouts when trying to send a new limit or power state
commands. after two timeouts were recorded, every additional timeout
will send a restart command to the inverter.
as a last resort, if the counter keeps climbing, the DTU is restarted.
notice that this only targets unresponsive inverters which are
reachable. unreachable inverters are not restarted and do not cause a
DTU reboot. this is important for solar-driven inverters, which are
unreachable during the night. the DPL will not calculate a new limit and
hence the updateInverter() method will do nothing while the target
inverter is unreachable.
publish the timeout counter to MQTT for monitoring purposes.
avoid performing a calculation based on a (slightly) outdated power
meter reading, which was aquired just before the limit was actually
applied by the inverter, but which was received by OpenDTU-OnBattery
after the inverter stats.
without a power meter configured, the DPL now sets the base load as the
inverter limit if the battery charge allows it. it also takes
solar-passthrough into account, i.e., if the battery is in a charge
cycle but the solar output (Victron MPPT) is significant, the solar
power will be used up until the base load. if the battery reaches the
full solar passthrough threshold, the DPL will match the inverter limit
to the MPPT solar output.
on power meter issues (usually a timeout), keep the inverter enabled and
make it produce the configured base load limit if the battery can be
discharged. that should be okay since the base load config value is
expected to be small and a little less than the actual household base
load, i.e., if this amount of power is produced, the household will
consume it in any case and no energy is fed into the grid.
makes the value match its description. since most values in the top part
of the live view are related to the AC side of the system, it makes
sense to use the correct value rather than to change the description.
* process "IL", "AR" and "MON"
* discard "BMV" and (unsolicited) History Data
* simplify isDataValid()
* veMpptStruct, veStruct: new, verbose variable names, including units,
and replace floats (save values with original integer precision)
* comment on rollover situation in isDataValid()
1. makes the DPL use the power generated by all connected charge
controllers for calculations based on solar passthrough.
2. makes the network total DC power appear as "MPPT Total Power" in the
live view at the top.
3. shows the network total DC power in the VE.Direct live data card.
* show charge controller temperature in live view
* send hex requests right after decoding a frame. this seems to have the
best chance of getting an answer to all requests.
* deem 0xFFFFFFFF value of network total DC power as invalid indicator.
neither network state, nor network info, nor network mode seem to
indicate that the charge controller is part of a VE.Smart network. for
that reason, we revert to always querying the network total DC power
value, but testing it for max(uin32_t) value, which seems to indicate
that the charge controller is not part of a VE.Smart network.
* improve (verbose) logging, e.g., use _logId, and print names of
response codes and known registers, always print error messages,
add additional tests to prevent overly verbose messages.
* move hex protocol definitions to VeDirectData.h header
and use enum classes
* define register addresses in enum class
* move values retrieved through hex protocol into main MPPT data struct
* do not send HEX requests if the serial interface cannot send data
* detect whether smart battery sense temperature is available
* web app: make all VE.Direct sub-cards iterable. this makes addind more
values much simpler and saves a bunch of code in the web app.
* make VeDirectFrameHandler state a type-safe enum class
* unindent MPPT controller loop()
* whitespace cleanup
double precision floating point numbers are not needed to handle
VE.Direct values. handling double is implemented in software and hence
*much* more resource intensive.
queue every text event until the frame was checked by it checksum. then
process the data directly into the buffer struct. do not clear the
buffer struct, so it will always include the most recent value of a
particular data point.
if only a single request was made (switch "Individual HTTP requests per
phase" is off), the user could still enable phase 2 and phase 3 config
and configure a respective JSON path. however, the value was never
extracted from the successful HTTP request for phase 1.
closes#637.
users are manipulating the DPL using HTTP POST requests. often they are
requesting the current settings using HTTP GET on the respective route,
then change a particular settings, and send all the data back using HTTP
POST. if they failed to remove the metadata node from the JSON,
OpenDTU-OnBattery would not be able to process the JSON due to its size.
the web app does not submit the metadata.
to avoid problems, the metadata is now split from the configuration
data.