Beispiel #1
0
class myFCM:
    ID = myConfig.get('fcm', 'userId')
    API = myConfig.get('fcm', 'url') 

    def __init__(self):
        self.SESSION = httplib2.Http()

    def send(self, rcpt, msg):
        dat = msg.copy();
        dat.update({
            'ttl': 1000,
            'priority': 'high',
            'id': self.ID
            });
        to = rcpt.split('=')
        try:
            dat[to[0]] = to[1]
        except IndexError:
            dat['device'] = rcpt
        response, content = self.SESSION.request(
                self.API, method="POST",
                headers={'Content-Type': 'application/json; charset=UTF-8'},
                body=json.dumps(dat)
        )
        
        return response.status == 200 and content.decode() == '{}'
Beispiel #2
0
class myMQTT:
    MQTTuser = myConfig.get('mqtt', 'user')
    MQTTpass = myConfig.get('mqtt', 'password')
    MQTTbroker = myConfig.get('mqtt', 'host')
    MQTTport = myConfig.get('mqtt', 'port')

    client = None

    def __init__(self):
        self.getSensors()

    def reload(self):
        self.getSensors()

    def getSensors(self):
        self.sensorsByAddr = {}
        self.sensorsByID = {}
        sensorsDB = mySensors()
        sensors = sensorsDB.getSensors({"type":"mqtt"}).values()
        for sensor in sensors:
            if not sensor['sensor'] in self.sensorsByAddr: self.sensorsByAddr[sensor['sensor']] = {} 
            self.sensorsByAddr[sensor['sensor']] = sensor.copy()
            if not sensor['sensor_id'] in self.sensorsByID: self.sensorsByID[sensor['sensor_id']] = {} 
            self.sensorsByID[str(sensor['sensor_id'])] = sensor.copy()
        sensorsDB.closeDB()

    def getSensorByAddr(self, addr):
        try:
            return self.sensorsByAddr[addr]
        except:
            return None

    def getSensorByID(self, id):
        try:
            return self.sensorsByID[str(id)]
        except:
            return None

    def updateSensorByAddr(self, addr, state, commit = True):
        ok = False
        sensor = self.getSensorByAddr(addr)
        #print(addr + " " + state)
        self.log(str(addr) + " " + state)
        if sensor and 'sensor_id' in sensor:
            try:
                # unable to use self.mySensors - mqtt callback is in another thred
                #print(str(sensor['sensor_id']) + " " + state)
                sensors = mySensors()
                sensors.saveSensorState(sensor['sensor_id'], state, commit)
                sensors.closeDB()
                self.log("Switched sensor " + str(sensor['sensor_id']) + " " + state)
            except Exception, e:
                self.log("*** ERROR *** " + str(e))
                pass
            ok = True
        #else: 
            #raise Exception("Sensor '" + addr + "' not found.") 
        return ok
Beispiel #3
0
class myFCM:
    ID = myConfig.get('fcm', 'userId')
    API = myConfig.get('fcm', 'url')
    errorCounter = 0

    def __init__(self):
        self.SESSION = httplib2.Http()

    def send(self, rcpt, msg):
        dat = msg.copy()
        dat.update({
            'ttl': 1000,
            'priority': 'high',
            'id': self.ID
        })
        to = rcpt.split('=')

        try:
            dat[to[0]] = to[1]
        except IndexError:
            dat['device'] = rcpt

        success = False
        while not success and self.errorCounter < 2:
            try:
                response, content = self.SESSION.request(
                    self.API,
                    method="POST",
                    headers={
                        'Content-Type': 'application/json; charset=UTF-8'
                    },
                    body=json.dumps(dat))
                if response.status == 200 and content.decode() == '{}':
                    self.errorCounter = 0
                    success = True
                else:
                    self.errorCounter += 1
                    time.sleep(1)
            except:
                self.errorCounter += 1
                time.sleep(1)

            if not success:
                fcmSensor = 23
                state = mySensors().getSensor(fcmSensor)
                if state['state'] == 'ON':
                    mySensors().saveSensorState(fcmSensor, 'OFF', True)

        return success
