Documentation

User-defined counters

Note: The cFos Charging Manager can read out most solar inverters using SunSpec (device type "SunSpec Solar Inverter / Meter"). In this case, you do not need to create your own meter definition.

The cFos Charging Manager allows you to create your own meter definitions to support meters that are not in the standard repertoire. There are currently three types: Modbus counters, HTTP/JSON counters and MQTT/JSON counters. The definition files for these counters are very similar. Modbus counters read their data via Modbus from specific registers, while HTTP/JSON counters fetch their data via HTTP request and parse JSON as a response. For MQTT/JSON counters, the cFos Charging Manager subscribes to MQTT topics and parses messages published under the topic as JSON. For parsing, the cFos Charging Manager uses a small "query language". Here is the documentation of the MQTT capabilities in the cFos Charging Manager.

In addition to a number of predefined variables, such as current and voltage, user-defined counters can also read in unknown user-defined variables, query inputs and set outputs. Reading in variables and setting outputs allows the evaluation of formulas. In combination with the Charging Manager variables and global Charging Manager outputs described below, this is a powerful feature and even allows certain home automation tasks and the control of external devices such as battery storage. If you realise control tasks with this, please give us feedback. We are very interested in what people control with the cFos Charging Manager and it helps us to further develop the Charging Manager according to customer needs.

Here is a simple example definition for Modbus that reads a single register for active power. You can easily modify the register number for your specific application:
Example definition for a single register.

Here is an example definition for Modbus and one for HTTP/JSON:
Download sample definition for Modbus meter
Download sample definition for HTTP/JSON meter

The Charging Manager already comes with a few such files, but you can upload your own files under "System configuration" and also delete them again.
Here you will find most of the meter definitions we provide:
Download supplied counter definitions

If you have created your own counter file and it could be relevant for other users, we would be very grateful if you could make it available to us. Then we will deliver it with future versions of the Charging Manager.

Download meter definitions for additional meters

Structure of a definition file:

Counter definitions are JSON files with a global JSON object that has properties and sub-objects. 'rtype' determines the type of read operation: 0 = Modbus, 1 = HTTP/JSON, 2 = MQTT/JSON. 'mtype' determines the device type: 0 = Other device, 1 = Meter, 2 = Inverter, 4 = Battery storage.

You can specify numbers either in decimal or hex with the prefix 0x. Single-line comments using // are also permitted. We recommend running your definition files through a JSON5 validator, e.g. this JSON5 validator

You should definitely have read the Formulas chapter to understand which values can be used in formulas in the following reference.

Modbus definitions have an object 'rtu' with the following properties:

silence_period, in msec. determined, the pause length before a Modbus RTU access, so that the device recognises the start of a message.
silence_same_slave, true: The pause is also observed with several accesses to the same device.
retries: The number of retries if the device does not respond.
rcv_timeout: in msec. the maximum waiting time per access until the device responds.

These global properties apply to Modbus TCP and RTU:

modbus_read: The function number of the Modbus read command, usually 3 or 4.
modbus_read_max_registers: The maximum number of registers that can be read at a time.
modbus_allow_gaps: true = Unused register areas may be read in a read operation.

For Modbus TCP and HTTP/JSON there is an object 'tcp' with the following properties:

connect_timeout: is msec. the maximum waiting time for a TCP connection.
delay_after_connect: in msec. Pause after the connection is established before sending the first command.

Both definition types (Modbus and HTTP/JSON) have the following additional properties:

upd_delay: in msec. determines the interval in which a device can be read. Some devices are overloaded if they are queried too often.
manufacturer: String, name of the manufacturer. This is displayed in the extended information of the tile.
delay_accumulated: true = Accumulated values (kWh) are only queried every 3 seconds or if there is sufficient power. false = These values are always queried.
ui_addr: URL, if different from the device address for calling the web interface.
reserved: Array with values that are interpreted as 0 (useful if the device supports certain values depending on the model).

If you omit the properties listed above, the cFos Charging Manager takes default values that work well in most cases.

In the JSON definition, the next step is the definition of variables that the meter uses to read or calculate values for current, voltage, etc. The following variables are used by the Charging Manager. The Charging Manager knows the following variables:
type_designation, version, firmware_version, serial: These form the model name as shown in the extended info of the tile. These are queried once when setting up or resetting the meter.
voltage_l1..voltage_l3, current_l1..current_l3, power_w, power_var, power_va, power_w_l1..power_w_l3: The cFos Charging Manager tries to calculate values for voltage_l1..l3, signed current_l1..l3, power_w and power_va from these. You do not have to specify all variables. The cFos Charging Manager tries to calculate the values from the existing variables.
import_wh, export_wh: The Charging Manager uses these variables to display import_wh and export_wh. For unidirectional meters (e.g. inverters), you should always define import_wh only. Export_wh should only be defined for bidirectional meters (such as storage tanks or grid reference meters).

