示例#1
0
def ParseConfigFile(configFilePath):
    parms = configparser.ConfigParser({
        "domain": "internetofthings.ibmcloud.com",
        "clean-session": "true"
    })
    sectionHeader = "device"
    try:
        with open(configFilePath) as f:
            try:
                parms.read_file(f)
            except AttributeError:
                # Python 2.7 support
                # https://docs.python.org/3/library/configparser.html#configparser.ConfigParser.read_file
                parms.readfp(f)

        domain = parms.get(sectionHeader, "domain")
        organization = parms.get(sectionHeader, "org")
        deviceType = parms.get(sectionHeader, "type")
        deviceId = parms.get(sectionHeader, "id")
        authMethod = parms.get(sectionHeader, "auth-method")
        authToken = parms.get(sectionHeader, "auth-token")
        cleanSession = parms.get(sectionHeader, "clean-session")

    except IOError as e:
        reason = "Error reading device configuration file '%s' (%s)" % (
            configFilePath, e[1])
        raise ConfigurationException(reason)

    return {
        'domain': domain,
        'org': organization,
        'type': deviceType,
        'id': deviceId,
        'auth-method': authMethod,
        'auth-token': authToken,
        'clean-session': cleanSession
    }
示例#2
0
    def __init__(self, options, logHandlers=None):
        self._options = options

        ### DEFAULTS ###
        if "domain" not in self._options:
            # Default to the domain for the public cloud offering
            self._options['domain'] = "internetofthings.ibmcloud.com"
        if "clean-session" not in self._options:
            self._options['clean-session'] = "true"

        if "org" not in self._options:
            # Default to the quickstart
            self._options['org'] = "quickstart"

        if "port" not in self._options and self._options["org"] != "quickstart":
            self._options["port"] = 8883

        if self._options["org"] == "quickstart":
            self._options["port"] = 1883

        ### REQUIRED ###
        if self._options['org'] == None:
            raise ConfigurationException("Missing required property: org")
        if self._options['type'] == None:
            raise ConfigurationException("Missing required property: type")
        if self._options['id'] == None:
            raise ConfigurationException("Missing required property: id")

        if self._options['org'] != "quickstart":
            if self._options['auth-method'] == None:
                raise ConfigurationException(
                    "Missing required property: auth-method")

            if (self._options['auth-method'] == "token"):
                if self._options['auth-token'] == None:
                    raise ConfigurationException(
                        "Missing required property for token based authentication: auth-token"
                    )
            else:
                raise UnsupportedAuthenticationMethod(options['auth-method'])

        AbstractClient.__init__(
            self,
            domain=self._options['domain'],
            organization=self._options['org'],
            clientId="d:" + self._options['org'] + ":" +
            self._options['type'] + ":" + self._options['id'],
            username="******" if
            (self._options['auth-method'] == "token") else None,
            password=self._options['auth-token'],
            logHandlers=logHandlers,
            cleanSession=self._options['clean-session'],
            port=self._options['port'])

        # Add handler for commands if not connected to QuickStart
        if self._options['org'] != "quickstart":
            self.client.message_callback_add("iot-2/cmd/+/fmt/+",
                                             self.__onCommand)

        self.subscriptionsAcknowledged = threading.Event()

        # Initialize user supplied callback
        self.commandCallback = None

        self.client.on_connect = self.on_connect

        self.setMessageEncoderModule('json', jsonCodec)
        self.setMessageEncoderModule('json-iotf', jsonIotfCodec)
        self.setMessageEncoderModule('xml', xmlCodec)