Beispiel #4
0
def _start():
    comet = CometClient.CometClient(onMessage)
    comet.listen(myConfig.get('fcm', 'websocket'))
Beispiel #5
0
class myTelegram:
    TOKEN = myConfig.get('telegram', 'token')
    URL = "https://api.telegram.org/bot{}/"
    
    def __init__(self):
        self.URL = self.URL.format(self.TOKEN)
        self.timeout = 5
        self.last_update_id = None

    def setTimeout(self, timeout):
        self.timeout = timeout
    
    def http(self):
        if not hasattr(self, '_http'):
            self._http = httplib2.Http(timeout=self.timeout)
        return self._http

    def enableLog(self):
        self.logHandler = myLogs('telegram-class', 0o666)

    def log(self, data):
        if hasattr(self, 'logHandler'):
            self.logHandler.log(data)

    def get_url(self, url):
        attempts = 20;
        while attempts > 0:
            try:
                response, data = self.http().request(url)
                if response.status == 200:
                    content = data.decode("utf8")
                    return content
            except Exception as e:
                attempts -= 1
                if (attempts < 1):
                    #fcm = myfcm();
                    #data = {"message": {"message":"telegram unable to connect",'cmd': 'showalert','from': 'raspberry'}}

                    #time.sleep(60)
                    raise
            time.sleep(1)
    
    def post_json(self, url, json):
        attempts = 20;
        while attempts > 0:
            try:
                response, data = self.http().request(
                    uri=url,
                    method='POST',
                    headers={'Content-Type': 'application/json; charset=UTF-8'},
                    body=json,
                )
                if response.status == 200:
                    content = data.decode("utf8")
                    return content
            except Exception as e:
                attempts -= 1
                if (attempts < 1):
                    #fcm = myfcm();
                    #data = {"message": {"message":"telegram unable to connect",'cmd': 'showalert','from': 'raspberry'}}

                    #time.sleep(60)
                    raise
            time.sleep(1)


    def get_json_from_url(self, url):
        content = self.get_url(url)
        js = json.loads(content)
        return js


    def get_updates(self, offset=None):
        tmout = self.timeout - 5
        if tmout < 1:
            tmout = 2
        url = self.URL + "getUpdates?timeout=" + str(tmout)
        if offset:
            url += "&offset={}".format(offset)
        js = self.get_json_from_url(url)
        return js


    def get_last_update_id(self, updates):
        update_ids = []
        for update in updates["result"]:
            update_ids.append(int(update["update_id"]))
        return max(update_ids)


    def echo_all(self, updates):
        for update in updates["result"]:
            #{'update_id': 968412429, 'channel_post': {'chat': {'type': 'channel', 'title': 'HomePi', 'id': -1001XXXXXXXX}, 'text': 'Hi', 'message_id': 4, 'date': 1541345540}}
            try: 
                if 'message' in update: #direct bot message
                    text = update["message"]["text"]
                    chat = update["message"]["chat"]["id"]
                elif 'channel_post' in update:
                    text = update['channel_post']['text']
                    chat = update["channel_post"]["chat"]["id"]
                    self.log("Got new message in " + str(chat) + ": " + text)
                text = re.compile('\W').split(text)[0]
                subprocess.Popen(['/home/scripts/actions/on-telegram-message.py', text], stdout=subprocess.PIPE).stdout.read().strip()
                #self.send_message('I have got: ' + text, chat)
            except Exception as e:
                self.log("Error processing message:" + str(e))
                #self.send_message('Error : ' + str(e), -1001420XXXXX)
                pass


    def get_last_chat_id_and_text(self, updates):
        num_updates = len(updates["result"])
        last_update = num_updates - 1
        text = updates["result"][last_update]["message"]["text"]
        chat_id = updates["result"][last_update]["message"]["chat"]["id"]
        return (text, chat_id)


    def send_message(self, text, chat_id, silent = False):
        #text = urllib.parse.quote_plus(text)
        #url = self.URL + "sendMessage?text={}&chat_id={}{}".format(text, chat_id, ('' if silent == False else '&disable_notification=true'))
        url = self.URL + "sendMessage"
        data = {
            'text': text,
            'chat_id': chat_id,
            'disable_notification': silent == False,
            #'reply_markup': {'inline_keyboard': [{
                #'text':'First Btn',
                #'url':'http://dobovo.com',
                #}]}
        }
        #print("sending" + json.dumps(data))
        return self.post_json(url, json.dumps(data));

        #return self.get_url(url)
    
    def send_photo(self, file, chat_id, silent = False):
        try:
            #url = "https://api.telegram.org/bot<Token>/sendPhoto";
            url = self.URL + "sendPhoto"
            if silent == True:
                url += '&disable_notification=true'
            files = [('photo', 'image.jpg', open(file, 'rb'))]
            fields = [('chat_id', str(chat_id))]
            content_type, body = MultipartFormdataEncoder().encode(fields, files)
            response, data = self.http().request(
                url,
                method="POST",
                headers={'Content-Type': content_type + '; charset=UTF-8'},
                body=body
            )
            return response.status == 200
        except:
            return False

    def start(self): #Long Pooling enabled by self.timeout
        while True:
            self.checkServer()
            time.sleep(0.1)

    def checkServer(self):
        updates = self.get_updates(self.last_update_id)
        #print(updates)
        self.processMessage(updates)

    def processMessage(self, updates):
        if len(updates["result"]) > 0:
            self.last_update_id = self.get_last_update_id(updates) + 1
            self.echo_all(updates)

    # old version with requests module
    #def startBot(self):
        #import CometClient
        #self.enableLog()
        #self.log("Starting bot")
        #comet = CometClient.CometClient(self.messageHandler)
        #timeout = 60
        #while True:
            #url = self.URL + "getUpdates?timeout=" + str(timeout-10)
            #if self.last_update_id:
                #url += "&offset={}".format(self.last_update_id)

            ##print("reconnect" + url)
            #comet.get(url, timeout)

    def messageHandler(self, data):
        #print(data)
        js = json.loads(data.decode("utf-8"))
        self.processMessage(js)

    def stop(self):
        pass
