How to have a history of commands in Basic UI

Hello,

I am trying to achieve to things:

  • Display in Basic UI an item (String / Text) showing the last issued command with time and date. That should principally look like this: “Light Kitchen ON [06.12.2017 18:43]”
  • Display a history of these commands (is that even possible in Basic UI?)

I am currently managing to perform the first task to show the last issues command from rules, by setting a String item with the text on every single command I have in the rules. Obviously that’s neither maintainable nor very pretty.

Does anybody have a hint, how I could achieve that on every sent command that String item is updated?

Tanks a lot in advance for any hint.

This is not difficult. My example is not tested, but should give you a hint. I also just created three log entries. This is just the history.

String newLog
String Log01
String Log02
String Log03

and a rule which switches the items

rule "new log message"
when 
Item newLog received update

then
Log03.postUpdate(Log02.state)
Log02.postUpdate(Log01.state)
Log01.postUpdate(newLog.state)
end
1 Like

Only thing I can think of is put everything into a Group and trigger a rule on updates to that Group. You can use the lastUpdate hack to see what item triggered the rule though I don’t think you need the sleep inn this case.

With that you can you the String Item.

Another alternative is to write a script that tails events.log and pushes that most recent commands to your String item using the rest API or MQTT or something.

Someone is working on a log binding that might be suitable for something like this.

I’m not sure there is a good solution for displaying the history though.

1 Like

Hello!

Thanks for the replies. I like the idea of reading events.log with a script and using the Exec binding for that seems appropriate. I will give that a try. Actually with reasonably used logInfo( “TAG”, “Value” ) I could parse for those entries and have them in the String variable. Though in BasicUI that’s still gonna show just the last value but not a true history (and even more not per-device).

Thanks for your ideas guys. Might end up in combining them :slight_smile:

Hello @rlkoshak, @sihui et al. :slight_smile:

thanks for your help and suggestions. So I ended up in doing the following hybrid solution: First I created two items, one of those uses the exec binding

String			LAST_COMMAND						"[%s]"											<logclock>			(gText)
String			LAST_COMMAND_RAW					"[%s]"											<logclock>			(gText)															{ channel="exec:command:xxxxxxxx:output" }

The exec command is calling a script that looks like this and thus provides the output to LAST_COMMAND_RAW:

#! /usr/bin/env bash
ITEM=$(awk '/ItemStateChangedEvent. - (HEAT|DOOR|TOR|LIGHT|PLUG|SWITCH|ROLL|RELAY)_/{ x=$2","$5","$10 } END { print x }' /var/log/openhab2/events.log)
echo $ITEM

Obviously, the heat, door, etc. devices are returned as comma separated values like

19:07:43.035,HEAT_EG_Flur,28

This is then fed into an OpenHAB rule

rule "History"
when
	Item	LAST_COMMAND_RAW		changed
then
	val String logTime = LAST_COMMAND_RAW.state.toString.split(",").get(0)
	val String itemTime = logTime.split(":").get(0) + ":" + logTime.split(":").get(1) + "h"
	val String itemName = LAST_COMMAND_RAW.state.toString.split(",").get(1)
	val String itemState = LAST_COMMAND_RAW.state.toString.split(",").get(2)

	var lastItem = gAll.allMembers.findFirst[name.equals(itemName)]

...

and then you can do with lastItem what you want. I actually create a string and feed that to LAST_COMMAND, so the output for the above comma separated output would be in Basic UI:

44

Thanks for all your suggestions. This works very nice for me.

1 Like

Hello @rlkoshak, @sihui and others!

My solution is working quite fine since some time and when using Grafana to create a table from the LAST_COMMAND item, I actually get a history list of the commands.

Well - almost. One problem still exists, and that is that my script only considers the last item changed in the log file and it’s run by the exec binding every 5 seconds. However, obviously this won’t catch each and every change.

Is there any possibility, to have the command used parse the log file is executed when the log file changes, i.e., can OpenHAB react to inotify? I assume there is no other way to listen on the eventbus!?

Perhaps somebody has an idea, of how I could always catch the last change in the log.

To elaborate, you have a script or program that runs outside of and independent of OH that reads the events.log file as it is being written to. It then parses each line and pushes information to OH using OH’s REST API or MQTT.

Your current approach, periodically calling a shell script from a Rule, will never work reliably. There is no way to achieve this from Rules directly.

You could configure the MQTT Binding and configure an Item to subscribe to all messages and set up a Rule to parse out which Item a given message is from.

Hi @rlkoshak,

sorry - I might have been misleading. My current set up is, that with the help of the EXEC binding, I run the script every 5 seconds. It is not running outside of OH but being called by the exec binding and the output is stored in LAST_COMMAND_RAW Item.

But it would be an idea to run the script totally separate from OH and use inotify to recognize the log file change. I just don’t know yet how to push then information to MQTT which, indeed, an Item could listen to.

From OH itself, there is no way I assume to listen to the eventbus?

Not misleading at all. I was just pointing out that you won’t be able to reliably make this work. The only way to guarantee you get every event in the log file is to read every byte written to that log file which at this time there is no way to achieve in an OH Rule.

Yes and no. Rules are all triggered based on events from the Event Bus so from that perspective the answer is Yes. If you had a Rule that triggers on ALL of your Items you would effectively be listeing to the Event Bus. But there is no way to directly just listen to the Event Bus from Rules.

Don’t listen for inotify. Since this program is running outside of OH you can just have it constantly reading the file all the time. The equivalent of

tail -f events.log