This forum uses cookies
This forum makes use of cookies to store your login information if you are registered, and your last visit if you are not. Cookies are small text documents stored on your computer; the cookies set by this forum can only be used on this website and pose no security risk. Cookies on this forum also track the specific topics you have read and when you last read them. Please confirm that you accept these cookies being set.

influxdb
#21
Thanks admin, that worked fine!
However, the script pushes a hell load of data to influx that is not really necessary.
I could use the "range" tip from above, but using "tags" would be easier and more flexible for future changes.
I tried my best, but I don't think I understand event.getvalue to be honest.

This particular GA have 2 tags, one of them is "influxdb"

BTW, any suggestion on the timestamp manipulation? Smile

Code:
function knx_callback(event)
  local id = event.dstraw
  local tagname = event.getvalue(tag)

  if tagname == "influxdb" then
    local addr = event.dst
    local value, dt = get_value(addr, event.datahex)
    if value ~= nil then
    send_metric('rawdata', dt.name, addr, value)
    end
  end
end
Reply
#22
Try this rewritten version:
Code:
local http = require('socket.http')
http.TIMEOUT = 5

local url = 'http://192.168.1.200:8086/api/v2/write?bucket=XXX&org=XXX'
local token = 'XXXXX'
local influxtable = 'rawdata'
local tagobjs = grp.tag('influxdb')

local function escape(value)
  return tostring(value):gsub('[\\ ,=]', '\\%1')
end

local objects = {}

for _, obj in ipairs(tagobjs) do
  objects[ obj.id ] = {
    name = escape(obj.name),
    datatype = obj.datatype,
  }
end

local function send(name, addr, value)
  local body

  if type(value) == 'boolean' then
    body = string.format('%s,name=%s,addr=%s state=%s', influxtable, name, addr, value)
  else
    body = string.format('%s,name=%s,addr=%s value=%s', influxtable, name, addr, escape(value))
  end

  local res, code = http.request({
    url = url,
    method = 'POST',
    body = body,
    headers = {
      Authorization = 'Token ' .. token
    }
  })

  if code ~= 204 then
    log('error sending to influx', res, code, body)
  end
end

local busclient = require('localbus').new(60)
busclient:sethandler('groupwrite', function(event)
  local obj = objects[ event.dstraw ]

  if obj then
    local value = busdatatype.decode(event.datahex, obj.datatype)

    if value ~= nil then
      send(obj.name, event.dst, value)
    end
  end
end)

while true do
  busclient:loop(60)
end
Reply
#23
Hi admin,

Above script is working perfectly however is there a way I can use this as a scheduled script?
I see it's now kept resident and sends data according what is generated by the objects and that can be alot making one object hijacking the stream.

I tried changing the busclient and while loop part but without any success, it only sends one objects data and then stops.
Is there any info on the localbus and how to use it?

Thanks!
Reply
#24
You don't need localbus for this as the current object value is already stored in the database.

Code:
local http = require('socket.http')
http.TIMEOUT = 5

local url = 'http://192.168.1.200:8086/api/v2/write?bucket=XXX&org=XXX'
local token = 'XXXXX'
local influxtable = 'rawdata'
local tagobjs = grp.tag('influxdb')

local function escape(value)
  return tostring(value):gsub('[\\ ,=]', '\\%1')
end

local function send(name, addr, value)
  local body

  if type(value) == 'boolean' then
    body = string.format('%s,name=%s,addr=%s state=%s', influxtable, name, addr, value)
  else
    body = string.format('%s,name=%s,addr=%s value=%s', influxtable, name, addr, escape(value))
  end

  local res, code = http.request({
    url = url,
    method = 'POST',
    body = body,
    headers = {
      Authorization = 'Token ' .. token
    }
  })

  if code ~= 204 then
    log('error sending to influx', res, code, body)
  end
end

for _, obj in ipairs(tagobjs) do
  send(escape(obj.name), obj.address, obj.value)
end
Reply
#25
Hi Admin,

Thank you very much for clearing that out and for the solution.

Greetings
Reply
#26
I have noted that influxDB somehow doesn't like the BOOL values sent to it. When trying to show the values I get the error "unsupported input type for mean aggregate: boolean"
If I set aggregate function to last in influxDB, it just give me an infinite line. Doesn't show the actual state of True/false.

Should the BOOL values also be "escape(value)" as the strings?
Reply
#27
A possible solution is to send 1/0 instead of true/false. Then you can use aggregate functions.
Code:
  if type(value) == 'boolean' then
    value = value and 1 or 0
  end

  body = string.format('%s,name=%s,addr=%s value=%s', influxtable, name, addr, escape(value))
Reply
#28
Hi!

I have a problem sending strings to influxdb

How can I send 250bytes or 14bytes strings?

I've tried with