Beispiel #6
0
class myTelegram:
    TOKEN = myConfig.get('telegram', 'token')
    URL = "https://api.telegram.org/bot{}/"

    #URL = "https://izbushka.kiev.ua/tmp/test.json?{}"

    def __init__(self):
        self.URL = self.URL.format(self.TOKEN)
        self.timeout = 5
        self.last_update_id = None

    def setTimeout(self, timeout):
        self.timeout = timeout

    def http(self):
        if not hasattr(self, '_http'):
            self._http = httplib2.Http(timeout=self.timeout)
        return self._http

    def enableLog(self):
        self.logHandler = myLogs('telegram-class', 0o666)

    def log(self, data):
        if hasattr(self, 'logHandler'):
            self.logHandler.log(data)

    def get_url(self, url):
        attempts = 20
        while attempts > 0:
            try:
                response, data = self.http().request(url)
                if response.status == 200:
                    content = data.decode("utf8")
                    return content
                else:
                    self.log("Got non-200 response: " + str(response.status) +
                             ": " + data.decode("utf8"))
            except Exception as e:
                self.log("Cann't fetch url: " + str(e))
                attempts -= 1
                if (attempts < 1):
                    #fcm = myfcm();
                    #data = {"message": {"message":"telegram unable to connect",'cmd': 'showalert','from': 'raspberry'}}

                    #time.sleep(60)
                    raise
            time.sleep(1)

    def post_json(self, url, json, attempts=20):
        while attempts > 0:
            try:
                response, data = self.http().request(
                    uri=url,
                    method='POST',
                    headers={
                        'Content-Type': 'application/json; charset=UTF-8'
                    },
                    body=json,
                )
                if response.status == 200:
                    content = data.decode("utf8")
                    return content
                elif response.status == 400 and attempts > 1:
                    attempts = 1  # try one more time, just in case
                else:
                    self.log("Wrong telegram response. Code: " +
                             str(response) + " " + str(data))
            except Exception as e:
                self.log("API call failed " + str(e))

            attempts = attempts - 1
            time.sleep(1)

        #fcm = myfcm();
        #data = {"message": {"message":"telegram unable to connect",'cmd': 'showalert','from': 'raspberry'}}
        raise Exception(response, data)

    def get_json_from_url(self, url):
        content = self.get_url(url)
        js = json.loads(content)
        return js

    def get_updates(self, offset=None):
        tmout = self.timeout - 5
        if tmout < 1:
            tmout = 2
        url = self.URL + "getUpdates?timeout=" + str(tmout)
        if offset:
            url += "&offset={}".format(offset)
        js = self.get_json_from_url(url)
        return js

    def get_last_update_id(self, updates):
        update_ids = []
        for update in updates["result"]:
            update_ids.append(int(update["update_id"]))
        return max(update_ids)

    def echo_all(self, updates):
        for update in updates["result"]:
            #{'update_id': 968412429, 'channel_post': {'chat': {'type': 'channel', 'title': 'HomePi', 'id': -1001XXXXXXXX}, 'text': 'Hi', 'message_id': 4, 'date': 1541345540}}
            try:
                # self.log("new event" + str(update))
                if 'message' in update:  #direct bot message
                    text = update["message"]["text"]
                    chat = update["message"]["chat"]["id"]
                    self.log("Got new message in " + str(chat) + ": " + text)
                elif 'channel_post' in update:
                    text = update['channel_post']['text']
                    chat = update["channel_post"]["chat"]["id"]
                    self.log("Got new post in " + str(chat) + ": " + text)
                elif 'callback_query' in update:
                    text = update["callback_query"]['data']
                    chat = update["callback_query"]["message"]["chat"]["id"]
                    self.log("Got new callback in " + str(chat) + ": " + text)
                else:
                    self.log("Got UNKNOWN event " + str(update))
                    continue

                subprocess.Popen(
                    ['/home/scripts/actions/on-telegram-message.py', text],
                    stdout=subprocess.PIPE).stdout.read().strip()
                #self.send_message('I have got: ' + text, chat)
            except Exception as e:
                self.log("Error processing message:" + str(e))
                #self.send_message('Error : ' + str(e), -1001420XXXXX)
                pass

    def get_last_chat_id_and_text(self, updates):
        num_updates = len(updates["result"])
        last_update = num_updates - 1
        text = updates["result"][last_update]["message"]["text"]
        chat_id = updates["result"][last_update]["message"]["chat"]["id"]
        return (text, chat_id)

    def send_message(self, text, chat_id, silent=False, showKeyboard=False):
        #text = urllib.parse.quote_plus(text)
        #url = self.URL + "sendMessage?text={}&chat_id={}{}".format(text, chat_id, ('' if silent == False else '&disable_notification=true'))
        url = self.URL + "sendMessage"
        if (int(chat_id) < -10000000000):  #private channel
            keyboard = {
                "inline_keyboard": [[
                    {
                        "text": "Help",
                        "callback_data": "help"
                    },
                    {
                        "text": "Hall",
                        "callback_data": "hall"
                    },
                    {
                        "text": "Bighall",
                        "callback_data": "bighall"
                    },
                    {
                        "text": "Room",
                        "callback_data": "room"
                    },
                    {
                        "text": "Kitchen",
                        "callback_data": "kitchen"
                    },
                ]]
            }
        else:
            keyboard = {
                "keyboard": [[
                    {
                        "text": "Help",
                        "callback_data": "help"
                    },
                    {
                        "text": "Hall",
                        "callback_data": "hall"
                    },
                    {
                        "text": "Bighall",
                        "callback_data": "bighall"
                    },
                    {
                        "text": "Room",
                        "callback_data": "room"
                    },
                    {
                        "text": "Kitchen",
                        "callback_data": "kitchen"
                    },
                ]],
                "resize_keyboard":
                True
            }

        data = {
            'text': text,
            'chat_id': chat_id,
            'disable_notification': silent == False,
            'reply_markup': keyboard if showKeyboard else {}
        }
        #print("sending" + json.dumps(data))
        return self.post_json(url, json.dumps(data))

        #return self.get_url(url)

    def send_photo(self, file, chat_id, silent=False):
        try:
            #url = "https://api.telegram.org/bot<Token>/sendPhoto";
            url = self.URL + "sendPhoto"
            if silent == True:
                url += '&disable_notification=true'
            # open(file, 'rb') will be closed automatically in  MultipartFormdataEncoder
            files = [('photo', 'image.jpg', open(file, 'rb'))]
            fields = [('chat_id', str(chat_id))]
            content_type, body = MultipartFormdataEncoder().encode(
                fields, files)
            response, data = self.http().request(
                url,
                method="POST",
                headers={'Content-Type': content_type + '; charset=UTF-8'},
                body=body)
            return response.status == 200
        except:
            return False

    def start(self):  #Long Pooling enabled by self.timeout
        self.enableLog()
        while True:
            self.checkServer()
            time.sleep(0.1)

    def checkServer(self):
        updates = self.get_updates(self.last_update_id)
        #print(updates)
        self.processMessage(updates)

    def processMessage(self, updates):
        if len(updates["result"]) > 0:
            self.last_update_id = self.get_last_update_id(updates) + 1
            self.echo_all(updates)

    # old version with requests module
    #def startBot(self):
    #import CometClient
    #self.enableLog()
    #self.log("Starting bot")
    #comet = CometClient.CometClient(self.messageHandler)
    #timeout = 60
    #while True:
    #url = self.URL + "getUpdates?timeout=" + str(timeout-10)
    #if self.last_update_id:
    #url += "&offset={}".format(self.last_update_id)

    ##print("reconnect" + url)
    #comet.get(url, timeout)

    def messageHandler(self, data):
        #print(data)
        js = json.loads(data.decode("utf-8"))
        self.processMessage(js)

    def stop(self):
        pass
