Thank for the feedback!
I still have something where I make a mistake and don’t know how to solve it.
I was able to get the e.g. [[inputs.cpu]] and [[inputs.disk]] template running in telegraf.conf. But when i try to add another .conf file, to receive data stream from somthing else onto a specific bucket, one of the buckets gets populated with the Measurements from the wrong output.
What I don’t understand is why is data from “[[outputs.influxdb_v2]]” from sdm630.conf ending up in bucket “db_home” and “db_sdm630” and why is the data from [[outputs.influxdb_v2]] solaredge_modbus.conf only added in bucket = “db_solaredge”?
I would like to get the data from the different configs in the associated buckets.
It would be great if someone could help me. Below my configs.
The main is /etc/telegraf/telegraf.conf
[global_tags]
[agent]
interval = "10s"
round_interval = true
metric_batch_size = 1000
metric_buffer_limit = 10000
collection_jitter = "0s"
flush_interval = "10s"
flush_jitter = "0s"
precision = ""
hostname = ""
omit_hostname = false
[[outputs.influxdb_v2]]
urls = ["http://127.0.0.1:8086"]
token = "<random>"
organization = "<random>"
bucket = "db_home"
[[inputs.cpu]]
percpu = true
totalcpu = true
collect_cpu_time = false
report_active = false
[[inputs.disk]]
Then i have the linux one /etc/telegraf/telegraf.d/sdm630.conf:
[[outputs.influxdb_v2]]
urls = ["http://127.0.0.1:8086"]
token = "<random>"
organization = "<random>"
bucket = "db_sdm630"
namepass = ["SDM630"]
# ------------------------------------------------ Inputs --------------------------------------------
[[inputs.modbus]]
interval = "5s"
name_override = "SDM630"
name = "NOT USED" # Not used
tagexclude = ["type", "name", "host"]
timeout = "2s"
## Serial (RS485; RS232)
controller = "file:///dev/ttyUSB-MODBUS"
baud_rate = 115200
data_bits = 8
parity = "E"
stop_bits = 1
transmission_mode = "RTU"
configuration_type = "request"
# ---------------------------------------------- slave_id = 1 ----------------------------------------
[[inputs.modbus.request]]
slave_id = 1
byte_order = "ABCD"
register = "input"
fields = [
{ address = 0, name = "Phase 1 line to neutral volts", type="FLOAT32" },
{ address = 2, name = "Phase 2 line to neutral volts", type="FLOAT32" },
{ address = 4, name = "Phase 3 line to neutral volts", type="FLOAT32" },
]
[inputs.modbus.request.tags]
sensor = "pv"
# ---------------------------------------------- slave_id = 2 ----------------------------------------
[[inputs.modbus.request]]
slave_id = 2
byte_order = "ABCD"
register = "input"
fields = [
{ address = 0, name = "Phase 1 line to neutral volts", type="FLOAT32" },
{ address = 2, name = "Phase 2 line to neutral volts", type="FLOAT32" },
{ address = 4, name = "Phase 3 line to neutral volts", type="FLOAT32" },
]
[inputs.modbus.request.tags]
sensor = "heat_pump_outdoors"
# ---------------------------------------------- slave_id = 3 ----------------------------------------
[[inputs.modbus.request]]
slave_id = 3
byte_order = "ABCD"
register = "input"
fields = [
{ address = 0, name = "Phase 1 line to neutral volts", type="FLOAT32" },
{ address = 2, name = "Phase 2 line to neutral volts", type="FLOAT32" },
{ address = 4, name = "Phase 3 line to neutral volts", type="FLOAT32" },
]
[inputs.modbus.request.tags]
sensor = "heat_pump_indoors"
I also have /etc/telegraf/telegraf.d/solaredge_modbus.conf:
[[outputs.influxdb_v2]]
urls = ["http://127.0.0.1:8086"]
token = "<random>"
organization = "<random>"
bucket = "db_solaredge"
namepass = ["inverter"]
# ------------------------------------------------ Inputs --------------------------------------------
[[inputs.modbus]]
interval = "15s"
name_override="inverter"
name = "NOT USED" # Not used
tagexclude = ["type", "name", "host"]
slave_id = 1
timeout = "5s"
controller = "tcp://xxx.xxx.xxx.xxx:502"
# Note: most static data is omitted (pointless to monitor)
# Note: battery and meter data is omitted (as i have none)
#
# Always 0/not used:
# { name = "I_Status_Vendor", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [108]}
# Disabled for now since Telegraf does not support reading strings
# { name = "c_serialnumber", address = [52, 67]},
holding_registers = [
{ name = "C_SunSpec_DID", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [69]},
{ name = "I_AC_Current", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [71]},
{ name = "I_AC_CurrentA", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [72]},
{ name = "I_AC_CurrentB", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [73]},
{ name = "I_AC_CurrentC", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [74]},
{ name = "I_AC_Current_SF", byte_order = "AB", data_type = "INT16", scale=1.0, address = [75]},
{ name = "I_AC_VoltageAB", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [76]},
{ name = "I_AC_VoltageBC", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [77]},
{ name = "I_AC_VoltageCA", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [78]},
{ name = "I_AC_VoltageAN" , byte_order = "AB", data_type = "UINT16", scale=1.0, address = [79]},
{ name = "I_AC_VoltageBN", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [80]},
{ name = "I_AC_VoltageCN", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [81]},
{ name = "I_AC_Voltage_SF", byte_order = "AB", data_type = "INT16", scale=1.0, address = [82]},
{ name = "I_AC_Power", byte_order = "AB", data_type = "INT16", scale=1.0, address = [83]},
{ name = "I_AC_Power_SF", byte_order = "AB", data_type = "INT16", scale=1.0, address = [84]},
{ name = "I_AC_Frequency", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [85]},
{ name = "I_AC_Frequency_SF", byte_order = "AB", data_type = "INT16", scale=1.0, address = [86]},
{ name = "I_AC_VA", byte_order = "AB", data_type = "INT16", scale=1.0, address = [87]},
{ name = "I_AC_VA_SF", byte_order = "AB", data_type = "INT16", scale=1.0, address = [88]},
{ name = "I_AC_VAR", byte_order = "AB", data_type = "INT16", scale=1.0, address = [89]},
{ name = "I_AC_VAR_SF", byte_order = "AB", data_type = "INT16", scale=1.0, address = [90]},
{ name = "I_AC_PF", byte_order = "AB", data_type = "INT16", scale=1.0, address = [91]},
{ name = "I_AC_PF_SF", byte_order = "AB", data_type = "INT16", scale=1.0, address = [92]},
{ name = "I_AC_Energy_WH", byte_order = "ABCD", data_type = "INT32", scale=1.0, address = [93, 94]},
{ name = "I_AC_Energy_WH_SF", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [95]},
{ name = "I_DC_Current", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [96]},
{ name = "I_DC_Current_SF", byte_order = "AB", data_type = "INT16", scale=1.0, address = [97]},
{ name = "I_DC_Voltage", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [98]},
{ name = "I_DC_Voltage_SF", byte_order = "AB", data_type = "INT16", scale=1.0, address = [99]},
{ name = "I_DC_Power", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [100]},
{ name = "I_DC_Power_SF", byte_order = "AB", data_type = "INT16", scale=1.0, address = [101]},
{ name = "I_Temp_Sink", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [103]},
{ name = "I_Temp_SF", byte_order = "AB", data_type = "INT16", scale=1.0, address = [106]},
{ name = "I_Status", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [107]},
{ name = "I_Status_Vendor", byte_order = "AB", data_type = "UINT16", scale=1.0, address = [108]}
]
# Must come last because Telegraf
[inputs.modbus.tags]
site = "<random>" # Site ID can be found on SolarEdge's website
sn = "<random>" # Inverter serial
# Apply the scaling and drop the scaling fields.
[[processors.starlark]]
namepass = ["inverter"]
source = '''
def scale(metric, name):
metric.fields[name] *= pow(metric.fields[name + "_SF"])
metric.fields.pop(name + "_SF")
def pow(exp):
# It works i suppose
return float("1e{}".format(exp))
def drop(metric, name):
metric.fields.pop(name)
metric.fields.pop(name + "_SF")
def apply(metric):
type = metric.fields["C_SunSpec_DID"]
metric.fields.pop("C_SunSpec_DID")
I_AC_Voltage_Scale = pow(metric.fields["I_AC_Voltage_SF"])
metric.fields["I_AC_VoltageAB"] *= I_AC_Voltage_Scale
metric.fields["I_AC_VoltageBC"] *= I_AC_Voltage_Scale
metric.fields["I_AC_VoltageCA"] *= I_AC_Voltage_Scale
metric.fields["I_AC_VoltageAN"] *= I_AC_Voltage_Scale
metric.fields["I_AC_VoltageBN"] *= I_AC_Voltage_Scale
metric.fields["I_AC_VoltageCN"] *= I_AC_Voltage_Scale
metric.fields.pop("I_AC_Voltage_SF")
# Drop meaningless measurements
if type == 101: # Single Phase
metric.fields.pop("I_AC_VoltageBC")
metric.fields.pop("I_AC_VoltageCA")
metric.fields.pop("I_AC_VoltageAN")
metric.fields.pop("I_AC_VoltageBN")
metric.fields.pop("I_AC_VoltageCN")
elif type == 102: # Split Phase
metric.fields.pop("I_AC_VoltageCA")
metric.fields.pop("I_AC_VoltageCN")
scale(metric, "I_AC_Frequency")
scale(metric, "I_DC_Voltage")
scale(metric, "I_Temp")
# Drop obsolete measurements at night/sleep mode to reduce stored data size.
if metric.fields["I_Status"] == 2:
drop(metric, "I_AC_Current")
metric.fields.pop("I_AC_CurrentA")
metric.fields.pop("I_AC_CurrentB")
metric.fields.pop("I_AC_CurrentC")
drop(metric, "I_AC_Power")
drop(metric, "I_AC_VA")
drop(metric, "I_AC_VAR")
drop(metric, "I_AC_PF")
drop(metric, "I_AC_Energy_WH")
drop(metric, "I_DC_Current")
drop(metric, "I_DC_Power")
else:
I_AC_Current_Scale = pow(metric.fields["I_AC_Current_SF"])
metric.fields["I_AC_Current"] *= I_AC_Current_Scale
metric.fields["I_AC_CurrentA"] *= I_AC_Current_Scale
metric.fields["I_AC_CurrentB"] *= I_AC_Current_Scale
metric.fields["I_AC_CurrentC"] *= I_AC_Current_Scale
metric.fields.pop("I_AC_Current_SF")
# Drop obsolete measurments
if type == 101: # Single Phase
metric.fields.pop("I_AC_CurrentB")
metric.fields.pop("I_AC_CurrentC")
elif type == 102: # Split Phase
metric.fields.pop("I_AC_CurrentC")
scale(metric, "I_AC_Power")
scale(metric, "I_AC_VA")
scale(metric, "I_AC_VAR")
scale(metric, "I_AC_PF")
scale(metric, "I_AC_Energy_WH")
scale(metric, "I_DC_Current")
scale(metric, "I_DC_Power")
# Convert serial to tag
#metric.tags["sn"] = metric.fields["C_SerialNumber"]
#metric.fields.pop("C_SerialNumber")
# Correct the type, we multiply by float but still some are reported as int (for reasons unkown).
for k, v in metric.fields.items():
if k != "I_Status":
metric.fields[k] = float(v)
return metric
'''