Conecte o dispositivo ao acelerador da solução de monitoramento remoto (Node.js)

Neste tutorial, você implementará um dispositivo Resfriador que envia a seguinte telemetria para o acelerador de solução de Monitoramento Remoto:

  • Temperatura
  • Pressão
  • Umidade

Para simplificar, o código gera valores de telemetria de exemplo para o Resfriador. Você pode estender o exemplo conectando sensores reais ao dispositivo e enviando telemetria real.

O dispositivo de exemplo também:

  • Envia os metadados à solução para descrever seus recursos.
  • Responde às ações disparadas da página Dispositivos na solução.
  • Responde às alterações de configuração da página Dispositivos na solução.

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

Antes de começar

Antes de escrever qualquer código para o dispositivo, implante o acelerador de solução de Monitoramento Remoto e adicione um novo dispositivo real à solução.

Implantar o acelerador de solução de Monitoramento Remoto

O dispositivo Resfriador criado neste tutorial envia os dados para uma instância do acelerador de solução de Monitoramento Remoto. Caso ainda não tenha provisionado o acelerador de solução de monitoramento remoto em sua conta do Azure, confira Implantar o acelerador de solução de monitoramento remoto

Quando o processo de implantação para a solução de Monitoramento Remoto for concluído, clique em Inicialização para abrir o painel da solução em seu navegador.

O painel da solução

Adicionar o dispositivo à solução de Monitoramento Remoto

Observação

Se você já adicionou um dispositivo em sua solução, poderá ignorar esta etapa. No entanto, a próxima etapa exige a cadeia de conexão do dispositivo. É possível recuperar a cadeia de conexão de um dispositivo a partir do Portal do Azure ou usando uma ferramente da CLI az iot.

Para que um dispositivo se conecte ao acelerador de solução, ele precisa se identificar para o Hub IoT usando credenciais válidas. É possível salvar a cadeia de conexão do dispositivo contendo essas credenciais, quando você adicionar o dispositivo à solução. Você incluirá a cadeia de conexão de dispositivo no seu aplicativo cliente, mais adiante neste tutorial.

Para adicionar um dispositivo à sua solução de Monitoramento Remoto, conclua as seguintes etapas na página Gerenciador de Dispositivos na solução:

  1. Escolha + Novo dispositivo e, em seguida, escolha Real como o Tipo de dispositivo:

    Adicionar um dispositivo real

  2. Insira Physical-chiller como a ID do dispositivo. Escolha as opções Chave Simétrica e Gerar chaves automaticamente:

    Escolher as opções do dispositivo

  3. Escolha Aplicar. Em seguida, anote os valores ID do dispositivo, Chave Primária e Cadeia de conexão – Chave primária:

    Recuperar credenciais

Agora, você adicionou um dispositivo real ao acelerador de solução de Monitoramento Remoto e anotou a cadeia de conexão do dispositivo. Nas seções a seguir, você implementará o aplicativo cliente que usa a cadeia de conexão do dispositivo para conectar-se à solução.

O aplicativo cliente implementa o modelo de dispositivo Resfriador interno. Um modelo de dispositivo de acelerador de solução especifica o seguinte sobre um dispositivo:

  • As propriedades que o dispositivo relata à solução. Por exemplo, um dispositivo Resfriador relata informações sobre seu firmware e sua localização.
  • Os tipos de telemetria que o dispositivo envia para a solução. Por exemplo, um dispositivo Resfriador envia valores de temperatura, umidade e pressão.
  • Os métodos que você pode agendar na solução para serem executados no dispositivo. Por exemplo, um dispositivo Resfriador deve implementar os métodos Reiniciar, FirmwareUpdate, EmergencyValveRelease e IncreasePressure.

Este tutorial mostra como conectar um dispositivo real ao acelerador de solução de Monitoramento Remoto. Neste tutorial, você usará o Node.js, que é uma boa opção para ambientes com poucas restrições de recursos.

Se você preferir simular um dispositivo, consulte Criar e testar um novo dispositivo simulado.

Criar uma solução Node.js