示例#3
0
    def __init__(self, options, logHandlers=None):
        self._options = options

        #Defaults
        if "domain" not in self._options:
            # Default to the domain for the public cloud offering
            self._options['domain'] = "internetofthings.ibmcloud.com"

        if "org" not in self._options:
            # Default to the quickstart ode
            self._options['org'] = "quickstart"

        if "clean-session" not in self._options:
            self._options['clean-session'] = "true"

        if "port" not in self._options and self._options["org"] != "quickstart":
            self._options["port"] = 8883

        if self._options["org"] == "quickstart":
            self._options["port"] = 1883

        #Check for any missing required properties
        if self._options['org'] == None:
            raise ConfigurationException("Missing required property: org")
        if self._options['type'] == None:
            raise ConfigurationException("Missing required property: type")
        if self._options['id'] == None:
            raise ConfigurationException("Missing required property: id")

        if self._options['org'] != "quickstart":
            if self._options['auth-method'] == None:
                raise ConfigurationException(
                    "Missing required property: auth-method")

            if (self._options['auth-method'] == "token"):
                if self._options['auth-token'] == None:
                    raise ConfigurationException(
                        "Missing required property for token based authentication: auth-token"
                    )
            else:
                raise UnsupportedAuthenticationMethod(options['authMethod'])
        self._options['subscriptionList'] = {}

        self.COMMAND_TOPIC = "iot-2/type/" + self._options[
            'type'] + "/id/" + self._options['id'] + "/cmd/+/fmt/+"

        AbstractClient.__init__(
            self,
            domain=self._options['domain'],
            organization=self._options['org'],
            clientId="g:" + self._options['org'] + ":" +
            self._options['type'] + ":" + self._options['id'],
            username="******" if
            (self._options['auth-method'] == "token") else None,
            password=self._options['auth-token'],
            logHandlers=logHandlers,
            port=self._options['port'])

        # Add handler for commands if not connected to QuickStart
        if self._options['org'] != "quickstart":
            gatewayCommandTopic = "iot-2/type/" + options[
                'type'] + "/id/" + options['id'] + "/cmd/+/fmt/json"
            messageNotificationTopic = "iot-2/type/" + options[
                'type'] + "/id/" + options['id'] + "/notify"
            #localTopic = "iot-2/type/iotsample-raspberrypi2/id/89898889/cmd/greeting/fmt/json"
            self.client.message_callback_add(gatewayCommandTopic,
                                             self.__onCommand)
            self.client.message_callback_add("iot-2/type/+/id/+/cmd/+/fmt/+",
                                             self.__onDeviceCommand)
            self.client.message_callback_add(messageNotificationTopic,
                                             self.__onMessageNotification)

        self.subscriptionsAcknowledged = threading.Event()

        # Initialize user supplied callback
        self.commandCallback = None
        self.deviceCommandCallback = None
        self.notificationCallback = None
        self.client.on_connect = self.on_connect
        self.setMessageEncoderModule('json', jsonCodec)
        self.setMessageEncoderModule('json-iotf', jsonIotfCodec)
        self.setMessageEncoderModule('xml', xmlCodec)

        # Create api key for gateway authentication
        self.gatewayApiKey = "g/" + self._options['org'] + '/' + self._options[
            'type'] + '/' + self._options['id']
        self.logger = logging.getLogger(self.__module__ + "." +
                                        self.__class__.__name__)
        self.logger.setLevel(logging.INFO)
        self.api = api.ApiClient(
            {
                "org": self._options['org'],
                "auth-token": self._options['auth-token'],
                "auth-key": self.gatewayApiKey
            }, self.logger)
示例#4
0
    def __init__(self, config, logHandlers=None, deviceInfo=None):
        """
        Override the constructor
        """
        if config['identity']['orgId'] == "quickstart":
            raise ConfigurationException(
                "QuickStart does not support device management")

        self._config = GatewayClientConfig(**config)

        AbstractClient.__init__(self,
                                domain=self._config.domain,
                                organization=self._config.orgId,
                                clientId=self._config.clientId,
                                username=self._config.username,
                                password=self._config.password,
                                port=self._config.port,
                                transport=self._config.transport,
                                cleanStart=self._config.cleanStart,
                                sessionExpiry=self._config.sessionExpiry,
                                keepAlive=self._config.keepAlive,
                                caFile=self._config.caFile,
                                logLevel=self._config.logLevel,
                                logHandlers=logHandlers)

        self.COMMAND_TOPIC = "iot-2/type/" + self._config.typeId + "/id/" + self._config.deviceId + "/cmd/+/fmt/+"

        gatewayCommandTopic = "iot-2/type/" + self._config.typeId + "/id/" + self._config.deviceId + "/cmd/+/fmt/json"
        deviceCommandTopic = "iot-2/type/+/id/+/cmd/+/fmt/+"
        messageNotificationTopic = "iot-2/type/" + self._config.typeId + "/id/" + self._config.deviceId + "/notify"

        self.client.message_callback_add(gatewayCommandTopic, self._onCommand)
        self.client.message_callback_add(deviceCommandTopic,
                                         self._onDeviceCommand)
        self.client.message_callback_add(messageNotificationTopic,
                                         self._onMessageNotification)

        # Initialize user supplied callback
        self.deviceCommandCallback = None
        self.notificationCallback = None

        # ---------------------------------------------------------------------
        # Device Management Specific code starts here
        # ---------------------------------------------------------------------
        self.readyForDeviceMgmt = threading.Event()

        # Add handler for supported device management commands
        self.client.message_callback_add("iotdm-1/#",
                                         self.__onDeviceMgmtResponse)

        # List of DM requests that have not received a response yet
        self._deviceMgmtRequestsPendingLock = threading.Lock()
        self._deviceMgmtRequestsPending = {}

        # List of DM notify hook
        self._deviceMgmtObservationsLock = threading.Lock()
        self._deviceMgmtObservations = []

        # Initialize local device data model
        self.metadata = {}
        if deviceInfo is not None:
            self._deviceInfo = deviceInfo
        else:
            self._deviceInfo = DeviceInfo()

        self._location = None
        self._errorCode = None

        # Initialize subscription list
        self._subscriptions[self.DM_RESPONSE_TOPIC_TEMPLATE %
                            (self._config.typeId, self._config.deviceId)] = 1
        self._subscriptions[self.DM_OBSERVE_TOPIC_TEMPLATE %
                            (self._config.typeId, self._config.deviceId)] = 1
        self._subscriptions[self.COMMAND_TOPIC] = 1
