Merge remote-tracking branch 'origin/mqttintegration'
This commit is contained in:
@@ -0,0 +1,320 @@
|
||||
# Configuration file for ebusd MQTT integration with Home Assistant (https://www.home-assistant.io/).
|
||||
|
||||
# Use this file with ebusd in MQTT JSON mode to have many seen messages automatically appear on HA. This is achieved by
|
||||
# using the MQTT Discovery feature of Home Assistant (see https://www.home-assistant.io/docs/mqtt/discovery/).
|
||||
# The commandline options to ebusd should contain e.g.:
|
||||
# --mqttport=1883 --mqttjson --mqttint=/etc/ebusd/mqtt-hassio.cfg
|
||||
|
||||
|
||||
# This file allows flexible construction of MQTT topics and payloads depending on message and field definitions as well
|
||||
# as global status topics.
|
||||
# It is a set of named variables (or constants) with the name on the left of an equal sign and the value on the right,
|
||||
# where only the value is allowed to contain references to other variables.
|
||||
# A reference to a variable is escaped by a leading "%" character in front of the variable name consisting of only
|
||||
# alphabetic characters or the underscore. A double percent character "%%" is replaced by a single "%" in the value.
|
||||
# Curly braces may be used to separate a variable explicitly from the rest, e.g. as "%{version}" instead of "%version".
|
||||
# Every variable without an underscore in the name is automatically made available as well with an uppercase name and a
|
||||
# normalized value composed of only alphanumeric characters or underscore (i.e. suitable for being part of a topic).
|
||||
# When using "?=" instead of only the equal sign in a variable definition, the variable value is set to empty when one
|
||||
# of the variables referred to is empty or missing.
|
||||
|
||||
# The variable replacements are constructed for each message and/or field (depending on whether the topic is field
|
||||
# specific or not) in the following order:
|
||||
|
||||
# 1. predefined constants from ebusd, i.e.
|
||||
# %version the ebusd version number.
|
||||
# %prefix the invariable prefix part of the "--mqtttopic" configuration option, defaults to "ebusd/".
|
||||
# %prefixn the same as %prefix but without trailing slashes or underscores.
|
||||
|
||||
# 2. variables referring to constants only (directly or indirectly).
|
||||
|
||||
# 3. circuit and message specific variables:
|
||||
# %circuit the circuit name.
|
||||
# %name the message name.
|
||||
# %priority the message poll priority (or 0).
|
||||
# %level the message access level (or empty).
|
||||
# %messagecomment the message comment.
|
||||
# %direction the message direction ("r", "w", "u", or "uw").
|
||||
# %topic the message update topic built from the mqtttopic configuration option (only if the topic is not field
|
||||
# specific) and/or the %topic variable defined here.
|
||||
|
||||
# 4. the direction mapped from variables named "direction_map-%direction" with the actual direction in the suffix.
|
||||
# Available as "%direction_map".
|
||||
|
||||
# 5. the field type mapped from variables named "type_map-%direction-%type" or "type_map-%type" as fallback with the
|
||||
# field type and the optional direction in the suffix. The variable including the direction is evaluated first and
|
||||
# if it is missing or the result is empty, the variable excluding the direction is used instead.
|
||||
# This is also an implicit field type filter as missing or empty mappings are not published at all.
|
||||
# Available as "%type_map".
|
||||
|
||||
# 6. other field specific variables for each field (only once for each message if the topic is field specific):
|
||||
# %index the field index (excluding ignored fields).
|
||||
# %field the field name (or the field index if no name is defined or the names are not unique in the message).
|
||||
# %type the field type (one of "number", "list", "string", "date", "time", or "datetime").
|
||||
# %basetype the base data type ID (e.g. "UCH").
|
||||
# %comment the field comment (if any).
|
||||
# %unit the field unit (if any).
|
||||
# %min and %max the minimum/maximum possible value for number fields.
|
||||
# %topic the field (or message) update topic built from the mqtttopic configuration option and/or the %topic variable
|
||||
# defined here.
|
||||
|
||||
# 7. optional field type switch in "%type_switch" using the value of the variable named "type_switch-by" and matching it
|
||||
# against the value lines of the variable named "type_switch-%type" with the field type in the suffix.
|
||||
# The value of such a variable needs to be a constant list of string pairs with one pair per line. Each pair is
|
||||
# separated by "=" and the left part is the value set to the "type_switch" variable when the wildcard pattern in the
|
||||
# right part matches the value of the "type_switch-by" value. The list is traversed from top to bottom with the
|
||||
# first match stopping the evaluation. Optionally, "type_switch-names" can be used to define a list of variable
|
||||
# names to be set in addition to the "type_switch" variable, in which case a list of variable names (comma
|
||||
# separated) is expected as "type_switch-names" value and the appropriate values to set on the left side of each
|
||||
# match list entry.
|
||||
# Available as "%type_switch" and optionally by the set of fields as defined in "%type_switch-names".
|
||||
|
||||
# 8. optional field type part mapping in "%type_part" for each field type in variables named "type_part-%type" with the
|
||||
# field type in the suffix (or the value of the "type_part-by" variable).
|
||||
|
||||
# 9. if the %fields_payload variable is used, then it is set to the concatenation of all fields of the message:
|
||||
# %field_payload is expected to build a single field payload.
|
||||
# %field-separator is the separator placed between consecutive field payloads.
|
||||
# %fields_payload is set to the concatenation of all fields of the message, separated by %field-separator.
|
||||
|
||||
# 10. %definition-topic, %definition-payload, and %definition-retain to build the message definition topic and payload
|
||||
# and determine the retain value.
|
||||
|
||||
|
||||
# Before constructing the variable replacements, the messages and fields can optionally be filtered in order to use
|
||||
# certain message definitions only. All of these criteria are applied, so they are basically combined by "AND".
|
||||
# Filters with a "partial match" mention in the documentation allow using a limited glob/regex inspired case insensitive
|
||||
# matching with the following options:
|
||||
# - "|" allows defining alternatives, e.g. "a|b" matches "but" as well as "all".
|
||||
# - "^" matches the beginning of the input, e.g. "^al" matches "al" but not "hal".
|
||||
# - "$" matches the end of the input, e.g. "al$" matches "hal" but not "all".
|
||||
# - "*" matches a single arbitrary length wildcard part in the middle, e.g. "^a*l$" matches "all" but not "always".
|
||||
|
||||
# include only messages having data sent at least once (only checked for passive or read messages, not for active write).
|
||||
# HA integration: filtering only seen messages to avoid unnecessary "pollution"
|
||||
filter-seen = 1
|
||||
# include only messages having a priority less than or equal to the specified value.
|
||||
#filter-priority =
|
||||
# include only messages having the specified circuit (partial match, alternatives and wildcard supported).
|
||||
#filter-circuit =
|
||||
# include only messages having the specified name (partial match, alternatives and wildcard supported).
|
||||
# HA integration: filter to some useful names for monitoring the heating circuit
|
||||
filter-name = status|temp|yield|count|energy|power|runtime|hours|starts|mode|curve|^load$|^party$
|
||||
# include only messages having the specified level (partial match, alternatives and wildcard supported).
|
||||
# Note: Since the empty string matches all levels, an explicit check for empty string (with "^$") needs to be used for
|
||||
# including only messages without a level.
|
||||
filter-level = ^$
|
||||
# include only messages having the specified direction ("r", "w", "u", or "uw". partial match, alternatives and wildcard supported).
|
||||
# HA integration: writable messages excluded for now
|
||||
filter-direction = r|u
|
||||
# include only fields having the specified name (partial match, alternatives and wildcard supported).
|
||||
#filter-field =
|
||||
|
||||
|
||||
# HA integration: home assistant configuration topics prefix
|
||||
haprefix = homeassistant
|
||||
# HA integration: the area of all entities in home assistant
|
||||
area = Heating
|
||||
|
||||
# HA integration: circuit specific part used as device entity for message definitions below
|
||||
circuit_part = {
|
||||
"identifiers":"%{PREFIX}_%CIRCUIT",
|
||||
"manufacturer":"ebusd.eu",
|
||||
"name":"%prefixn %circuit",
|
||||
"via_device":"%PREFIXN",
|
||||
"sw_version":"%version",
|
||||
"suggested_area":"%area"
|
||||
}
|
||||
|
||||
# the field type mapped from variables named "type_map-%direction-%type" or "type_map-%type" as fallback with the
|
||||
# field type and the optional direction in the suffix. The variable including the direction is evaluated first and
|
||||
# if it is missing or the result is empty, the variable excluding the direction is used instead.
|
||||
# This is also an implicit field type filter as missing or empty mappings are not published at all.
|
||||
type_map-number = number
|
||||
type_map-list = string
|
||||
# HA integration: skip string/date/time types completely
|
||||
type_map-string =
|
||||
type_map-date =
|
||||
type_map-time =
|
||||
type_map-datetime =
|
||||
|
||||
# field type switch designator, see below.
|
||||
# HA integration: this is used to set several variable values depending on the field type, name, message, and field unit.
|
||||
type_switch-by = %name%field,%unit
|
||||
|
||||
# field type switch variables names to use in addition to %type_switch in case of multiple keys (separated by comma).
|
||||
# HA integration: var names for topic/class/state values mapped from field type, name, message, and unit.
|
||||
type_switch-names = type_topic,type_class,type_state
|
||||
|
||||
# field type switch for each field type and optionally direction (between dash before the field type) available as
|
||||
# %type_switch (as well as the variable names defined in "type_switch-names" if any).
|
||||
# The value needs to be a constant list of string pairs with one pair per line. Each pair is separated by "=" and the
|
||||
# left part is the value set to the type_switch variable (as well as the variable names defined in %type_switch-names)
|
||||
# when the wildcard string in the right part matched the "type_switch-by" value. The list is traversed from top to
|
||||
# bottom stopping at the first match. If direction specific definitions exist, these are traversed first. If no line
|
||||
# matches at all, the variable(s) are set to the empty string.
|
||||
# HA integration: the mapping list for (potentially) writable number entities by field type, name, message, and unit.
|
||||
type_switch-w-number =
|
||||
number,temperature, = temp|,°C$
|
||||
number,power_factor, = power*%%
|
||||
number,power, = power|,kW$|,W$
|
||||
number,voltage, = volt|,V$
|
||||
number,current, = current,|,A$
|
||||
number,pressure, = bar$
|
||||
number,gas, = gas*/min$
|
||||
number,humidity, = humid*%%$
|
||||
|
||||
# HA integration: the mapping list for numeric sensor entities by field type, name, message, and unit.
|
||||
type_switch-number =
|
||||
sensor,temperature,measurement = temp|,°C$
|
||||
sensor,power_factor,measurement = power*%%
|
||||
sensor,power,measurement = power|,kW$|,W$
|
||||
sensor,voltage,measurement = volt|,V$
|
||||
sensor,current,measurement = current,|,A$
|
||||
sensor,energy,total_increasing = energy|,Wh$
|
||||
sensor,yield,total_increasing = total*,Wh$
|
||||
sensor,,total_increasing = hours|,h$
|
||||
sensor,,total_increasing = starts*,$
|
||||
sensor,pressure,measurement = bar$
|
||||
sensor,gas,measurement = gas*/min$
|
||||
sensor,humidity,measurement = humid*%%$
|
||||
sensor,, =
|
||||
|
||||
# HA integration: the mapping list for (potentially) writable binary switch entities by field type, name, message, and unit.
|
||||
type_switch-w-list =
|
||||
switch,, = onoff
|
||||
|
||||
# HA integration: the mapping list for rather binary sensor entities by field type, name, message, and unit.
|
||||
type_switch-list =
|
||||
binary_sensor,,measurement = onoff
|
||||
sensor,, =
|
||||
|
||||
# HA integration: currently unused mapping lists for non-numeric/non-binary entities.
|
||||
#type_switch-string =
|
||||
# sensor,, =
|
||||
#type_switch-date =
|
||||
# sensor,,measurement =
|
||||
#type_switch-time =
|
||||
# sensor,,measurement =
|
||||
#type_switch-datetime =
|
||||
# sensor, =
|
||||
|
||||
# HA integration: optional variable with the entity device class for numbers
|
||||
type_class_number ?= ,
|
||||
"device_class":"%type_class"
|
||||
|
||||
# HA integration: optional variable with the entity device class for sensors
|
||||
type_class_sensor ?= ,
|
||||
"device_class":"%type_class"
|
||||
|
||||
# HA integration: optional variable with the entity state class
|
||||
state_class ?= ,
|
||||
"state_class":"%type_state"
|
||||
|
||||
# HA integration: optional variable with the entity unit
|
||||
unit_of_measurement ?= ,
|
||||
"unit_of_measurement":"%unit"
|
||||
|
||||
# field type part suffix to use instead of the field type itself, see below.
|
||||
# HA integration: %type_part variable mapped from the mapped %type_topic
|
||||
type_part-by = %type_topic
|
||||
|
||||
# field type part mappings for each field type (or the "type_part-by" variable value) in the suffix (available as
|
||||
# %type_part).
|
||||
# HA integration: %type_part variable for number %type_topic
|
||||
type_part-number = ,
|
||||
"command_topic":"%topic/set",
|
||||
"min":%min,
|
||||
"max":%max%unit_of_measurement%state_class%type_class_number
|
||||
|
||||
# HA integration: %type_part variable for sensor %type_topic
|
||||
type_part-sensor = %unit_of_measurement%state_class%type_class_sensor
|
||||
|
||||
# HA integration: %type_part variable for switch %type_topic
|
||||
type_part-switch = ,
|
||||
"command_topic":"%topic/set",
|
||||
"payload_on":"on",
|
||||
"payload_off":"off"%state_class
|
||||
|
||||
# HA integration: %type_part variable for binary_sensor %type_topic
|
||||
type_part-binary_sensor = ,
|
||||
"payload_on":"on",
|
||||
"payload_off":"off"%state_class
|
||||
|
||||
# the field specific part (evaluated after the message specific part).
|
||||
# HA integration: set to the mapped %type_part from above
|
||||
field_payload = %type_part
|
||||
|
||||
|
||||
# the message definition config topic, payload, and retain setting.
|
||||
# HA integration: the config topic for HA's MQTT discovery for the ebusd message definition found.
|
||||
# set to conditionally to avoid incomplete configs.
|
||||
definition-topic ?= %haprefix/%type_topic/%{TOPIC}_%FIELD/config
|
||||
# HA integration: this is the config topic payload for HA's MQTT discovery.
|
||||
definition-payload = {
|
||||
"unique_id":"%{TOPIC}_%FIELD",
|
||||
"name":"%prefixn %circuit %name %field",
|
||||
"device":%circuit_part,
|
||||
"value_template":"{{value_json[\"%field\"].value}}",
|
||||
"state_topic":"%topic"%field_payload
|
||||
}
|
||||
#definition-retain = 0
|
||||
|
||||
|
||||
# the message value topic (if other than the default). If set here, it will be replaced by the "--mqtttopic"
|
||||
# configuration option only if that one contains at least one variable. If the the "--mqtttopic" configuration option
|
||||
# does not contain any variable, it is taken as prefix and can be used here as well.
|
||||
# HA integration: use the prefix from --mqtttopic and non field specific topic for the actual data
|
||||
topic = %prefix/%circuit/%name
|
||||
|
||||
|
||||
# HA integration: global part used as device entity for the global config topics
|
||||
global_device = {
|
||||
"identifiers":"%PREFIXN",
|
||||
"manufacturer":"ebusd.eu",
|
||||
"name":"%prefixn",
|
||||
"sw_version":"%version",
|
||||
"suggested_area":"%area"
|
||||
}
|
||||
|
||||
# HA integration: common prefix for global parts
|
||||
global_prefix = {
|
||||
"unique_id":"%TOPIC",
|
||||
"device":%global_device,
|
||||
"state_topic":"%topic",
|
||||
"name":"%prefixn %name"
|
||||
|
||||
# HA integration: boolean suffix for global parts
|
||||
global_boolean_suffix = ,
|
||||
"state_class":"measurement",
|
||||
"payload_on":"true",
|
||||
"payload_off":"false"
|
||||
}
|
||||
|
||||
# the common global config topic, payload, and retain setting (used by running, version, signal, uptime, updatecheck,
|
||||
# and scan if not otherwise defined explicitly).
|
||||
# HA integration: the config topic for HA's MQTT discovery for the ebusd global parts.
|
||||
def_global-topic = %haprefix/sensor/%TOPIC/config
|
||||
def_global-payload = %global_prefix,
|
||||
"state_class":"measurement"
|
||||
}
|
||||
#def_global-retain = 0
|
||||
|
||||
# individual global running, version, signal, uptime, updatecheck, and scan config topic, payload, and retain setting.
|
||||
def_global_running-topic = %haprefix/binary_sensor/%TOPIC/config
|
||||
def_global_running-payload = %global_prefix,
|
||||
"device_class":"running"%global_boolean_suffix
|
||||
def_global_version-topic =
|
||||
def_global_uptime-payload = %global_prefix,
|
||||
"state_class":"total_increasing",
|
||||
"unit_of_measurement":"s"
|
||||
}
|
||||
def_global_signal-topic = %haprefix/binary_sensor/%TOPIC/config
|
||||
def_global_signal-payload = %global_prefix,
|
||||
"device_class":"connectivity"%global_boolean_suffix
|
||||
|
||||
|
||||
# the topic and payload to listen to in order to republish all config messages.
|
||||
# HA integration: force republish of all configs when HA goes down and comes up again.
|
||||
config_restart-topic = %haprefix/status
|
||||
config_restart-payload = online
|
||||
@@ -0,0 +1,180 @@
|
||||
# Configuration file for ebusd MQTT integration.
|
||||
|
||||
# This file allows flexible construction of MQTT topics and payloads depending on message and field definitions as well
|
||||
# as global status topics.
|
||||
# It is a set of named variables (or constants) with the name on the left of an equal sign and the value on the right,
|
||||
# where only the value is allowed to contain references to other variables.
|
||||
# A reference to a variable is escaped by a leading "%" character in front of the variable name consisting of only
|
||||
# alphabetic characters or the underscore. A double percent character "%%" is replaced by a single "%" in the value.
|
||||
# Curly braces may be used to separate a variable explicitly from the rest, e.g. as "%{version}" instead of "%version".
|
||||
# Every variable without an underscore in the name is automatically made available as well with an uppercase name and a
|
||||
# normalized value composed of only alphanumeric characters or underscore (i.e. suitable for being part of a topic).
|
||||
# When using "?=" instead of only the equal sign in a variable definition, the variable value is set to empty when one
|
||||
# of the variables referred to is empty or missing.
|
||||
|
||||
# The variable replacements are constructed for each message and/or field (depending on whether the topic is field
|
||||
# specific or not) in the following order:
|
||||
|
||||
# 1. predefined constants from ebusd, i.e.
|
||||
# %version the ebusd version number.
|
||||
# %prefix the invariable prefix part of the "--mqtttopic" configuration option, defaults to "ebusd/".
|
||||
# %prefixn the same as %prefix but without trailing slashes or underscores.
|
||||
|
||||
# 2. variables referring to constants only (directly or indirectly).
|
||||
|
||||
# 3. circuit and message specific variables:
|
||||
# %circuit the circuit name.
|
||||
# %name the message name.
|
||||
# %priority the message poll priority (or 0).
|
||||
# %level the message access level (or empty).
|
||||
# %messagecomment the message comment.
|
||||
# %direction the message direction ("r", "w", "u", or "uw").
|
||||
# %topic the message update topic built from the mqtttopic configuration option (only if the topic is not field
|
||||
# specific) and/or the %topic variable defined here.
|
||||
|
||||
# 4. the direction mapped from variables named "direction_map-%direction" with the actual direction in the suffix.
|
||||
# Available as "%direction_map".
|
||||
|
||||
# 5. the field type mapped from variables named "type_map-%direction-%type" or "type_map-%type" as fallback with the
|
||||
# field type and the optional direction in the suffix. The variable including the direction is evaluated first and
|
||||
# if it is missing or the result is empty, the variable excluding the direction is used instead.
|
||||
# This is also an implicit field type filter as missing or empty mappings are not published at all.
|
||||
# Available as "%type_map".
|
||||
|
||||
# 6. other field specific variables for each field (only once for each message if the topic is field specific):
|
||||
# %index the field index (excluding ignored fields).
|
||||
# %field the field name (or the field index if no name is defined or the names are not unique in the message).
|
||||
# %type the field type (one of "number", "list", "string", "date", "time", or "datetime").
|
||||
# %basetype the base data type ID (e.g. "UCH").
|
||||
# %comment the field comment (if any).
|
||||
# %unit the field unit (if any).
|
||||
# %min and %max the minimum/maximum possible value for number fields.
|
||||
# %topic the field (or message) update topic built from the mqtttopic configuration option and/or the %topic variable
|
||||
# defined here.
|
||||
|
||||
# 7. optional field type switch in "%type_switch" using the value of the variable named "type_switch-by" and matching it
|
||||
# against the value lines of the variable named "type_switch-%type" with the field type in the suffix.
|
||||
# The value of such a variable needs to be a constant list of string pairs with one pair per line. Each pair is
|
||||
# separated by "=" and the left part is the value set to the "type_switch" variable when the wildcard pattern in the
|
||||
# right part matches the value of the "type_switch-by" value. The list is traversed from top to bottom with the
|
||||
# first match stopping the evaluation. Optionally, "type_switch-names" can be used to define a list of variable
|
||||
# names to be set in addition to the "type_switch" variable, in which case a list of variable names (comma
|
||||
# separated) is expected as "type_switch-names" value and the appropriate values to set on the left side of each
|
||||
# match list entry.
|
||||
# Available as "%type_switch" and optionally by the set of fields as defined in "%type_switch-names".
|
||||
|
||||
# 8. optional field type part mapping in "%type_part" for each field type in variables named "type_part-%type" with the
|
||||
# field type in the suffix (or the value of the "type_part-by" variable).
|
||||
|
||||
# 9. if the %fields_payload variable is used, then it is set to the concatenation of all fields of the message:
|
||||
# %field_payload is expected to build a single field payload.
|
||||
# %field-separator is the separator placed between consecutive field payloads.
|
||||
# %fields_payload is set to the concatenation of all fields of the message, separated by %field-separator.
|
||||
|
||||
# 10. %definition-topic, %definition-payload, and %definition-retain to build the message definition topic and payload
|
||||
# and determine the retain value.
|
||||
|
||||
|
||||
# Before constructing the variable replacements, the messages and fields can optionally be filtered in order to use
|
||||
# certain message definitions only. All of these criteria are applied, so they are basically combined by "AND".
|
||||
# Filters with a "partial match" mention in the documentation allow using a limited glob/regex inspired case insensitive
|
||||
# matching with the following options:
|
||||
# - "|" allows defining alternatives, e.g. "a|b" matches "but" as well as "all".
|
||||
# - "^" matches the beginning of the input, e.g. "^al" matches "al" but not "hal".
|
||||
# - "$" matches the end of the input, e.g. "al$" matches "hal" but not "all".
|
||||
# - "*" matches a single arbitrary length wildcard part in the middle, e.g. "^a*l$" matches "all" but not "always".
|
||||
|
||||
# include only messages having data sent at least once (only checked for passive or read messages, not for active write).
|
||||
filter-seen = 1
|
||||
# include only messages having a priority less than or equal to the specified value.
|
||||
#filter-priority =
|
||||
# include only messages having the specified circuit (partial match, alternatives and wildcard supported).
|
||||
#filter-circuit =
|
||||
# include only messages having the specified name (partial match, alternatives and wildcard supported).
|
||||
#filter-name =
|
||||
# include only messages having the specified level (partial match, alternatives and wildcard supported).
|
||||
# Note: Since the empty string matches all levels, an explicit check for empty string (with "^$") needs to be used for
|
||||
# including only messages without a level.
|
||||
filter-level = ^$
|
||||
# include only messages having the specified direction ("r", "w", "u", or "uw". partial match, alternatives and wildcard supported).
|
||||
filter-direction = r|u
|
||||
# include only fields having the specified name (partial match, alternatives and wildcard supported).
|
||||
#filter-field =
|
||||
|
||||
|
||||
# the field type mapped from variables named "type_map-%direction-%type" or "type_map-%type" as fallback with the
|
||||
# field type and the optional direction in the suffix. The variable including the direction is evaluated first and
|
||||
# if it is missing or the result is empty, the variable excluding the direction is used instead.
|
||||
# This is also an implicit field type filter as missing or empty mappings are not published at all.
|
||||
type_map-number = number
|
||||
type_map-list = string
|
||||
type_map-string = string
|
||||
type_map-date = string
|
||||
type_map-time = string
|
||||
type_map-datetime = string
|
||||
|
||||
|
||||
# field type switch designator, see below.
|
||||
#type_switch-by = %name%field,%unit
|
||||
|
||||
# field type switch variables names to use in addition to %type_switch in case of multiple keys (separated by comma).
|
||||
#type_switch-names = type_topic,type_class,type_state
|
||||
|
||||
# field type switch for each field type and optionally direction (between dash before the field type) available as
|
||||
# %type_switch (as well as the variable names defined in "type_switch-names" if any).
|
||||
# The value needs to be a constant list of string pairs with one pair per line. Each pair is separated by "=" and the
|
||||
# left part is the value set to the type_switch variable (as well as the variable names defined in %type_switch-names)
|
||||
# when the wildcard string in the right part matched the "type_switch-by" value. The list is traversed from top to
|
||||
# bottom stopping at the first match. If direction specific definitions exist, these are traversed first. If no line
|
||||
# matches at all, the variable(s) are set to the empty string.
|
||||
#type_switch-w-number =
|
||||
|
||||
|
||||
# field type part suffix to use instead of the field type itself, see below.
|
||||
#type_part-by = %type_topic
|
||||
|
||||
# field type part mappings for each field type (or the "type_part-by" variable value) in the suffix (available as
|
||||
# %type_part).
|
||||
#type_part-number = ,
|
||||
|
||||
|
||||
# the field specific part (evaluated after the message specific part).
|
||||
#field_payload = %type_part
|
||||
|
||||
|
||||
# the message definition config topic, payload, and retain setting.
|
||||
definition-topic = %prefixn/config/%CIRCUIT/%NAME/%FIELD
|
||||
definition-payload = {
|
||||
"name":"%prefixn %circuit %name %field",
|
||||
"topic":"%topic"
|
||||
}
|
||||
#definition-retain = 0
|
||||
|
||||
|
||||
# the message value topic (if other than the default). If set here, it will be replaced by the "--mqtttopic"
|
||||
# configuration option only if that one contains at least one variable. If the the "--mqtttopic" configuration option
|
||||
# does not contain any variable, it is taken as prefix and can be used here as well.
|
||||
#topic=%prefix/%circuit/%name
|
||||
|
||||
|
||||
# the common global config topic, payload, and retain setting (used by running, version, signal, uptime, updatecheck,
|
||||
# and scan if not otherwise defined explicitly).
|
||||
def_global-topic = %prefixn/config/global/%FIELD
|
||||
def_global-payload = {
|
||||
"name":"%prefixn global %field",
|
||||
"topic":"%topic"
|
||||
}
|
||||
#def_global-retain = 0
|
||||
|
||||
# individual global running, version, signal, uptime, updatecheck, and scan config topic, payload, and retain setting.
|
||||
#def_global_running-...
|
||||
#def_global_version-...
|
||||
#def_global_signal-...
|
||||
#def_global_uptime-...
|
||||
#def_global_updatecheck-...
|
||||
#def_global_scan-...
|
||||
|
||||
|
||||
# the topic and payload to listen to in order to republish all config messages.
|
||||
#config_restart-topic =
|
||||
#config_restart-payload =
|
||||
@@ -66,15 +66,18 @@ if [ -n "$reusebuilddir" ] || [ -z "$keepbuilddir" ]; then
|
||||
fi
|
||||
make DESTDIR="$PWD/$RELEASE" install-strip || exit 1
|
||||
extralibs=
|
||||
mqtt=
|
||||
ldd $RELEASE/usr/bin/ebusd | egrep -q libmosquitto.so.0
|
||||
if [ $? -eq 0 ]; then
|
||||
extralibs=', libmosquitto0'
|
||||
PACKAGE="${PACKAGE}_mqtt0"
|
||||
mqtt=1
|
||||
else
|
||||
ldd $RELEASE/usr/bin/ebusd | egrep -q libmosquitto.so.1
|
||||
if [ $? -eq 0 ]; then
|
||||
extralibs=', libmosquitto1'
|
||||
PACKAGE="${PACKAGE}_mqtt1"
|
||||
mqtt=1
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -105,6 +108,10 @@ cp contrib/debian/systemd/ebusd.service $RELEASE/lib/systemd/system/ebusd.servic
|
||||
mkdir -p $RELEASE/etc/init.d || exit 1
|
||||
cp contrib/debian/init.d/ebusd $RELEASE/etc/init.d/ebusd || exit 1
|
||||
cp contrib/debian/default/ebusd $RELEASE/etc/default/ebusd || exit 1
|
||||
if [ -n "$mqtt" ]; then
|
||||
mkdir -p $RELEASE/etc/ebusd || exit 1
|
||||
cp contrib/etc/ebusd/mqtt*.cfg $RELEASE/etc/ebusd/ || exit 1
|
||||
fi
|
||||
cp contrib/etc/logrotate.d/ebusd $RELEASE/etc/logrotate.d/ || exit 1
|
||||
cp ChangeLog.md $RELEASE/DEBIAN/changelog || exit 1
|
||||
cat <<EOF > $RELEASE/DEBIAN/control
|
||||
@@ -132,6 +139,12 @@ EOF
|
||||
cat <<EOF > $RELEASE/DEBIAN/conffiles
|
||||
/etc/default/ebusd
|
||||
EOF
|
||||
if [ -n "$mqtt" ]; then
|
||||
echo '/etc/ebusd' >> $RELEASE/DEBIAN/dirs
|
||||
for i in contrib/etc/ebusd/mqtt*.cfg; do
|
||||
echo "${i##contrib}" >> $RELEASE/DEBIAN/conffiles
|
||||
done
|
||||
fi
|
||||
cat <<EOF > $RELEASE/DEBIAN/postinst
|
||||
#!/bin/sh
|
||||
if [ -d /run/systemd/system ]; then
|
||||
|
||||
+52
-31
@@ -338,7 +338,7 @@ static const char* knownFieldNames[] = {
|
||||
/** the number of known field names. */
|
||||
static const size_t knownFieldCount = sizeof(knownFieldNames) / sizeof(char*);
|
||||
|
||||
std::pair<string, int> makeField(const string name, bool isField) {
|
||||
std::pair<string, int> makeField(const string& name, bool isField) {
|
||||
if (!isField) {
|
||||
return {name, -1};
|
||||
}
|
||||
@@ -350,38 +350,55 @@ std::pair<string, int> makeField(const string name, bool isField) {
|
||||
return {name, knownFieldCount};
|
||||
}
|
||||
|
||||
void addPart(ostringstream& stack, int inField, vector<std::pair<string, int>>& parts) {
|
||||
string str = stack.str();
|
||||
if (inField == 1 && str == "_") {
|
||||
inField = 0; // single "%_" pattern to reduce to "_"
|
||||
} else if (inField == 2) {
|
||||
str = "%{" + str;
|
||||
inField = 0;
|
||||
}
|
||||
if (inField == 0 && str.empty()) {
|
||||
return;
|
||||
}
|
||||
stack.str("");
|
||||
if (inField == 0 && !parts.empty() && parts[parts.size()-1].second < 0) {
|
||||
// append constant to previous constant
|
||||
parts[parts.size()-1].first += str;
|
||||
return;
|
||||
}
|
||||
parts.push_back(makeField(str, inField>0));
|
||||
}
|
||||
|
||||
bool MqttReplacer::parse(const string& templateStr, bool onlyKnown, bool noKnownDuplicates, bool emptyIfMissing) {
|
||||
m_parts.clear();
|
||||
size_t end = templateStr.length();
|
||||
bool inField = false;
|
||||
int inField = 0; // 1 after '%', 2 after '%{'
|
||||
ostringstream stack;
|
||||
for (size_t pos = 0; pos < end+1; pos++) {
|
||||
char ch = pos<end ? templateStr[pos] : '\0';
|
||||
for (auto ch : templateStr) {
|
||||
bool empty = stack.tellp()<=0;
|
||||
if (ch=='%' || ch=='\0') {
|
||||
if (inField && empty) { // %% for plain %
|
||||
inField = false;
|
||||
if (ch=='%') {
|
||||
if (inField==1 && empty) { // %% for plain %
|
||||
inField = 0;
|
||||
stack << ch;
|
||||
} else {
|
||||
if (!empty) {
|
||||
m_parts.push_back(makeField(stack.str(), inField));
|
||||
stack.str("");
|
||||
}
|
||||
inField = true;
|
||||
addPart(stack, inField, m_parts);
|
||||
inField = 1;
|
||||
}
|
||||
} else if (ch=='{' && inField==1 && empty) {
|
||||
inField = 2;
|
||||
} else if (ch=='}' && inField==2) {
|
||||
addPart(stack, 1, m_parts);
|
||||
inField = 0;
|
||||
} else {
|
||||
if (inField && !((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_')) {
|
||||
if (inField>0 && !((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_')) {
|
||||
// invalid field character
|
||||
if (stack.tellp()>0) {
|
||||
m_parts.push_back(makeField(stack.str(), true));
|
||||
stack.str("");
|
||||
}
|
||||
inField = false;
|
||||
addPart(stack, inField, m_parts);
|
||||
inField = 0;
|
||||
}
|
||||
stack << ch;
|
||||
}
|
||||
}
|
||||
addPart(stack, inField, m_parts);
|
||||
if (onlyKnown || noKnownDuplicates) {
|
||||
int foundMask = 0;
|
||||
int knownCount = knownFieldCount;
|
||||
@@ -576,7 +593,7 @@ ssize_t MqttReplacer::matchTopic(const string& topic, string* circuit, string* n
|
||||
// non-name in remainder found
|
||||
return -static_cast<ssize_t>(idx)-1;
|
||||
}
|
||||
value = topic;
|
||||
value = topic.substr(last);
|
||||
}
|
||||
last += value.length();
|
||||
switch (part.second) {
|
||||
@@ -1075,7 +1092,7 @@ void MqttHandler::notifyTopic(const string& topic, const string& data) {
|
||||
logOtherDebug("mqtt", "received topic %s with data %s", topic.c_str(), data.c_str());
|
||||
string circuit, name, field;
|
||||
ssize_t match = m_replacers.get("topic").matchTopic(topic.substr(0, pos), &circuit, &name, &field);
|
||||
if (match<0 && !isList) { // TODO
|
||||
if (match<0 && !isList) {
|
||||
logOtherError("mqtt", "received unmatchable topic %s", topic.c_str());
|
||||
}
|
||||
if (isList) {
|
||||
@@ -1251,12 +1268,16 @@ void MqttHandler::run() {
|
||||
m_definitionsSince = 1;
|
||||
}
|
||||
if (m_connected && m_hasDefinitionTopic) {
|
||||
ostringstream ostr;
|
||||
deque<Message*> messages;
|
||||
m_messages->findAll("", "", "", false, true, true, true, true, true, 0, 0, false, &messages);
|
||||
for (const auto& message : messages) {
|
||||
if (filterSeen) {
|
||||
if (message->getLastUpdateTime()==0) {
|
||||
continue; // no data ever
|
||||
if (message->isPassive() || !message->isWrite()) {
|
||||
// only wait for data on passive or read messages
|
||||
continue; // no data ever
|
||||
}
|
||||
}
|
||||
if (message->getDataHandlerState()==1) {
|
||||
// already seen in the past, check for poll prio update
|
||||
@@ -1286,9 +1307,6 @@ void MqttHandler::run() {
|
||||
msgValues.set("level", message->getLevel());
|
||||
msgValues.set("direction", direction);
|
||||
msgValues.set("messagecomment", message->getAttribute("comment"));
|
||||
if (!m_publishByField) {
|
||||
msgValues.set("topic", getTopic(message, "", "")); // TODO already present?
|
||||
}
|
||||
msgValues.reduce(true);
|
||||
string str = msgValues.get("direction_map-"+direction, false, false);
|
||||
msgValues.set("direction_map", str);
|
||||
@@ -1325,7 +1343,7 @@ void MqttHandler::run() {
|
||||
} else {
|
||||
typeStr = "string";
|
||||
}
|
||||
ostringstream ostr;
|
||||
ostr.str("");
|
||||
ostr << "type_map-" << direction << "-" << typeStr;
|
||||
str = msgValues.get(ostr.str(), false, false);
|
||||
if (str.empty()) {
|
||||
@@ -1337,11 +1355,11 @@ void MqttHandler::run() {
|
||||
continue;
|
||||
}
|
||||
MqttReplacers values = msgValues; // need a copy here as the contents are manipulated
|
||||
values.set("index", static_cast<signed>(index));
|
||||
values.set("field", fieldName);
|
||||
values.set("type", typeStr);
|
||||
values.set("type_map", str);
|
||||
values.set("basetype", dataType->getId());
|
||||
values.set("index", static_cast<signed>(index));
|
||||
values.set("field", fieldName);
|
||||
values.set("comment", field->getAttribute("comment"));
|
||||
values.set("unit", field->getAttribute("unit"));
|
||||
if (dataType->isNumeric()) {
|
||||
@@ -1390,9 +1408,6 @@ void MqttHandler::run() {
|
||||
}
|
||||
str = values.get("type_part-" + typePartSuffix, false, false);
|
||||
values.set("type_part", str);
|
||||
if (m_publishByField) {
|
||||
values.set("topic", getTopic(message, "", fieldName)); // TODO already present?
|
||||
}
|
||||
values.reduce();
|
||||
if (m_hasDefinitionFieldsPayload) {
|
||||
string value = values["field_payload"];
|
||||
@@ -1413,6 +1428,12 @@ void MqttHandler::run() {
|
||||
if (filterSeen && message->getLastUpdateTime()>message->getCreateTime()) {
|
||||
// ensure data is published as well
|
||||
m_updatedMessages[message->getKey()]++;
|
||||
} else if (filterSeen && direction=="w") {
|
||||
// publish data for read pendant of write message
|
||||
Message* read = m_messages->find(message->getCircuit(), message->getName(), "", true);
|
||||
if (read && read->getLastUpdateTime()>0) {
|
||||
m_updatedMessages[read->getKey()]++;
|
||||
}
|
||||
}
|
||||
}
|
||||
time(&m_definitionsSince);
|
||||
|
||||
@@ -129,7 +129,7 @@ bool FileReader::matches(const string& input, const string& search, bool ignoreC
|
||||
return matches(inputSub, search, false, true);
|
||||
}
|
||||
string searchSub = search;
|
||||
tolower(&inputSub);
|
||||
tolower(&searchSub);
|
||||
return matches(inputSub, searchSub, false, true);
|
||||
}
|
||||
// walk through alternatives
|
||||
|
||||
Reference in New Issue
Block a user