Пример #1
0
class WebCameraControl(LoopTask):
    """
    Heroku CloundMQTTを購読し、Web Cameraを操作する
    """

    def __init__(self):
        super(WebCameraControl, self).__init__()

    def setup(self):
        try:
            self.proxy = appservice.ServiceProxy()

            proxy = appservice.ServiceProxy()
            url = proxy.get_account("heroku")["CLOUDMQTT_URL"]
            url = urlparse.urlparse(url)

            self.mqttc = MqttClient(url.hostname, url.port)
            self.mqttc.client.username_pw_set(url.username, url.password)
            self.mqttc.subscribe("automation/camera/+", self.callback)

            self.cmdq = Queue()

            logger.info("setup: done.")
        except:
            logger.critical("unhandled exception")
            raise

    def loop(self):
        try:
            self.mqttc.secure_connection()

            cmd = self.cmdq.get()
            if cmd == "send":
                self.send_mail()

            self.cmdq.task_done()
            logger.info("loop: cmd={} done.".format(cmd))
        except:
            logger.error("unhandled exception")

    def callback(self, topic, payload):
        try:
            logger.info("callback: topic={}, payload={}".format(topic, payload))
            self.cmdq.put(topic.split("/")[-1])
        except:
            logger.error("unhandled exception")

    def send_mail(self):
        with tempfile.NamedTemporaryFile(suffix=".png") as imgfile:
            cam = webcam.OpenCVCamera()  # must be initialized in main thread
            cam.capture_to_file(imgfile.name)
            self.proxy.sendmail_with_media(
                self.proxy.get_account("personal")["email"],
                "Live Image by Web Camera",
                str(datetime.datetime.now()),
                xmlrpclib.Binary(imgfile.read()),
            )
Пример #2
0
class EnvironmentMonitor(LoopTask):
    '''
    MQTTにより、センサの値を購読し、Redis(RPi, Heroku)に登録する
    '''
    
    def setup(self):
        try:
            self.last_access = {}
            self.mqttc = MqttClient()
            self.mqttc.subscribe('sensors/+/+', self.callback)
            self.rs = redis.StrictRedis(host=config.raspi2, port=6379, db=0)
            proxy = appservice.ServiceProxy()
            self.heroku = proxy.get_account('heroku')['URL']
            logger.info('setup: done.')
        except:
            logger.critical('unhandled exception')
            raise

    def loop(self):
        try:
            self.mqttc.secure_connection()
            self.watchdog()
            time.sleep(10)
        except:
            logger.error('unhandled exception')
            
    def callback(self, topic, payload):
        logger.debug('callback(): topic="{}", payload="{}"'.format(topic, payload))

        # print topic, payload
        try:
            path = topic.split('/')
            vtype = path[-1]
            client = path[-2]
            value = payload
            timestamp = datetime.datetime.now()

            # Register access time
            self.last_access[client] = timestamp

            # Upload data
            self.store(topic, value)
            self.store(topic + '/datetime', str(timestamp))

        except:
            logger.error('unhandled exception')

    def watchdog(self):
        proxy = appservice.ServiceProxy()

        for client, last in self.last_access.items():
            tdiff = datetime.datetime.now() - last
            if tdiff.total_seconds() <= 60 * 60:
                continue

            msg = '{} is inactive.'.format(client)
            logger.warning(msg)
            proxy.line_me({'value1': msg})
            self.last_access[client] = datetime.datetime.now()

    def store(self, topic, value):

        # Redis
        self.rs.set(topic, value)

        # Heroku
        upload = '{}/kv/{}'.format(self.heroku, topic)
        r = requests.put(url=upload, data=value)
        if r.status_code != 200:
            logger.error('status_code != 200: upload={}, date={}'.format(upload, value))