Beispiel #7
0
class myMQTT:
    MQTTuser = myConfig.get('mqtt', 'user')
    MQTTpass = myConfig.get('mqtt', 'password')
    MQTTbroker = myConfig.get('mqtt', 'host')
    MQTTport = int(myConfig.get('mqtt', 'port'))

    client = None

    def __init__(self):
        self.getSensors()

    def reload(self):
        self.getSensors()

    def getSensors(self):
        self.sensorsByAddr = {}
        self.sensorsByID = {}
        sensorsDB = mySensors()
        sensors = sensorsDB.getSensors({"type":"mqtt"}).values()
        for sensor in sensors:
            if not sensor['sensor'] in self.sensorsByAddr: self.sensorsByAddr[sensor['sensor']] = {} 
            self.sensorsByAddr[sensor['sensor']] = sensor.copy()
            if not sensor['sensor_id'] in self.sensorsByID: self.sensorsByID[sensor['sensor_id']] = {} 
            self.sensorsByID[str(sensor['sensor_id'])] = sensor.copy()
        sensorsDB.closeDB()
        del sensorsDB

    def getSensorByAddr(self, addr):
        try:
            return self.sensorsByAddr[addr]
        except:
            return None

    def getSensorByID(self, id):
        try:
            return self.sensorsByID[str(id)]
        except:
            return None

    def updateSensorByAddr(self, addr, state, commit = True):
        ok = False
        sensor = self.getSensorByAddr(addr)
        #print(addr + " " + state)
        self.log(str(addr) + " " + state)
        if sensor and 'sensor_id' in sensor:
            try:
                #print(str(sensor['sensor_id']) + " " + state)
                
                # WARNING!
                # 1. unable to use self.mySensors - mqtt callback is in another thred
                # 2. unable to update DB here - memory leak, every updateSensorByAddr leak 4kb
                # 3. tmp solution - actions/save_sensor_state.py
                # TODO: sqlite multithread (queue to standalone process)

                #sensors = mySensors()
                #sensors.saveSensorState(sensor['sensor_id'], state, commit)
                #sensors.closeDB()

                subprocess.Popen(['/home/scripts/actions/save_sensor_state.py', str(sensor['sensor_id']), state]);

                self.log("Switched sensor " + str(sensor['sensor_id']) + " " + state)
            except Exception as e:
                self.log("*** ERROR *** " + str(e))
                pass
            ok = True
        #else: 
            #raise Exception("Sensor '" + addr + "' not found.") 
        del sensor
        return ok

    def commit(self):
        pass
        #self.mySensors.saveDB()

    def switchByAddr(self, addr, state):
        topic = "control/" + addr;
        #print (topic + " " + state)
        self.log("MQTT publish to " + topic)
        if state[0:1] == '{': # json
            self.client.publish(topic, state)
        else:
            self.client.publish(topic,"{\"state\":\"" + state + "\"}")
        # TODO: MQTT CALL
        #urlreq.urlopen('http://' + addr + '/' + state.lower())

    def switchById(self, id, state):
        sensor = self.getSensorByID(id);
        if sensor and 'sensor' in sensor:
            addr = sensor['sensor']
            self.switchByAddr(addr, state)
            # TODO: MQTT CALL
            #response = urlreq.urlopen('http://' + addr + '/' + state.lower())
            return None
    
    def onDisconnect(self, client, userdata, rc):
        self.log("--- GOT MQTT DISCONNECT")

    def onConnect(self, client, userdata, flags, rc):
        if (self.doSubscribe):
            self.subscribe()
        self.log("+++ MQTT CONNECTED!")

    def onMqttMessage(self, client, userdata, message):
        #print(message.topic + ": message ",str(message.payload.decode("utf-8")))
        topic = message.topic.split('/')
        data  = json.loads(str(message.payload.decode("utf-8")))
        self.log(" GOT MQTT message on " + message.topic + " " + str(message.payload))
        
        if topic[0] == "sensors":
            self.updateSensorByAddr("/".join(topic[1:]), data["state"]);
        elif topic[0] == "lwt":
            host = topic[1]
            for addr in self.sensorsByAddr:
                path = addr.split('/')
                if path[0] == host:
                    sensor = self.sensorsByAddr[addr]
                    if sensor['group'] == 'light-switch':
                        self.updateSensorByAddr(addr, 'ERR');
        del topic
        del data
    
    def log(self, msg):
        logs = myLogs('mqtt-messages')
        logs.log(msg)
        pass

    def connect(self, subscribe = False):
        self.doSubscribe = subscribe
        self.client = paho.Client("PythonMQTT-" + str(time.time()))
        self.client.username_pw_set(username=self.MQTTuser, password=self.MQTTpass)
        res = self.client.connect(self.MQTTbroker, self.MQTTport)
        self.client.on_message = self.onMqttMessage
        self.client.on_disconnect = self.onDisconnect
        self.client.on_connect = self.onConnect
        self.log(" *** Connecting to MQTT")

    def subscribe(self):
        #self.client.loop_start()
        self.client.subscribe("sensors/#")
        self.client.subscribe("lwt/#")

    def disconnect(self):
        self.log(" *** Disconnecting")
        self.client.disconnect() #disconnect
        self.client.loop_stop() #stop loop

    def loop(self):
        self.client.loop_forever()