0
votes

The context is to apply the scenario described in the following page by packaging the app in a snap so that I can use it in different linux distributions (e.g. Ubuntu Core)

https://docs.microsoft.com/en-us/azure/iot-hub/quickstart-send-telemetry-python

When I execute the app as a script through terminal, everything runs as supposed. After creating the snap and trying to execute it I get the following error:


    Unexpected error in ._run_op() call
    Traceback (most recent call last):
      File "/snap/send-telemetry-sample/x1/lib/python3.6/site-packages/azure/iot/device/common/pipeline/pipeline_stages_base.py", line 102, in run_op
        self._run_op(op)
      File "/snap/send-telemetry-sample/x1/lib/python3.6/site-packages/azure/iot/device/common/pipeline/pipeline_thread.py", line 198, in wrapper
        return func(*args, **kwargs)
      File "/snap/send-telemetry-sample/x1/lib/python3.6/site-packages/azure/iot/device/common/pipeline/pipeline_stages_mqtt.py", line 127, in _run_op
        proxy_options=self.pipeline_root.pipeline_configuration.proxy_options,
      File "/snap/send-telemetry-sample/x1/lib/python3.6/site-packages/azure/iot/device/common/mqtt_transport.py", line 133, in __init__
        self._mqtt_client = self._create_mqtt_client()
      File "/snap/send-telemetry-sample/x1/lib/python3.6/site-packages/azure/iot/device/common/mqtt_transport.py", line 154, in _create_mqtt_client
        client_id=self._client_id, clean_session=False, protocol=mqtt.MQTTv311
      File "/snap/send-telemetry-sample/x1/lib/python3.6/site-packages/paho/mqtt/client.py", line 566, in __init__
        self._sockpairR, self._sockpairW = _socketpair_compat()
      File "/snap/send-telemetry-sample/x1/lib/python3.6/site-packages/paho/mqtt/client.py", line 270, in _socketpair_compat
        socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_IP)
      File "/snap/send-telemetry-sample/x1/usr/lib/python3.6/socket.py", line 144, in __init__
        _socket.socket.__init__(self, family, type, proto, fileno)
    PermissionError: [Errno 13] Permission denied

Application code


    # Copyright (c) Microsoft. All rights reserved.
    # Licensed under the MIT license. See LICENSE file in the project root for full license information.

    import random
    import time
    import os

    # Using the Python Device SDK for IoT Hub:
    #   https://github.com/Azure/azure-iot-sdk-python
    # The sample connects to a device-specific MQTT endpoint on your IoT Hub.
    from azure.iot.device import IoTHubDeviceClient, Message

    # The device connection string to authenticate the device with your IoT hub.
    CONNECTION_STRING = "some connection string"

    # Define the JSON message to send to IoT Hub.
    TEMPERATURE = 20.0
    HUMIDITY = 60
    MSG_TXT = '{{"temperature": {temperature},"humidity": {humidity}}}'


    def main():
        try:
            # Create an IoT Hub client
            client = IoTHubDeviceClient.create_from_connection_string(CONNECTION_STRING)

            print ( "IoT Hub device sending periodic messages, press Ctrl-C to exit" )
            while True:
                # Build the message with simulated telemetry values.
                temperature = TEMPERATURE + (random.random() * 15)
                humidity = HUMIDITY + (random.random() * 20)
                msg_txt_formatted = MSG_TXT.format(temperature=temperature, humidity=humidity)
                message = Message(msg_txt_formatted)

                # Add a custom application property to the message.
                # An IoT hub can filter on these properties without access to the message body.
                if temperature > 30:
                  message.custom_properties["temperatureAlert"] = "true"
                else:
                  message.custom_properties["temperatureAlert"] = "false"

                # Send the message.
                print( "Sending message: {}".format(message) )
                client.send_message(message)
                print ( "Message successfully sent" )
                time.sleep(1)
        except KeyboardInterrupt:
            print ( "IoTHubClient sample stopped" )


    if __name__ == '__main__':
        print ( "IoT Hub Quickstart #1 - Simulated device" )
        print ( "Press Ctrl-C to exit" )
        main()

This is the snapcraft.yaml


    name: send-telemetry-sample 
    base: core18 
    version: '1.0' 
    summary: Send telemetry to Azure IoT Hub 
    description: |
      This is a sample application for sending randomly created temperature and humidity 
      data to Azure IoT Hub.

    grade: stable 
    confinement: strict 

    apps:
      sendTel:
        command: bin/send-telemetry-sample.sendtel

    parts:
      sendtel:
        plugin: python
        python-version: python3
        source: .

And this the setup.py


    from setuptools import setup, find_packages
    import sys,os

    setup(
        name = 'send-telemetry-sample',
        version = '1.0.0',
        description = 'Send telemetry data to Azure IoT Hub',
        license='GPL v3',
        author = 'Eltjon Sulaj',
        packages = find_packages(),
        install_requires=['azure-iot-device'],
        entry_points = {
            'console_scripts': [
                'send-telemetry-sample.sendtel=src.SimulatedDevice:main']
                },
        classifiers = [
                'Programming Language :: Python :: 3.8',
                'Operating System :: OS Independent',
                'License :: OSI Approved :: GNU General Public License v3 (GPLv3)']
    )

All this runs inside an Ubuntu 20.04 vm inside Hyper-V.

Anyone with some experience on IoT snaps?

1

1 Answers

0
votes

Solved! What was going wrong is that a snap with 'strict' confinement cannot gain access to network resources unless an interface is added within the app metadata of the snapcraft.yaml. More info in this page: https://snapcraft.io/docs/snapcraft-interfaces