The cFos Charging Manager allows the dynamic evaluation of formulas. This functionality is available for a meter of the type "Expression" and for charging rules of the type "Formula".
You can therefore set up meters that calculate values from other meters or EVSEs and keep them ready and display them. The charging rules can also use formulas to dynamically calculate the charging current and also access meters and EVSEs (including meters of the "Expression" type).
The following operations are possible with the formulas:
+ - * / % | Addition, subtraction, multiplication, division, modulus |
& | | bitwise AND and OR |
^ | Power calculation, e.g. 10^2 = 100 |
min(x,y) | Minimum of x and y, more than 2 arguments possible |
max(x,y) | Maximum of x and y, more than 2 arguments possible |
abs(x) | Absolute value of x, e.g. abs(-2) = 2 |
clamp(x,min,max) | Value x = min (if x < min), x = max (if x > max), otherwise keep x |
round(x) | Round x to whole number. Example: Rounding to 1 decimal place: round(10*x)/10. |
sqrt(x) | Square root of x |
exists(x) | true if the variable x exists, otherwise false |
Furthermore, the following logical expressions are possible:==
(equal), !=
(unequal), <
(less), <=
(less-equal), >
(greater), >=
(greater-equal), !
(not), ||
(logical Or), &&
(logical And), ?
(conditional operator, e.g. x ? y : z
, returns y if x is true, otherwise z
)
This allows, for example, the current to be switched off depending on conditions: M1.current >= 6500 ? M1.current : 0
returns the current of M1 if it is greater than 6.5A and 0 otherwise, which pauses the charging. For such conditions, it is also possible to query inputs (see below)
The following names are possible:
Mx | Meter with unit ID x, e.g. M1 |
Ex | EVSE with device ID x, e.g. E1 |
It is also possible to access virtual meters, such as solar surplus, grid draw or "Power avail. for EVSEs" (power available for wallboxes), by setting up the meter and then using the corresponding device ID in the formula.
You can then access individual values of the units by means of the point. These are called as follows:
current_l1 | Current of phase 1 in mA |
current_l2 | Current of phase 2 in mA |
current_l3 | Current of phase 3 in mA |
current | Current of the current phase in mA (for charging rules, the Charging Manager queries all phases one after the other; for meters of the type "Expression", the respective phase to which the formula refers applies. If you have specified a formula for "Current L1", you can omit the fields for Current L2 and L3. Then the formula for current L1 is used) |
power_w | Current active power in watts |
offered | Wallbox: Current offered in mA |
import_wh | Energy drawn in Wh |
export_wh | Injected energy in Wh |
dt | The time that has passed since the last update (in seconds), only for counter "Expression", see also CM._dt. |
inputN | Input number N of the device, 1 = active, 0 = inactive, N is the number of the input, starting with 1. |
soc | SOC, charge level in per cent (counter/memory) - if supported by the device |
id | Device Id, Modbus ID |
txn_duration | Duration of the current transaction in seconds (EVSE) |
charging_dur | Actual charging time of the current transaction in seconds (Wallbox) |
txn_energy | Charged energy of the current transaction in Wh (EVSE) |
min_current | Minimum charging current in mA (EVSE) |
max_current | Maximum charging current in mA (EVSE) |
state | Status: 1 waiting, 2 plugged in, 3 charging, 4 charging with ventilation, 5 error, 6 offline (EVSE) |
cphases | Number of charging phases (0-3) |
pphases | Number of predicted charging phases (0-3) |
lb_cur_l1 | Currently calculated current of phase 1 in mA (wallbox). Only during the calculation of the wallbox charging rules, otherwise 0 |
lb_cur_l2 | Current calculated current of phase 2 in mA (wallbox). Only during the calculation of the wallbox charging rules, otherwise 0 |
lb_cur_l3 | Currently calculated current of phase 3 in mA (wallbox). Only during the calculation of the wallbox charging rules, otherwise 0 |
lb_cur | Current calculated for the current phase in mA (wallbox). Only during the calculation of the wallbox charging rules, otherwise 0. The Charging Manager queries all phases one after the other. |
surplus_pcur | PV excess current per (predicted) phase in mA |
surplus_wanted | 1, if a PV surplus rule has already been applied, otherwise 0 |
budget | KWh or minutes in the current budget |
budget_amount | Maximum kWh or minutes on the current budget |
budget_used | KWh or minutes used on the current budget |
com_err | 1, if there is a COM error, otherwise 0 |
com_err2 | 1, if a COM error is present for longer than 12 sec, otherwise 0 |
reactive_power | Reactive power specification in watts (if supported by the device), positive values: Inductive, negative values: Capacitive |
switch_phases | For wallboxes with phase switching: Manual phase switching, 1 = 1-phase, 3 = 3-phase, -1 = automatic phase switching |
departure | ISO 15118 departure time as unit timestamp (for wallboxes that support this, otherwise 0) |
req_energy | ISO 15118 Required energy in Wh (for wallboxes that support this, otherwise 0) |
plugin_start | Unix timestamp, time of cable insertion |
plugin_energy | Previously charged energy in Wh from the time the cable was plugged in |
M1.current_l1 | Current of meter M1, phase 1 |
E2.import_wh | Consumed Wh of the EVSE E2 |
E3.power_w | Current charging power of E3 in watts |
If you use the formulas for a meter of type "Expression", you can also omit the device ID. Then the field names refer to this meter, e.g. 'power_w' is then the power of this meter in watts. By means of 'dt' you can realise a few extended functions, e.g. in a meter of the type "Expression":
import_wh + M1.power_w * dt / 3600
updates the sourced energy based on the power during the past update time(power_w * (20 - dt) + M1.power_w * dt) / 20
smoothes the power over the last 20 seconds.date
date.year | Current year |
date.month | Month from 0..11 |
date.day | Day from 1..31 |
date.weekday | Weekday SO=0, Mon=1, Tue=2, ... Sat=6 |
date.yearday | Day in the year from 0..366 |
date.hour | Hour from 0..23 |
date.minute | Minute from 0..60 |
date.second | Second from 0..60 |
date.daysecond | Second of this day from 0..86399 |
date.dayminute | Minute of this day from 0..1439 |
date.dst | 0 = winter time, 1 = summer time |
date.timestamp | Unix timespamp, secs since 1.1.1970 |
PB (nur cFos Power Brain)
PB.input1 | S0 Input 1, 1 = active, 0 = inactive |
PB.input2 | S0 Input 2, 1 = active, 0 = inactive |
CM Charging Manager Variables
These variables can be set by the admin under 'Configuration'. For example, if the admin sets the variable 'var_x' to 1.5, CM.var_x returns the value 1.5.
Predefined variables:
_num_charging: Number of wallboxes currently charging
_num_charging1: Number of currently charging wallboxes, 1 if none is charging
_max_total_current: Maximum current of the house connection in mA per phase
_max_total_evse_current: Maximum current for wallboxes in mA per phase
_price: Current electricity price
_price_level: Current electricity price level, -2=very expensive, -3=expensive, -4=normal, -5=cheap, -6=very cheap
_surplus: Current solar surplus in watts
_org_surplus: Solar surplus as would have been calculated by the Charging Manager independently of its own formulas
_storage_home_max_capacity: Total capacity of the storage, home, if specified in the meter configuration, in Wh
_storage_home_capacity: Current capacity of the storage, home, if specified in the meter configuration, in Wh
_storage_all_max_capacity: Total capacity of the storage, All, if specified in the counter configuration, in Wh
_storage_all_capacity: Current capacity of the storage, All, if specified in the counter configuration, in Wh
_max_total_current_prc: Percentage of the available maximum total charging current. This variable can also be written (by counter definitions and Charging Manager variables)
_dt: The time that has elapsed since the last update (in seconds).
Use of the global objects:
charge 8A starting at 8:00am: date.dayminute >= 480 ? 8000 : 0
charge 16A on Saturday and Sunday: date.weekday == 5 || date.weekday == 6 ? 16000 : 0
charge 6A if input 2 active: PB.input2 ? 6000 : 0
charge 6A if CM variable non-zero: cm.var1 ? 6000 : 0
Note:
Under Custom Counters you will also find instructions on how to use formulas with global Charging Manager variables and outputs.
GM Global counters
GM.grid_demand | Mains reference |
GM.consumed | Consumption |
GM.produced | Generation |
GM.consumed_evse | Consumption e-cars |
GM.available_evse | Available power |
GM.surplus | PV surplus |
GM.storage_home | Memory Home |
GM.storage_all | Memory Everything |
GM.error | Performance through error |
Use of the global counters
Jeder Zähler hat die Felder power_w, current, current_l1, current_l2, current_l3, import_wh und export_wh,
z.B. GM.prod_pwr.current_l1 oder GM.cons_pwr.power_w
. Bei 'current' wird der Strom der gerade betrachteten Phase ausgewertet. Ströme werden in mA geliefert, Leistung in W, Energie in Wh.
You want to additionally limit the charging current with regard to a consumption meter of a flat. To do this, you can set up a charging rule with the formula 16000 - M1.current
.
M1 is the meter that measures the consumption of the flat. The load management of the cFos Charging Manager first tries to provide the EVSE with the maximum current in relation to the house connection power, but then limits this to 16A minus the consumption of the flat.
Using min_price(s), max_price(s), you can determine the cheapest price of your energy provider in euros, whereby the prices are searched from the current time to max s seconds of the day or the following day, e.g. min_price(25200) returns the cheapest price until 7:00 am. For example, you can create a charging rule with the condition CM._price <= min_price(25200) in order to charge at the most favourable time, but with the condition that you want to set off from 8:00 a.m., for example (assuming a charging time of 1 hour). Similarly, there are the two functions min_price_secs(s) and max_price_secs(s), which return the start time of the cheapest price in seconds of the day started. You can then compare these with date.daysecond, for example.