openHAB and Tankerkönig gas prices + Telegram integration - Second iteration

Posted by ads' corner on Saturday, 2020-08-15
Posted in [Ansible][Linux][Openhab]

In my previous blog post about “Tankerkönig” I explained the details of how to integrate this binding into openHAB and provide a Telegram interface.

Someone on the openHAB community forum pointed out that Telegram bots allow queries, where one can present the user with options, and the user only has to click on one of the options. That makes it easier to use, and less typing is required as well. I went ahead and implemented that.

Most of the implementation does not change, especially all the Things and Items are the same. The Rules change however.

Initial question

The user can still send a /tanken question:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
rule "Telegram Bot receive tanken"
when
    Item telegramlastMessageDate received update
then
    val telegramAction = getActions("telegram","telegram:telegramBot:HA_Bot")

    if (telegramLastMessage.state.toString.toLowerCase == "/tanken") {
       telegramAction.sendTelegramQuery(Long::parseLong(telegramLastMessageChatId.state.toString), "Tank Optionen:", Tanken_ReplyId, "E10", "Diesel", "E5")
    }
end

The bot will pick the question up, and answer with a list of options:

Telegram Tankerkoenig
Telegram Tankerkoenig

The sendTelegramAnswer() function accepts the following parameters:

  • Channel/Group ID
  • The question (What the bot is asking or presenting to the user) - this text will remain after the query is answered
  • A ReplyId
  • One or multiple options

The ReplyId is unique for this question, Telegram will send back the ReplyId along with the answer (more about this later). I defined the ReplyId as a static variable ($Tanken_ReplyId) in the head of the rules file:

1
val Tanken_ReplyId = "Tankerkoenig_tanken"

Pick any string you want, it does not have to be a variable - but this way I ensure that I don’t mix up different strings in the rules file.

The answer

This part became a bit more complicated. The Item telegramLastMessageReplyId is updated when the user selects one of the options. However a rule is only fired iff the value of the Item changes. This does not happen if the user sends the same /tanken question twice, and you have the same ReplyId. On the other hand, you can use unique ReplyIds, but then you have to keep track of all open questions. Telegram unfortunately does not allow a timeout for questions. I solve this part by resetting telegramLastMessageReplyId to NULL if it is equal $Tanken_ReplyId.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
rule "Telegram Bot receive tanken answer"
when
    Item telegramLastMessageReplyId received update Tankerkoenig_tanken
then
    val telegramAction = getActions("telegram","telegram:telegramBot:HA_Bot")

    if (telegramLastMessage.state.toString == "Diesel") {
        var reply = "Dieselpreise:"

        // place calculation here
        telegramAction.sendTelegramAnswer(Long::parseLong(telegramLastMessageChatId.state.toString), telegramLastMessageReplyId.state.toString, reply)

    } else if (telegramLastMessage.state.toString == "E10") {
        // ...

    } else if (telegramLastMessage.state.toString == "E5") {
        // ...

    } else {
        telegramAction.sendTelegram(Long::parseLong(telegramLastMessageChatId.state.toString), "Unknown option!")
    }

    if (telegramLastMessageReplyId.state.toString == Tanken_ReplyId) {
        // make sure the next request can see an update for "telegramLastMessageReplyId"
        telegramLastMessageReplyId.postUpdate(NULL)
    }
end

The part for Diesel shows how the bot sends a reply, once the reply string is available in $reply. The calculation has not changed from the previous blog post, and I’m not repeating that part here. At the end, I’m resetting $telegramLastMessageReplyId to NULL. This way the next reply will change/update this variable.

Telegram Bot shows gas prices
Telegram Bot shows gas prices


Categories: [Ansible] [Linux] [Openhab]