Пример #3
0
class SolarMonitor(LoopTask):
    '''
    MQTT topic solar/values を購読し、値をRedis(RPi, Heroku)に登録する
    登録した値は、Munin, Heroku Webにより利用される
    '''

    def setup(self):
        try:
            self.mqttc = MqttClient()
            self.mqttc.subscribe('solar/values', self.callback)
            self.rs = redis.StrictRedis(host=config.raspi2, port=6379, db=0)

            proxy = appservice.ServiceProxy()
            self.heroku = proxy.get_account('heroku')['URL']
            logger.info('setup: done.')
        except:
            logger.critical('unhandled exception')
            raise

    def loop(self):
        try:
            self.mqttc.secure_connection()
            time.sleep(10)
        except:
            logger.error('unhandled exception')
            
    def callback(self, topic, payload):
        ''' 
        瞬時の電圧・電流・電力から、積算電力も算出して、Redisに登録
        '''
        try:
            cur_values = json.loads(payload)
            prev_values = dict(cur_values)
            prev = self.rs.get(topic)
            if prev:
                prev_values = json.loads(prev)

            cur_time = cur_values.get('Time', time.time())
            prev_time = prev_values.get('Time', cur_time)
            dt = (cur_time - prev_time) / 60.0 / 60.0  # hour

            accum_pp = prev_values.get('AccumSolarPower', 0.0)
            accum_bp = prev_values.get('AccumBatteryPower', 0.0)
            accum_cp = prev_values.get('AccumLoadPower', 0.0)

            accum_pp += (prev_values['SolarPower']
                         + cur_values['SolarPower']) * dt / 2.0
            accum_bp += (prev_values['BatteryPower']
                         + cur_values['BatteryPower']) * dt / 2.0
            accum_cp += (prev_values['LoadPower']
                         + cur_values['LoadPower']) * dt / 2.0

            cur_values['AccumSolarPower'] = accum_pp
            cur_values['AccumBatteryPower'] = accum_bp
            cur_values['AccumLoadPower'] = accum_cp

            # Redisに保存するデータは、数値型を維持するためにJSON形式とした
            # (Redisには、数値型がない)
            timestamp = str(datetime.datetime.now())
            values = json.dumps(cur_values)

            self.rs.set(topic, values)
            self.rs.set(topic + '/datetime', timestamp)
            upload = '{0}/kv/{1}'.format(self.heroku, topic)
            r = requests.put(url=upload, data=values)
            if r.status_code != 200:
                logger.warning('status_code != 200: upload={}, data={}'.format(upload, value))
            upload = upload + '/datetime'
            r = requests.put(url=upload, data=timestamp)
            if r.status_code != 200:
                logger.warning('status_code != 200: upload={}, data={}'.format(upload, timestamp))
        except:
            logger.error('unhandled exception')
Пример #4
0
class AirControl(LoopTask):
    '''
    Heroku CloundMQTTを購読し、エアコンを操作する
    '''

    def __init__(self):
        super(AirControl, self).__init__()

    def setup(self):
        try:
            self.ac = AirConditioner()

            self.proxy = appservice.ServiceProxy()
            url = self.proxy.get_account('heroku')['CLOUDMQTT_URL']
            url = urlparse.urlparse(url)

            self.mqttc = MqttClient(url.hostname, url.port)
            self.mqttc.client.username_pw_set(url.username, url.password)
            self.mqttc.subscribe('automation/ac/stat', self.callback)

            self.cmdq = Queue()
            logger.info('setup: done.')
        except:
            logger.critical('unhandled exception')
            raise

    def loop(self):
        try:
            self.mqttc.secure_connection()
            
            cmd = self.cmdq.get()
            func = lambda: None
            msg = None
            if cmd == 'on':
                func = self.ac.on
                msg = u'エアコンをオンしました。'
            if cmd == 'off':
                func = self.ac.off
                msg = u'エアコンをオフしました。'
                
            for _ in range(3):
                func()
                time.sleep(3)

            self.cmdq.task_done()
            logger.info('loop: cmd={} done.'.format(cmd))
            if msg:
                self.proxy.line_family(msg)
            
        except:
            logger.error('unhandled exception')

    def callback(self, topic, payload):
        try:
            logger.info('callback: topic={}, payload={}'.format(topic, payload))

            if len(payload) == 0:
                return
            if payload[0] == '1':
                self.cmdq.put('on')
            if payload[0] == '0':
                self.cmdq.put('off')
        except:
            logger.error('unhandled exception')