New Telegram Binding - Tester and Feedback welcome

Hi,

as mentioned earlier in some thread I started working on a Telegram Binding. As a byproduct, I had to customize the existing Telegram action from @paolo_denti

Example command for the action:

var String json_keyboard = '{"inline_keyboard":[[{"text":"Erledigt","callback_data":"trash_done"},{"text":"Erinnere mich nochmal.","callback_data":"trash_later"}]]}'
sendTelegram("BiergartenBot", "%s und %s solltest du noch raus stellen.", json_keyboard, gCal_Abfall_Event1_Summary.state.toString, gCal_Abfall_Event2_Summary.state.toString)

Creates this:


(Translation: Bring the trash out: [Done] [Remember me again])

It is easy to ingegrate e.g. item names into the JSON string

This JSON is also possible and would create a little different keyboard:
'{"keyboard":[["opt 1","opt 2","opt 3"],["menu"]]}'
See here https://core.telegram.org/bots/api#replykeyboardmarkup ff

Example rule for the binding:

rule "New Telegram message: trash_done"
when
	Item TelegramLasteMessageDate received update
then
	if(TelegramLasteMessageDText.state.toString == "trash_done"){
        Abfall_Steht_An.postUpdate(OFF)
    }
end

The binding for now uses this library https://github.com/rubenlagus/TelegramBots.

The rules is triggerd when a new message (from given ChatID) is received.

Configuration of the binding:

You have to put the name and the token of your bot and your ChatID into the Thing configuration. The binding only accepts messages from the give ChatID


image

Thinks I want to do:

  • Add multiple ChadIds (haven’t found out yet how to read the multiple="true" config
)
  • Find a better solution to trigger a new Message in the rule
  • Shrink the sice of the binding
  • alot(!) of testing and overall code clearing
  • 


Sooo, If you like download the JARs and placed them in your addons folder.
Feedback is very welcome! It was a fun journey so far and I dont want to stop it now. :wink:

Download:
https://drive.google.com/drive/folders/17jW8zK2ZHLUGTAqS_ai7kfjZAYsrf3Cg




Before I had some problems, ignore from here: :wink:

Based on a timer and an item, a rule triggers and sends me a message over Telegram that should look like this:

“You have to take the trash out today.
[Done.] [Remember me later.] [Its not necessary today.]”

Depending on the answer openHAB does different things. In this example, it would change an item state or send another message after 10 Minutes.

I followed this tutorial https://www.openhab.org/docs/developer/development/ide.html and started developing.

So first of all, as a byproduct, I had to customize the existing Telegram action from @paolo_denti
It now accepts an additional optional JSON-String Parameter to create the custom keybord. Syntax is shown here: https://core.telegram.org/bots/api#replykeyboardmarkup ff

At second I followed this tutorial https://www.openhab.org/docs/developer/development/bindings.html#choosing-a-namespace and created my very first binding. It for now uses this library https://github.com/rubenlagus/TelegramBots.

Despite my rusty java skills this was somehow the easy part. :wink:
Both the Action and the Binding are working fine when openHAB is started via Eclipse. The Action can send different custom keyboards and the Binding gets messages send to the bot (whether from a custom keyboard or not).

There is plenty of work to do and I have quite some ideas what could be done, but the very basics are working when started via Eclipse.

I want to test things on my productive environment (openHABian) but this is where I stuck. :frowning:
I exported the JAR via Eclipse (right click -> export -> JAR -> Finish), placed the JAR file in the addons folder and restarted openHAB. But I can see the Binding anywhere in the PaperUI.
If I export with the “Generate the Manifest file”-option checked in the last step I get the following warning:
JAR export finished with warnings. See details for additional information.
org.openhab.action.telegram/META-INF/MANIFEST.MF was replaced by the generated MANIFEST.MF and is no longer in the JAR.

