I use a Python script to convert data from a database to a target database. Basically, the script works if the target database does not yet exist. However, the data should be transferred to an existing target database.
Then the following error message appears:
influxdb.exceptions.InfluxDBClientError: 400: {"error":"partial write: field type conflict: input field \"Netzbezug Leistung\" on measurement \"modbus\" is type float, already exists as type integer dropped=7586"}
With the command “show field keys from modbus” I get the information of the target database:
name: modbus
fieldKey fieldType
-------- ---------
Netzbezug Leistung integer
The data generated with the script has the “fieldType: float”
How can I change the script so that the converted data is written in “fieldType: integer”?
#!/opt/bin/python3
from influxdb import InfluxDBClient
client = InfluxDBClient(host='192.168.xxx.xx', port=8086, username='admin', password='secret',database = 'homeassistant')
db_data = client.query(" select * FROM W WHERE entity_id = 'netzbezug_leistung_ksem' AND time >= now() - 1h ")
data_to_write = [
{
'measurement': 'modbus',
'tags': {'host': 'telegraf', 'name': 'KSEM', 'slave_id': '1', 'type': 'holding_register'},
'time': d['time'],
'fields': {'Netzbezug Leistung': d['value']}
}
for d in db_data.get_points()
]
client.write_points(data_to_write, database='test', retention_policy='infinite')
I have almost 0 knowledge of Python and I’d expect the client to have some data type management function (I don’t know if that’s the case tho)
What I can tell you is the difference between float and integer when writing raw data (line protocol), values like 20
or 20.6
will usually be float, as that’s the assumed datatype for any numeric field. in order to write an integer it has to be specified by appending i
to the value meaning that
20 → float
20i → integer
sample point
temperature sensor1 25i
1 Like
Hallo @Giovanni_Luisotto thank you very much for your quick answer. I had already found the solution you showed. But unfortunately I can’t use them in the Python script. Unfortunately, I also lack Python knowledge.
I might have another solution and I might need some help here as well.
The raw data stored in integers comes from the Telegraf collector.
Now I’m experimenting here with the “processors.converter.fields”. The data is hereby stored in “float”.
[[processors.converter]]
[processors.converter.fields]
float = [
"Netzbezug Leistung",
"Netzeinspeisung Leistung",
"Netzbezug Energie",
"Netzeinspeisung Energie"
]
This works very well!
However, I have much more than the 4 fields entered. I would definitely not have to pass about 30 more fields to the processor module so that they are then saved in “float”.
Now I can enter this line by line in the [processors.converter.fields] section.
Or could I somehow simplify it so that the complete database “modbus” is stored in “float”?
I can’t tell what’s the best case, you should be able to put simple float = ["*"]
, but what if you have string fields?
You can somehow simplify the creation of the specific list by querying the DB with a simple SHOW FIELD KEYS ON "__YourDB__" FROM "modbus"
and use the result to quickly build the list… of course if any metric is added you will also need to add it in the config which is not that flexible
1 Like
Thanks, @Giovanni_Luisotto for your hint. In the case of Python-based InfluxDB client does not require field type to be declared explicitly. Anyway, the bash-based InfluxDB client requires the correct type of data.
import influxdb_client
from influxdb_client import InfluxDBClient, Point, WritePrecision
from influxdb_client.client.write_api import SYNCHRONOUS
token = ""
org = ""
url = "http://localhost:8086"
bucket=""
measurement = ""
write_client = influxdb_client.InfluxDBClient(url=url, token=token, org=org)
write_api = write_client.write_api(write_options=SYNCHRONOUS)
node, observed_at, fmt_observed_at = "", "", ""
current, voltage = 0, 0
power = round(voltage * current / 1000, 2)
try:
point = (
Point(measurement)
.tag("by_node", node)
.field("observed_at", observed_at)
.field("fmt_observed_at", fmt_observed_at)
.field("current", current)
.field("voltage", voltage)
.field("power", power)
)
write_api.write(bucket=bucket, org=org, record=point)
except KeyboardInterrupt:
print("Closing the program!")
except Exception as e:
print(e)
For the above code, I had to write bash code (i with integer values) as follows:
TOKEN=""
BUCKET=""
ORG=""
measurement=""
node="";
observed_at="";
fmt_observed_at="";
current=0;
voltage=0;
power=$(echo "scale=2; $voltage*$current/1000" | bc -l);
influx write \
--org $ORG \
--token $TOKEN \
--bucket $BUCKET \
"
$measurement,by_node=$node observed_at=${observed_at}i,fmt_observed_at=\"$fmt_observed_at\",current=${current}i,voltage=${voltage}i,power=$power
"