Ejemplo n.º 1
0
def get_first_active_mpd():
    port_config = get_json_param(Constant.P_MPD_PORT_ZONE).split(',')
    first_port = None
    alt_port = None
    alt_zone = None

    client = _get_client()
    # get the zone playing, only if one is active
    port_list_play = []
    for pair in port_config:
        port_val = int(pair.split('=')[1])
        if first_port is None:
            first_port = port_val
        zone_val = pair.split('=')[0]
        client.connect(get_json_param(Constant.P_MPD_SERVER), port_val)
        if client.status()['state'] == 'play':
            port_list_play.append(port_val)
            alt_zone = zone_val
        client.close()
        client.disconnect()
    if len(port_list_play) == 1:
        alt_port = port_list_play[0]
        zone = alt_zone
    if alt_port is not None:
        client.connect(get_json_param(Constant.P_MPD_SERVER), alt_port)
        return client
    else:
        client.connect(get_json_param(Constant.P_MPD_SERVER), first_port)
        return client
Ejemplo n.º 2
0
def init():
    dispatcher.connect(send_notification, signal=Constant.SIGNAL_EMAIL_NOTIFICATION, sender=dispatcher.Any)
    global __notif_from, __notif_pass, __notif_dest
    __notif_from = get_json_param(Constant.P_GMAIL_NOTIFY_FROM_EMAIL)
    __notif_dest = get_json_param(Constant.P_NOTIFY_EMAIL_RECIPIENT)
    __notif_pass = _get_pass(__notif_from)
    global initialised
    initialised = True
Ejemplo n.º 3
0
def connect_socket():
    host = get_json_param(Constant.P_AMP_SERIAL_HOST)
    port = int(get_json_param(Constant.P_AMP_SERIAL_PORT))
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    L.l.debug("Connecting socket")
    s.settimeout(2)
    s.connect((host, port))
    s.settimeout(None)
    L.l.debug("Connected socket")
    return s
Ejemplo n.º 4
0
def thread_run():
    prctl.set_name("heat")
    threading.current_thread().name = "heat"
    if P.threshold is None:
        P.threshold = float(get_json_param(Constant.P_TEMPERATURE_THRESHOLD))
        P.temp_limit = float(get_json_param(Constant.P_HEAT_SOURCE_MIN_TEMP))
        P.MAX_DELTA_TEMP_KEEP_WARM = float(
            get_json_param(Constant.P_MAX_DELTA_TEMP_KEEP_WARM))
    month = datetime.datetime.today().month
    P.season = "summer" if month in range(5, 9) else "winter"
    _set_main_heat_source()
    _loop_zones()
    prctl.set_name("idle_heat")
    threading.current_thread().name = "idle_heat"
    return 'Heat ok'
Ejemplo n.º 5
0
def init():
    L.l.info('Openhab module initialising')
    rules.P.openhab_topic = get_json_param(Constant.P_MQTT_TOPIC_OPENHAB_SEND)
    P.mqtt_topic_receive = get_json_param(
        Constant.P_MQTT_TOPIC_OPENHAB_RECEIVE)
    P.mqtt_topic_receive_prefix = P.mqtt_topic_receive.replace('#', '')
    mqtt_io.P.mqtt_client.message_callback_add(P.mqtt_topic_receive,
                                               mqtt_on_message)
    mqtt_io.add_message_callback(P.mqtt_topic_receive, mqtt_on_message)
    __load_rules()
    thread_pool.add_interval_callable(thread_run, run_interval_second=1)
    dispatcher.connect(parse_rules,
                       signal=Constant.SIGNAL_DB_CHANGE_FOR_RULES,
                       sender=dispatcher.Any)
    P.initialised = True
Ejemplo n.º 6
0
def keep_alive():
    if P.auth_key is None:
        auth()
    if P.auth_key is not None:
        server_url = get_json_param(Constant.P_ATREA_LOCAL_URL) + P.state_url
        state_text = utils.get_url_content(
            server_url.replace("<key>", P.auth_key))
        if "HTTP: 403 Forbidden AUTH" in state_text:
            auth()
        else:
            try:
                mode = int(
                    utils.parse_text_ex(state_text, P.mode_resp_start,
                                        P.mode_resp_end))
                power_level = int(
                    utils.parse_text_ex(state_text, P.power_level_resp_start,
                                        P.power_level_resp_end))
                rec = m.Ventilation.find_one({m.Ventilation.id: 0})
                rec.mode = mode
                rec.power_level = power_level
                rec.save_changed_fields(persist=True)
                L.l.info("Atrea mode={}-{} power={}".format(
                    mode, P.mode_values[mode], power_level))
            except Exception as ex:
                L.l.warning(
                    "Unexpected Atrea state response: {}".format(state_text))
    else:
        L.l.warning("Unable to get auth key")