Is there anything I am missing? If it helps I can upload my (not working!) JAR.
Any feedback to the general idea of this Binding (and Action) is also very welcome.

13 Likes

Right-click on the pom.xml, select „maven install“. You‘ll find a jar in the /target directory of your binding. Put that in /addons.

Thank you for the help!
The build failed with five warnings and one error:

[WARNING] Could not transfer metadata org.openhab:pom-tycho:2.4.0-SNAPSHOT/maven-metadata.xml from/to p2-openhab-deps-repo (https://dl.bintray.com/openhab/p2/openhab-deps-repo/${ohdr.version}): Cannot access https://dl.bintray.com/openhab/p2/openhab-deps-repo/${ohdr.version} with type p2 using the available connector factories: AetherRepositoryConnectorFactory, BasicRepositoryConnectorFactory
[WARNING] Could not transfer metadata org.openhab:pom:2.4.0-SNAPSHOT/maven-metadata.xml from/to p2-openhab-deps-repo (https://dl.bintray.com/openhab/p2/openhab-deps-repo/${ohdr.version}): Cannot access https://dl.bintray.com/openhab/p2/openhab-deps-repo/${ohdr.version} with type p2 using the available connector factories: AetherRepositoryConnectorFactory, BasicRepositoryConnectorFactory    
[WARNING] Source tree does not exist. Ignoring D:\openHABProject\git\openhab2-addons\addons\binding\org.openhab.binding.telegram\target\generated-sources\annotations
[WARNING] Source tree does not exist. Ignoring D:\openHABProject\git\openhab2-addons\addons\binding\org.openhab.binding.telegram\target\generated-sources\annotations
[WARNING] Source tree does not exist. Ignoring D:\openHABProject\git\openhab2-addons\addons\binding\org.openhab.binding.telegram\target\generated-sources\annotations

[ERROR] Failed to execute goal org.eclipse.tycho:tycho-packaging-plugin:1.2.0:package-plugin (default-package-plugin) on project org.openhab.binding.telegram: D:\openHABProject\git\openhab2-addons\addons\binding\org.openhab.binding.telegram\build.properties: bin.includes value(s) [NOTICE] do not match any files. -> [Help 1]

It feels like I am doing something wrong on this part? https://www.openhab.org/docs/developer/development/bindings.html#include-the-binding-in-the-build-and-the-distro
Or is there anything else I am missing. I’ll do further investigations tomorrow. Thank you for pointing me in the right direction.

You’re supposed to put a “NOTICE” file into the root of the project. This was added somewhat lately, the doc’s may not reflect that yet.

Cheers,
-Th

1 Like

Thank you. I created a NOTICE File (atm only containing “text”) and run “maven install” again.
The “style-checker” found some errors that I fixed one by one, till the build was a success.
I copied the JAR file to the addon folder and restarted openhab.
Nothing happened, no Telegram Binding in PaperUI visible. :frowning:

Restart should not be needed. Under PaperUI - > Configuration - > Things when you press to add a new thing is it listed there? If not, check karaf console output with bundle:list and see if its listed there.

Good to know. That saves me some time. :wink:

No, unfortunately not.

It is listed as “Installed” (but not “Active”).

bundle:requirements <ID> -> Bundle <ID> is not resolved.
and bundle:resolve remains silent

Havn’t fiddled around with developement bindings in a while and never had such problems. As a next step I would try to build it with maven and see if that works. If not, then it’s back to the drawing board.

Edit: I just noticed that you triggered maven build from eclipse. Is it the same thing if you run it from command line?

I think so. At first I tried “export -> JAR”.

That is what I do now. It still gives me two warnings

[WARNING] Could not transfer metadata org.openhab:pom-tycho:2.4.0-SNAPSHOT/maven-metadata.xml from/to p2-openhab-deps-repo (https://dl.bintray.com/openhab/p2/openhab-deps-repo/${ohdr.version}): Cannot access https://dl.bintray.com/openhab/p2/openhab-deps-repo/${ohdr.version} with type p2 using the available connector factories: AetherRepositoryConnectorFactory, BasicRepositoryConnectorFactory
[WARNING] Could not transfer metadata org.openhab:pom:2.4.0-SNAPSHOT/maven-metadata.xml from/to p2-openhab-deps-repo (https://dl.bintray.com/openhab/p2/openhab-deps-repo/${ohdr.version}): Cannot access https://dl.bintray.com/openhab/p2/openhab-deps-repo/${ohdr.version} with type p2 using the available connector factories: AetherRepositoryConnectorFactory, BasicRepositoryConnectorFactory

and this at the end after downloading several files.

[INFO] Adding repository https://dl.bintray.com/openhab/p2/openhab-deps-repo/1.0.33
[INFO] Resolving dependencies of MavenProject: org.openhab.binding:org.openhab.binding.telegram:2.4.0-SNAPSHOT @ D:\openHABProject\git\openhab2-addons\addons\binding\org.openhab.binding.telegram\pom.xml
[INFO] Resolving class path of MavenProject: org.openhab.binding:org.openhab.binding.telegram:2.4.0-SNAPSHOT @ D:\openHABProject\git\openhab2-addons\addons\binding\org.openhab.binding.telegram\pom.xml
[INFO] 
[INFO] ----------< org.openhab.binding:org.openhab.binding.telegram >----------
[INFO] Building Telegram Binding 2.4.0-SNAPSHOT
[INFO] ---------------------------[ eclipse-plugin ]---------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ org.openhab.binding.telegram ---
[INFO] Deleting D:\openHABProject\git\openhab2-addons\addons\binding\org.openhab.binding.telegram\target
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 36.991 s
[INFO] Finished at: 2018-10-28T12:45:27+01:00
[INFO] ------------------------------------------------------------------------

Ok, so when I did bundle:start <ID> it says Unresolved requirement: Import-Package: com.google.gson; version="2.8.2"
I used that at the beginning, but not anymore. After deleting it from the MANIFEST and builing it again it now works!

Thank you so much, I learned a lot!

Edit: At least for the binding. But I’ll figure out the action too. :slight_smile:

1 Like

Updated my first post with the download link of the JARs:
https://drive.google.com/open?id=17jW8zK2ZHLUGTAqS_ai7kfjZAYsrf3Cg

Can you share your code in github?

I will do that. I have to read the PULL_REQUEST_TEMPLATE.md etc. first.
Will be doing it till at least the end of this week.

Ok, already uploadet it.
But be aware. Like I said my Java is a little rusty and there is definitely much work todo

Binding:

Action:

For now I’m just trying to get feedback on whether the beaten path is the right one.

I’m interested in such a binding/action for Telegram, especially useful to send reminders, like in your example, to “take the trash out” or the like.
However,I think it will be nicer to get the reply from the custom keyboard returned by the action, not through the binding.
Something like:

var String json_keyboard = '{"inline_keyboard":[[{"text":"Erledigt","callback_data":"trash_done"},{"text":"Erinnere mich nochmal.","callback_data":"trash_later"}]]}'
var String reply = sendTelegram("BiergartenBot", "%s und %s solltest du noch raus stellen.", json_keyboard, gCal_Abfall_Event1_Summary.state.toString, gCal_Abfall_Event2_Summary.state.toString)
if(reply == "trash_done"){
        Abfall_Steht_An.postUpdate(OFF)
    }

What do you think?
Wouldn’t it be easier to write rules?

LATER EDIT:
But some timeout will be needed, otherwise the action will wait indefinitely


About the binding now

Seems to work pretty well, however I have some observations:

  • lastMessageDate maybe should return DateTime.
  • lastMessageUsername is not populated, it remains empty (NULL)

First of all: Thank you for the feedback!

If I understand you correctly, you want the rule to wait for an answer to happen. Unfortunately I don’t think that this is how rules in OpenHAB are intended to work.
Plus: The Telegram API also splits sending and receiving messages. Afaik there is no method for sending a new message that also returns a possible answer.
And I think there is a good reason why:
There could be minutes or even ours between the message send from the Bot and someone sending an answer (thought a button or not). You probably don’t want the rule to wait for such a long time but you want to get and work with the answer, even if it comes half a day later.
I think the binding also should work without the action.

But I totaly agree with you, that the current implementation isn’t very good either. I will definitely try to find a better solution and I will have your idea in mind.

Valid point. I will definitely look into this.

It is only populated if you have an username set in Telegram. Since its optional to have one it can be NULL. Could you check if you have a username set please? In the Telegram App you can set one under “Settings” in the Hamburger menu. The second row should be your username. (Android, iOS may vary)

Hey, update here since November 2018. How is it going? Can’t wat to try that extention!

We are working on it :slight_smile: I’m trying to support Belgadon with the binding.

What we did so far is to migrate the actions provided by the OH1 telegram action module to the OH2 framework and to make use of the TelegramBots API instead of using a http client directly which provides a better abstraction and saves us some code. Now, it’s not necessary anymore to use both the OH1 action to send messages and the OH2 binding to receive replies from the user.

I would like to present my proposal here to have a base for further discussions. I currently see two use-cases:

1. Use-case: your bot wants to send you a message (and wants an answer from the user)
This is very similar to what Belgadon already presented. I will just shows how it would look in a real working example.

Let’s say we have the following items

String telegramMessage "Telegram Message" { channel = "telegram:telegramBot:620b3747:lastMessageText" }
String telegramReplyId "Telegram Reply Id" { channel = "telegram:telegramBot:620b3747:replyId" }
Switch PresenceAnyone "Anyone [MAP(presence.map):%s]" <presence>

and this is our first rule:

rule "Nobody's at home"
when
   Item PresenceAnyone changed to OFF
then
    val actions = getActions("telegram","telegram:telegramBot:620b3747")
   actions.sendTelegram("MyOH2Bot", "No one is at home, but some lights are still on. Do you want me to turn off the lights?", "Reply_Lights", "Yes", "No")
end

Notice that the third arguments “Reply_Lights” is quite important because it acts as a connection between the sent message and the answer (we will see later)

The other arguments define the button names that will be shown. The alternative of using variable arguments would be to use exactly one argument like “[ Yes ] [ No ]” and to split that internally with String operations.

After this is send, it looks like this:

Then, we have a second rule

rule "Reply handler for lights"
when
    Item telegramReplyId received update Reply_Lights
then
    val actions = getActions("telegram","telegram:telegramBot:620b3747")

    if (telegramMessage.state.toString == "Yes")
    {
        gLights.sendCommand(OFF)
        actions.sendTelegramAnswer("MyOH2Bot", telegramReplyId.state.toString, "Ok, lights are *off* now.") 
    }
    else
    {
        actions.sendTelegramAnswer("MyOH2Bot", telegramReplyId.state.toString, "Ok, I'll leave them *on*.")
    }
end

Here, the “Reply_Lights” is again used in the rule to know for what request the Yes/No answer belongs to.

After the user pressed one of the buttons, the reply markup is removed and the answer is provided:

I pushed the changes for this prototype to Belgadons repository.

2. Use-case: Providing commands

This is not yet implemented, but I think it would be useful if the user could send commands to the bot via /sendcommand Bedroomlight ON
or to get a status: /status TemperatureLivingRoom with reply “The temperature in the “Living Room” is 21°C”
With /help or /list we could show the user a list of available commands and items.

The UI of the telegram client can even show you a list of available commands and you just have to tap on one of them (see Commands).

3 Likes

Wow, it sounds good. :grinning:
@ZzetT Any plans to offer in next time a jar file with your changes to test the binding?