Certifique-se de que o Node.js versão 4.0.0 ou posterior esteja instalado no computador de desenvolvimento. Você pode executar node --version na linha de comando para verificar a versão.

  1. Crie uma pasta chamada remotemonitoring no computador de desenvolvimento. Navegue até essa pasta no ambiente de linha de comando.

  2. Para baixar e instalar os pacotes que você precisa para concluir o aplicativo de exemplo, execute os seguintes comandos:

    npm init
    npm install async azure-iot-device azure-iot-device-mqtt --save
    
  3. Na pasta remotemonitoring, crie um arquivo chamado remote_monitoring.js. Abra esse arquivo em um editor de texto.

  4. No arquivo remote_monitoring.js, adicione as seguintes instruções require:

    var Protocol = require('azure-iot-device-mqtt').Mqtt;
    var Client = require('azure-iot-device').Client;
    var Message = require('azure-iot-device').Message;
    var async = require('async');
    
  5. Adicione as declarações de variável a seguir após as instruções require . Substitua o valor de espaço reservado {device connection string} pelo valor indicado para o dispositivo provisionado na solução de monitoramento remoto:

    var connectionString = '{device connection string}';
    
  6. Para definir alguns dados telemétricos base, adicione as seguintes variáveis:

    var temperature = 50;
    var temperatureUnit = 'F';
    var humidity = 50;
    var humidityUnit = '%';
    var pressure = 55;
    var pressureUnit = 'psig';
    
  7. Para definir alguns valores de propriedade, adicione as seguintes variáveis:

    var schema = "real-chiller;v1";
    var deviceType = "RealChiller";
    var deviceFirmware = "1.0.0";
    var deviceFirmwareUpdateStatus = "";
    var deviceLocation = "Building 44";
    var deviceLatitude = 47.638928;
    var deviceLongitude = -122.13476;
    var deviceOnline = true;
    
  8. Adicione a seguinte variável para definir as propriedades relatadas a serem enviadas para a solução. Essas propriedades incluem metadados para exibição na interface do usuário da Web:

    var reportedProperties = {
      "SupportedMethods": "Reboot,FirmwareUpdate,EmergencyValveRelease,IncreasePressure",
      "Telemetry": {
        [schema]: ""
      },
      "Type": deviceType,
      "Firmware": deviceFirmware,
      "FirmwareUpdateStatus": deviceFirmwareUpdateStatus,
      "Location": deviceLocation,
      "Latitude": deviceLatitude,
      "Longitude": deviceLongitude,
      "Online": deviceOnline
    }
    
  9. Para imprimir os resultados da operação, adicione a função auxiliar a seguir:

    function printErrorFor(op) {
        return function printError(err) {
            if (err) console.log(op + ' error: ' + err.toString());
        };
    }
    
  10. Adicione a seguinte função auxiliar para usar para tornar os valores de telemetria aleatórios:

    function generateRandomIncrement() {
        return ((Math.random() * 2) - 1);
    }
    
  11. Adicione a função genérica a seguir para lidar com chamadas de método diretas da solução. A função exibe informações sobre o método direto que foi chamado, mas neste exemplo não modifica o dispositivo de nenhuma maneira. A solução usa métodos diretos para agir nos dispositivos:

    function onDirectMethod(request, response) {
      // Implement logic asynchronously here.
      console.log('Simulated ' + request.methodName);
    
      // Complete the response
      response.send(200, request.methodName + ' was called on the device', function (err) {
        if (err) console.error('Error sending method response :\n' + err.toString());
        else console.log('200 Response to method \'' + request.methodName + '\' sent successfully.');
      });
    }
    
  12. Adicione a função a seguir para lidar com chamadas de método direto FirmwareUpdate da solução. A função verifica os parâmetros passados na carga do método direto e, em seguida, é executada assincronamente uma simulação de atualização de firmware:

    function onFirmwareUpdate(request, response) {
      // Get the requested firmware version from the JSON request body
      var firmwareVersion = request.payload.Firmware;
      var firmwareUri = request.payload.FirmwareUri;
    
      // Ensure we got a firmware values
      if (!firmwareVersion || !firmwareUri) {
        response.send(400, 'Missing firmware value', function(err) {
          if (err) console.error('Error sending method response :\n' + err.toString());
          else console.log('400 Response to method \'' + request.methodName + '\' sent successfully.');
        });
      } else {
        // Respond the cloud app for the device method
        response.send(200, 'Firmware update started.', function(err) {
          if (err) console.error('Error sending method response :\n' + err.toString());
          else {
            console.log('200 Response to method \'' + request.methodName + '\' sent successfully.');
    
            // Run the simulated firmware update flow
            runFirmwareUpdateFlow(firmwareVersion, firmwareUri);
          }
        });
      }
    }
    
  13. Adicione a função a seguir para simular um fluxo de atualização de firmware demorado que relate o progresso para a solução:

    // Simulated firmwareUpdate flow
    function runFirmwareUpdateFlow(firmwareVersion, firmwareUri) {
      console.log('Simulating firmware update flow...');
      console.log('> Firmware version passed: ' + firmwareVersion);
      console.log('> Firmware URI passed: ' + firmwareUri);
      async.waterfall([
        function (callback) {
          console.log("Image downloading from " + firmwareUri);
          var patch = {
            FirmwareUpdateStatus: 'Downloading image..'
          };
          reportUpdateThroughTwin(patch, callback);
          sleep(10000, callback);
        },
        function (callback) {
          console.log("Downloaded, applying firmware " + firmwareVersion);
          deviceOnline = false;
          var patch = {
            FirmwareUpdateStatus: 'Applying firmware..',
            Online: false
          };
          reportUpdateThroughTwin(patch, callback);
          sleep(8000, callback);
        },
        function (callback) {
          console.log("Rebooting");
          var patch = {
            FirmwareUpdateStatus: 'Rebooting..'
          };
          reportUpdateThroughTwin(patch, callback);
          sleep(10000, callback);
        },
        function (callback) {
          console.log("Firmware updated to " + firmwareVersion);
          deviceOnline = true;
          var patch = {
            FirmwareUpdateStatus: 'Firmware updated',
            Online: true,
            Firmware: firmwareVersion
          };
          reportUpdateThroughTwin(patch, callback);
          callback(null);
        }
      ], function(err) {
        if (err) {
          console.error('Error in simulated firmware update flow: ' + err.message);
        } else {
          console.log("Completed simulated firmware update flow");
        }
      });
    
      // Helper function to update the twin reported properties.
      function reportUpdateThroughTwin(patch, callback) {
        console.log("Sending...");
        console.log(JSON.stringify(patch, null, 2));
        client.getTwin(function(err, twin) {
          if (!err) {
            twin.properties.reported.update(patch, function(err) {
              if (err) callback(err);
            });      
          } else {
            if (err) callback(err);
          }
        });
      }
    
      function sleep(milliseconds, callback) {
        console.log("Simulate a delay (milleseconds): " + milliseconds);
        setTimeout(function () {
          callback(null);
        }, milliseconds);
      }
    }
    
  14. Adicione o seguinte código para enviar dados de telemetria para a solução. O aplicativo cliente adiciona propriedades à mensagem para identificar o esquema de mensagem:

    function sendTelemetry(data, schema) {
      if (deviceOnline) {
        var d = new Date();
        var payload = JSON.stringify(data);
        var message = new Message(payload);
        message.properties.add('iothub-creation-time-utc', d.toISOString());
        message.properties.add('iothub-message-schema', schema);
    
        console.log('Sending device message data:\n' + payload);
        client.sendEvent(message, printErrorFor('send event'));
      } else {
        console.log('Offline, not sending telemetry');
      }
    }
    
  15. Adicione o seguinte código para criar uma instância do cliente:

    var client = Client.fromConnectionString(connectionString, Protocol);
    
  16. Adicione o seguinte código a:

    • Abra a conexão.

    • Configure um manipulador para as propriedades desejadas.

    • Envie as propriedades relatadas.

    • Registre manipuladores para os métodos diretos. O exemplo usa um manipulador separado para o método direto de atualização de firmware.

    • Comece a enviar a telemetria.

      client.open(function (err) {
      if (err) {
        printErrorFor('open')(err);
      } else {
        // Create device Twin
        client.getTwin(function (err, twin) {
          if (err) {
            console.error('Could not get device twin');
          } else {
            console.log('Device twin created');
      
            twin.on('properties.desired', function (delta) {
              // Handle desired properties set by solution
              console.log('Received new desired properties:');
              console.log(JSON.stringify(delta));
            });
      
            // Send reported properties
            twin.properties.reported.update(reportedProperties, function (err) {
              if (err) throw err;
              console.log('Twin state reported');
            });
      
            // Register handlers for all the method names we are interested in.
            // Consider separate handlers for each method.
            client.onDeviceMethod('Reboot', onDirectMethod);
            client.onDeviceMethod('FirmwareUpdate', onFirmwareUpdate);
            client.onDeviceMethod('EmergencyValveRelease', onDirectMethod);
            client.onDeviceMethod('IncreasePressure', onDirectMethod);
          }
        });
      
        // Start sending telemetry
        var sendDeviceTelemetry = setInterval(function () {
          temperature += generateRandomIncrement();
          pressure += generateRandomIncrement();
          humidity += generateRandomIncrement();
          var data = {
            'temperature': temperature,
            'temperature_unit': temperatureUnit,
            'humidity': humidity,
            'humidity_unit': humidityUnit,
            'pressure': pressure,
            'pressure_unit': pressureUnit
          };
          sendTelemetry(data, schema)
        }, 5000);
      
        client.on('error', function (err) {
          printErrorFor('client')(err);
          if (sendTemperatureInterval) clearInterval(sendTemperatureInterval);
          if (sendHumidityInterval) clearInterval(sendHumidityInterval);
          if (sendPressureInterval) clearInterval(sendPressureInterval);
          client.close(printErrorFor('client.close'));
        });
      }
      });
      
  17. Salve as alterações no arquivo remote_monitoring.js.

  18. Execute o seguinte comando no prompt de comando para inicializar o aplicativo de exemplo:

    node remote_monitoring.js
    

