from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText import sys import time import logging import threading import RPi.GPIO as GPIO import requests import smtplib import json import tweepy from time import localtime, strftime import paho.mqtt.publish as mqttpublish from six.moves.configparser import ConfigParser from tweepy import OAuthHandler as TweetHandler from slackclient import SlackClient PUSHOVER_SOUNDS = None def email(msg): try: message = MIMEMultipart('related') message['Subject'] = msg message['From'] = email_sender message['To'] = email_recipient message.preamble = 'This is a multi=part message in MIME format.' message_alternative = MIMEMultipart('alternative') message.attach(message_alternative) message_text = MIMEText(msg + '\n') message_text = MIMEText('

' + msg + '

') message_text.replace_header('Content-Type', 'text/html') message_alternative.attach(message_text) s = smtplib.SMTP(email_server, email_port) s.starttls() s.login(email_sender, email_password) s.sendmail(email_sender, email_recipient, message.as_string()) s.quit() except (KeyboardInterrupt, SystemExit): raise except: pass def mqtt(msg): try: mqtt_auth = None if len(mqtt_username) > 0: mqtt_auth = { 'username': mqtt_username, 'password': mqtt_password } mqttpublish.single(mqtt_topic, msg, qos=0, retain=False, hostname=mqtt_hostname, port=int(mqtt_port), client_id=mqtt_clientid, keepalive=60, will=None, auth=mqtt_auth, tls=None) except (KeyboardInterrupt, SystemExit): raise except: pass def pushbullet(cfg, msg): try: data_send = {"type": "note", "body": msg} requests.post( 'https://api.pushbullet.com/v2/pushes', data=json.dumps(data_send), headers={'Authorization': 'Bearer ' + cfg, 'Content-Type': 'application/json'}) except (KeyboardInterrupt, SystemExit): raise except: pass def get_pushoversounds(app_key): global PUSHOVER_SOUNDS if not PUSHOVER_SOUNDS: url_data = "https://api.pushover.net/1/sounds.json?token={}" .format(app_key) try: r = requests.get(url_data) json_data = r.json() PUSHOVER_SOUNDS = json_data['sounds'] except (KeyboardInterrupt, SystemExit): raise except: pass def pushover(user_key, app_key, msg, device='', sound=''): global PUSHOVER_SOUNDS if not PUSHOVER_SOUNDS: get_pushoversounds(app_key) data_send = {"user": user_key, "token": app_key, "message": msg} if device: data_send['device'] = device if sound in PUSHOVER_SOUNDS: data_send['sound'] = sound try: requests.post( 'https://api.pushover.net/1/messages.json', data=json.dumps(data_send), headers={'Content-Type': 'application/json'}) except (KeyboardInterrupt, SystemExit): raise except: pass def iftt(msg): try: iftt_url = "https://maker.ifttt.com/trigger/{}/with/key/{}".format(iftt_maker_channel_event, iftt_maker_channel_key) report = {"value1" : msg} resp = requests.post(iftt_url, data=report) except (KeyboardInterrupt, SystemExit): raise except: pass def slack_webhook(msg): try: requests.post(slack_webhook_url, json={'text': msg}, headers={"Content-type": "application/json"}) except (KeyboardInterrupt, SystemExit): raise except: pass def tweet(msg): try: # Twitter is the only API that NEEDS something like a timestamp, # since it will reject identical tweets. tweet = msg + ' ' + strftime("%Y-%m-%d %H:%M:%S", localtime()) auth = TweetHandler(twitter_api_key, twitter_api_secret) auth.set_access_token(twitter_access_token, twitter_access_token_secret) tweepy.API(auth).update_status(status=tweet) except (KeyboardInterrupt, SystemExit): raise except: pass def slack(msg): try: slack = msg + ' ' + strftime("%Y-%m-%d %H:%M:%S", localtime()) sc = SlackClient(slack_api_token) sc.api_call( 'chat.postMessage', channel='#random', text=slack) except (KeyboardInterrupt, SystemExit): raise except: pass def telegram(msg): try: telegram_url = "https://api.telegram.org/bot{}/sendMessage?chat_id={}&text={}".format(telegram_api_token, telegram_user_id, msg) resp = requests.post(telegram_url) except (KeyboardInterrupt, SystemExit): raise except: pass def send_alert(message): if len(message) > 1: logging.info(message) if len(pushover_user_key) > 0 and len(pushover_app_key) > 0: pushover(pushover_user_key, pushover_app_key, message, pushover_device, pushover_sound) if len(pushbullet_api_key) > 0: pushbullet(pushbullet_api_key, message) if len(pushbullet_api_key2) > 0: pushbullet(pushbullet_api_key2, message) if len(twitter_api_key) > 0: tweet(message) if len(slack_api_token) > 0: slack(message) if len (slack_webhook_url) > 0: slack_webhook(message) if len(iftt_maker_channel_key) > 0: iftt(message) if len(mqtt_topic) > 0: mqtt(message) if len(email_recipient) > 0: email(message) if len(telegram_api_token) > 0 and len(telegram_user_id) > 0: telegram(message) def send_appliance_active_message(): send_alert(start_message) global appliance_active appliance_active = True def send_appliance_inactive_message(): send_alert(end_message) global appliance_active appliance_active = False def vibrated(x): global vibrating global last_vibration_time global start_vibration_time logging.debug('Vibrated') last_vibration_time = time.time() if not vibrating: start_vibration_time = last_vibration_time vibrating = True def heartbeat(): current_time = time.time() logging.debug("HB at {}".format(current_time)) global vibrating delta_vibration = last_vibration_time - start_vibration_time if (vibrating and delta_vibration > begin_seconds and not appliance_active): send_appliance_active_message() if (not vibrating and appliance_active and current_time - last_vibration_time > end_seconds): send_appliance_inactive_message() vibrating = current_time - last_vibration_time < 2 threading.Timer(1, heartbeat).start() logging.basicConfig(format='%(message)s', level=logging.INFO) if len(sys.argv) == 1: logging.critical("No config file specified") sys.exit(1) vibrating = False appliance_active = False last_vibration_time = time.time() start_vibration_time = last_vibration_time config = ConfigParser() config.read(sys.argv[1]) verbose = config.getboolean('main', 'VERBOSE') sensor_pin = config.getint('main', 'SENSOR_PIN') begin_seconds = config.getint('main', 'SECONDS_TO_START') end_seconds = config.getint('main', 'SECONDS_TO_END') pushbullet_api_key = config.get('pushbullet', 'API_KEY') pushover_user_key = config.get('pushover', 'user_api_key') pushover_app_key = config.get('pushover', 'app_api_key') pushover_device = config.get('pushover', 'device') pushover_sound = config.get('pushover', 'sound') mqtt_hostname = config.get('mqtt', 'mqtt_hostname') mqtt_port = config.get('mqtt', 'mqtt_port') mqtt_topic = config.get('mqtt', 'mqtt_topic') mqtt_username = config.get('mqtt', 'mqtt_username') mqtt_password = config.get('mqtt', 'mqtt_password') mqtt_clientid = config.get('mqtt', 'mqtt_clientid') pushbullet_api_key2 = config.get('pushbullet', 'API_KEY2') start_message = config.get('main', 'START_MESSAGE') end_message = config.get('main', 'END_MESSAGE') twitter_api_key = config.get('twitter', 'api_key') twitter_api_secret = config.get('twitter', 'api_secret') twitter_access_token = config.get('twitter', 'access_token') twitter_access_token_secret = config.get('twitter', 'access_token_secret') slack_api_token = config.get('slack', 'api_token') slack_webhook_url = config.get('slack','webhook_url') iftt_maker_channel_event = config.get('iftt','maker_channel_event') iftt_maker_channel_key = config.get('iftt','maker_channel_key') email_recipient = config.get('email', 'recipient') email_sender = config.get('email', 'sender') email_password = config.get('email', 'password') email_server = config.get('email', 'server') email_port = config.get('email', 'port') telegram_api_token = config.get('telegram', 'telegram_api_token') telegram_user_id = config.get('telegram', 'telegram_user_id') if verbose: logging.getLogger().setLevel(logging.DEBUG) send_alert(config.get('main', 'BOOT_MESSAGE')) GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) GPIO.setup(sensor_pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.add_event_detect(sensor_pin, GPIO.RISING) GPIO.add_event_callback(sensor_pin, vibrated) logging.info('Running config file {} monitoring GPIO pin {}'\ .format(sys.argv[1], str(sensor_pin))) threading.Timer(1, heartbeat).start()