diff options
author | Maximilien Cuony <maximilien@theglu.org> | 2016-09-12 19:20:35 +0200 |
---|---|---|
committer | Maximilien Cuony <maximilien@theglu.org> | 2016-09-12 19:20:35 +0200 |
commit | 18fb541004d3666cf722e3eeae8ed9aeab9503d2 (patch) | |
tree | 5802e1c9c488b2df4d11bae892fc7164cb9a68de | |
parent | 2e679e549baca6d3573dacaa925672189b5e034a (diff) | |
download | glutte-serial-web-18fb541004d3666cf722e3eeae8ed9aeab9503d2.tar.gz glutte-serial-web-18fb541004d3666cf722e3eeae8ed9aeab9503d2.tar.bz2 glutte-serial-web-18fb541004d3666cf722e3eeae8ed9aeab9503d2.zip |
Add twitter bot
-rw-r--r-- | adsl.py | 206 | ||||
-rw-r--r-- | config.py.dist | 4 | ||||
-rwxr-xr-x | glutte_serial_web.py | 3 | ||||
-rwxr-xr-x | reboot.sh | 3 | ||||
-rw-r--r-- | requirements.txt | 1 |
5 files changed, 217 insertions, 0 deletions
@@ -0,0 +1,206 @@ +#!/usr/bin/env python +# +# The MIT License (MIT) +# +# Copyright (c) 2016 Matthias P. Braendli, Maximilien Cuony +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +from twx.botapi import TelegramBot +import threading +import time +import os +import datetime + + +import config + + +class Monitor(threading.Thread): + + def __init__(self, ser): + threading.Thread.__init__(self) + + self.ser = ser + self.reset_states() + + def reset_states(self): + + self.current_state = None + self.status_starttime = {} + self.status_duration = {} + self.last_gps_balise = None + self.last_message = None + self.last_balise = None + self.reseted = False + + def run(self): + + queue = self.ser.register_client() + + while True: + + try: + line = queue.popleft() + except IndexError: + time.sleep(1) + line = None + + if line: + line = line.strip() + + self.last_message = datetime.datetime.now() + + if line.endswith("common init"): + self.reset_states() + self.reseted = True + + if "T_GPS" in line: + self.last_gps_balise = datetime.datetime.now() + + if "FSM: FSM_" in line: + new_state = line.split(' ')[-1] + + if self.current_state: + self.status_duration[self.current_state] = datetime.datetime.now() - self.status_starttime[self.current_state] + + self.status_starttime[new_state] = datetime.datetime.now() + self.current_state = new_state + + if "FSM: FSM_BALISE_LONGUE" in line or "FSM: FSM_BALISE_SPECIALE" in line: + self.last_balise = datetime.datetime.now() + + def alarms(self): + + MAXIMUM_STATES = { + 'FSM_OISIF': (10800, '3 hours'), + 'FSM_OPEN1': (120, '2 minutes'), + 'FSM_OPEN2': (120, '2 minutes'), + 'FSM_LETTRE': (120, '2 minutes'), + 'FSM_ECOUTE': (120, '2 minutes'), + 'FSM_ATTENTE': (120, '2 minutes'), + 'FSM_QSO': (1800, '30 minutes'), + 'FSM_ANTI_BAVARD': (120, '2 minutes'), + 'FSM_BLOQUE': (120, '2 minutes'), + 'FSM_TEXTE_73': (120, '2 minutes'), + 'FSM_TEXTE_HB9G': (120, '2 minutes'), + 'FSM_TEXTE_LONG': (120, '2 minutes'), + 'FSM_BALISE_LONGUE': (120, '2 minutes'), + 'FSM_BALISE_SPECIALE': (120, '2 minutes'), + 'FSM_BALISE_COURTE': (120, '2 minutes'), + 'FSM_BALISE_COURTE_OPEN': (120, '2 minutes'), + } + + result = [] + + if self.reseted: + result.append("A reset occured !") + self.reseted = False + + if self.last_message and (datetime.datetime.now() - self.last_message).total_seconds() > 300: + result.append("No message on UART for more than 5 minutes !") + + if self.last_gps_balise and (datetime.datetime.now() - self.last_gps_balise).total_seconds() > 300: + result.append("No GPS for more than 5 minutes !") + + if self.last_balise and (datetime.datetime.now() - self.last_balise).total_seconds() > 10800: + result.append("No FSM_BALISE_LONGUE nor FSM_BALISE_SPECIALE for more than 3 hours !") + + if self.current_state and self.current_state in MAXIMUM_STATES and (datetime.datetime.now() - self.status_starttime[self.current_state]).total_seconds() > MAXIMUM_STATES[self.current_state][0] / 10: + result.append("The FSM has been in the state {} for more than {} !".format(self.current_state, MAXIMUM_STATES[self.current_state][1])) + + return result + + +class ADSL(threading.Thread): + + def __init__(self, ser): + threading.Thread.__init__(self) + self.monitor = Monitor(ser) + + def run(self): + + self.monitor.start() + + alarms = [] + + if not config.TELEGRAM_API_TOKEN or not config.TELEGRAM_GROUP: + print("Telegram not configured, ADSL not running.") + return + + bot = TelegramBot(config.TELEGRAM_API_TOKEN) + bot.update_bot_info().wait() + print("Telegram bot {} ready".format(bot.username)) + + offset = None + + bot.send_message(config.TELEGRAM_GROUP, '\xe2\x84\xb9 Hello ! I have been started, so everything has been reset on my side.').wait() + + while True: + + updates = bot.get_updates(offset=offset, limit=1, timeout=15).wait() + if updates: + offset = updates[0].update_id + 1 + + try: + if int(updates[0].message.chat.id) == int(config.TELEGRAM_GROUP): + + if updates[0].message.text.startswith('/status'): + response = "Here is the current status:\n\n" + + response += "Current state: {}\n".format(self.monitor.current_state) + if self.monitor.last_message: + response += "Last message: {} ({} seconds ago)\n".format(self.monitor.last_message.strftime("%H:%M:%S %d/%m/%Y"), int((datetime.datetime.now() - self.monitor.last_message).total_seconds())) + if self.monitor.last_gps_balise: + response += "Last GPS: {} ({} seconds ago)\n".format(self.monitor.last_gps_balise.strftime("%H:%M:%S %d/%m/%Y"), int((datetime.datetime.now() - self.monitor.last_gps_balise).total_seconds())) + if self.monitor.last_balise: + response += "Last Balise: {} ({} seconds ago)\n".format(self.monitor.last_balise.strftime("%H:%M:%S %d/%m/%Y"), int((datetime.datetime.now() - self.monitor.last_balise).total_seconds())) + + response += "\n" + + for state, starttime in self.monitor.status_starttime.items(): + response += "{}: Started on {} ({} seconds ago)".format(state, starttime.strftime("%H:%M:%S %d/%m/%Y"), int((datetime.datetime.now() - starttime).total_seconds())) + + if state == self.monitor.current_state: + response += ", in progress\n" + else: + response += ", duration: {} seconds\n".format(int(self.monitor.status_duration[state].total_seconds())) + + bot.send_message(config.TELEGRAM_GROUP, response).wait() + + if updates[0].message.text.startswith('/reboot'): + os.system(config.TELEGRAM_REBOOT_COMMAND) + bot.send_message(config.TELEGRAM_GROUP, '\xe2\x84\xb9 I issued a reboot command. I hope everything is ok.').wait() + except: + pass + + new_alarms = self.monitor.alarms() + + for alarm in new_alarms: + if alarm not in alarms: + bot.send_message(config.TELEGRAM_GROUP, '\xe2\x9a\xa0 Problem \xe2\x9a\xa0\nSorry to bother you, but I think there is a problem with the glutt-o-matique: \n\n{}'.format(alarm)).wait() + + for old_alarm in alarms: + if old_alarm not in new_alarms: + bot.send_message(config.TELEGRAM_GROUP, '\xe2\x9c\x85 Problem fixed \xe2\x9c\x85\nThe following problem is not anymore a problem with the glutt-o-matique:\n\n{}'.format(alarm)).wait() + + alarms = new_alarms + + time.sleep(1) diff --git a/config.py.dist b/config.py.dist index 8edb5d8..0e27155 100644 --- a/config.py.dist +++ b/config.py.dist @@ -2,3 +2,7 @@ SERIALPORT = "/dev/ttyUSB0" BAUDRATE = 9600 LINES_TO_KEEP = 200 LAST_LINE_TO_KEEP = 1000 + +TELEGRAM_API_TOKEN = '' +TELEGRAM_GROUP = '' +TELEGRAM_REBOOT_COMMAND = './reboot.sh' diff --git a/glutte_serial_web.py b/glutte_serial_web.py index 72bc6e4..9966646 100755 --- a/glutte_serial_web.py +++ b/glutte_serial_web.py @@ -28,11 +28,13 @@ from time import sleep from flask import Flask, render_template from flask_sockets import Sockets import serialrx +import adsl app = Flask(__name__) sockets = Sockets(app) ser = serialrx.SerialRX() +adsl = adsl.ADSL(ser) @app.route('/') @@ -66,6 +68,7 @@ def stream(socket): ser.unregister_client(queue) ser.start() +adsl.start() if __name__ == "__main__": print("You're running in dev mode, only one client at a time will works ! Please use gunicorn to fix this :)") diff --git a/reboot.sh b/reboot.sh new file mode 100755 index 0000000..e606947 --- /dev/null +++ b/reboot.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +sudo /usr/bin/openocd -f /usr/share/openocd/scripts/board/stm32f4discovery.cfg -c "init" -c "reset" -c "exit" diff --git a/requirements.txt b/requirements.txt index e9ee31f..925dfbf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,4 @@ pyserial==3.1.1 Werkzeug==0.11.11 Flask-Sockets==0.2.1 gunicorn==19.6.0 +twx.botapi==2.1.0 |