Ejemplo n.º 7
0
def load_db():
    global db
    data_file = common.get_json_param(common.Constant.P_DB_PATH)
    data_path = os.path.dirname(data_file)
    # conn = CustomFileTinyMongoClient(foldername=data_path)
    conn = CustomMemoryTinyMongoClient()
    db = conn.haiot
    _init_flask_admin()
Ejemplo n.º 8
0
def init():
    L.l.info('Sonoff module initialising')
    P.sonoff_topic = str(get_json_param(Constant.P_MQTT_TOPIC_SONOFF_1))
    # mqtt_io.P.mqtt_client.message_callback_add(P.sonoff_topic, mqtt_on_message)
    mqtt_io.add_message_callback(P.sonoff_topic, mqtt_on_message)
    _read_mac_files()
    thread_pool.add_interval_callable(thread_run, P.check_period, long_running=True)
    P.initialised = True
Ejemplo n.º 9
0
def init():
    L.l.info('Owntracks module initialising')
    config_file = get_json_param(Constant.P_ALL_CREDENTIAL_FILE)
    with open(config_file, 'r') as f:
        config = json.load(f)
        P.phonetrack_token = config['nextcloud_phonetrack_token']
    P.phonetrack_url = get_json_param(
        Constant.P_NEXTCLOUD_PHONETRACK_URL).replace('<token>',
                                                     P.phonetrack_token)
    P.mqtt_topic_receive = get_json_param(
        Constant.P_MQTT_TOPIC_OWNTRACKS_RECEIVE)
    P.mqtt_topic_receive_prefix = P.mqtt_topic_receive.replace('#', '')
    mqtt_io.P.mqtt_client.message_callback_add(P.mqtt_topic_receive,
                                               mqtt_on_message)
    mqtt_io.add_message_callback(P.mqtt_topic_receive, mqtt_on_message)
    thread_pool.add_interval_callable(thread_run, run_interval_second=10)
    P.initialised = True
Ejemplo n.º 10
0
def _init_comm():
    P.thread_pool_status = 'init ows bus list'
    ohost = "none"
    oport = "none"
    try:
        ohost = get_json_param(Constant.P_OWSERVER_HOST_1)
        oport = int(get_json_param(Constant.P_OWSERVER_PORT_1))
        _get_bus_list(ohost, oport)
        P.initialised = True
        P.warning_issued = False
    except Exception as ex:
        if not P.warning_issued:
            L.l.info(
                '1-wire owserver not initialised on host {} port {}, ex={}'.
                format(ohost, oport, ex))
            P.initialised = False
            P.warning_issued = True
    return P.initialised
Ejemplo n.º 11
0
def set_mode(mode):
    L.l.info("Setting ventilation mode to {}".format(mode))
    server_url = get_json_param(Constant.P_ATREA_LOCAL_URL) + P.mode_url
    server_url = server_url.replace("X", str(mode))
    if P.auth_key is not None:
        state_text = utils.get_url_content(
            server_url.replace("<key>", P.auth_key))
        L.l.info("Setting ventilation mode to {} returned {}".format(
            mode, state_text))
    else:
        L.l.info("Failed setting ventilation mode, not authenticated")
Ejemplo n.º 12
0
def _get_pass(email=None):
    config_file = get_json_param(Constant.P_GMAIL_CREDENTIAL_FILE)
    try:
        with open(config_file , 'r') as f:
            config_list = json.load(f)
            if email in config_list.keys():
                record = config_list[email]
                return record['password']
    except Exception as ex:
        L.l.warning("Could not read credential email file {}".format(config_file))
    return None
Ejemplo n.º 13
0
def auth():
    server_url = get_json_param(Constant.P_ATREA_LOCAL_URL) + P.auth_url
    server_url = server_url.replace("<magic>",
                                    get_secure_general("magic_atrea"))
    key = utils.parse_http(server_url, P.auth_resp_start, P.auth_resp_end)
    if key is not None and len(key) == 5:
        P.auth_key = key
        L.l.info("Got Atrea auth key: {}".format(key))
    else:
        L.l.warning(
            "Unable to get Atrea auth key, response was:{}".format(key))
Ejemplo n.º 14
0
def init_solar_aps():
    try:
        production = utils.parse_http(
            get_json_param(Constant.P_SOLAR_APS_LOCAL_URL), P.start_keyword,
            P.end_keyword)
        if production is not None and production is not '':
            P.initialised = True
        else:
            P.initialised = False
        return P.initialised
    except Exception as ex:
        L.l.warning("Unable to connect to aps solar server, ex={}".format(ex))
Ejemplo n.º 15
0
def set_power_level(level):
    L.l.info("Setting ventilation power level to {}".format(level))
    server_url = get_json_param(
        Constant.P_ATREA_LOCAL_URL) + P.power_level_set_url
    level_text = f'{level:03}'
    server_url = server_url.replace("XXX", level_text)
    if P.auth_key is not None:
        state_text = utils.get_url_content(
            server_url.replace("<key>", P.auth_key))
        L.l.info("Setting ventilation power level to {} returned {}".format(
            level, state_text))
    else:
        L.l.info("Failed setting ventilation power, not authenticated")