Exibir telemetria de dispositivo

Você pode exibir a telemetria enviada do dispositivo na página Gerenciador de Dispositivos na solução.

  1. Selecione o dispositivo que você provisionou na lista de dispositivos na página Gerenciador de Dispositivos. Um painel exibe informações sobre seu dispositivo, incluindo um gráfico de telemetria do dispositivo:

    Consultar detalhes do dispositivo

  2. Escolha Pressão para alterar a exibição de telemetria:

    Exibir telemetria de pressão

  3. Para exibir informações de diagnóstico sobre o dispositivo, role para baixo até Diagnóstico:

    Exibir diagnóstico do dispositivo

Agir no dispositivo

Para invocar métodos nos seus dispositivos, use a página Gerenciador de Dispositivos na solução de Monitoramento Remoto. Por exemplo, na solução de Monitoramento Remoto, os dispositivos Resfriadores implementam um método Reiniciar.

  1. Escolha Dispositivos para navegar até a página Gerenciador de Dispositivos na solução.

  2. Selecione o dispositivo que você provisionou na lista de dispositivos na página Gerenciador de Dispositivos:

    Selecione seu dispositivo real

  3. Para exibir uma lista dos métodos que você pode chamar no seu dispositivo, escolha Trabalhos e, em seguida, Métodos. Para agendar um método a ser executado em vários dispositivos, você pode selecionar vários dispositivos na lista. O painel Trabalhos mostra os tipos de método comuns a todos os dispositivos selecionados.

  4. Escolha Reinicializar, defina o nome do trabalho como RebootPhysicalChiller e, em seguida, escolha Aplicar:

    Agendar a atualização do firmware

  5. Uma sequência de mensagens é exibida no console executando o código de dispositivo, enquanto o dispositivo simulado manipula o método.

Observação

Para acompanhar o status do trabalho na solução, escolha Exibir Status do Trabalho.

Próximas etapas

O artigo Personalizar o acelerador de solução de Monitoramento Remoto pré-configurado descreve algumas maneiras de personalizar o acelerador da solução.