soc: If available, the State of Charge of a battery storage tank is displayed in % in the tile.
In addition, you can define other variables with different names that are read out with each update or calculated using formulas. If you define variables that begin with CM., e.g. CM._set_price, the assigned values are stored in the global Charging Manager variables (see below) and can be queried accordingly.
Variables with *: If you define variables that begin with *, they are displayed in the UI in the tile of the meter under extended information, e.g. the temperature of a battery storage.

Definition of a variable:

The object is named after the name of the variable listed above and has the following properties:
fixed: String with a fixed value. Useful if, for example, no value can be determined, e.g. for type_designation or voltage.
expr: String, the variable is not read out but evaluated as a formula.
type: If not fixed or expr, the type of variable: int16, uint16, int32, uint32, float, int64, string. This is important for Modbus in order to read the registers in the correct format. uint16 and uint32 are types that can only accept positive numbers. With JSON/HTTP, you can usually use float.
resolution: float, the read value is multiplied by 'resolution'. Values for voltage must be in volts, currents in milliamperes, power in watts, energy in watt-hours (Wh). With negative 'resolution' you can invert a value if it has the opposite sign.
once: bool (true or false), if true, the value is only read once when the device is initialised, otherwise periodically.
address: number (Modbus) or string (HTTP/JSON), the Modbus register number or the HTTP URL of the value to be read.
query: String, for HTTP JSON the specification in the query language of the Charging Manager with which it finds the value to be read in the JSON response.
order: String, for Modbus the byte order, either "hl" or "lh", in which the value is present. length: number, for Modbus the length of a string in registers. For the variables 'version' and 'firmware_version', 'length' is used to turn numerical versions into strings with dots. Values of 2 or 4 are permitted for 'length', which then result in the version formats a.b, and a.b.c.d. With 'length' 2 and type 'int16' or 'uint16', the Charging Manager separates low and high byte with a dot, with 'int32' or 'uint32' low and high word, with 'int64' low and high dword. For 'lenth' 4 and 'int32' or 'uint32', the Charging Manager splits the value into 4 bytes separated by a dot. For 'int64' the 4 words accordingly.
regex: String. If a regular expression is specified, the counter response does not need to be in JSON. Either the entire match of the regular expression or the first group is evaluated as the result. Please only use this if the device does not return JSON. Here is the list of features of our regular expressions:
any char: .
named classes: \d \s \w \D \S \W
anonymous classes: [a-z0-9_], [^0-9], [^\d]
groups with alternatives: (ab|cd|ef)
non-captured groups: (?:ab|cd)
(greedy) once or none: a?, a???
(greedy ) many or none: a*, a*?
(greedy) once or more: a+, a+?
begin of string: ^
end of string: $

Definition of inputs:

The Charging Manager can query up to 32 input values from different registers or JSON elements per device. The "Inputs" property is a JSON array. You must define the following properties for each input:
address: Address (Modbus register or URL).
count: Number of input bits that will be read with this request.
query: For HTTP/JSON, query language to find the value in the response.

The cFos Charging Manager reads all inputs defined in this way with each update and places the bits internally in an array, which can then be queried with in formulas, Input1..InputN..

Definition of outputs:

The Charging Manager can switch up to 32 outputs per device. Outputs are defined in "outputs" as a JSON array of output objects. All outputs are switched at the end of each update cycle if the status of the respective output has changed.
For each output, you must define the following properties in the output object:
address: HTTP URL with optional HTTP method, e.g. GET http://www.example.com?output1=${var1}. To set Modbus registers, you can use the HTTP API of the cFos Charging Manager. The Charging Manager detects matching accesses on localhost and redirects the request to the internal handler, so you don't need authorisation as with external HTTP API accesses. If the URL is empty after all replacements, no output is set. For example, you can only switch outputs if certain variables exist (see formulas: exists() function). In the address you can additionally specify ${address} and ${id}. This is the current device address and Modbus ID as defined in the settings. Address and id are mainly used for using the Modbus API (see below).
body: Optional HTTP body for POST or PUT.
In the URL and body, you can use ${expr} formulas that reference global Charging Manager variables or from the respective counter. The formula 'expr' is evaluated when setting the output and replaced in the text of the URL or the body. If, in the above example, http://www.example.com?output1=1 sets the output and http://www.example.com?output1=0 deletes it, you can define a variable 'var1' and set it to 1 or 0 as desired. In this way, you can also write numerical values to control memory performance in Modbus registers that you have previously stored in a variable using a formula.
If instead of passing a numerical value in the URL you need to replace one text with another depending on the formula, such as with Shelly WLAN sockets, you can write it like this: ${if expr`text1`text2}. The 'apostrophe' is a backtick (ASCII code 96). If the 'expr' != 0, text1 is inserted, otherwise text2. For Shelly WLAN socket, the URL then looks like this: http://<ip-addr>/relay/0?turn=${if expr`on`off}, i.e. if expr != 0, the Charging Manager then calls http://<ip-addr>/relay/0?turn=on, otherwise http://<ip-addr>/relay/0?turn=off.