Ejemplo n.º 16
0
def init():
    L.l.debug('FlaskAdmin UI module initialising')
    app.wsgi_app = ReverseProxied(app.wsgi_app)
    app.config['STATIC_FOLDER'] = os.path.join(os.path.dirname(__file__),
                                               'static')
    host = '0.0.0.0'
    port = int(get_json_param(Constant.P_FLASK_WEB_PORT))
    P.flask_thread = helpers.FlaskInThread(app,
                                           host=host,
                                           port=port,
                                           debug=False,
                                           use_reloader=False)
    P.initialised = True
    P.flask_thread.start()
Ejemplo n.º 17
0
def _read_port_config():
    port_config = get_json_param(Constant.P_MPD_PORT_ZONE).split(',')
    for pair in port_config:
        split = pair.split('=')
        names = split[0]
        port = split[1]
        if ':' in names:
            name_list = names.split(':')
            for name in name_list:
                P.zone_port[name] = int(port)
                P.unique_ports[int(port)] = name
        else:
            P.zone_port[names] = int(port)
            P.unique_ports[int(port)] = names
Ejemplo n.º 18
0
def get_song_id(artist, title):
    url = get_json_param(Constant.P_GMUSICPROXY_URL)
    title = urllib.parse.quote(title.encode('utf-8'), safe='')
    artist = urllib.parse.quote(artist.encode('utf-8'), safe='')
    param = '/search_id?type=song&title={}&artist={}&exact=yes'.format(
        title, artist)
    try:
        result = urllib.request.get('{}{}'.format(url, param), timeout=7).text
        if result == '':
            return None
        else:
            return result
    except Exception as ex:
        L.l.critical("Error on get song from google proxy: {}".format(ex))
        return None
Ejemplo n.º 19
0
def init():
    L.l.debug('Newtifry module initialising')
    global _source_key
    _source_key = get_json_param(Constant.P_NEWTIFY_KEY)
    dispatcher.connect(send_message,
                       signal=Constant.SIGNAL_PUSH_NOTIFICATION,
                       sender=dispatcher.Any)
    send_message(title="Initialising",
                 message="Module initialising",
                 priority=1)
    # send_message(title="Initialised", message="Module initialised")
    # send_message(title="Initialised 2", message="Module initialised 2")
    thread_pool.add_interval_callable(_send_queue, run_interval_second=60)
    global initialised
    initialised = True
Ejemplo n.º 20
0
def __read_hddparm(disk_dev=''):
    output = io.StringIO()
    hddparm_out = "None"
    global ERR_TEXT_NO_DEV
    try:
        if import_module_psutil_exist:
            try:
                use_sudo = bool(get_json_param(Constant.P_USESUDO_DISKTOOLS))
                if Constant.OS in Constant.OS_LINUX and use_sudo:
                    hddparm_out = subprocess.check_output(['sudo', 'hdparm', '-C', disk_dev], stderr=subprocess.STDOUT)
                else:
                    hddparm_out = subprocess.check_output(['hdparm', '-C', disk_dev], stderr=subprocess.STDOUT)
            except subprocess.CalledProcessError as ex1:
                hddparm_out = ex1.output
                if ERR_TEXT_NO_DEV in hddparm_out or ERR_TEXT_NO_DEV_2 in hddparm_out:
                    raise ex1
            except Exception as ex:
                L.l.warning("Error running process, err={}".format(ex))
                hddparm_out = None
            if hddparm_out:
                output.reset()
                output.write(hddparm_out)
                output.seek(0)
                pos = -1
                while pos != output.tell():
                    pos = output.tell()
                    line = output.readline()
                    if Constant.HDPARM_STATUS in line:
                        words = line.split(': ')
                        power_status = words[1].replace('\r', '').replace('\n', '').replace('/', '-').lstrip()
                        if power_status == 'active-idle':
                            power_status = 1 + Constant.HOST_PRIORITY
                        elif power_status == 'standby':
                            power_status = 0
                        else:
                            power_status = -1 - Constant.HOST_PRIORITY
                        return power_status
        else:
            power_status = 'not available'
            return power_status
    except subprocess.CalledProcessError as ex:
        L.l.debug('Invalid disk {} err {}'.format(disk_dev, ex))
    except Exception as exc:
        L.l.exception('Disk read error disk was {} err {}'.format(disk_dev, exc))
Ejemplo n.º 21
0
def init():
    config_file = get_json_param(Constant.P_LASTFM_CONFIG_FILE)
    if os.path.isfile(config_file):
        with open(config_file, 'r') as f:
            config_list = json.load(f)
        API_KEY = config_list['lastfm_api']
        API_SECRET = config_list['lastfm_secret']
        P.USERNAME = config_list['lastfm_user']
        PASSWORD = config_list['lastfm_pass']
        # In order to perform a write operation you need to authenticate yourself
        password_hash = pylast.md5(PASSWORD)
        try:
            P.network = pylast.LastFMNetwork(
                api_key=API_KEY, api_secret=API_SECRET, username=P.USERNAME, password_hash=password_hash)
            #set_tag_loved_tracks('love')
        except Exception as ex:
            L.l.error("Cannot init lastfm, ex={}".format(ex))
    else:
        L.l.info('Missing config file for lastfm')
Ejemplo n.º 22
0
def first_read_all_vehicles():
    for i, vehicle in enumerate(P.vehicles):
        name = vehicle['display_name']
        vin = vehicle['vin']
        state = vehicle['state']
        car = m.ElectricCar.find_one({m.ElectricCar.name: name})
        if car is not None:
            car.vin = vin
            car.state = state
            car.save_changed_fields(broadcast=False, persist=True)
            P.teslamate_topic = str(
                get_json_param(Constant.P_MQTT_TOPIC_TESLAMATE)).replace(
                    "<car_id>", str(car.id))
            P.teslamate_topic += "#"
            mqtt_io.add_message_callback(P.teslamate_topic, mqtt_on_message)
            L.l.info("Teslamate connected to mqtt topic: {}".format(
                P.teslamate_topic))
            vehicle_update(car.id)
        else:
            L.l.warning(
                "Cannot find electric car = {} in config file".format(name))
        L.l.info("Electric car {} vin={} state={}".format(name, vin, state))
Ejemplo n.º 23
0
    def __init__(self,
                 listener,
                 pooller,
                 port,
                 index,
                 root_url,
                 server_version,
                 persistent_uuid,
                 other_headers=None,
                 ip_address=None):
        self.listener = listener
        self.poller = pooller
        self.port = port
        self.root_url = root_url
        self.server_version = server_version
        self.persistent_uuid = persistent_uuid
        self.uuid = uuid.uuid4()
        self.other_headers = other_headers

        if ip_address:
            self.ip_address = ip_address
        else:
            self.ip_address = upnp_device.local_ip_address()

        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        if self.port == 0:
            self.port = (int)(get_json_param(
                Constant.P_ALEXA_WEMO_LISTEN_PORT)) + index
            # self.port = self.socket.getsockname()[1]
        L.l.info("Listening wemo on ip {} port {}".format(
            self.ip_address, self.port))
        self.socket.bind((self.ip_address, self.port))
        self.socket.listen(5)
        self.poller.add(self)
        self.client_sockets = {}
        self.listener.add_device(self)
Ejemplo n.º 24
0
def thread_run():
    if not P.initialised:
        init_solar_aps()
    if P.initialised:
        try:
            aps_text = str(
                urllib.request.urlopen(
                    get_json_param(Constant.P_SOLAR_APS_LOCAL_URL)).read())
            production = utils.parse_text(aps_text, P.start_keyword,
                                          P.end_keyword)
            last_power = utils.parse_text(aps_text, P.start_keyword_now,
                                          P.end_keyword_now)
            temperature = utils.parse_text(aps_text,
                                           P.start_key_temp,
                                           P.end_key_temp,
                                           end_first=True)
            panel_id = utils.parse_text(aps_text,
                                        P.start_key_panel,
                                        P.end_key_panel,
                                        end_first=True)
            utility_name = get_json_param(Constant.P_SOLAR_UTILITY_NAME)
            if temperature is not None:
                zone_sensor = m.ZoneSensor.find_one(
                    {m.ZoneSensor.sensor_address: panel_id})
                if zone_sensor is None:
                    L.l.warning(
                        'Solar panel id {} is not defined in zone sensor list'.
                        format(panel_id))
                record = m.Sensor.find_one({m.Sensor.address: panel_id})
                if record is None:
                    record = m.Sensor()
                    record.address = panel_id
                    record.type = 'solar'
                    if zone_sensor:
                        record.sensor_name = zone_sensor.sensor_name
                    else:
                        record.sensor_name = record.type + panel_id
                record.temperature = temperature
                record.updated_on = utils.get_base_location_now_date()
                # fixme: keeps saving same temp even when panels are off. stop during night.
                record.save_changed_fields(broadcast=True, persist=True)
            if production is not None:
                production = float(production)
                record = m.Utility.find_one(
                    {m.Utility.utility_name: utility_name})
                if record is None:
                    record = m.Utility()
                    record.utility_name = utility_name
                    record.units_delta = production
                    record.units_total = production
                else:
                    if record.units_total is None:
                        record.units_total = production
                        record.units_delta = 0
                    else:
                        record.units_delta = production - record.units_total
                        if record.units_delta == 0:
                            # do not waste db space if no power generated
                            L.l.info(
                                'Solar production is energy={} watts={} temp={}'
                                .format(production, last_power, temperature))
                            # return
                        else:
                            L.l.info('Solar production is {}'.format(
                                record.units_delta))
                record.units_2_delta = last_power
                # L.l.info('Solar watts is {}'.format(last_power))
                if record.unit_cost is None:
                    record.unit_cost = 0.0
                record.cost = 1.0 * record.units_delta * record.unit_cost
                record.save_changed_fields(broadcast=True, persist=True)
            else:
                L.l.info('Solar production is none')
        except Exception as ex:
            L.l.error("Got exception on solar thread run, ex={}".format(ex),
                      exc_info=True)
Ejemplo n.º 25
0
def _get_client(port=None):
    client = MPDClient()
    client.timeout = 5
    if port is not None:
        client.connect(get_json_param(Constant.P_MPD_SERVER), port)
    return client
Ejemplo n.º 26
0
def _loop_zones():
    try:
        heat_is_on = False
        P.heat_status = ''
        zone_list = m.Zone.find()
        for zone in zone_list:
            P.thread_pool_status = 'do zone {}'.format(zone.name)
            heat_schedule_list = m.HeatSchedule.find({
                m.HeatSchedule.zone_id:
                zone.id,
                m.HeatSchedule.season:
                P.season
            })
            if len(heat_schedule_list) > 1:
                L.l.warning('Multiple heat schedules for this zone, iterating')
            # todo: fix needed to avoid multiple state changes on same relays rapidly, on multiple schedules
            for heat_schedule in heat_schedule_list:
                zonesensor_list = m.ZoneSensor.find({
                    m.ZoneSensor.zone_id:
                    zone.id,
                    m.ZoneSensor.is_main:
                    True
                })
                sensor_processed = {}
                P.heat_status += 'zone=' + zone.name + ': heat_sched {} sensors_count {} '.format(
                    heat_schedule, len(zone_list))
                for zonesensor in zonesensor_list:
                    if heat_schedule is not None and zonesensor is not None:
                        sensor = m.Sensor.find_one(
                            {m.Sensor.address: zonesensor.sensor_address})
                        if sensor is not None:
                            P.heat_status += 'sensor: {} {} '.format(
                                sensor.address, sensor.sensor_name)
                            heat_state, main_source_needed = _update_zone_heat(
                                zone, heat_schedule, sensor)
                            P.heat_status += 'heat on: {} main {},'.format(
                                heat_state, main_source_needed)
                            if not heat_is_on:
                                heat_is_on = main_source_needed and heat_state
                            if zonesensor.zone_id in sensor_processed:
                                prev_sensor = sensor_processed[
                                    zonesensor.zone_id]
                                L.l.warning(
                                    'Already processed temp sensor {} in zone {}, duplicate?'
                                    .format(prev_sensor, zonesensor.zone_id))
                            else:
                                sensor_processed[
                                    zonesensor.zone_id] = sensor.sensor_name
                        else:
                            P.heat_status += ' sensor={}'.format(sensor)
                    else:
                        P.heat_status += ' sched={} zonesensor={}'.format(
                            heat_schedule, zonesensor)
        # turn on/off the main heating system based on zone heat needs
        # check first to find alternate valid heat sources
        heatrelay_main_source = m.ZoneHeatRelay.find_one(
            {m.ZoneHeatRelay.is_alternate_heat_source: True})
        if heatrelay_main_source is None:
            heatrelay_main_source = m.ZoneHeatRelay.find_one(
                {m.ZoneHeatRelay.is_main_heat_source: True})
        if heatrelay_main_source is not None:
            main_source_zone = m.Zone.find_one(
                {m.Zone.id: heatrelay_main_source.zone_id})
            main_thermo = m.ZoneThermostat.find_one(
                {m.ZoneThermostat.zone_id: main_source_zone.id})
            if main_source_zone is not None:
                update_age_mins = (
                    utils.get_base_location_now_date() -
                    P.last_main_heat_update).total_seconds() / 60
                # # avoid setting relay state too often but do periodic refreshes every x minutes
                # check when thermo is none
                if main_thermo is None or (
                        main_thermo.heat_is_on != heat_is_on
                        or update_age_mins >= int(
                            get_json_param(
                                Constant.P_HEAT_STATE_REFRESH_PERIOD))):
                    # L.l.info("Setting main heat on={}, zone={}, status={}".format(
                    #    heat_is_on, main_source_zone.name, P.heat_status))
                    _save_heat_state_db(zone=main_source_zone,
                                        heat_is_on=heat_is_on)
                    P.last_main_heat_update = utils.get_base_location_now_date(
                    )
            else:
                L.l.critical('No heat main_src found using zone id {}'.format(
                    heatrelay_main_source.zone_id))
        else:
            L.l.critical('No heat main source is defined in db')
    except Exception as ex:
        L.l.error('Error loop_zones, err={}'.format(ex), exc_info=True)
Ejemplo n.º 27
0
def mpd(request):
    if request.json is not None:
        L.l.info('ALEXA request request={}'.format(request.json['request']))
        if 'intent' in request.json['request']:
            intent = request.json['request']['intent']
            if intent is not None:
                cmd = None
                zone = None
                if intent['name'] == 'AMAZON.PauseIntent':
                    cmd = 'pause'
                elif intent['name'] == 'AMAZON.ResumeIntent':
                    cmd = 'resume'
                elif intent['name'] == 'AMAZON.NextIntent':
                    cmd = 'next'
                elif intent['name'] == 'AMAZON.PreviousIntent':
                    cmd = 'previous'
                if 'slots' in intent.keys():
                    slots = intent['slots']
                    for name, value in slots.iteritems():
                        if name == 'Action':
                            if 'value' in value.keys():
                                cmd = value['value']
                        elif name == 'Zone':
                            if 'value' in value.keys():
                                zone = value['value']
                port_config = get_json_param(
                    Constant.P_MPD_PORT_ZONE).split(',')
                alt_port = None
                client = MPDClient()
                client.timeout = 5
                if zone is None:
                    # get the zone playing, only if one is active
                    port_list_play = []
                    alt_zone = None
                    for pair in port_config:
                        port_val = int(pair.split('=')[1])
                        zone_val = pair.split('=')[0]
                        client.connect(get_json_param(Constant.P_MPD_SERVER),
                                       port_val)
                        if client.status()['state'] == 'play':
                            port_list_play.append(port_val)
                            alt_zone = zone_val
                        client.close()
                        client.disconnect()
                    if len(port_list_play) == 1:
                        alt_port = port_list_play[0]
                        zone = alt_zone
                if cmd is not None and zone is not None:
                    L.l.info('ALEXA executes {} in {}'.format(cmd, zone))
                    port = None
                    for pair in port_config:
                        if zone in pair:
                            port = int(pair.split('=')[1])
                            break
                    if port is None:
                        port = alt_port
                    if port is not None:
                        client.connect(get_json_param(Constant.P_MPD_SERVER),
                                       port)
                        status = client.status()
                        outcome = 'not available'
                        if cmd == 'next':
                            client.next()
                            outcome = client.currentsong()['title']
                        elif cmd == 'previous':
                            client.previous()
                            outcome = client.currentsong()['title']
                        elif cmd == 'pause' or cmd == 'stop':
                            client.pause(1)
                            outcome = client.status()['state']
                        elif cmd == 'resume' or cmd == 'play':
                            client.pause(0)
                            outcome = client.status()['state']
                        elif cmd == 'volumeup' or cmd == 'louder':
                            client.setvol(int(status['volume']) + 5)
                            outcome = client.status()['volume']
                        elif cmd == 'volumedown' or cmd == 'quiet':
                            client.setvol(int(status['volume']) - 5)
                            outcome = client.status()['volume']
                        client.close()
                        client.disconnect()
                        response = 'Action done, {} in zone {}, result is {}'.format(
                            cmd, zone, outcome)
                    else:
                        response = 'Could not connect to MPD server, port not found'
                else:
                    response = 'Warning, action not done, was {} in zone {}'.format(
                        cmd, zone)
            else:
                response = 'Warning, incomplete action'
        else:
            response = 'Warning, intent not found'
    else:
        response = 'Invalid command'
    return '{ "version": "1.0", "sessionAttributes": {}, ' \
           '"response": { "outputSpeech": {"type": "PlainText", "text": " ' + response + ' "}, ' \
           '"shouldEndSession": true }}'
Ejemplo n.º 28
0
def init():
    # carefull with order of imports
    import common
    from main import logger_helper
    from common import utils

    common.init_simple()
    logger_helper.L.init_logging()
    signal.signal(signal.SIGTERM, signal_handler)

    L.l.info('Collecting system info')
    from main import system_info
    system_info.init()

    from common import Constant
    common.init()

    global app, db, DB_LOCATION
    common.load_config_json()
    DB_TYPE = common.get_json_param(common.Constant.P_DB_TYPE)

    DB_LOCATION = "sqlite:///" + common.get_json_param(common.Constant.P_DB_PATH)
    L.l.info("DB file is at " + DB_LOCATION)

    L.l.info('Initialising flask')
    # http://stackoverflow.com/questions/20646822/how-to-serve-static-files-in-flask
    # set the project root directory as the static folder, you can set others.
    app = Flask('main', static_folder='../webui/static')  # , static_url_path='')

    # app.config['TESTING'] = True
    app.config.update(DEBUG=True, SQLALCHEMY_ECHO=False, SQLALCHEMY_DATABASE_URI=DB_LOCATION)
    app.debug = True
    app.config['SECRET_KEY'] = 'secret'
    app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
    L.l.info('Initialising SQLAlchemy')
    # http://flask.pocoo.org/docs/0.12/patterns/sqlalchemy/
    db = SQLAlchemy(app)

    L.l.info('Checking main db tables')
    import admin.model_helper
    global MODEL_AUTO_UPDATE

    admin.model_helper.populate_tables(MODEL_AUTO_UPDATE)
    reporting_enabled = admin.model_helper.get_param(Constant.DB_REPORTING_LOCATION_ENABLED)
    if reporting_enabled == "1" and not IS_STANDALONE_MODE:
        L.l.info('Checking history db tables')
        # try several times to connect to reporting DB
        for i in range(10):
            try:
                admin.model_helper.init_reporting()
                break
            except Exception as ex:
                L.l.critical("Local DB reporting capability is not available, err={}".format(ex))
                app.config['SQLALCHEMY_BINDS'] = None
            time.sleep(10)
    elif IS_STANDALONE_MODE:
        L.l.info('Skipping reporting feature initialising, standalone mode')

    import transport
    if not IS_STANDALONE_MODE:
        transport.init()
    else:
        L.l.info('Skipping transport initialising, standalone mode')

    class LogMessage:
        def __init__(self):
            pass

        message_type = 'logging'
        message = ''
        level = ''
        source_host_ = Constant.HOST_NAME  # field name must be identical with constant.JSON_PUBLISH_SOURCE_HOST
        datetime = utils.date_serialised(utils.get_base_location_now_date())

    import logging

    class TransportLogging(logging.Handler):
        def emit(self, record):
            if transport.initialised and transport.mqtt_io.client_connected:
                msg = LogMessage()
                msg.message = self.format(record)
                msg.level = record.levelname
                transport.send_message_json(utils.unsafeobj2json(msg))

    if L.LOG_TO_TRANSPORT:
        L.l.addHandler(TransportLogging())
        L.l.info('Initialised logging via transport proxy')

    L.l.info('Initialising events - import')
    from admin import event
    L.l.info('Initialising events - init')
    event.init()

    L.l.info('Machine type is {}'.format(Constant.HOST_MACHINE_TYPE))
    L.l.info('Initialising modules')
    init_modules(init_mod=True)

    L.l.info('Initialising generic processing threads')
    from main import thread_pool
    import threading
    t = threading.Thread(target=thread_pool.run_thread_pool)
    t.daemon = True
    t.start()

    from common import performance
    performance.init(admin.model_helper.get_param(Constant.P_PERF_FILE_PATH))

    global initialised, shutting_down
    initialised = True

    # trap all DB changes and propagate to event.py
    @models_committed.connect_via(app)
    def on_models_committed(sender, changes):
        from storage.sqalc import event
        # L.l.debug('Model commit detected sender {} change {}'.format(sender, changes))
        event.on_models_committed(sender, changes)
        # pass

    @before_models_committed.connect_via(app)
    def bef_models_committed(sender, changes):
        pass

    init_post_modules()
    L.l.info('Feeding dogs with grass until app will exit')
    global exit_code
    # stop app from exiting
    try:
        while not shutting_down:
            time.sleep(1)
    except KeyboardInterrupt:
        print('CTRL+C was pressed, exiting')
        exit_code = 1
    except Exception as ex:
        print('Main exit with exception {}'.format(ex))
    finally:
        unload()
    L.l.critical('Looping ended, app will exit')
Ejemplo n.º 29
0
def __update_ddns_rackspace():
    try:
        ConfigFile = get_json_param(Constant.P_DDNS_RACKSPACE_CONFIG_FILE)
        with open(ConfigFile, 'r') as f:
            config_list = json.load(f)
        global cache
        if cache == {} or cache is None:
            cache = {}
            cache['auth'] = {}
            cache['auth']['expires'] = str(utils.get_base_location_now_date())
        config = {}
        ip_json_test = ''
        try:
            #ip_json_test = requests.get('http://ip-api.com/json').text
            ip_json_test = requests.get('http://ipinfo.io').text
            ip_json_obj = utils.json2obj(ip_json_test)
            #public_ip = ip_json_obj['query']
            #public_isp = ip_json_obj['isp']
            public_ip = ip_json_obj['ip']
            public_isp = ip_json_obj['org']
        except Exception as ex:
            L.l.warning('Unable to get my ip, err={} text={}'.format(
                ex, ip_json_test))
            return

        for config in config_list.values():
            # check if public address is for this config dns entry
            isp = config['isp']
            if isp != public_isp:
                continue

            # get IP address
            try:
                cache['ip:' + isp] = socket.gethostbyname(
                    config['record_name'])
            except Exception as ex:
                cache['ip:' + isp] = None
                L.l.warning('Unable to get ip for host {}, err={}'.format(
                    config['record_name'], ex))

            if public_ip == '' or public_ip is None or public_ip == cache[
                    'ip:' + isp]:
                L.l.debug('IP address for ' + isp + ' is still ' + public_ip +
                          '; nothing to update.')
                return
            else:
                L.l.info('IP address was changed for {}, old was {} new is {}'.
                         format(isp, cache['ip:' + isp], public_ip))

            cache['ip:' + isp] = public_ip
            now = utils.get_base_location_now_date()
            expires = parser.parse(cache['auth']['expires'])
            now = pytz.utc.localize(now)
            expires = pytz.utc.localize(expires)
            if expires <= now:
                L.l.info(
                    'Expired rackspace authentication token; reauthenticating...'
                )
                # authenticate with Rackspace
                authUrl = 'https://identity.api.rackspacecloud.com/v2.0/tokens'
                authData = {
                    'auth': {
                        'RAX-KSKEY:apiKeyCredentials': {
                            'username': config['username'],
                            'apiKey': config['api_key']
                        }
                    }
                }
                authHeaders = {
                    'Accept': 'application/json',
                    'Content-type': 'application/json'
                }
                auth = requests.post(authUrl,
                                     data=json.dumps(authData),
                                     headers=authHeaders)
                auth = utils.json2obj(auth.text)
                cache['auth']['expires'] = auth['access']['token']['expires']
                cache['auth']['token'] = auth['access']['token']['id']

            # update DNS record
            url = 'https://dns.api.rackspacecloud.com/v1.0/' + config['account_id'] + \
                  '/domains/' + config['domain_id'] + '/records/' + config['record_id']
            data = {
                'ttl': config['record_ttl'],
                'name': config['record_name'],
                'data': public_ip
            }
            headers = {
                'Accept': 'application/json',
                'Content-type': 'application/json',
                'X-Auth-Token': cache['auth']['token']
            }
            result = requests.put(url, data=json.dumps(data), headers=headers)
            if result.ok:
                L.l.info('Updated IP address for {} to {}'.format(
                    config['record_name'], public_ip))
            else:
                L.l.warning('Unable to update IP, response={}'.format(result))
    except Exception as ex:
        L.l.warning('Unable to check and update dns, err={}'.format(ex))
