A todo list / check list approach within openHAB

This is a simple approach to create a todo list / check list within openhab. Although this is just a copy/paste from another topic, i think this shouldn’t be buried in that topic. Maybe this helps someone.

  1. Define an empty group and a group which contaisn all todos.
Group:Switch:AND(ON,OFF) gTodo_List
Group gAllTodos
  1. Define a virtual Switch for every todo
Switch Todo1 "Todo 1" (gAllTodos)
Switch Todo2 "Todo 2" (gAllTodos)
  1. Define one or more rules which fill the todo-list (this example just fills the list every minute, you can use multiple rules / triggers, just as you like and need.
rule "fill Todo"
when 
	Time cron "0 * * * * ?"
then	
for (item : gAllTodos.members)
{
	item.postUpdate(OFF)
	gTodo_List.addMember(item)
}
end
  1. Create a single rule, which removes a todo from the group. If you need to do something special, you can do it here as well. If you need something special, you can create additional rules.
rule "remove Todo"
when 
	Member of gAllTodos changed from OFF to ON	
then
      	Thread::sleep(300)
	gTodo_List.removeMember(triggeringItem)
end
  1. Add the group to the sitemap
sitemap Home label="Todo list" {
    Frame {
		Group item=gTodo_List
    }
}
1 Like

I like this but where does all this go? Is it one file, 3 files? What folder? ~/openhab/conf?

Thanks for the info!

yes.

1.+2. in one or more *.items file in the items folder
3.+4. in one or more *.rules file in the rules folder
5. in a *.sitemap file in the sitemaps folder

Cool! I’ll go look…

I just checked, the android app works fine. (i did just test this at first.)

Using the browser (chrome in my case), needs an adjustment: A small delay before removing the item from the group. Edited the original post.

Very Interesting,
Could a text file be read to create or enable the todo items, and therefore the labels be used from the text file,as I thing the ToDo system must be hardcoded ?

Could the data be read out of a REST API?
Did you find an answer to your question?

With the current possibilities “Member of” and “triggeringItem” this can be extremely simplified.

You can easily generate the *.items from something else.

Since it is still of interest, i will update the stuff today.

any updates?

Sorry, was busy with other stuff. I will update tomorrow hopefully.

I updated the first post with the features, “triggeringItem” & “Member of”.

You can now easily generate the items file in 2. The logic is now generic so the only thing which needs to be generated is the items file.

1 Like

I’ll show you my alternative. I have oriented myself to this one. So I count up the items at the end with a postfix todo1, todo2, todo3 and so on. If I have completed a todo, it is deleted from the list. Means, I delete even the whole item, so that I do not have sometime in openHAB all todo items that are no longer assigned to the group. Means but also after counting, I must adjust the item names, because otherwise the indices are no longer correct.

I implemented this with Python:

import core
from core.rules import rule
from core.triggers import when
from core.actions import LogAction
import core.items

@rule("Create To-Do Item")
@when("Item iSmartHome_ToDo_Liste_EintragHinzufuegen received command")
def create_todo_item(event):
    new_todo_label = unicode(event.itemCommand)
    existing_labels = [item.label for item in ir.getItem("iSmartHome_ToDo_Liste_Elemente").members]

    if new_todo_label not in existing_labels and new_todo_label != "":
        todo_number = len(existing_labels) + 1
        new_todo_item_name = "iSmartHome_ToDo_Liste_todo" + str(todo_number)

        # Add new Switch Item to iSmartHome_ToDo_Liste_Elemente group
        core.items.add_item(new_todo_item_name, item_type="Switch", groups=["iSmartHome_ToDo_Liste_Elemente"], label=new_todo_label)
        events.sendCommand(new_todo_item_name, "OFF")
        #ir.getItem("iSmartHome_ToDo_Liste_Elemente").addMember(new_todo_item_name)

        # Reset the iSmartHome_ToDo_Liste_EintragHinzufuegen to ""
        events.postUpdate("iSmartHome_ToDo_Liste_EintragHinzufuegen", "")

        LogAction.logInfo("To-Do Liste Rules", "Created new ToDo: {} - Item: {}", new_todo_label, new_todo_item_name)
    else:
        LogAction.logWarn("To-Do Liste Rules", "ToDo '{}' already exists.", new_todo_label)

@rule("Remove ToDo Item")
@when("Member of iSmartHome_ToDo_Liste_Elemente received command ON")
def remove_todo_item(event):
    todo_list = list(ir.getItem("iSmartHome_ToDo_Liste_Elemente").members)

    removed_item_index = next((i for i, item in enumerate(todo_list) if item.name == event.itemName), None)

    if removed_item_index is not None:
        triggering_item = todo_list[removed_item_index]

        todo_list = list(ir.getItem("iSmartHome_ToDo_Liste_Elemente").members)
        removed_item_index = todo_list.index(triggering_item)

        # Remove the ToDo item from the group
        for member in ir.getItem("iSmartHome_ToDo_Liste_Elemente").members:
            if member.name == event.itemName:
                ir.getItem("iSmartHome_ToDo_Liste_Elemente").removeMember(member)
        core.items.remove_item(event.itemName)

        # Update the item names and labels
        for i, todo_item in enumerate(todo_list[removed_item_index + 1:], start=removed_item_index + 1):
            new_todo_number = i
            new_todo_name = "iSmartHome_ToDo_Liste_todo" + str(new_todo_number)
            new_todo_label = todo_item.label

            # Rename and update label of the ToDo item
            core.items.remove_item(todo_item.name)
            core.items.add_item(new_todo_name, item_type="Switch", groups=["iSmartHome_ToDo_Liste_Elemente"], label=new_todo_label)
            events.sendCommand(new_todo_name, "OFF")

            LogAction.logInfo("To-Do Liste Rules", "Updated ToDo: {} - Item: {}", new_todo_label, new_todo_name)

@rule("System Start - Reset To-Do-Liste")
@when("System started")
def system_start(event):
    # Reset the iSmartHome_ToDo_Liste_EintragHinzufuegen to ""
    events.postUpdate("iSmartHome_ToDo_Liste_EintragHinzufuegen", "")

    # Set all ToDo Switches to OFF
    for todo_item in ir.getItem("iSmartHome_ToDo_Liste_Elemente").members:
        events.sendCommand(todo_item.name, "OFF")
        LogAction.logInfo("To-Do Liste Rules", "Reset ToDo: {} - Item: {}", todo_item.label, todo_item.name)

@rule("Scheduled To-Do Entries")
@when("Time cron 0 0 ? * 2,4 *")  # Dienstag und Donnerstag
def tue_thu_schedule(event):
    events.sendCommand("iSmartHome_ToDo_Liste_EintragHinzufuegen", "Krafttraining")

@rule("Scheduled To-Do Entries")
@when("Time cron 0 0 ? * 3,7 *")  # Mittwoch und Sonntag
def wed_sun_schedule(event):
    events.sendCommand("iSmartHome_ToDo_Liste_EintragHinzufuegen", "Bouldern")

@rule("Scheduled To-Do Entries")
@when("Time cron 0 0 ? * 2 *")  # Montag
def mon_schedule(event):
    events.sendCommand("iSmartHome_ToDo_Liste_EintragHinzufuegen", "Einkaufen")

@rule("Scheduled To-Do Entries")
@when("Time cron 0 0 ? * 6 *")  # Freitag
def fri_schedule(event):
    events.sendCommand("iSmartHome_ToDo_Liste_EintragHinzufuegen", "Aufräumen & Putzen")

Have now admitted another example of how I use this in Rules or more precisely with Cron, for example to add recurring tasks automatically. Excluded in my list is a duplication of entries.

I have previously defined the following items:

Group iSmartHome_ToDo_Liste "To-Do Liste" <text> (gSmartHome)

String iSmartHome_ToDo_Liste_EintragHinzufuegen "To-Do Liste Neuer Eintrag [%s]" <text> (iSmartHome_ToDo_Liste)
Group:Switch:AND(ON,OFF) iSmartHome_ToDo_Liste_Elemente <text> (iSmartHome_ToDo_Liste)

The sitemap looks like this:

sitemap Todo label="To-Do-Liste"
{
    Frame label="To-Do-Liste" icon="text"
    {
        Text item=iSmartHome_ToDo_Liste_EintragHinzufuegen
        Group item=iSmartHome_ToDo_Liste_Elemente
    }
}