Share via


Ligue o seu dispositivo à solução pré-configurada de monitorização remota (Linux)

Scenario overview (Descrição geral do cenário)

Neste cenário, vai criar um dispositivo que envia a seguinte telemetria para solução pré-configurada de monitorização remota:

  • Temperatura externa
  • Temperatura interna
  • Humidade

Para simplificar, o código no dispositivo gera valores de exemplo, mas incentivamo-lo a alargar a amostra ao ligar sensores reais ao dispositivo e enviar telemetria real.

O dispositivo também é capaz de responder a métodos invocados a partir do dashboard da solução e a valores de propriedades pretendidas definidos no dashboard da solução.

Para concluir este tutorial, precisa de uma conta ativa do Azure. Se não tiver uma conta, pode criar uma de avaliação gratuita em apenas alguns minutos. Para obter mais detalhes, consulte Avaliação Gratuita do Azure.

Antes de começar

Antes de escrever qualquer código para o seu dispositivo, terá de aprovisionar a sua solução pré-configurada de monitorização remota e aprovisionar um novo dispositivo personalizado nessa solução.

Aprovisionar a solução pré-configurada de monitorização remota

O dispositivo que vai criar neste tutorial envia dados para uma instância da solução pré-configurada de monitorização remota. Se ainda não aprovisionou a solução pré-configurada de monitorização remota na sua conta do Azure, utilize os seguintes passos:

  1. https://www.azureiotsolutions.com/ Na página, clique + para criar uma solução.
  2. Clique em Selecionar no painel Monitorização remota para criar a solução.
  3. Na página Criar solução de monitorização remota, introduza um Nome da solução à sua escolha, selecione a Região onde pretende implementar e selecione a subscrição do Azure que pretende utilizar. Em seguida, clique em Criar solução.
  4. Aguarde até à conclusão do processo de aprovisionamento.

Aviso

As soluções pré-configuradas utilizam serviços do Azure faturáveis. Certifique-se de que remove a solução pré-configurada da sua subscrição quando terminar para evitar eventuais encargos desnecessários. Pode remover completamente uma solução pré-configurada da sua subscrição visitando a https://www.azureiotsolutions.com/ página.

Quando o processo de aprovisionamento para a solução de monitorização remota terminar, clique em Iniciar para abrir o dashboard da solução no seu browser.

Dashboard de soluções

Aprovisionar o dispositivo na solução de monitorização remota

Nota

Se já tiver aprovisionado um dispositivo na sua solução, pode ignorar este passo. Precisa de saber as credenciais do dispositivo quando criar a aplicação cliente.

Para que um dispositivo ligue à solução pré-configurada, este tem de se identificar no Hub IoT utilizando credenciais válidas. Pode obter as credenciais do dispositivo a partir do dashboard da solução. Vai incluir as credenciais do dispositivo na sua aplicação cliente mais à frente neste tutorial.

Para adicionar um dispositivo à sua solução de monitorização remota, execute os passos seguintes no dashboard da solução:

  1. No canto inferior esquerdo do dashboard, clique em Adicionar um dispositivo.

    Adicionar um dispositivo

  2. No painel Dispositivo Personalizado, clique em Adicionar novo.

    Adicionar um dispositivo personalizado

  3. Escolha Definir o meu próprio ID do Dispositivo. Introduza um ID do Dispositivo, como, por exemplo, mydevice, clique em Verificar ID para verificar se o nome já não está a ser utilizado e, em seguida, clique em Criar para aprovisionar o dispositivo.

    Adicionar ID do dispositivo

  4. Anote as credenciais do dispositivo (ID do Dispositivo, Nome do Anfitrião do Hub IoT e Chave do Dispositivo). A aplicação cliente precisa destes valores para ligar à solução de monitorização remota. Em seguida, clique em Fazer.

    Ver as credenciais do dispositivo

  5. Selecione o seu dispositivo na lista de dispositivos no dashboard da solução. Em seguida, no painel Detalhes do Dispositivo, clique em Ativar Dispositivo. O estado do seu dispositivo é agora Em execução. A solução de monitorização remota pode agora receber telemetria do seu dispositivo e invocar métodos no dispositivo.