示例#5
0
    def __init__(self, config, logHandlers=None, deviceInfo=None):
        if config['identity']['orgId'] == "quickstart":
            raise ConfigurationException(
                "QuickStart does not support device management")

        DeviceClient.__init__(self, config, logHandlers)

        # Initialize user supplied callback
        self.deviceActionCallback = None
        self.firmwereActionCallback = None
        self.dmeActionCallback = None

        messages_callbacks = (
            ("iotdm-1/#", self.__onDeviceMgmtResponse),
            (ManagedDeviceClient.DM_REBOOT_TOPIC, self.__onRebootRequest),
            (ManagedDeviceClient.DM_FACTORY_REESET,
             self.__onFactoryResetRequest),
            (ManagedDeviceClient.DM_FIRMWARE_UPDATE_TOPIC,
             self.__onFirmwereUpdate),
            (ManagedDeviceClient.DM_OBSERVE_TOPIC, self.__onFirmwereObserve),
            (ManagedDeviceClient.DM_FIRMWARE_DOWNLOAD_TOPIC,
             self.__onFirmwereDownload),
            (ManagedDeviceClient.DM_UPDATE_TOPIC, self.__onUpdatedDevice),
            (ManagedDeviceClient.DM_CANCEL_OBSERVE_TOPIC,
             self.__onFirmwereCancel),
            (ManagedDeviceClient.DME_ACTION_TOPIC, self.__onDMEActionRequest),
        )

        # Add handler for supported device management commands
        for message, callback in messages_callbacks:
            self.client.message_callback_add(message, callback)

        # Initialize user supplied callback
        self.client.on_subscribe = self._onSubscribe
        self.client.on_disconnect = self._onDisconnect

        self.readyForDeviceMgmt = threading.Event()

        # List of DM requests that have not received a response yet
        self._deviceMgmtRequestsPendingLock = threading.Lock()
        self._deviceMgmtRequestsPending = {}

        # List of DM notify hook
        self._deviceMgmtObservationsLock = threading.Lock()
        self._deviceMgmtObservations = []

        # Initialize local device data model
        self.metadata = {}
        if deviceInfo is not None:
            self._deviceInfo = deviceInfo
        else:
            self._deviceInfo = DeviceInfo()

        self._location = None
        self._errorCode = None
        self.__firmwareUpdate = None

        self.manageTimer = None

        # Register startup subscription list
        self._subscriptions[self.DM_RESPONSE_TOPIC] = 1
        self._subscriptions[self.DM_OBSERVE_TOPIC] = 1
        self._subscriptions[self.DM_REBOOT_TOPIC] = 1
        self._subscriptions[self.DM_FACTORY_REESET] = 1
        self._subscriptions[self.DM_UPDATE_TOPIC] = 1
        self._subscriptions[self.DM_FIRMWARE_UPDATE_TOPIC] = 1
        self._subscriptions[self.DM_FIRMWARE_DOWNLOAD_TOPIC] = 1
        self._subscriptions[self.DM_CANCEL_OBSERVE_TOPIC] = 1
        self._subscriptions[self._COMMAND_TOPIC] = 1
        self._subscriptions[self.DME_ACTION_TOPIC] = 1
示例#6
0
    def __init__(self, **kwargs):
        # Validate the arguments
        if 'identity' not in kwargs:
            raise ConfigurationException("Missing identity from configuration")
        if 'orgId' not in kwargs['identity'] or kwargs['identity']['orgId'] is None:
            raise ConfigurationException("Missing identity.orgId from configuration")
        if 'typeId' not in kwargs['identity'] or kwargs['identity']['typeId'] is None:
            raise ConfigurationException("Missing identity.typeId from configuration")
        if 'deviceId' not in kwargs['identity'] or kwargs['identity']['deviceId'] is None:
            raise ConfigurationException("Missing identity.deviceId from configuration")
        
        # Authentication is not supported for quickstart
        if kwargs['identity']['orgId'] is "quickstart":
            if 'auth' in kwargs:
                raise ConfigurationException("Quickstart service does not support device authentication")
        else:
            if 'auth' not in kwargs:
                raise ConfigurationException("Missing auth from configuration")
            if 'token' not in kwargs['auth'] or kwargs['auth']['token'] is None:
                raise ConfigurationException("Missing auth.token from configuration")
        
        if 'options' in kwargs and 'mqtt' in kwargs['options']:
            # validate port
            if 'port' in kwargs['options']['mqtt'] and kwargs['options']['mqtt']['port'] is not None:
                if not isinstance(kwargs['options']['mqtt']['port'], int):
                    raise ConfigurationException("Optional setting options.mqtt.port must be a number if provided")
            # Validate cleanStart
            if 'cleanStart' in kwargs['options']['mqtt'] and not isinstance(kwargs['options']['mqtt']['cleanStart'], bool):
                raise ConfigurationException("Optional setting options.mqtt.cleanStart must be a boolean if provided")
        

        # Set defaults for optional configuration
        if 'options' not in kwargs:
            kwargs['options'] = {}

        if "domain" not in kwargs['options']:
            kwargs['options']['domain'] = "internetofthings.ibmcloud.com"
        
        if "logLevel" not in kwargs['options']:
            kwargs['options']['logLevel'] = logging.INFO

        if 'mqtt' not in kwargs['options']:
            kwargs['options']['mqtt'] = {}
        
        if "port" not in kwargs['options']['mqtt']:
            kwargs['options']['mqtt']['port'] = None
        
        if "transport" not in kwargs['options']['mqtt']:
            kwargs['options']['mqtt']['transport'] = 'tcp'

        if "cleanStart" not in kwargs['options']['mqtt']:
            kwargs['options']['mqtt']['cleanStart'] = False

        if "sessionExpiry" not in kwargs['options']['mqtt']:
            kwargs['options']['mqtt']['sessionExpiry'] = 3600

        if "keepAlive" not in kwargs['options']['mqtt']:
            kwargs['options']['mqtt']['keepAlive'] = 60

        if "caFile" not in kwargs['options']['mqtt']:
            kwargs['options']['mqtt']['caFile'] = None

        
        dict.__init__(self, **kwargs)
示例#7
0
def ParseEnvVars():
    """
    Parse environment variables into a Python dictionary suitable for passing to the 
    device client constructor as the `options` parameter

    - `WIOTP_IDENTITY_ORGID`
    - `WIOTP_IDENTITY_TYPEID`
    - `WIOTP_IDENTITY_DEVICEID`
    - `WIOTP_AUTH_TOKEN`
    - `WIOTP_DOMAIN` (optional)
    - `WIOTP_LOGLEVEL` (optional)
    - `WIOTP_OPTIONS_MQTT_PORT` (optional)
    - `WIOTP_OPTIONS_MQTT_TRANSPORT` (optional)
    - `WIOTP_OPTIONS_MQTT_CAFILE` (optional)
    - `WIOTP_OPTIONS_MQTT_CLEANSTART` (optional)
    - `WIOTP_OPTIONS_MQTT_SESSIONEXPIRY` (optional)
    - `WIOTP_OPTIONS_MQTT_KEEPALIVE` (optional)
    """

    # Identify
    orgId     = os.getenv("WIOTP_IDENTITY_ORGID", None)
    typeId    = os.getenv("WIOTP_IDENTITY_TYPEID", None)
    deviceId  = os.getenv("WIOTP_IDENTITY_DEVICEID", None)
    # Auth
    authToken = os.getenv("WIOTP_AUTH_TOKEN", None)
    # Options
    domain        = os.getenv("WIOTP_OPTIONS_DOMAIN", None)
    logLevel      = os.getenv("WIOTP_OPTIONS_LOGLEVEL", "info")
    port          = os.getenv("WIOTP_OPTIONS_MQTT_PORT", None)
    transport     = os.getenv("WIOTP_OPTIONS_MQTT_TRANSPORT", None)
    caFile        = os.getenv("WIOTP_OPTIONS_MQTT_CAFILE", None)
    cleanStart    = os.getenv("WIOTP_OPTIONS_MQTT_CLEANSTART", "False")
    sessionExpiry = os.getenv("WIOTP_OPTIONS_MQTT_SESSIONEXPIRY", "3600")
    keepAlive     = os.getenv("WIOTP_OPTIONS_MQTT_KEEPALIVE", "60")
    caFile        = os.getenv("WIOTP_OPTIONS_MQTT_CAFILE", None)
    
    if orgId is None:
        raise ConfigurationException("Missing WIOTP_IDENTITY_ORGID environment variable")
    if typeId is None:
        raise ConfigurationException("Missing WIOTP_IDENTITY_TYPEID environment variable")
    if deviceId is None:
        raise ConfigurationException("Missing WIOTP_IDENTITY_DEVICEID environment variable")
    if orgId is not "quickstart" and authToken is None:
        raise ConfigurationException("Missing WIOTP_AUTH_TOKEN environment variable")
    if port is not None:
        try:
            port = int(port)
        except ValueError as e:
            raise ConfigurationException("WIOTP_OPTIONS_MQTT_PORT must be a number")

    try:
        sessionExpiry = int(sessionExpiry)
    except ValueError as e:
        raise ConfigurationException("WIOTP_OPTIONS_MQTT_SESSIONEXPIRY must be a number")

    try:
        keepAlive = int(keepAlive)
    except ValueError as e:
        raise ConfigurationException("WIOTP_OPTIONS_MQTT_KEEPAIVE must be a number")

    if logLevel not in ["error", "warning", "info", "debug"]:
        raise ConfigurationException("WIOTP_OPTIONS_LOGLEVEL must be one of error, warning, info, debug")  
    else:
        # Convert log levels from string to int (we need to upper case our strings from the config)
        logLevel = logging.getLevelName(logLevel.upper())

    cfg = {
        'identity': {
            'orgId': orgId,
            'typeId': typeId,
            'deviceId': deviceId
        },
        'options': {
            'domain': domain,
            'logLevel': logLevel,
            'mqtt': {
                'port': port,
                'transport': transport,
                'caFile': caFile,
                'cleanStart': cleanStart in ["True", "true", "1"],
                'sessionExpiry': sessionExpiry,
                'keepAlive': keepAlive
            }
        }
    }

    # Quickstart doesn't support auth, so ensure we only add this if it's defined
    if authToken is not None:
        cfg['auth'] = { 'token': authToken }
    
    return cfg
示例#8
0
    def __init__(self, options, logHandlers=None):
        self._options = options

        if self._options['org'] == None:
            raise ConfigurationException("Missing required property: org")
        if self._options['type'] == None:
            raise ConfigurationException("Missing required property: type")
        if self._options['id'] == None:
            raise ConfigurationException("Missing required property: id")

        if self._options['org'] != "quickstart":
            if self._options['auth-method'] == None:
                raise ConfigurationException(
                    "Missing required property: auth-method")

            if (self._options['auth-method'] == "token"):
                if self._options['auth-token'] == None:
                    raise ConfigurationException(
                        "Missing required property for token based authentication: auth-token"
                    )
            else:
                raise UnsupportedAuthenticationMethod(options['authMethod'])
        self._options['subscriptionList'] = {}

        # Include staging
        self._options[
            'staging'] = options['staging'] if 'staging' in options else None

        AbstractClient.__init__(self,
                                organization=options['org'],
                                clientId="g:" + options['org'] + ":" +
                                options['type'] + ":" + options['id'],
                                username="******" if
                                (options['auth-method'] == "token") else None,
                                password=options['auth-token'],
                                logHandlers=logHandlers,
                                staging=options['staging'])

        # Add handler for commands if not connected to QuickStart
        if self._options['org'] != "quickstart":
            gatewayCommandTopic = "iot-2/type/" + options[
                'type'] + "/id/" + options['id'] + "/cmd/+/fmt/json"
            messageNotificationTopic = "iot-2/type/" + options[
                'type'] + "/id/" + options['id'] + "/notify"
            #localTopic = "iot-2/type/iotsample-raspberrypi2/id/89898889/cmd/greeting/fmt/json"
            self.client.message_callback_add(gatewayCommandTopic,
                                             self.__onCommand)
            self.client.message_callback_add("iot-2/type/+/id/+/cmd/+/fmt/+",
                                             self.__onDeviceCommand)
            self.client.message_callback_add(messageNotificationTopic,
                                             self.__onMessageNotification)

        self.subscriptionsAcknowledged = threading.Event()

        # Initialize user supplied callback
        self.commandCallback = None
        self.deviceCommandCallback = None
        self.notificationCallback = None
        self.client.on_connect = self.on_connect
        self.setMessageEncoderModule('json', jsonCodec)
        self.setMessageEncoderModule('json-iotf', jsonIotfCodec)