普通文本  |  181行  |  6.66 KB

# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging
import os
import pprint
import sys

import wardmodem_exceptions as wme

CONF_DIR_NAME = 'configurations'
DEFAULT_CONF_FILE = 'base.conf'
MODEM_CONF_FILE = {
        'e362': 'e362.conf',
}

class ModemConfiguration(object):
    """
    All modem specific configuration needed by WardModem.

    This class serves the dual purpose of loading the configuration data needed
    by different parts of wardmodem in a single place, and providing
    documentation regarding the configuration parameters available in the file.

    """

    def __init__(self, modem=None):
        """
        @param modem The modem for which the configuration needs to be loaded.
                |modem| can be None. In that case, only the configuration for
                the base modem is loaded.
                Otherwise, |modem| must be a key in |MODEM_CONF_FILE|.
        """
        self._logger = logging.getLogger(__name__)

        if modem and modem not in MODEM_CONF_FILE:
            raise wme.WardModemSetupException('Unknown modem: |%s|' % modem)

        # TODO(pprabhu) Figure out if it makes sense to use Configurable to
        # (de)serialize configuration. See crbug.com/252475
        # First load the default configuration
        self._logger.info('Loading basic configuration.')
        self.base_conf = self._load_conf(DEFAULT_CONF_FILE)
        self._logger.debug('Basic configuration:\n%s',
                           pprint.pformat(self.base_conf))

        # Now load the plugin conf data.
        self.plugin_conf = {}
        if modem:
            self._logger.info('Loading modem specific configuration for modem '
                              '|%s|', modem)
            self.plugin_conf = self._load_conf(MODEM_CONF_FILE[modem])
        self._logger.debug('Plugin configuration:\n%s',
                           pprint.pformat(self.plugin_conf))

        self._populate_config()


    def _populate_config(self):
        """
        Assign configuration data loaded into self variable for easy access.

        """
        # The basic map from AT commands to wardmodem actions common to all
        # modems.
        self.base_at_to_wm_action_map = self.base_conf['at_to_wm_action_map']

        # The map from AT commands to wardmodem actions specific to the current
        # modem.
        self.plugin_at_to_wm_action_map = (
                self.plugin_conf.get('at_to_wm_action_map', {}))

        # The basic map from wardmodem responses to AT commands common to all
        # modems.
        self.base_wm_response_to_at_map = (
                self.base_conf['wm_response_to_at_map'])

        # The map from wardmodem responses to AT commands specific to the
        # current modem.
        self.plugin_wm_response_to_at_map = (
                self.plugin_conf.get('wm_response_to_at_map', {}))

        # State-less request response map.
        self.base_wm_request_response_map = (
                self.base_conf.get('wm_request_response_map', {}))
        self.plugin_wm_request_response_map = (
                self.plugin_conf.get('wm_request_response_map', {}))

        # The state machines loaded by all modems.
        self.base_state_machines = self.base_conf['state_machines']

        # The state machines specific to the current modem.
        self.plugin_state_machines =  self.plugin_conf.get('state_machines', [])

        # The fallback state machine for unmatched AT commands.
        self._load_variable('fallback_machine', strict=False, default='')
        self._load_variable('fallback_function', strict=False, default='')


        # The modemmanager plugin to be used for the modem.
        self._load_variable('mm_plugin')

        # The string to be prepended to all AT commands from modemmanager to
        # modem.
        self._load_variable('mm_to_modem_at_prefix')

        # The string to be appended to all AT commands from modemmanager to
        # modem.
        self._load_variable('mm_to_modem_at_suffix')

        # The string to be prepended to all AT commands from modem to
        # modemmanager.
        self._load_variable('modem_to_mm_at_prefix')

        # The string to be appended to all AT commands from modem to
        # modemmanager.
        self._load_variable('modem_to_mm_at_suffix')

        # ######################################################################
        # Configuration data for various state machines.
        self._load_variable('modem_power_level_allowed_levels')
        self._load_variable('modem_power_level_initial_level')
        self._load_variable('modem_power_level_reset_by_default')

        self._load_variable('network_identity_default_mcc')
        self._load_variable('network_identity_default_mnc')
        self._load_variable('network_identity_default_msin')
        self._load_variable('network_identity_default_mdn')

        self._load_variable('network_operators')
        self._load_variable('network_operator_default_index')

        self._load_variable('level_indicators_items')
        self._load_variable('level_indicators_defaults')


    def _load_variable(self, varname, strict=True, default=None):
        """
        Load a variable from the configuration files.

        Implement the most common way of loading variables from configuration.

        @param varname: The name of the variable to load.

        @param strict: If True, we expect some value to be available.

        @param default: Value to assign if none can be loaded. Only makes sense
                when |strint| is False.

        """
        if strict:
            value = self.plugin_conf.get(varname, self.base_conf[varname])
        else:
            value = self.plugin_conf.get(varname,
                                         self.base_conf.get(varname, default))
        setattr(self, varname, value)


    def _load_conf(self, conf_file):
        """
        Load the configuration data from file.

        @param conf_file Name of the file to load from.

        @return The conf data loaded from file.

        """
        # The configuration file is an executable python file. Since the file
        # name is known only at run-time, we must find the module directory and
        # manually point execfile to the directory for loading the configuration
        # file.
        current_module = sys.modules[__name__]
        dir_name = os.path.dirname(current_module.__file__)
        full_path = os.path.join(dir_name, CONF_DIR_NAME, conf_file)
        conf = {}
        execfile(full_path, conf)
        # These entries added by execfile are a nuisance in pprint'ing
        del conf['__builtins__']
        return conf