次の方法で共有


デバイスをリモート監視構成済みソリューションに接続する (Linux)

シナリオの概要

このシナリオでは、構成済みソリューション リモート監視に次のテレメトリを送信するデバイスを作成します。

  • 外部温度
  • 内部温度
  • 湿度

わかりやすくするために、デバイス上のコードはサンプル値を生成しますが、実際のセンサーをデバイスに接続し、実際のテレメトリを送信することでサンプルを拡張することをお勧めします。

デバイスは、ソリューション ダッシュボードから呼び出されたメソッドと、ソリューション ダッシュボードで設定された必要なプロパティ値にも応答できます。

このチュートリアルを完了するには、アクティブな Azure アカウントが必要です。 アカウントがない場合は、無料試用アカウントを数分で作成することができます。 詳細については、「Azure の無料試用版サイト」を参照してください。

開始する前に

デバイスのコードを記述する前に、リモート監視の構成済みソリューションをプロビジョニングし、そのソリューションに新しいカスタム デバイスをプロビジョニングする必要があります。

リモート監視構成済みソリューションをプロビジョニングする

このチュートリアルで作成したデバイスは、構成済みソリューションの リモート監視 インスタンスにデータを送信します。 Azure アカウントでリモート監視構成済みソリューションをまだプロビジョニングしていない場合は、次の手順を使用します。

  1. [https://www.azureiotsolutions.com/] ページで、[+] をクリックしてソリューションを作成します。
  2. リモート監視 パネルで [ の選択] をクリックして、ソリューションを作成します。
  3. リモート監視ソリューション の作成] ページで、任意の ソリューション名を入力し、デプロイする リージョンを選択し、使用する Azure サブスクリプションを選択します。 [ソリューション 作成] をクリックします。
  4. プロビジョニング プロセスが完了するまで待ちます。

警告

構成済みのソリューションでは、課金対象の Azure サービスが使用されます。 不要な料金が発生しないように、サブスクリプションが完了したら、構成済みのソリューションをサブスクリプションから削除してください。 https://www.azureiotsolutions.com/ ページにアクセスして、構成済みのソリューションをサブスクリプションから完全に削除できます。

リモート監視ソリューションのプロビジョニング プロセスが完了したら、[Launch] をクリックして、ブラウザーでソリューション ダッシュボードを開きます。

ソリューション ダッシュボード

リモート監視ソリューションでデバイスをプロビジョニングする

ソリューションで既にデバイスをプロビジョニングしている場合は、この手順をスキップできます。 クライアント アプリケーションを作成するときに、デバイスの資格情報を知る必要があります。

デバイスが構成済みソリューションに接続するには、有効な資格情報を使用して IoT Hub に自身を識別する必要があります。 ソリューション ダッシュボードからデバイスの資格情報を取得できます。 このチュートリアルの後半で、クライアント アプリケーションにデバイス資格情報を含めます。

