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.

Logs in visu
#1
Hi all
I'd like to show a user an object log for just one object in my visu. Is it possible?
I know I can show data for trends. But I've not found a way how to do it in case the object has no trend.
LM5Lp, firmware: 2018.08.22 and 2021.12.15, FlashSYS v2, ARMv7 Processor rev 5 (v7l), kernel 4.4.151 and 4.4.259
Reply
#2
Hi,

When there is no trend attached to the object or the object log is not enabled on this object there is no historical data available for this object anywhere in the system.

You could store historical data to a table in the storage and call it from a .lp file, but i would use a trend as this is the easiest way to do it..

BR,

Erwin
Reply
#3
search for eventlog
KNX Advanced Partner + Tutor
Reply
#4
.lp file example. Pass object address/name like this: /user/logs.lp?obj=1/1/1
The number of log entries is limited to 100. You can change this value in query if needed.
Code:
<?
require('apps')
alias = getvar('obj') or ''
obj = grp.find(alias)

if not obj then
  print('object not found')
  return
end
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Object logs</title>
  <link rel="stylesheet" href="/apps/css/bootstrap.css">
  <style>
    .table { table-layout: fixed; }
  </style>
</head>
<body>
<table class="table">
  <tr>
    <th>Date/time</th>
    <th>Source</th>
    <th>Event type</th>
    <th>Value</th>
  </tr>
<?
query = 'SELECT * FROM objectlog WHERE address=? ORDER BY id DESC LIMIT 100'
items = db:getall(query, obj.id)

for _, item in ipairs(items) do
  datetime = os.date('%c', item.logtime)

  if item.src > 0 then
    src = buslib.decodeia(item.src)
  else
    src = 'local'
  end

  if item.eventtype == 'write' then
    value = busdatatype.decode(item.datahex, obj.datatype)
  else
    value = ''
  end
?>
  <tr>
    <td><?=escape(datetime)?></td>
    <td><?=escape(src)?></td>
    <td><?=escape(item.eventtype)?></td>
    <td><?=escape(value)?></td>
  </tr>
<? end ?>
</table>
</body>
</html>
Reply
#5
(13.02.2020, 08:34)admin Wrote: .lp file example. Pass object address/name like this: /user/logs.lp?obj=1/1/1
The number of log entries is limited to 100. You can change this value in query if needed.

Thank you for the file. But there is few issues.
buslib.encodeia(item.src) doesn't work at all. My KNX object which is source of the log record has address 1.3.63.
item.src = 46081
Result of buslib.encodeia(46081) is nil.
I thought there should be buslib.decodeia(item.src) instead of encode. But it doesn't work either. buslib.decodeia(46081) returns 11.4.1 so it looks like there's a bit ordering mismatch etc.


The second problem is:
busdatatype.decode(item.datahex, obj.datatype) returns only basic datatypes. But I'd like to see fully decoded values. Like switch on/off, open/close etc. Is it possible?

In attachments below I'm sending you what I see in log and what's on this newly created page.
   
LM5Lp, firmware: 2018.08.22 and 2021.12.15, FlashSYS v2, ARMv7 Processor rev 5 (v7l), kernel 4.4.151 and 4.4.259
Reply
#6
Right, it should be buslib.decodeia() instead of buslib.encodeia(). As for wrong address 1.3.63 is 4927 in integer form. You've probably mistaken it with 22/4/1 which is 46081 in integer form.
There are no server-side function for decoding sub-datatypes apart from scaling and angle. You can write your own conversion function if needed.
Reply
#7
Hi,

Try this:

