Ankündigung

Einklappen
Keine Ankündigung bisher.

Telegram, Alternative zu WhatsApp

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    #61
    Hallo liebe Freunde des Telegram Plugins.

    aktuell nutzen wir die telepot lib im threads modus. Dies hat zur folge, dass die drei threads der telepot lib nicht mit shng beendet werden können. Meist ist bei mir daher ein kill -9 zum beenden von shng notwendig.

    Es gibt in der telepot lib auch die möglichkeit mit asyncio zu arbeiten. dabei sollte dieses problem nicht mehr auftreten.

    ich habe versucht folgendes beispiel https://github.com/nickoala/telepot/...e/skeletona.py

    in ein shng plugin zu übertragen

    doch schon bei den imports:

    Code:
    import asyncio
    import telepot.aio
    import telepot.aio.api
    from telepot.aio.loop import MessageLoop
    tritt folgender Fehler auf
    Code:
    2017-12-29 12:06:33 ERROR    plugin       Main         Plugin 'telegram' exception during import of __init__.py: There is no current event loop in thread 'Main'. -- plugin.py:__init__:366
    Traceback (most recent call last):
      File "/home/smarthome/smarthome/lib/plugin.py", line 364, in __init__
        exec("import {0}".format(classpath))
      File "<string>", line 1, in <module>
      File "/home/smarthome/smarthome/plugins/telegram/__init__.py", line 40, in <module>
        import telepot.aio
      File "<frozen importlib._bootstrap>", line 969, in _find_and_load
      File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 634, in _load_backward_compatible
      File "/usr/local/lib/python3.5/dist-packages/telepot-12.5-py3.5.egg/telepot/aio/__init__.py", line 8, in <module>
        from . import helper, api
      File "<frozen importlib._bootstrap>", line 969, in _find_and_load
      File "<frozen importlib._bootstrap>", line 958, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 664, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 634, in _load_backward_compatible
      File "/usr/local/lib/python3.5/dist-packages/telepot-12.5-py3.5.egg/telepot/aio/api.py", line 10, in <module>
        _loop = asyncio.get_event_loop()
      File "/usr/lib/python3.5/asyncio/events.py", line 671, in get_event_loop
        return get_event_loop_policy().get_event_loop()
      File "/usr/lib/python3.5/asyncio/events.py", line 583, in get_event_loop
        % threading.current_thread().name)
    RuntimeError: There is no current event loop in thread 'Main'.

    aktuell sieht mein erster versuch wie folgt aus
    Code:
    import time
    import random
    import datetime
    import logging
    import urllib3
    import telepot
    #import telepot.api
    from lib.model.smartplugin import SmartPlugin
    
    
    
    import asyncio
    import telepot.aio
    import telepot.aio.api
    from telepot.aio.loop import MessageLoop
    
    
    PLUGIN_ATTR_TOKEN        = 'token'
    PLUGIN_ATTR_CHAT_IDS    = 'trusted_chat_ids'
    
    ITEM_ATTR_MESSAGE        = 'telegram_message'
    ITEM_ATTR_MATCHREGEX        = 'telegram_value_match_regex'
    
    MESSAGE_TAG_ID          = '[ID]'
    MESSAGE_TAG_NAME        = '[NAME]'
    MESSAGE_TAG_VALUE       = '[VALUE]'
    MESSAGE_TAG_CALLER      = '[CALLER]'
    MESSAGE_TAG_SOURCE      = '[SOURCE]'
    MESSAGE_TAG_DEST        = '[DEST]'
    
    
    class Telegram(SmartPlugin):
        PLUGIN_VERSION = "2.0.0"
        ALLOW_MULTIINSTANCE = False
    
        # Storage Array for all items using telegram attributes
        _items = []
        _chat_ids = []
    
        # called, before items are loaded
        def __init__(self, smarthome, token='dummy', trusted_chat_ids='none', name='SH Telegram Gateway', welcome_msg='SmarthomeNG Telegram Plugin is up and running'):
            self._sh = smarthome
            self.logger = logging.getLogger(__name__)
    
        # Really don't need to hear about connections being brought up again after server has closed it
            # use logging.yaml or
            # logging.getLogger("requests.packages.urllib3.connectionpool").setLevel(logging.WARNING)
    
    
            self._bot = telepot.aio.Bot(token)
            self._loop = asyncio.get_event_loop()
    #        self._loop = asyncio.new_event_loop()
    #        asyncio.set_event_loop(self._loop)
    
            self._loop.create_task(MessageLoop(self._bot, self.message_handler).run_forever())
            print('Listening ...')
    
            self.loop.run_forever()
    
            self._chat_ids = list(map(int, trusted_chat_ids.split(',')))
    
            if len(self._chat_ids) < 1:
                self.logger.info("No trusted chat ids configured!")
            # self._name = "GAMA HOME"
            self._name = name
    
            self._msg_broadcast(welcome_msg)

    Wäre super, wenn jemand der sich damit auskennt mal ein Auge darauf wirft.

    Für mich sieht es so aus als ob das Plugin in einem eigenen Thread läuft und der Event Loop aber im Main Thread gesucht wird. Wahrscheinlich nur eine Kleinigkeit...


    LG

    mode

    Kommentar


      #62
      Bezüglich der "Verbindungsprobleme" nutzte ich seit Monaten "python-telegram-bot" ohne jeglich Probleme, da bei mir die Verbindungsprobleme ebenfalls auftraten.
      Da ich auch das Image von
      Onkelandy für den raspberryPi benutze habe ich nun im Produktivsystem auch wieder telepot zu laufen und parallel auf einem Testsystem python-telegram-bot.
      Ich nutze, wie ich im ersten Beitrag beschrieben habe, bis jetzt nur Logiken zum Versenden von Nachrichten. Bei der Nutzung des Testsystems werden alle Nachrichten übermittelt beim Produktivsystem nicht.
      Das Versenden von Nachrichten zwischen telepot und python-telegram-bot unterscheidet sich ein wenig:

      Telepot:
      Code:
      bot.sendMessage(chat_id, 'Text!')
      Python-telegram-bot:
      Code:
      bot.sendMessage(chat_id=chat_id, text='Text!')
      Versuchsweise habe ich das telegram-plugin dahingehend angepasst. Leider fehlt mir das Wissen um commands zu implementieren wie es z.B
      ivande gemacht hat.
      Vielleicht hat jemand Lust auch mal python-telegram-bot zu testen und das plugin so anzupassen das auch commands funktionieren.

      Kommentar


        #63
        Danke für den Beitrag! Wusste gar nicht, dass es eine weitere Python lib für Telegram gibt, aber der erste Eindruck von python-telegram-bot ist gut. Gefühlt wird diese Toolbox auch aktiver entwickelt und sich daher die Umstellung evtl. lohnen...

        Kommentar


          #64
          Hallo. Tolles Plugin. Kann mir jemand ein Beispiel für die Benutzung von telegram_value_match_regex geben? Oder wie kann ich bedingt eines Item Values eine Nachricht schicken?

          Kommentar


            #65
            telegram_value_match_regex ist im Plugin noch nicht implementiert: (obwohl in der Readme.md beschrieben,..)

            Code:
             # TODO: ITEM_ATTR_MATCHREGEX
             # p = re.compile('\d+')
             # m = p.match( 'string goes here' )
             # if m:
             #    print('Match found: ', m.group())
             # else:
             #    print('No match')
            es wird mit dem aktuellen Plugin-Stand eine Nachricht bei jeder Item Änderung gesendet..

            Gruß Ivan

            Kommentar


              #66
              grisu911 könntest Du die entsprechenden Code-Zeilen posten, so könnte man bei Gelegenheit versuchen das Plugin auf python-telegram-bot umzubauen.

              Zitat von grisu911 Beitrag anzeigen
              Versuchsweise habe ich das telegram-plugin dahingehend angepasst.

              ich nutze das Plugin seit ca. 1 Monat (telepot lib) regelmäßig, konnte bisher jedoch gar keine Verbindungsprobleme feststellen..

              Kommentar


                #67
                grisu911
                Forums-Einsteiger
                grisu911 Ich würde mich freuen, wenn Du Deine Implementation vorstellst. Ich habe durchaus mal das eine oder andere mal Verbindungsprobleme aber mich stört auch das drei Threads immer hängen bleiben beim Beenden von SmartHomeNG.

                Kommentar


                  #68
                  Hallo,
                  wie ich schon geschrieben habe nutze ich telegram zur Zeit nur in Logiken, nach folgendem Schema:
                  Code:
                  #import requests
                  import telegram
                  bot = telegram.Bot('token')
                  
                  bot.sendMessage(chat_id=-123456789,
                  text='*Gestern:*\n_max. Temp.:_ ' + str(sh.WS300.Tempaussen.TempMaxGestern()) + '\n_min. Temp.:_ ' + str(sh.WS300.Tempaussen.TempMinGestern()) + '\n_Regenmenge:_ ' + str(sh.WS300.Regen_Tag()) + '\n_max. Windgeschw.:_ ' + str(sh.WS300.Wind.WindMaxGestern()) + '', parse_mode=telegram.ParseMode.MARKDOWN)
                  Hierzu habe ich python-telegram-bot über pip installiert und telepot deinstalliert.

                  Versuchsweise (testsystem) hatte ich die __init__.py im telegram-plugin modifiziert:
                  Code:
                  #!/usr/bin/env python3
                  # vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab
                  #########################################################################
                  # Copyright 2017 Markus Garscha                 http://knx-user-forum.de/
                  #########################################################################
                  #
                  #  This file is part of SmartHomeNG.
                  #
                  #  SmartHomeNG is free software: you can redistribute it and/or modify
                  #  it under the terms of the GNU General Public License as published by
                  #  the Free Software Foundation, either version 3 of the License, or
                  #  (at your option) any later version.
                  #
                  #  SmartHomeNG is distributed in the hope that it will be useful,
                  #  but WITHOUT ANY WARRANTY; without even the implied warranty of
                  #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                  #  GNU General Public License for more details.
                  #
                  #  You should have received a copy of the GNU General Public License
                  #  along with SmartHomeNG. If not, see <http://www.gnu.org/licenses/>.
                  #
                  #########################################################################
                  
                  #### Setup Phyton lib for telegram manually
                  # apt-get install python-pip
                  # pip install telepot
                  
                  import time
                  import random
                  import datetime
                  import logging
                  import urllib3
                  import telegram
                  import telegram.ext
                  [MARKIEREN]from telegram.ext import Updater
                  from telegram.ext import CommandHandler
                  #import telepot
                  #import telepot.api[/MARKIEREN]
                  from lib.model.smartplugin import SmartPlugin
                  
                  PLUGIN_ATTR_TOKEN        = 'token'
                  PLUGIN_ATTR_CHAT_IDS    = 'trusted_chat_ids'
                  
                  ITEM_ATTR_MESSAGE        = 'telegram_message'
                  ITEM_ATTR_MATCHREGEX    = 'telegram_value_match_regex'
                  
                  MESSAGE_TAG_ID          = '[ID]'
                  MESSAGE_TAG_NAME        = '[NAME]'
                  MESSAGE_TAG_VALUE       = '[VALUE]'
                  MESSAGE_TAG_CALLER      = '[CALLER]'
                  MESSAGE_TAG_SOURCE      = '[SOURCE]'
                  MESSAGE_TAG_DEST        = '[DEST]'
                  
                  
                  class Tele_New(SmartPlugin):
                      PLUGIN_VERSION = "0.1"
                      ALLOW_MULTIINSTANCE = False
                  
                      # Storage Array for all items using telegram attributes
                      _items = []
                      _chat_ids = []
                  
                      # called, before items are loaded
                      def __init__(self, smarthome, token='dummy', trusted_chat_ids='none', name='SH Telegram Gateway', welcome_msg='SmarthomeNG Telegram Plugin is up and running'):
                          self._sh = smarthome
                          self.logger = logging.getLogger(__name__)
                  
                      # Really don't need to hear about connections being brought up again after server has closed it
                          # use logging.yaml or
                          # logging.getLogger("requests.packages.urllib3.connectionpool").setLevel(logging.WARNING)
                  
                          #telepot.api._pools = {
                          #    'default': urllib3.PoolManager(num_pools=3, maxsize=10, retries=3, timeout=30),
                          #}
                  
                          self._bot = telegram.Bot(token=token)  #prüfen
                          #self._bot = telepot.Bot(token)
                          self.logger.info("Telegram bot is listening: {0}".format(self._bot.getMe()))
                  
                  
                  
                          #self._bot.message_loop(self.message_handler)
                          #self._bot.update_queue(self.message_handler)
                  
                          self._chat_ids = list(map(int, trusted_chat_ids.split(',')))
                  
                          if len(self._chat_ids) < 1:
                              self.logger.info("No trusted chat ids configured!")
                          # self._name = "GAMA HOME"
                          self._name = name
                  
                          self._msg_broadcast(welcome_msg)
                  
                      # triggered by sh.telegram(msg)
                      def __call__(self, msg):
                          [MARKIEREN]#self._bot.sendMessage(self._chat_id, msg)
                          self._bot.sendMessage(chat_id=self._chat_id, text=msg)[/MARKIEREN]
                  
                          # called once at startup after all items are loaded
                      def run(self):
                          self.alive = True
                          # if you want to create child threads, do not make them daemon = True!
                          # They will not shutdown properly. (It's a python bug)
                      def stop(self):
                          self._bot.close()
                          self.alive = False
                      # close files and data connections
                  
                      # called for each item during startup, "item.conf" contains the attibute=value tuples
                      def parse_item(self, item):
                          if ITEM_ATTR_MESSAGE in item.conf:
                              self.logger.debug("parse item: {0}".format(item))
                              value = item.conf[ITEM_ATTR_MESSAGE]
                              self._items.append(item)
                              return self.update_item
                          else:
                              return None
                  
                      def parse_logic(self, logic):
                          if 'xxx' in logic.conf:
                              # self.function(logic['name'])
                              pass
                  
                      # called each time an item changes.
                      def update_item(self, item, caller=None, source=None, dest=None):
                          if caller != 'smarthome-telegram':
                              self.logger.info("update item: {0}".format(item.id()))
                  
                          if ITEM_ATTR_MESSAGE in item.conf:
                              msg_txt_tmpl = item.conf[ITEM_ATTR_MESSAGE]
                  
                              item_id = item.id()
                              item_value = "{0}".format(item())
                  
                              # TODO: ITEM_ATTR_MATCHREGEX
                              # p = re.compile('\d+')
                              # m = p.match( 'string goes here' )
                              # if m:
                              #    print('Match found: ', m.group())
                              # else:
                              #    print('No match')
                  
                              caller = "None" if caller is None else str(caller)
                              source = "None" if source is None else str(source)
                              dest = "None" if dest is None else str(dest)
                  
                              if 'name' in item.conf:
                                  item_name = item.conf['name']
                              else:
                                  item_name = 'NONAME'
                  
                              # TODO: item.__changed_by
                  
                              # replace Tags with id,value,caller,source,dest,...
                              msg_txt = msg_txt_tmpl.replace(MESSAGE_TAG_ID, item_id)
                              msg_txt = msg_txt.replace(MESSAGE_TAG_NAME, item_name)
                              msg_txt = msg_txt.replace(MESSAGE_TAG_VALUE, item_value)
                              msg_txt = msg_txt.replace(MESSAGE_TAG_CALLER, caller)
                              msg_txt = msg_txt.replace(MESSAGE_TAG_SOURCE, source)
                              msg_txt = msg_txt.replace(MESSAGE_TAG_DEST, dest)
                  
                              # DEBUG
                              # msg_txt = msg_txt_tmpl
                  
                              self.logger.info("send Message: {}".format(msg_txt))
                  
                              self._msg_broadcast(msg_txt)
                              # for cid in self._chat_ids:
                              #    self._bot.sendMessage(cid, msg_txt)
                  
                      def _msg_broadcast(self, msg):
                          for cid in self._chat_ids:
                              try:
                                 [MARKIEREN] #self._bot.sendMessage(cid, msg)
                                  self._bot.sendMessage(chat_id=cid, text=msg)[/MARKIEREN]
                              except:
                                  self.logger.error("could not broadcast to chat id [%d]" % cid)
                  
                  
                      def time(bot, update):
                  
                          self.logger.info("[%d] command received: %s" % (self._chat_id, command))
                  
                          bot.send_message(chat_id=update.message.chat_id, text='Das ist ein Test?')
                  
                          # /roll: just a dummy to test interaction
                          #if command == '/roll':
                                  #self._bot.sendMessage(self._chat_id, random.randint(1,6))
                          #        self._bot.sendMessage(chat_id=self._chat_id, text=random.randint(1,6))
                  
                      # /time: return server time
                          #elif command == '/time':
                                  #self._bot.sendMessage(self._chat_id, str(datetime.datetime.now()))
                          self._bot.sendMessage(chat_id=self._chat_id, text=str(datetime.datetime.now()))
                  
                  
                      def list_items(self, chat_idd):
                          textt = ""
                          for item in self._items:
                              if item.type():
                                  text += "{0} = {1}\n".format(item.id(), item())
                              else:
                                  text += "{0}\n".format(item.id())
                  
                          # self._bot.sendMessage(self._chat_id, "<b>bold</b> and <i>italic</i>", parse_mode='HTML')
                          # self._bot.sendMessage(self._chat_id, "|ABC|DEF|\n|abc|def|", parse_mode='Markdown')
                          # self._bot.sendMessage(self._chat_id, "*bold* _italic_ ~deleted~ `code` ````code\nblock```  [link](http://www.google.com)", parse_mode='Markdown')
                          #self._bot.sendMessage(chat_idd, text)
                          self._bot.sendMessage(chat_id=chat_idd, text=textt)
                  
                      if __name__ == '__main__':
                  
                          updater = Updater(token)
                  
                          caps_handler = CommandHandler('time', time)
                          dispatcher.add_handler(caps_handler)
                  
                          updater.start_polling()
                          updater.idle()
                  
                  
                   #     logging.basicConfig(level=logging.DEBUG)
                  #     myplugin = PluginName('smarthome-telegram')
                  #     myplugin.run()
                  Ich habe hier letzendlich nur die Nomenklatur zum Versenden der Nachricht geändert, wie in Beitrag #62 beschrieben.

                  Leider habe ich es zeitlich noch nicht geschafft mich mit dem Senden von Commands zu beschäftigen., ala
                  ivande .

                  Aufgefallen ist mir noch das bei telepot das Verbindungsproblem auftritt wenn ca. 15 min lang keine Nachricht gesendet wurde. Die erste wird dann "verschluckt", die zweite soweit sie innerhalb der nächsten ca. 15 min gesendet wird funktioniert.

                  Kommentar


                    #69
                    Hab das Plugin nun auf "python-telegram-bot" umgebaut. Zum testen natürlich python-telegram-bot installieren, mit pip oder pip3..

                    PHP-Code:
                      sudo pip install python-telegram-bot 
                    Code:
                    #!/usr/bin/env python3
                    # vim: set encoding=utf-8 tabstop=4 softtabstop=4 shiftwidth=4 expandtab
                    #########################################################################
                    # Copyright 2017 Markus Garscha                 http://knx-user-forum.de/
                    #########################################################################
                    #
                    #  This file is part of SmartHomeNG.
                    #
                    #  SmartHomeNG is free software: you can redistribute it and/or modify
                    #  it under the terms of the GNU General Public License as published by
                    #  the Free Software Foundation, either version 3 of the License, or
                    #  (at your option) any later version.
                    #
                    #  SmartHomeNG is distributed in the hope that it will be useful,
                    #  but WITHOUT ANY WARRANTY; without even the implied warranty of
                    #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                    #  GNU General Public License for more details.
                    #
                    #  You should have received a copy of the GNU General Public License
                    #  along with SmartHomeNG. If not, see <http://www.gnu.org/licenses/>.
                    #
                    #########################################################################
                    
                    #### Setup Phyton lib for telegram manually
                    # apt-get install python-pip
                    # pip install python-telegram-bot
                    
                    import time
                    import random
                    import datetime
                    import logging
                    import urllib3
                    import telegram
                    import telegram.ext
                    from telegram.ext import Updater
                    from telegram.ext import CommandHandler
                    
                    from lib.model.smartplugin import SmartPlugin
                    from lib.logic import Logics
                    
                    PLUGIN_ATTR_TOKEN       = 'token'
                    PLUGIN_ATTR_CHAT_IDS    = 'trusted_chat_ids'
                    
                    ITEM_ATTR_MESSAGE       = 'telegram_message'
                    ITEM_ATTR_INFO          = 'telegram_info'
                    ITEM_ATTR_MATCHREGEX    = 'telegram_value_match_regex'
                    
                    MESSAGE_TAG_ID          = '[ID]'
                    MESSAGE_TAG_NAME        = '[NAME]'
                    MESSAGE_TAG_VALUE       = '[VALUE]'
                    MESSAGE_TAG_CALLER      = '[CALLER]'
                    MESSAGE_TAG_SOURCE      = '[SOURCE]'
                    MESSAGE_TAG_DEST        = '[DEST]'
                    
                    
                    class Telegram(SmartPlugin):
                        PLUGIN_VERSION = "1.1.3"
                        ALLOW_MULTIINSTANCE = False
                    
                        # Storage Array for all items using telegram attributes
                        _items = []
                        _chat_ids = []
                        _items_info = {}    # dict used whith the info-command: key = attibute_value, val= item_list
                    
                        # called, before items are loaded
                        def __init__(self, smarthome, token='dummy', trusted_chat_ids='none', name='SH Telegram Gateway', welcome_msg='SmarthomeNG Telegram Plugin is up and running'):
                            self._sh = smarthome
                            self.logger = logging.getLogger(__name__)
                    
                            self._updater = Updater(token=token)
                            self._bot = self._updater.bot
                    
                            self.logger.info("Telegram bot is listening: {0}".format(self._bot.getMe()))
                    
                            dispatcher = self._updater.dispatcher
                            dispatcher.add_handler(CommandHandler('time', self.cHandler_time))
                            dispatcher.add_handler(CommandHandler('help', self.cHandler_help))
                            dispatcher.add_handler(CommandHandler('hide', self.cHandler_hide))
                            dispatcher.add_handler(CommandHandler('list', self.cHandler_list))
                            dispatcher.add_handler(CommandHandler('info', self.cHandler_info))
                            dispatcher.add_handler(CommandHandler('lo', self.cHandler_lo))
                            dispatcher.add_handler(CommandHandler('tr', self.cHandler_tr, pass_args=True))
                    
                            self._updater.start_polling()   # (poll_interval=0.0, timeout=10, network_delay=None, clean=False, bootstrap_retries=0, read_latency=2.0, allowed_updates=None)
                    
                            self._chat_ids = list(map(int, trusted_chat_ids.split(',')))
                    
                            if len(self._chat_ids) < 1:
                                self.logger.info("No trusted chat ids configured!")
                    
                            self._name = name
                    
                            self._msg_broadcast(welcome_msg)
                    
                        # triggered by sh.telegram(msg)
                        def __call__(self, msg):
                            #self._bot.sendMessage(self._chat_id, msg)
                            self._bot.sendMessage(chat_id=self._chat_id, text=msg)
                    
                            # called once at startup after all items are loaded
                        def run(self):
                            self.alive = True
                            self.logics = Logics.get_instance() # Returns the instance of the Logics class, to be used to access the logics-api
                    
                            # if you want to create child threads, do not make them daemon = True!
                            # They will not shutdown properly. (It's a python bug)
                    
                    
                        # close files and data connections
                        def stop(self):
                            self.alive = False
                            try:
                                self.logger.info("stop updater")
                                self._updater.stop()
                            except:
                                pass
                    
                        # called for each item during startup, "item.conf" contains the attibute=value tuples
                        def parse_item(self, item):
                            if ITEM_ATTR_MESSAGE in item.conf:
                                self.logger.debug("parse item: {0}".format(item))
                                value = item.conf[ITEM_ATTR_MESSAGE]
                                self._items.append(item)
                                return self.update_item
                    
                            if ITEM_ATTR_INFO in item.conf:
                                key = item.conf[ITEM_ATTR_INFO]
                                self.logger.debug("parse item: {0} {1}".format(item, key))
                                if key in self._items_info:
                                    self._items_info[key].append(item)
                                else:
                                    self._items_info[key] = [item]  # dem dict neue Liste hinzufuegen
                                    self._updater.dispatcher.add_handler(CommandHandler(key, self.cHandler_info_attr))
                                return self.update_item
                    
                            else:
                                return None
                    
                        def parse_logic(self, logic):
                            if 'xxx' in logic.conf:
                                # self.function(logic['name'])
                                pass
                    
                        # called each time an item changes.
                        def update_item(self, item, caller=None, source=None, dest=None):
                            if caller != 'smarthome-telegram':
                                self.logger.info("update item: {0}".format(item.id()))
                    
                            if ITEM_ATTR_MESSAGE in item.conf:
                                msg_txt_tmpl = item.conf[ITEM_ATTR_MESSAGE]
                    
                                item_id = item.id()
                                item_value = "{0}".format(item())
                    
                                # TODO: ITEM_ATTR_MATCHREGEX
                                # p = re.compile('\d+')
                                # m = p.match( 'string goes here' )
                                # if m:
                                #    print('Match found: ', m.group())
                                # else:
                                #    print('No match')
                    
                                caller = "None" if caller is None else str(caller)
                                source = "None" if source is None else str(source)
                                dest = "None" if dest is None else str(dest)
                    
                                if 'name' in item.conf:
                                    item_name = item.conf['name']
                                else:
                                    item_name = 'NONAME'
                    
                                # TODO: item.__changed_by
                    
                                # replace Tags with id,value,caller,source,dest,...
                                msg_txt = msg_txt_tmpl.replace(MESSAGE_TAG_ID, item_id)
                                msg_txt = msg_txt.replace(MESSAGE_TAG_NAME, item_name)
                                msg_txt = msg_txt.replace(MESSAGE_TAG_VALUE, item_value)
                                msg_txt = msg_txt.replace(MESSAGE_TAG_CALLER, caller)
                                msg_txt = msg_txt.replace(MESSAGE_TAG_SOURCE, source)
                                msg_txt = msg_txt.replace(MESSAGE_TAG_DEST, dest)
                    
                                # DEBUG
                                # msg_txt = msg_txt_tmpl
                    
                                self.logger.info("send Message: {}".format(msg_txt))
                    
                                self._msg_broadcast(msg_txt)
                                # for cid in self._chat_ids:
                                #    self._bot.sendMessage(cid, msg_txt)
                    
                        def _msg_broadcast(self, msg, chat_id=None):
                            for cid in self.get_chat_id_list(chat_id):
                                try:
                                    self._bot.sendMessage(chat_id=cid, text=msg)
                                except:
                                    self.logger.error("could not broadcast to chat id [%d]" % cid)
                    
                        def _photo_broadcast(self, photofile, msg, chat_id=None):
                            for cid in self.get_chat_id_list(chat_id):
                                try:
                                    self._bot.sendPhoto(chat_id=cid, photo=open(str(photofile),'rb'), caption=msg)
                                except:
                                    self.logger.error("could not broadcast to chat id [%d]" % cid)
                    
                        def get_chat_id_list(self, att_chat_id):
                            chat_ids_to_send = []                           # new list
                            if att_chat_id is None:                         # no attribute specified
                                chat_ids_to_send = self._chat_ids           # chat_ids from plugin configuration
                            else:
                                if isinstance(att_chat_id, list):           # if attribute is a list
                                    chat_ids_to_send = att_chat_id
                                else:                                       # if attrubute is a single chat_id
                                    chat_ids_to_send.append(att_chat_id)    # append to list
                            return chat_ids_to_send
                    
                        # /time: return server time
                        def cHandler_time(self, bot, update):
                            bot.send_message(chat_id=update.message.chat_id, text=str(datetime.datetime.now()))
                    
                        # /help: show available commands als keyboard
                        def cHandler_help(self, bot, update):
                            bot.send_message(chat_id=update.message.chat_id, text="choose", reply_markup={"keyboard":[["/hide"], ["/time","/list"], ["/lo","/info"]]})
                    
                        # /hide: hide keyboard
                        def cHandler_hide(self, bot, update):
                            hide_keyboard = {'hide_keyboard': True}
                            bot.send_message(chat_id=update.message.chat_id, text="I'll hide the keyboard", reply_markup=hide_keyboard)
                    
                        # /list: show registered items and value
                        def cHandler_list(self, bot, update):
                            self.list_items(update.message.chat_id)
                    
                        # /info: show item-menu with registered items with specific attribute
                        def cHandler_info(self, bot, update):
                            bot.send_message(chat_id=update.message.chat_id, text="Infos from the items:", reply_markup={"keyboard":self.create_info_reply_markup()})
                    
                        # /xx show registered items and value with specific attribute/key
                        def cHandler_info_attr(self, bot, update):
                            c_key = update.message.text.replace("/", "", 1)
                            if c_key in self._items_info:
                                self.logger.debug("info-command: {0}".format(c_key))
                                self.list_items_info(update.message.chat_id, c_key)
                            else:    
                                self._bot.sendMessage(chat_id=update.message.chat_id, text="unkown command %s" % (c_key))
                    
                        # /lo: show logics
                        def cHandler_lo(self, bot, update):
                            tmp_msg="Logics:\n"
                            for logic in sorted(self.logics.return_defined_logics()):    # list with the names of all logics that are currently loaded
                                data = []
                                info = self.logics.get_logic_info(logic)
                                if not info['enabled']:
                                    data.append("disabled")
                                if 'next_exec' in info:
                                    data.append("scheduled for {0}".format(info['next_exec']))
                                tmp_msg+=("{0}".format(logic))
                                if len(data):
                                    tmp_msg+=(" ({0})".format(", ".join(data)))
                                tmp_msg+=("\n")
                            self.logger.info("send Message: {0}".format(tmp_msg))
                            self._bot.sendMessage(chat_id=update.message.chat_id, text=tmp_msg)
                    
                        # /tr xx: trigger logic xx
                        def cHandler_tr(self, bot, update, args):
                            try:
                                self.logger.debug("trigger_logic: {0}".format(args))
                                self.logics.trigger_logic(args[0], by='telegram')      # Trigger a logic
                            except Exception as e:
                                tmp_msg = ("could not trigger logic %s error %s" % (para, e))
                                self._bot.sendMessage(chat_id=self._chat_id, text=tmp_msg)
                    
                        def list_items(self, chat_id):
                            text = ""
                            for item in self._items:
                                if item.type():
                                    text += "{0} = {1}\n".format(item.id(), item())
                                else:
                                    text += "{0}\n".format(item.id())
                            self._bot.sendMessage(chat_id=chat_id, text=text)
                    
                        # show registered items and value with specific attribute/key
                        def list_items_info(self, chat_id, key):
                            text = ""
                            for item in self._items_info[key]:
                                if item.type():
                                    text += "{0} = {1}\n".format(item.id(), item())
                                else:
                                    text += "{0}\n".format(item.id())
                            self._bot.sendMessage(chat_id=chat_id, text=text)
                    
                        #
                        def create_info_reply_markup(self):
                            # reply_markup={"keyboard":[["/roll","/hide"], ["/time","/list"], ["/lo","/info"]]})
                            button_list = []
                            for key, value in self._items_info.items():
                                button_list.append("/"+key)
                            #self.logger.debug("button_list: {0}".format(button_list))
                            header = ["/help"]
                            #self.logger.debug("header: {0}".format(header))
                            keyboard = self.build_menu(button_list, n_cols=2, header_buttons=header)
                            #self.logger.debug("keyboard: {0}".format(keyboard))
                            return keyboard
                    
                        # util to create a bot-menu    
                        def build_menu(self, buttons, n_cols, header_buttons=None, footer_buttons=None):
                            menu = [buttons[i:i + n_cols] for i in range(0, len(buttons), n_cols)]
                            if header_buttons:
                                menu.insert(0, header_buttons)
                            if footer_buttons:
                                menu.append(footer_buttons)
                            return menu
                    
                     #     logging.basicConfig(level=logging.DEBUG)
                    #     myplugin = PluginName('smarthome-telegram')
                    #     myplugin.run()
                    Zuletzt geändert von ivande; 28.01.2018, 11:17.

                    Kommentar


                      #70
                      Hallo ivande,

                      tolle Arbeit, habe es grade kurz getestet, funktioniert super.

                      Eine Fehlermeldung ist bei /list im Log zu finden:
                      Code:
                      2018-01-29  00:20:59 WARNING  dispatcher   A TelegramError was raised while processing the Update
                      2018-01-29  00:20:59 ERROR    dispatcher   No error handlers are registered, logging exception...
                      Traceback (most recent call last):
                        File "/usr/local/lib/python3.5/dist-packages/telegram/ext/dispatcher.py", line 279, in process_update
                          handler.handle_update(update, self)
                        File "/usr/local/lib/python3.5/dist-packages/telegram/ext/commandhandler.py", line 171, in handle_update
                          return self.callback(dispatcher.bot, update, **optional_args)
                        File "/usr/local/smarthome/plugins/telegram/__init__.py", line 231, in cHandler_list
                          self.list_items(update.message.chat_id)
                        File "/usr/local/smarthome/plugins/telegram/__init__.py", line 279, in list_items
                          self._bot.sendMessage(chat_id=chat_id, text=text)
                        File "/usr/local/lib/python3.5/dist-packages/telegram/bot.py", line 60, in decorator
                          result = func(self, *args, **kwargs)
                        File "/usr/local/lib/python3.5/dist-packages/telegram/bot.py", line 85, in decorator
                          result = self._request.post(url, data, timeout=kwargs.get('timeout'))
                        File "/usr/local/lib/python3.5/dist-packages/telegram/utils/request.py", line 272, in post
                          **urlopen_kwargs)
                        File "/usr/local/lib/python3.5/dist-packages/telegram/utils/request.py", line 210, in _request_wrapper
                          raise BadRequest(message)
                      telegram.error.BadRequest: Message text is empty

                      Kommentar


                        #71
                        Cool, ich habe es mal mit aufgenommen zum Test (und vielen Dank für die Unterstützung - mir fehlt es derzeit an allen Ecken und Enden an Zeit)

                        Kommentar


                          #72
                          hab noch ein paar Änderungen gemacht.

                          https://github.com/ivan73/plugins/bl...am/__init__.py
                          https://github.com/ivan73/plugins/bl...gram/README.md

                          ich hoffe der Fehler ist behoben:
                          Zitat von grisu911 Beitrag anzeigen
                          Eine Fehlermeldung ist bei /list im Log zu finden:

                          noch ein witeres SH-Item-Attribut hinzugefügt.
                          SH-Items mit dem Attribut "telegram_text" bekommen den Text aus der Telegram-Message direkt in das Item geschrieben.
                          so kann man dann in einer eigenen Logik bei Änderung des Items den empfangenen Text auswerten,.. ohne Commands einbauen zu müssen + ohne Änderungen im Plugin vornehmen zu müssen.

                          Code:
                          telegram_text
                          
                          [B]write message-text into the SH-item whit this attribut[/B]
                          
                          [telegram_message]
                          name = Textnachricht von Telegram
                          type = str
                          telegram_text = "true"

                          telegram_value_match_regex kann ebenfalls getestet werden

                          Code:
                          [TestNum]
                                  type = num
                                  cache = True
                                  telegram_message = TestNum: [VALUE]
                                  telegram_value_match_regex = [0-1][0-9]    # nur Nachrichten senden wenn Zahlen von 0 - 19
                          [TestBool]
                                  type = bool
                                  cache = True
                                  telegram_message = TestBool: [VALUE]
                                  telegram_value_match_regex = 1              # nur Nachricht senden wenn 1 (True)
                          Voraussetzung für das Plugin SH Version 1.4.0
                          Zuletzt geändert von ivande; 29.01.2018, 23:40.

                          Kommentar


                            #73
                            Danke für die Updates! Die Abfrage mit /wetter funktioniert bei mir prima, automatisches Senden einer Msg ebenfalls.
                            Beim README ist mir aufgefallen, dass beim simple example conf und yaml vertauscht sind. Das regex Example wäre auch noch für die README schön. Thx!

                            Kommentar


                              #74
                              Hi,

                              ich habe noch einen Error Handler hinzugefügt:

                              Code:
                               dispatcher.add_error_handler(self.eHandler)

                              Code:
                                  def eHandler(bot, update, error, dummy):
                                      try:
                                          self.logger.warning('Update "%s" caused error "%s"', update, error)
                                      except:
                                          pass

                              Kommentar


                                #75
                                Ich glaube in Python3 wird diese Syntax bevorzugt:
                                Code:
                                 
                                 self.logger.warning('Update {} caused error {}'.format(update, error))
                                https://pyformat.info/#simple

                                Kommentar

                                Lädt...
                                X