Code:
local function escape(value)
  return tostring(value):gsub('[\\ ,=]', '\\%1')
end

if type(value) == 'string' then
    body = string.format('%s,name=%s,addr=%s string=%s', influxtable, name, addr, escape(value))
end

if type(value) == 'string' then
    body = string.format('%s,name=%s,addr=%s string=%s', influxtable, name, addr, value)
end

but doesn´t work. This is the error:

Code:
  * string: {"code":"invalid","message":"unable to parse 'DatosLM,name=PruebaString,addr=32/1/4 value=Probando\\ String': invalid boolean"}
Reply
#29
You need to use a different field name for each data type (boolean, number, string). See how it's done here: https://kb.logicmachine.net/integration/influxdb/

It looks like you've already written a boolean value into "string" field so it won't accept string data into this field anymore. Either choose a different field name and modify the script accordingly. Or delete the bucket and create it again.
Reply
#30
Thanks! It works

I don´t know whiy doesn´t work because I try with diferent "field" names. But now it works.
Reply
#31
Hi!

I have a question about Grafana representacion of influxdb data. I know that is grafana question but anyone says nothing, this forum is not active... Mayby somebody made.
I send data from LM to influxdb when they change, no in scheduled script.

If I put time filter I can't see the first value (the value before the change). And if there are no changes in the data in the filter, it says "No data". Is there a way to represent the last value in the database if there are no changes?

Attached Files Thumbnail(s)
       
Reply
#32
You can setup a scheduled script that periodically sends the current value. I don't see any other solution.
Reply
#33
(12.01.2024, 15:08)admin Wrote: You can setup a scheduled script that periodically sends the current value. I don't see any other solution.

Ok thanks! that's what I had thought.
I was wondering if there was another way to save the data in real time.

Thanks!
Reply
#34
You can use both resident and scheduled scripts for influxdb in parallel.
Reply
#35
Hi,
I am trying to export all the data from the bus to influxdb but I am afraid I am not sure whether is working or not since I am not very familiar with influxdb. 
I have tagged all the objects with the proper label and set the script to resident following the indications. I also have configured the proper URL and the token which I have checked works since in Grafana I use the same data. What I don´t see is from the server any bytes received or sent to the influxdb so I suspect is not working well.
I have mainly two questions, One is to know why I am getting so many errors in the error log that I have attached.
The other is to know within my new ´ets´ bucket, what will be the data model so I know how to query the data since I don´t see any familiar fields. If you have any example query to see all the KNX bus data I could try that one.
Thanks!

Attached Files Thumbnail(s)
   
Reply
#36
What is influxtable variable set to in your script? It must be a string but it looks like you have a Lua table there.
Reply
#37
(12.08.2024, 07:10)admin Wrote: What is influxtable variable set to in your script? It must be a string but it looks like you have a Lua table there.

Hi, I left it as it was in the original script:
local influxtable = 'rawdata'
Reply
#38
Post your script.
Reply
#39
(12.08.2024, 07:38)admin Wrote: Post your script.

Code:
local http = require('socket.http')
http.TIMEOUT = 5

local url = 'http://192.168.100.20:8086/api/v2/write?bucket=ets&org=Matrix'
local token = 'deleted'
local influxtable = 'rawdata'
local tagobjs = grp.tag('influxdb')

local function escape(value)
  return tostring(value):gsub('[\\ ,=]', '\\%1')
end

local objects = {}

for _, obj in ipairs(tagobjs) do
  objects[ obj.id ] = {
    name = escape(obj.name),
    datatype = obj.datatype,
  }
end

local function send(name, addr, value)
  local body

  if type(value) == 'boolean' then
    body = string.format('%s,name=%s,addr=%s state=%s', table, name, addr, value)
  elseif type(value) == 'number' then
    body = string.format('%s,name=%s,addr=%s value=%s', table, name, addr, value)
  elseif type(value) == 'string' then
    body = string.format('%s,name=%s,addr=%s string=%q', table, name, addr, value)
  else
    log('invalid data type', addr, type(value))
    return
  end

  local res, code = http.request({
    url = url,
    method = 'POST',
    body = body,
    headers = {
      Authorization = 'Token ' .. token
    }
  })

  if code ~= 204 then
    log('error sending to influx', res, code, body)
  end
end

local busclient = require('localbus').new(60)
busclient:sethandler('groupwrite', function(event)
  local obj = objects[ event.dstraw ]

  if obj then
    local value = busdatatype.decode(event.datahex, obj.datatype)

    if value ~= nil then
      send(obj.name, event.dst, value)
    end
  end
end)

while true do
  busclient:loop(60)
end
Reply
#40
Turns out the script is not fully correct. To fix this replace table with influxtable on line 26, 28 and 30.
Reply


Forum Jump: