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
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
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
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'
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
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")
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()
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
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
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
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")
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
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))
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))
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")
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()
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
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
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
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))
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')
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))
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)
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)
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
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)
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 }}'
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')
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))
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