Ejemplo n.º 30
0
def init():
    # not a good ideea to set a timeout as it will crash pigpio_gpio callback
    # socket.setdefaulttimeout(10)
    try:
        if P.is_client_connecting is True:
            L.l.warning(
                'Mqtt client already in connection process, skipping attempt to connect until done'
            )
            return False
        P.is_client_connecting = True
        host_list = [[
            common.get_json_param(common.Constant.P_MQTT_HOST_1),
            int(common.get_json_param(Constant.P_MQTT_PORT_1))
        ],
                     [
                         common.get_json_param(Constant.P_MQTT_HOST_2),
                         int(common.get_json_param(Constant.P_MQTT_PORT_2))
                     ]]
        config_file = common.get_json_param(Constant.P_ALL_CREDENTIAL_FILE)
        with open(config_file, 'r') as f:
            config = json.load(f)
            user = config['mqtt_username']
            passwd = config['mqtt_password']
        P.topic = str(common.get_json_param(Constant.P_MQTT_TOPIC))
        P.topic_main = str(common.get_json_param(Constant.P_MQTT_TOPIC_MAIN))
        P.mqtt_client = mqtt.Client(client_id=Constant.HOST_NAME)

        for host_port in host_list:
            host = host_port[0]
            port = host_port[1]
            L.l.info(
                'MQTT publisher module initialising, host={} port={}'.format(
                    host, port))
            retry_count = 0
            while (not P.client_connected) and (
                    retry_count < Constant.ERROR_CONNECT_MAX_RETRY_COUNT):
                try:
                    P.mqtt_client.on_connect = on_connect_paho
                    P.mqtt_client.on_subscribe = on_subscribe
                    P.mqtt_client.on_unsubscribe = on_unsubscribe
                    P.mqtt_client.username_pw_set(user, passwd)
                    P.mqtt_client.max_inflight_messages_set(100)
                    P.mqtt_client.max_queued_messages_set(0)
                    P.mqtt_client.connect(host=host, port=port, keepalive=60)
                    P.mqtt_client.loop_start()
                    seconds_lapsed = 0
                    while not P.client_connected and seconds_lapsed < 10:
                        time.sleep(1)
                        seconds_lapsed += 1
                        L.l.info('Waiting for mqtt connect {}'.format(
                            seconds_lapsed))
                    if P.client_connected:
                        P.mqtt_client.message_callback_add(
                            P.topic_main, on_message)
                        P.mqtt_client.on_disconnect = on_disconnect
                        # thread_pool.add_interval_callable(thread_run, run_interval_second=10)
                        P.initialised = True
                    else:
                        L.l.warning('Timeout connecting to mqtt')
                        retry_count += 1
                except socket.error as ex:
                    L.l.error(
                        'mqtt client not connected, err {}, pause and retry {}'
                        .format(ex, retry_count))
                    retry_count += 1
                    time.sleep(Constant.ERROR_CONNECT_PAUSE_SECOND)
                finally:
                    P.last_connect_attempt = utils.get_base_location_now_date()
            if P.client_connected:
                L.l.info('Noticed mqtt connected, init')
                break
            else:
                L.l.warning('Unable to connect to mqtt server {}:{}'.format(
                    host, port))
        if not P.client_connected:
            L.l.critical(
                'MQTT connection not available, all connect attempts failed')
    except Exception as ex:
        L.l.error('Exception on mqtt init, err={}'.format(ex))
        exit(0)

    finally:
        P.is_client_connecting = False