Construa e faça uma amostra C cliente Linux

Os passos a seguir mostram como criar uma aplicação do cliente que comunica com a solução pré-configurada de monitorização remota. Esta aplicação está escrita em C e construída e executada em Ubuntu Linux.

Para completar estes passos, precisa de um dispositivo que execute a versão Ubuntu 15.04 ou 15.10. Antes de prosseguir, instale as embalagens pré-requisitos no seu dispositivo Ubuntu utilizando o seguinte comando:

sudo apt-get install cmake gcc g++

Instale as bibliotecas do cliente no seu dispositivo

As bibliotecas Hub IoT do Azure clientes estão disponíveis como um pacote que pode instalar no seu dispositivo Ubuntu utilizando o comando apt-get. Preencha os seguintes passos para instalar o pacote que contém a biblioteca do cliente Hub IoT e ficheiros de cabeçalho no seu computador Ubuntu:

  1. Numa concha, adicione o repositório AzureIoT ao seu computador:

    sudo add-apt-repository ppa:aziotsdklinux/ppa-azureiot
    sudo apt-get update
    
  2. Instale o pacote azure-iot-sdk-c-dev

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

Instale o pároco JSON

As bibliotecas de clientes Hub IoT usam o pároco JSON para analisar as cargas de mensagens. Numa pasta adequada no seu computador, clone o repositório Parson GitHub utilizando o seguinte comando:

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

Prepare o seu projeto

Na sua máquina Ubuntu, crie uma pasta chamada remote_monitoring. Na pasta remote_monitoring :

  • Crie os quatro ficheiros main.c, remote_monitoring.c, remote_monitoring.h e CMakeLists.txt.
  • Criar pasta chamada pároco.

Copie os ficheiros parson.c e parson.h da sua cópia local do repositório parson para a pasta remote_monitoring/pároco .

Num editor de texto, abra o ficheiro remote_monitoring.c . Adicione as seguintes instruções #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"

Especificar o comportamento do dispositivo IoT

A biblioteca de clientes do serializador do Hub IoT utiliza um modelo para especificar o formato das mensagens que o dispositivo troca com o Hub IoT.

  1. Adicione as seguintes declarações de variáveis a seguir às instruções #include. Substitua os valores do espaço reservado [ID do dispositivo] e [Tecla do dispositivo] pelos valores que notou para o seu dispositivo no painel de instrumentos de monitorização remota. Utilize o Nome de anfitrião do Hub IoT no dashboard da solução para substituir [IoTHub Name]. Por exemplo, se o Nome de anfitrião do seu Hub IoT for contoso.azure devices.net, substitua [IoTHub Name] por contoso:

    static const char* deviceId = "[Device Id]";
    static const char* connectionString = "HostName=[IoTHub Name].azure-devices.net;DeviceId=[Device Id];SharedAccessKey=[Device Key]";
    
  2. Adicione o código seguinte para definir o modelo que permite que o dispositivo comunique com o Hub IoT. Este modelo especifica que o dispositivo:

    • Pode enviar temperatura, temperatura externa, humidade e um dispositivo de identificação como telemetria.
    • Pode enviar metadados sobre o dispositivo para o Hub IoT. O dispositivo envia metadados básicos num objeto DeviceInfo no arranque.
    • Pode enviar propriedades comunicadas para o dispositivo duplo no Hub IoT. Estas propriedades comunicadas são agrupadas em propriedades de configuração, de dispositivo e de sistema.
    • Pode receber uma ação sobre as propriedades pretendidas definidas no dispositivo duplo no Hub IoT.
    • Pode responder aos métodos diretos Reboot e InitiateFirmwareUpdate invocados através do portal da solução. O dispositivo envia informações sobre os métodos diretos que suporta utilizando propriedades comunicadas.
    // 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);
    

Implementar o comportamento do dispositivo