リモート監視ソリューションにデバイスを追加するには、ソリューション ダッシュボードで次の手順を実行します。

  1. ダッシュボードの左下隅にある [デバイス の追加]クリックします。

    デバイス を追加する

  2. [カスタム デバイス] パネルで、[新しいを追加] をクリックします。

    カスタム デバイス を追加する

  3. [自分でデバイス IDを定義する] を選択します。 mydeviceなどのデバイス ID を入力し、[ID の確認] をクリックして名前がまだ使用されていないことを確認し、[作成] をクリックしてデバイスをプロビジョニングします。

    デバイス ID を追加する

  4. デバイスの資格情報 (デバイス ID、IoT Hub ホスト名、デバイス キー) を書き留めます。 クライアント アプリケーションは、リモート監視ソリューションに接続するためにこれらの値を必要とします。 次に、 [Done] をクリックします。

    デバイス資格情報の を表示する

  5. ソリューション ダッシュボードのデバイス一覧でデバイスを選択します。 次に、デバイスの詳細 パネルで、[デバイス を有効にするをクリックします。 デバイスの状態は現在 実行中のになりました。 リモート監視ソリューションは、デバイスからテレメトリを受信し、デバイスでメソッドを呼び出すようになりました。

サンプル C クライアント Linux をビルドして実行する

次の手順では、リモート監視構成済みソリューションと通信するクライアント アプリケーションを作成する方法を示します。 このアプリケーションは C で記述され、Ubuntu Linux 上でビルドおよび実行されます。

これらの手順を完了するには、Ubuntu バージョン 15.04 または 15.10 を実行しているデバイスが必要です。 続行する前に、次のコマンドを使用して、Ubuntu デバイスに前提条件パッケージをインストールします。

sudo apt-get install cmake gcc g++

デバイスにクライアント ライブラリをインストールする

Azure IoT Hub クライアント ライブラリは、 apt-get コマンドを使用して Ubuntu デバイスにインストールできるパッケージとして使用できます。 次の手順を実行して、IoT Hub クライアント ライブラリとヘッダー ファイルを含むパッケージを Ubuntu コンピューターにインストールします。

  1. シェルで、AzureIoT リポジトリをコンピューターに追加します。

    sudo add-apt-repository ppa:aziotsdklinux/ppa-azureiot
    sudo apt-get update
    
  2. azure-iot-sdk-c-dev パッケージをインストールする

    sudo apt-get install -y azure-iot-sdk-c-dev
    

Parson JSON パーサーをインストールする

IoT Hub クライアント ライブラリは、Parson JSON パーサーを使用してメッセージ ペイロードを解析します。 コンピューター上の適切なフォルダーで、次のコマンドを使用して Parson GitHub リポジトリを複製します。

git clone https://github.com/kgabis/parson.git

プロジェクトを準備する

Ubuntu マシンで、 remote_monitoringという名前のフォルダーを作成します。 remote_monitoring フォルダー内:

  • main.c、remote_monitoring.cremote_monitoring.hおよびCMakeLists.txt の 4 つのファイルを作成します。
  • parson という名前のフォルダーを作成します。

Parson リポジトリのローカル コピーから remote_monitoring/parson フォルダーに parson.c ファイルと parson.h ファイルをコピーします。

テキスト エディターで、 remote_monitoring.c ファイルを開きます。 次の #include ステートメントを追加します。

#include "iothubtransportmqtt.h"
#include "schemalib.h"
#include "iothub_client.h"
#include "serializer_devicetwin.h"
#include "schemaserializer.h"
#include "azure_c_shared_utility/threadapi.h"
#include "azure_c_shared_utility/platform.h"
#include "parson.h"

IoT デバイスの動作を指定する

IoT Hub シリアライザー クライアント ライブラリでは、モデルを使用して、デバイスが IoT Hub と交換するメッセージの形式を指定します。

  1. #include ステートメントの後に、次の変数宣言を追加します。 プレースホルダーの値 [デバイス ID] と [デバイス キー] を、リモート監視ソリューション ダッシュボードでデバイス用に指定した値に置き換えます。 [IoTHub 名] を置き換えるには、ソリューション ダッシュボードの IoT Hub ホスト名を使用します。 たとえば、IoT Hub ホスト名が contoso.azure-devices.netの場合は、[IoTHub 名] を contosoに置き換えます。

    static const char* deviceId = "[Device Id]";
    static const char* connectionString = "HostName=[IoTHub Name].azure-devices.net;DeviceId=[Device Id];SharedAccessKey=[Device Key]";
    
  2. 次のコードを追加して、デバイスが IoT Hub と通信できるようにするモデルを定義します。 このモデルでは、デバイスが次のことが指定されます。

    • 温度、外部温度、湿度、デバイス ID をテレメトリとして送信できます。
    • デバイスに関するメタデータを IoT Hub に送信できます。 デバイスは、起動時に DeviceInfo オブジェクトに基本的なメタデータを送信します。
    • 報告されたプロパティを IoT Hub のデバイス ツインに送信できます。 これらの報告されるプロパティは、構成、デバイス、およびシステムのプロパティにグループ化されます。
    • IoT Hub のデバイス ツインで設定された必要なプロパティを受信して操作できます。
    • 再起動InitiateFirmwareUpdate のダイレクトメソッドに応答可能で、ソリューションポータルを介して呼び出されます。 デバイスは、報告されたプロパティを使用して、サポートされているダイレクト メソッドに関する情報を送信します。
    // Define the Model
    BEGIN_NAMESPACE(Contoso);
    
    /* Reported properties */
    DECLARE_STRUCT(SystemProperties,
      ascii_char_ptr, Manufacturer,
      ascii_char_ptr, FirmwareVersion,
      ascii_char_ptr, InstalledRAM,
      ascii_char_ptr, ModelNumber,
      ascii_char_ptr, Platform,
      ascii_char_ptr, Processor,
      ascii_char_ptr, SerialNumber
    );
    
    DECLARE_STRUCT(LocationProperties,
      double, Latitude,
      double, Longitude
    );
    
    DECLARE_STRUCT(ReportedDeviceProperties,
      ascii_char_ptr, DeviceState,
      LocationProperties, Location
    );
    
    DECLARE_MODEL(ConfigProperties,
      WITH_REPORTED_PROPERTY(double, TemperatureMeanValue),
      WITH_REPORTED_PROPERTY(uint8_t, TelemetryInterval)
    );
    
    /* Part of DeviceInfo */
    DECLARE_STRUCT(DeviceProperties,
      ascii_char_ptr, DeviceID,
      _Bool, HubEnabledState
    );
    
    DECLARE_DEVICETWIN_MODEL(Thermostat,
      /* Telemetry (temperature, external temperature and humidity) */
      WITH_DATA(double, Temperature),
      WITH_DATA(double, ExternalTemperature),
      WITH_DATA(double, Humidity),
      WITH_DATA(ascii_char_ptr, DeviceId),
    
      /* DeviceInfo */
      WITH_DATA(ascii_char_ptr, ObjectType),
      WITH_DATA(_Bool, IsSimulatedDevice),
      WITH_DATA(ascii_char_ptr, Version),
      WITH_DATA(DeviceProperties, DeviceProperties),
    
      /* Device twin properties */
      WITH_REPORTED_PROPERTY(ReportedDeviceProperties, Device),
      WITH_REPORTED_PROPERTY(ConfigProperties, Config),
      WITH_REPORTED_PROPERTY(SystemProperties, System),
    
      WITH_DESIRED_PROPERTY(double, TemperatureMeanValue, onDesiredTemperatureMeanValue),
      WITH_DESIRED_PROPERTY(uint8_t, TelemetryInterval, onDesiredTelemetryInterval),
    
      /* Direct methods implemented by the device */
      WITH_METHOD(Reboot),
      WITH_METHOD(InitiateFirmwareUpdate, ascii_char_ptr, FwPackageURI),
    
      /* Register direct methods with solution portal */
      WITH_REPORTED_PROPERTY(ascii_char_ptr_no_quotes, SupportedMethods)
    );
    
    END_NAMESPACE(Contoso);
    

デバイスの動作を実装する

次に、モデルで定義されている動作を実装するコードを追加します。

  1. ソリューション ダッシュボードで設定された必要なプロパティを処理する次の関数を追加します。 これらの必要なプロパティは、モデルで定義されます。

    void onDesiredTemperatureMeanValue(void* argument)
    {
      /* By convention 'argument' is of the type of the MODEL */
      Thermostat* thermostat = argument;
      printf("Received a new desired_TemperatureMeanValue = %f\r\n", thermostat->TemperatureMeanValue);
    
    }
    
    void onDesiredTelemetryInterval(void* argument)
    {
      /* By convention 'argument' is of the type of the MODEL */
      Thermostat* thermostat = argument;
      printf("Received a new desired_TelemetryInterval = %d\r\n", thermostat->TelemetryInterval);
    }
    
  2. IoT ハブを介して呼び出されるダイレクト メソッドを処理する次の関数を追加します。 これらのダイレクト メソッドは、モデルで定義されます。

    /* Handlers for direct methods */
    METHODRETURN_HANDLE Reboot(Thermostat* thermostat)
    {
      (void)(thermostat);
    
      METHODRETURN_HANDLE result = MethodReturn_Create(201, "\"Rebooting\"");
      printf("Received reboot request\r\n");
      return result;
    }
    
    METHODRETURN_HANDLE InitiateFirmwareUpdate(Thermostat* thermostat, ascii_char_ptr FwPackageURI)
    {
      (void)(thermostat);
    
      METHODRETURN_HANDLE result = MethodReturn_Create(201, "\"Initiating Firmware Update\"");
      printf("Recieved firmware update request. Use package at: %s\r\n", FwPackageURI);
      return result;
    }
    
  3. 構成済みソリューションにメッセージを送信する次の関数を追加します。

    /* Send data to IoT Hub */
    static void sendMessage(IOTHUB_CLIENT_HANDLE iotHubClientHandle, const unsigned char* buffer, size_t size)
    {
      IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromByteArray(buffer, size);
      if (messageHandle == NULL)
      {
        printf("unable to create a new IoTHubMessage\r\n");
      }
      else
      {
        if (IoTHubClient_SendEventAsync(iotHubClientHandle, messageHandle, NULL, NULL) != IOTHUB_CLIENT_OK)
        {
          printf("failed to hand over the message to IoTHubClient");
        }
        else
        {
          printf("IoTHubClient accepted the message for delivery\r\n");
        }
    
        IoTHubMessage_Destroy(messageHandle);
      }
      free((void*)buffer);
    }
    
  4. デバイスが構成済みソリューションに新しい報告されたプロパティ値を送信したときに実行される次のコールバック ハンドラーを追加します。

    /* Callback after sending reported properties */
    void deviceTwinCallback(int status_code, void* userContextCallback)
    {
      (void)(userContextCallback);
      printf("IoTHub: reported properties delivered with status_code = %u\n", status_code);
    }
    
  5. 次の関数を追加して、デバイスをクラウドの構成済みソリューションに接続し、データを交換します。 この関数は、次の手順を実行します。

    • プラットフォームを初期化します。
    • Contoso 名前空間をシリアル化ライブラリに登録します。
    • デバイス接続文字列を使用してクライアントを初期化します。
    • Thermostat モデルのインスタンスを作成します。
    • 報告されたプロパティ値を作成して送信します。
    • DeviceInfo オブジェクトを送信します。
    • テレメトリを 1 秒ごとに送信するループを作成します。
    • すべてのリソースを初期化解除します。
    void remote_monitoring_run(void)
    {
      if (platform_init() != 0)
      {
        printf("Failed to initialize the platform.\n");
      }
      else
      {
        if (SERIALIZER_REGISTER_NAMESPACE(Contoso) == NULL)
        {
          printf("Unable to SERIALIZER_REGISTER_NAMESPACE\n");
        }
        else
        {
          IOTHUB_CLIENT_HANDLE iotHubClientHandle = IoTHubClient_CreateFromConnectionString(connectionString, MQTT_Protocol);
          if (iotHubClientHandle == NULL)
          {
            printf("Failure in IoTHubClient_CreateFromConnectionString\n");
          }
          else
          {
    #ifdef MBED_BUILD_TIMESTAMP
            // For mbed add the certificate information
            if (IoTHubClient_SetOption(iotHubClientHandle, "TrustedCerts", certificates) != IOTHUB_CLIENT_OK)
            {
                printf("Failed to set option \"TrustedCerts\"\n");
            }
    #endif // MBED_BUILD_TIMESTAMP
            Thermostat* thermostat = IoTHubDeviceTwin_CreateThermostat(iotHubClientHandle);
            if (thermostat == NULL)
            {
              printf("Failure in IoTHubDeviceTwin_CreateThermostat\n");
            }
            else
            {
              /* Set values for reported properties */
              thermostat->Config.TemperatureMeanValue = 55.5;
              thermostat->Config.TelemetryInterval = 3;
              thermostat->Device.DeviceState = "normal";
              thermostat->Device.Location.Latitude = 47.642877;
              thermostat->Device.Location.Longitude = -122.125497;
              thermostat->System.Manufacturer = "Contoso Inc.";
              thermostat->System.FirmwareVersion = "2.22";
              thermostat->System.InstalledRAM = "8 MB";
              thermostat->System.ModelNumber = "DB-14";
              thermostat->System.Platform = "Plat 9.75";
              thermostat->System.Processor = "i3-7";
              thermostat->System.SerialNumber = "SER21";
              /* Specify the signatures of the supported direct methods */
              thermostat->SupportedMethods = "{\"Reboot\": \"Reboot the device\", \"InitiateFirmwareUpdate--FwPackageURI-string\": \"Updates device Firmware. Use parameter FwPackageURI to specify the URI of the firmware file\"}";
    
              /* Send reported properties to IoT Hub */
              if (IoTHubDeviceTwin_SendReportedStateThermostat(thermostat, deviceTwinCallback, NULL) != IOTHUB_CLIENT_OK)
              {
                printf("Failed sending serialized reported state\n");
              }
              else
              {
                printf("Send DeviceInfo object to IoT Hub at startup\n");
    
                thermostat->ObjectType = "DeviceInfo";
                thermostat->IsSimulatedDevice = 0;
                thermostat->Version = "1.0";
                thermostat->DeviceProperties.HubEnabledState = 1;
                thermostat->DeviceProperties.DeviceID = (char*)deviceId;
    
                unsigned char* buffer;
                size_t bufferSize;
    
                if (SERIALIZE(&buffer, &bufferSize, thermostat->ObjectType, thermostat->Version, thermostat->IsSimulatedDevice, thermostat->DeviceProperties) != CODEFIRST_OK)
                {
                  (void)printf("Failed serializing DeviceInfo\n");
                }
                else
                {
                  sendMessage(iotHubClientHandle, buffer, bufferSize);
                }
    
                /* Send telemetry */
                thermostat->Temperature = 50;
                thermostat->ExternalTemperature = 55;
                thermostat->Humidity = 50;
                thermostat->DeviceId = (char*)deviceId;
    
                while (1)
                {
                  unsigned char*buffer;
                  size_t bufferSize;
    
                  (void)printf("Sending sensor value Temperature = %f, Humidity = %f\n", thermostat->Temperature, thermostat->Humidity);
    
                  if (SERIALIZE(&buffer, &bufferSize, thermostat->DeviceId, thermostat->Temperature, thermostat->Humidity, thermostat->ExternalTemperature) != CODEFIRST_OK)
                  {
                    (void)printf("Failed sending sensor value\r\n");
                  }
                  else
                  {
                    sendMessage(iotHubClientHandle, buffer, bufferSize);
                  }
    
                  ThreadAPI_Sleep(1000);
                }
    
                IoTHubDeviceTwin_DestroyThermostat(thermostat);
              }
            }
            IoTHubClient_Destroy(iotHubClientHandle);
          }
          serializer_deinit();
        }
      }
      platform_deinit();
    }
    

    参考までに、事前構成済みソリューションに送信されるテレメトリ メッセージ サンプルを次に示します。

    {"DeviceId":"mydevice01", "Temperature":50, "Humidity":50, "ExternalTemperature":55}
    

remote_monitoring_run関数を呼び出す

テキスト エディターで、 remote_monitoring.h ファイルを開きます。 次のコードを追加します。

void remote_monitoring_run(void);

テキスト エディターで、 main.c ファイルを開きます。 次のコードを追加します。

#include "remote_monitoring.h"

int main(void)
{
    remote_monitoring_run();

    return 0;
}

アプリケーションの構築と実行

次の手順では、 CMake を使用してクライアント アプリケーションをビルドする方法について説明します。

  1. テキスト エディターで、 remote_monitoring フォルダー内の CMakeLists.txt ファイルを開きます。

  2. 次の手順を追加して、クライアント アプリケーションをビルドする方法を定義します。

    macro(compileAsC99)
      if (CMAKE_VERSION VERSION_LESS "3.1")
        if (CMAKE_C_COMPILER_ID STREQUAL "GNU")
          set (CMAKE_C_FLAGS "--std=c99 ${CMAKE_C_FLAGS}")
          set (CMAKE_CXX_FLAGS "--std=c++11 ${CMAKE_CXX_FLAGS}")
        endif()
      else()
        set (CMAKE_C_STANDARD 99)
        set (CMAKE_CXX_STANDARD 11)
      endif()
    endmacro(compileAsC99)
    
    cmake_minimum_required(VERSION 2.8.11)
    compileAsC99()
    
    set(AZUREIOT_INC_FOLDER "${CMAKE_SOURCE_DIR}" "${CMAKE_SOURCE_DIR}/parson" "/usr/include/azureiot" "/usr/include/azureiot/inc")
    
    include_directories(${AZUREIOT_INC_FOLDER})
    
    set(sample_application_c_files
        ./parson/parson.c
        ./remote_monitoring.c
        ./main.c
    )
    
    set(sample_application_h_files
        ./parson/parson.h
        ./remote_monitoring.h
    )
    
    add_executable(sample_app ${sample_application_c_files} ${sample_application_h_files})
    
    target_link_libraries(sample_app
        serializer
        iothub_client
        iothub_client_mqtt_transport
        aziotsharedutil
        umqtt
        pthread
        curl
        ssl
        crypto
        m
    )
    
  3. remote_monitoring フォルダーに、CMake によって生成される make ファイルを格納するフォルダーを作成し、次のように cmake コマンドと make コマンドを実行します。

    mkdir cmake
    cd cmake
    cmake ../
    make
    
  4. クライアント アプリケーションを実行し、IoT Hub にテレメトリを送信します。

    ./sample_app
    

ダッシュボードでデバイス テレメトリを表示する

リモート監視ソリューションのダッシュボードを使用すると、デバイスが IoT Hub に送信するテレメトリを表示できます。

  1. ブラウザーで、リモート監視ソリューション ダッシュボードに戻り、左側のパネルで [デバイス ] をクリックして、デバイスの一覧に移動します。

  2. デバイスの一覧で、デバイスの状態が [実行中の ]表示されます。 有効でない場合は、[デバイスの詳細] パネルで [デバイス を有効にする] をクリックします。

    デバイスの状態 を表示する

  3. ダッシュボードに戻るには、ダッシュボード をクリックし、表示するデバイス のドロップダウンからデバイスを選択して、そのテレメトリを表示します。 サンプル アプリケーションからのテレメトリは、内部温度が 50 単位、外部温度が 55 単位、湿度が 50 単位です。

    デバイス テレメトリの を表示する

デバイスでメソッドを呼び出す

リモート監視ソリューションのダッシュボードを使用すると、IoT Hub を介してデバイス上のメソッドを呼び出すことができます。 たとえば、リモート監視ソリューションでは、メソッドを呼び出してデバイスの再起動をシミュレートできます。

  1. リモート監視ソリューション ダッシュボードで、左側のパネルの [デバイス] をクリックして、デバイスの一覧に移動します。

  2. デバイスの一覧で、お使いのデバイスのデバイス IDをクリックします。

  3. [デバイスの詳細 パネル]で、[メソッドをクリックします。]

    デバイスの方法

  4. メソッド ドロップダウンで、InitiateFirmwareUpdate 選択し、FWPACKAGEURI ダミー URL を入力します。 [メソッドを呼び出し] をクリックして、デバイス上でメソッドを呼び出します。

    デバイス メソッドを呼び出す

  5. デバイスがメソッドを処理するときに、デバイス コードを実行しているコンソールにメッセージが表示されます。 メソッドの結果は、ソリューション ポータルの履歴に追加されます。

    メソッド履歴の表示

次のステップ

構成済みソリューション カスタマイズ 記事では、このサンプルを拡張するいくつかの方法について説明します。 可能な拡張機能には、実際のセンサーの使用や追加のコマンドの実装が含まれます。

azureiotsuite.com サイト に対するのアクセス許可の詳細を確認できます。