If you enter a relative path as the URL, the Charging Manager takes the address configured for the respective device. If you enter 'localhost' as the domain, the Charging Manager takes the address of the device on which it is running. If it detects an access to its own API, it uses the internal handler instead of executing a full HTTP access, so that you do not have to store a user name and password in the counter definition. A URL that starts with a * will cause the Charging Manager to always perform a full HTTP access.

Reset outputs: In addition to an "outputs" array, you can also define an array named "resets" that is structured like the "outputs" array. This can be used to reset outputs to their initial values when the device is deactivated. With this, in combination with user-defined variables and "once": true, you can set the unit back to its initial state.
Write outputs periodically: For some devices, the outputs must be written periodically, otherwise the device resets the values to "default". For example, the Kostal memory uses its default rules again if the memory control has not been written actively for a while. To set outputs periodically, you can prefix the address with #xxx#, where xxx indicates every how many seconds the output is rewritten, even if the value to be written has remained the same. For example, if the address is /cnf?cmd=set_cm_vars&name=test&val=42, you can use #30#/cnf?cmd=set_cm_vars&name=test&val=42 to ensure that this value is written every 30 seconds.

Definition of query langage:

Currently, member names and the operators "." and "[]" can be used in the "query" search expressions, examples:

testElement named "test"
name1.name2Element named "name2" in child object "name1"
name[idx]Element "idx" of the object element "name". "idx" can be a number, e.g. for arrays or a string
name["u2"]Element "u2" of the object element "name", corresponds to "name.u2"
name[{"el1": "v1", "el2": 3}].valueSelect the array element that fulfils the condition of the object notation and evaluate the element named 'value'. Here, for example, in the array 'name', the element is selected that has as object elements 'el1' with value 'v1' and 'el2' with value 3 and then the value of the element 'value' is returned from this object.

Global Charging Manager variables:

You can create variables in the Charging Manager configuration. You can use a fixed value or a formula as the value. At the end of each update cycle, the Charging Manager recalculates the value of these variables if necessary. You can then use them in (certain) Charging Manager parameters, Charging Rules or to control outputs. You can also write Ex.member or Mx.member as variables. Here, Exand Mxare the device ID of a wallbox or meter set up in the Charging Manager. member is a "user-defined" variable that is stored in the corresponding device. Some of the variables may have a special meaning: For KEBA "out1" is a switching output, for ABB B23 meters "out1" and "out2" are switching outputs (for models that support this). A 1 switches the output, a 0 switches it off again.

If you have appliances that have to be switched on under certain conditions but then run for a while (e.g. washing machine, dishwasher), you can also define the variable as a "trigger". Then the formula of the variable is the condition with which the variable is set to 1. After an adjustable time, it is then set to 0 again. A "retrigger condition" allows the time until switching off (i.e. setting the variable to 0) to be extended again and again as long as the condition is fulfilled.

For test purposes, you can display Charging Manager and meter variables, e.g. the current Awattar prices:


                        Screenshot display of counter variables

Global Charging Manager Outputs:

In the Charging Manager configuration, you can configure global outputs as described above in the counter definition under 'Outputs'. These are set at the end of each update cycle if their status has changed. If you want to control switching outputs in user-defined devices, the above convention is recommended (see Charging Manager Variables): You set variables with names "out1", "out2", etc. in the user-defined counter and set up outputs in the user-defined counter that switch the output depending on the value of these variables.

Global Modbus API of the Charging Manager:

The Modbus API of the Charging Manager is used to control Modbus devices that have any Modbus RTU or TCP address (accessible from the Charging Manager). For Modbus RTU, enter COMx,bd,8,p,s as the address, where x is the COM port number, bd is the baud rate, p is the parity ('N', 'E' or 'O') and s is the number of stop bits (1 or 2), as in the configuration of the individual devices. For Modbus TCP, the addressee is the IP address of the device in the Charging Manager's network including the port number.
The URL (for HTTP GET) of the Modbus API is:
/cnf?cmd=modbus_get or /cnf?cmd=modbus_set
The cFos Charging Manager supports the following additional query parameters:
addr: The Modbus RTU or TCP device address mentioned above.
func: Modbus function number, e.g. for reading 3 or 4, for writing 6 or 16.
id: Device ID of the Modbus device.
reg: The Modbus register number. The value can be given in decimal or hex (with prefix 0x).
val: number, value to be written into the register. Omit when reading.
type: 'w' 16bit (default), d = 32bit, f = float, q = 64bit, s = string.
cnt: number, the maximum length of the string in registers, omit for other types or set to 1.
order: String, the byte order, either "hl" or "lh".

Note: If your 'counter' primarily has control tasks, you can tick the option 'Hide device' in the settings of this tile so that this device does not appear on the start page.

Note: Some meters that are read via HTTP require a user name/password as authorisation. You can specify this in the address for HTTP access, e.g. with http://username:password@192.168.2.111. If your user name or password contains an "@", you must replace it with "%40".