Agora, adicione código que implementa o comportamento definido no modelo.

  1. Adicione as seguintes funções que processam as propriedades pretendidas definidas no dashboard da solução. Estas propriedades pretendidas são definidas no modelo:

    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. Adicione as seguintes funções que processam os métodos diretos invocados através do hub IoT. Estes métodos diretos são definidos no modelo:

    /* 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. Adicione a seguinte função que envia uma mensagem para a solução pré-configurada:

    /* 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. Adicione o seguinte processador de chamada de retorno que é executado quando o dispositivo envia novos valores de propriedades comunicadas para a solução pré-configurada:

    /* 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. Adicione a seguinte função para ligar o seu dispositivo à solução pré-configurada na cloud e trocar dados. Esta função executa os seguintes passos:

    • Inicializa a plataforma.
    • Regista o espaço de nomes Contoso na biblioteca de serialização.
    • Inicializa o cliente com a cadeia de ligação do dispositivo.
    • Cria uma instância do modelo Termóstato.
    • Cria e envia os valores das propriedades comunicadas.
    • Envia uma objeto DeviceInfo.
    • Cria um ciclo para enviar telemetria a cada segundo.
    • Desinicializa todos os recursos.
    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();
    }
    

    Para sua referência, eis um exemplo de mensagem de Telemetria enviada para a solução pré-configurada:

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

Chame a função remote_monitoring_run

Num editor de texto, abra o ficheiro remote_monitoring.h . Adicione o seguinte código:

void remote_monitoring_run(void);

Num editor de texto, abra o ficheiro main.c . Adicione o seguinte código:

#include "remote_monitoring.h"

int main(void)
{
    remote_monitoring_run();

    return 0;
}

Compilar e executar a aplicação

Os seguintes passos descrevem como usar o CMake para construir a sua aplicação de cliente.

  1. Num editor de texto, abra o ficheiro CMakeLists.txt na pasta remote_monitoring .

  2. Adicione as seguintes instruções para definir como construir a sua aplicação ao cliente:

    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. Na pasta remote_monitoring , crie uma pasta para armazenar os ficheiros de fazer que o CMake gera e, em seguida, executar o cmake e fazer comandos da seguinte forma:

    mkdir cmake
    cd cmake
    cmake ../
    make
    
  4. Executar o pedido de cliente e enviar telemetria para Hub IoT:

    ./sample_app
    

Ver telemetria do dispositivo no dashboard

O dashboard na solução de monitorização remota permite-lhe ver a telemetria que os seus dispositivos enviam para o Hub IoT.

  1. No browser, regresse ao dashboard da solução de monitorização remota e clique em Dispositivos no painel à esquerda para navegar para a Lista de dispositivos.

  2. Na Lista de dispositivos, deverá ver que o estado do seu dispositivo é Em execução. Se não for, clique em Ativar Dispositivo no painel Detalhes do Dispositivo.

    Ver o estado do dispositivo

  3. Clique em Dashboard para voltar ao dashboard e selecione o seu dispositivo na lista pendente Dispositivo a Visualizar para ver a respetiva telemetria. A telemetria da aplicação de amostra é 50 unidades para temperatura interna, 55 unidades para temperatura externa e 50 unidades para humidade.

    Ver a telemetria do dispositivo

Invocar um método no seu dispositivo

O dashboard na solução de monitorização remota permite-lhe invocar os métodos nos seus dispositivos através do Hub IoT. Por exemplo, na solução de monitorização remota pode invocar um método para simular o reinício de um dispositivo.

  1. No dashboard da solução de monitorização remota, clique em Dispositivos no painel à esquerda para navegar para a Lista de dispositivos.

  2. Clique em ID do Dispositivo para o seu dispositivo na Lista de dispositivos.

  3. No painel Detalhes do dispositivo, clique em Métodos.

    Métodos do dispositivo

  4. Na lista pendente de Método, selecione InitiateFirmwareUpdate e, em seguida, em FWPACKAGEURI, introduza um URL fictício. Clique em Invocar Método para chamar o método no dispositivo.

    Invocar um método de dispositivo

  5. Verá uma mensagem na consola que está a executar o código do dispositivo quando o dispositivo processar o método. Os resultados do método são adicionados ao histórico no portal da solução:

    Ver o histórico do método

Passos seguintes

O artigo Personalizar soluções pré-configuradas descreve algumas formas através das quais pode expandir este exemplo. As extensões possíveis incluem a utilização de sensores reais e a implementação de comandos adicionais.

Pode saber mais sobre as permissões no site azureiotsuite.com.