1) Run code below once to create the logs.lp
2) To have normal decoding use http://<ip>/user/logs.lp?obj=1/1/1
3) To use the custom values during decoding http://<ip>/user/logs.ip?obj=1/1/1&custom=true
4) To reduce or increase the number of lines (default 100) use http://<ip>/user/logs.ip?obj=1/1/1&lines=20 or  http://<ip>/user/logs.ip?obj=1/1/1&custom=true&lines=20
Code:
dst = '/www/user/logs.lp'
io.writefile(dst, [[
<?
require('apps')
alias = getvar('obj') or ''
custom = getvar('custom') or 'false'
lines = tonumber(getvar('lines')) or 100
obj = grp.find(alias)

if not obj then
  print('object not found')
  return
end

function decodevalue(obj, value)
  if obj.enums and custom == 'true' then
    require('json')
    enums = json.pdecode(obj.enums)
    if type(value) == 'boolean' then
      if value == true then
          value = enums['1']
      else
        value = enums['0']
      end
    else
       value = enums[tostring(value)]
    end
    if value == nil or value == '' then
      value = enums['default']
    end
  else
    dt = {
      [1] = {
        dttype = 'boolean',
        enums = {
          [true] = 'true',
          [false] = 'false'
        }
      },
      [1001] = {
        dttype = 'switch',
        enums = {
          [true] = 'on',
          [false] = 'off'
        }
      },
      [1002] = {
        dttype = 'boolean',
        enums = {
          [true] = 'true',
          [false] = 'false'
        }
      },
      [1003] = {
        dttype = 'enable',
        enums = {
          [true] = 'enable',
          [false] = 'disable'
        }
      },
      [1004] = {
        dttype = 'transition',
        enums = {
          [true] = 'ramp',
          [false] = 'no ramp'
        }
      },
      [1005] = {
        dttype = 'alarm',
        enums = {
          [true] = 'alarm',
          [false] = 'no alarm'
        }
      },
      [1006] = {
        dttype = 'low/high',
        enums = {
          [true] = 'high',
          [false] = 'low'
        }
      },
      [1007] = {
        dttype = 'step',
        enums = {
          [true] = 'increase',
          [false] = 'decrease'
        }
      },
      [1008] = {
        dttype = 'up/down',
        enums = {
          [true] = 'up',
          [false] = 'down'
        }
      },
      [1009] = {
        dttype = 'open/close',
        enums = {
          [true] = 'close',
          [false] = 'open'
        }
      },
      [1010] = {
        dttype = 'start/stop',
        enums = {
          [true] = 'start',
          [false] = 'stop'
        }
      },
      [1011] = {
        dttype = 'activity',
        enums = {
          [true] = 'active',
          [false] = 'inactive'
        }
      },
      [1012] = {
        dttype = 'inversion',
        enums = {
          [true] = 'inverted',
          [false] = 'not inverted'
        }
      },
      [1013] = {
        dttype = 'dim style',
        enums = {
          [true] = 'cyclically',
          [false] = 'start/stop'
        }
      },
      [1014] = {
        dttype = 'data source',
        enums = {
          [true] = 'calculated',
          [false] = 'fixed'
        }
      },
      [2] = {
        dttype = '2 bit (1 bit controlled)',
        enums = {
          [0] = 'No control, 0',
          [1] = 'No control, 1',
          [2] = 'Control, 0',
          [3] = 'Control, 1'
        }
      },
      [3] = {
        dttype = '4 bit (3 bit controlled)',
        enums = {
          [0] = 'No control, Break',
          [1] = 'No control, Step 1',
          [2] = 'No control, Step 2',
          [3] = 'No control, Step 3',
          [4] = 'No control, Step 4',
          [5] = 'No control, Step 5',
          [6] = 'No control, Step 6',
          [7] = 'No control, Step 7',
          [8] = 'Control, Break',
          [9] = 'Control, Step 1',
          [10] = 'Control, Step 2',
          [11] = 'Control, Step 3',
          [12] = 'Control, Step 4',
          [13] = 'Control, Step 5',
          [14] = 'Control, Step 6',
          [15] = 'Control, Step 7',
        }
      },
      [3007] = {
        dttype = '4 bit dim/blinds step',
        enums = {
          [0] = 'Stop',
          [1] = 'Down 100%',
          [2] = 'Down 50%',
          [3] = 'Down 25%',
          [4] = 'Down 12%',
          [5] = 'Down 6%',
          [6] = 'Down 3%',
          [7] = 'Down 1%',
          [8] = 'Stop',
          [9] = 'Up 100%',
          [10] = 'Up 50%',
          [11] = 'Up 25%',
          [12] = 'Up 12%',
          [13] = 'Up 6%',
          [14] = 'Up 3%',
          [15] = 'Up 1%',
        }
      }
    }
      if dt[obj.datatype] then
           value = dt[obj.datatype]['enums'][value]
    end
    end
  return value
end
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Object logs</title>
  <link rel="stylesheet" href="/apps/css/bootstrap.css">
  <style>
    .table { table-layout: fixed; }
  </style>
</head>
<body>
<table class="table">
  <tr>
    <th>Date/time</th>
    <th>Source</th>
    <th>Event type</th>
    <th>Value</th>
  </tr>
<?
query = 'SELECT * FROM objectlog WHERE address=? ORDER BY id DESC LIMIT ?'
items = db:getall(query, obj.id, lines)
for _, item in ipairs(items) do
  datetime = os.date('%c', item.logtime)

  if item.src > 0 then
    src = buslib.decodeia(item.src)
  else
    src = 'local'
  end

  if item.eventtype == 'write' then
    value = busdatatype.decode(item.datahex, obj.datatype)
    value = decodevalue(obj, value)
  else
    value = ''
  end
?>
  <tr>
    <td><?=escape(datetime)?></td>
    <td><?=escape(src)?></td>
    <td><?=escape(item.eventtype)?></td>
    <td><?=escape(value)?></td>
  </tr>
<? end ?>
</table>
<script type="text/javascript">
  var itemsdata = <? json.write(items) ?>;
  //console.log(itemsdata);
</script>
</body>
</html>
]])
script.disable(_SCRIPTNAME)
BR,

Erwin
Reply
#8
Thank you, works well.

FYI 1009 is wrong. I think it's for Nobel price for someone who invented it but according to KNX specs the correct setting is:
[1009] = {
        dttype = 'open/close',
        enums = {
    [false] = 'open',
    [true] = 'close'
        }
LM5Lp, firmware: 2018.08.22 and 2021.12.15, FlashSYS v2, ARMv7 Processor rev 5 (v7l), kernel 4.4.151 and 4.4.259
Reply
#9
I have the code working fine although been trying to mod (unsuccessfully) I would like to know how I can adjust the coding to give me.
1. Be able display all logged events
2. Be able to provide the user the ability to filter logs. Like using a custom value set against an 2 byte integer (where 0= 1/1/1, 1=1/1/3, 2=32/1/5) where they can choose which group to list, would be nice if the custom value list could automatically be generated / updated with group addresses that have been selected to be logged.
3. To show in the list the actual group address against each event.  

Thanks for any suggestions.
Reply


Forum Jump: