使用MQTT从Azure IOT Hub接收消息

时间:2018-08-22 06:56:59

标签: azure mqtt azure-iot-hub

我正在尝试使用MQTT和Azure Device SDK库将消息发送到Azure IOT集线器。在IOT集线器上配置了两个设备。两种设备都有不同的连接字符串。

设备1的连接字符串

connString =“ HostName = ABC.azure-devices.net; DeviceId = ABC; SharedAccessKey = sharedKey”;

设备2的连接字符串

connString =“ HostName = DEF.azure-devices.net; DeviceId = DEF; SharedAccessKey = sharedKey”;

我写了两个发布者将消息发送到IOT集线器,以及订户将接收来自发布者发送的来自IOT集线器的消息。

在第一个发布者中,我传递了设备1的连接字符串,而在第二个发布者中,传递了设备2的连接字符串。现在,当我同时运行两个发布者类时,订阅者正在接收来自两个发布者的消息。谁能让我知道如何修改代码,以便即使两个发布者同时运行,订阅者也只能接收到发布者1发送的消息。

这是我的Publisher 1代码。

package com.iot.mqtt.connection;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Properties;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.google.gson.Gson;
import com.microsoft.azure.sdk.iot.device.DeviceClient;
import com.microsoft.azure.sdk.iot.device.IotHubClientProtocol;
import com.microsoft.azure.sdk.iot.device.IotHubEventCallback;
import com.microsoft.azure.sdk.iot.device.IotHubStatusCode;
import com.microsoft.azure.sdk.iot.device.Message;
//import com.microsoft.docs.iothub.samples.SimulatedDevice.EventCallback;
//import com.microsoft.docs.iothub.samples.SimulatedDevice.MessageSender;
//import com.microsoft.docs.iothub.samples.SimulatedDevice.TelemetryDataPoint;

public class SimulatedDevice {
      // The device connection string to authenticate the device with your IoT hub.
      // Using the Azure CLI:
      // az iot hub device-identity show-connection-string --hub-name {YourIoTHubName} --device-id MyJavaDevice --output table


      private static String connString = "HostName=ABC.azure-devices.net;DeviceId=ABC;SharedAccessKey=aTVNu55sN9a2Y9+V0BCAOXdo8nSFDNzByfiTqMvNb20=";

      // Using the MQTT protocol to connect to IoT Hub
      private static IotHubClientProtocol protocol = IotHubClientProtocol.MQTT;
      private static DeviceClient client;

      // Specify the telemetry to send to your IoT hub.
      private static class TelemetryDataPoint {
        public double temperature;
        public double humidity;
        public String message;
        public String timeStamp;

        // Serialize object to JSON format.
        public String serialize() {
          Gson gson = new Gson();
          return gson.toJson(this);
        }
      }

      // Print the acknowledgement received from IoT Hub for the telemetry message sent.
      private static class EventCallback implements IotHubEventCallback {
        public void execute(IotHubStatusCode status, Object context) {
          System.out.println("IoT Hub responded to message with status: " + status.name());

          if (context != null) {
            synchronized (context) {
              context.notify();
            }
          }
        }
      }

      private static class MessageSender implements Runnable {
        public void run() {
          try {
            // Initialize the simulated telemetry.
            double minTemperature = 20;
            double minHumidity = 60;
            String message;
            Random rand = new Random();

            InputStream is = null;
            Properties prop = null;

            prop = new Properties();
            is = new FileInputStream("C:\\Users\\H251970\\eclipse-workspace\\IOTMqttTestProject\\resources\\config.properties");
            prop.load(is);
            message = prop.getProperty("message");
            minTemperature = Double.parseDouble(prop.getProperty("temperature"));
            minHumidity = Double.parseDouble(prop.getProperty("humidity"));
            //System.out.println(message);

            while (true) {
              // Simulate telemetry.
              double currentTemperature = minTemperature + rand.nextDouble() * 15;
              double currentHumidity = minHumidity + rand.nextDouble() * 20;
              String datatimeStamp= new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(Calendar.getInstance().getTime());;
              TelemetryDataPoint telemetryDataPoint = new TelemetryDataPoint();
              telemetryDataPoint.temperature = currentTemperature;
              telemetryDataPoint.humidity = currentHumidity;
              telemetryDataPoint.message = message;
              telemetryDataPoint.timeStamp = datatimeStamp;
              // Add the telemetry to the message body as JSON.
              String msgStr = telemetryDataPoint.serialize();

              Message msg = new Message(msgStr);

              // Add a custom application property to the message.
              // An IoT hub can filter on these properties without access to the message body.
              msg.setProperty("temperatureAlert", (currentTemperature > 30) ? "true" : "false");

              System.out.println("Sending message: " + msgStr);

              Object lockobj = new Object();

              // Send the message.
              EventCallback callback = new EventCallback();
              client.sendEventAsync(msg, callback, lockobj);

              synchronized (lockobj) {
                lockobj.wait();
              }
              Thread.sleep(3000);
            }
          } catch (Exception e) {
                System.out.println("Exception: " + e);
            } /*finally {
                inputStream.close();
            }*/  
        }
      }

      public static void main(String[] args) throws IOException, URISyntaxException {

        // Connect to the IoT hub.
        client = new DeviceClient(connString, protocol);
        client.open();

        // Create new thread and start sending messages 
        MessageSender sender = new MessageSender();
        ExecutorService executor = Executors.newFixedThreadPool(1);
        executor.execute(sender);

        // Stop the application.
        System.out.println("Press ENTER to exit.");
        System.in.read();
        executor.shutdownNow();
        client.closeNow();
      }
    }

发布者2的代码也相同,只是连接字符串不同。

connString = "HostName=DEF.azure-devices.net;DeviceId=DEF;SharedAccessKey=aTVNu55sN9a2Y9+V0BCAOXdo8nSFDNzByfiTqMvNb20=";

订户正在接收以下形式的消息。

Sending message: {"temperature":"27.739594911863872°C","voltage":"15.81301816513805V","motorspeed":"5.0m/s","inverterName":"i550","timeStamp":"22/08/2018 11:18:03"}
IoT Hub responded to message with status: OK_EMPTY

这是订户类的代码

package com.microsoft.docs.iothub.samples;

import com.microsoft.azure.eventhubs.ConnectionStringBuilder;
import com.microsoft.azure.eventhubs.EventData;
import com.microsoft.azure.eventhubs.EventHubClient;
import com.microsoft.azure.eventhubs.EventHubException;
import com.microsoft.azure.eventhubs.EventPosition;
import com.microsoft.azure.eventhubs.EventHubRuntimeInformation;
import com.microsoft.azure.eventhubs.PartitionReceiver;

import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.nio.charset.Charset;
import java.net.URI;
import java.net.URISyntaxException;

public class ReadDeviceToCloudMessages {

  // az iot hub show --query properties.eventHubEndpoints.events.endpoint --name {your IoT Hub name}
  //private static final String eventHubsCompatibleEndpoint = "{your Event Hubs compatible endpoint}";
  private static final String eventHubsCompatibleEndpoint = "sb://ihsuprodmares009dednamespace.servicebus.windows.net/";

  // az iot hub show --query properties.eventHubEndpoints.events.path --name {your IoT Hub name}
  //private static final String eventHubsCompatiblePath = "{your Event Hubs compatible name}";
  private static final String eventHubsCompatiblePath = "eventHubsCompatiblePathString";

  // az iot hub policy show --name iothubowner --query primaryKey --hub-name {your IoT Hub name}
  private static final String iotHubSasKey = "iotHubSasKeyString=";
  private static final String iotHubSasKeyName = "iothubowner";

  // Track all the PartitionReciever instances created.
  private static ArrayList<PartitionReceiver> receivers = new ArrayList<PartitionReceiver>();

  // Asynchronously create a PartitionReceiver for a partition and then start 
  // reading any messages sent from the simulated client.
  private static void receiveMessages(EventHubClient ehClient, String partitionId)
      throws EventHubException, ExecutionException, InterruptedException {

    final ExecutorService executorService = Executors.newSingleThreadExecutor();

    // Create the receiver using the default consumer group.
    // For the purposes of this sample, read only messages sent since 
    // the time the receiver is created. Typically, you don't want to skip any messages.
    ehClient.createReceiver(EventHubClient.DEFAULT_CONSUMER_GROUP_NAME, partitionId,
        EventPosition.fromEnqueuedTime(Instant.now())).thenAcceptAsync(receiver -> {
          System.out.println(String.format("Starting receive loop on partition: %s", partitionId));
          System.out.println(String.format("Reading messages sent since: %s", Instant.now().toString()));

          receivers.add(receiver);

          while (true) {
            try {
              // Check for EventData - this methods times out if there is nothing to retrieve.
              Iterable<EventData> receivedEvents = receiver.receiveSync(100);

              // If there is data in the batch, process it.
              if (receivedEvents != null) {
                for (EventData receivedEvent : receivedEvents) {
                  System.out.println(String.format("Telemetry received:\n %s",
                      new String(receivedEvent.getBytes(), Charset.defaultCharset())));
                  System.out.println(String.format("Application properties (set by device):\n%s",receivedEvent.getProperties().toString()));
                  System.out.println(String.format("System properties (set by IoT Hub):\n%s\n",receivedEvent.getSystemProperties().toString()));
                }
              }
            } catch (EventHubException e) {
              System.out.println("Error reading EventData");
            }
          }
        }, executorService);
  }

  public static void main(String[] args)
      throws EventHubException, ExecutionException, InterruptedException, IOException, URISyntaxException {

    final ConnectionStringBuilder connStr = new ConnectionStringBuilder()
        .setEndpoint(new URI(eventHubsCompatibleEndpoint))
        .setEventHubName(eventHubsCompatiblePath)
        .setSasKeyName(iotHubSasKeyName)
        .setSasKey(iotHubSasKey);

    // Create an EventHubClient instance to connect to the
    // IoT Hub Event Hubs-compatible endpoint.
    final ExecutorService executorService = Executors.newSingleThreadExecutor();
    final EventHubClient ehClient = EventHubClient.createSync(connStr.toString(), executorService);

    // Use the EventHubRunTimeInformation to find out how many partitions 
    // there are on the hub.
    final EventHubRuntimeInformation eventHubInfo = ehClient.getRuntimeInformation().get();

    // Create a PartitionReciever for each partition on the hub.
    for (String partitionId : eventHubInfo.getPartitionIds()) {
      receiveMessages(ehClient, partitionId);
    }

    // Shut down cleanly.
    System.out.println("Press ENTER to exit.");
    System.in.read();
    System.out.println("Shutting down...");
    for (PartitionReceiver receiver : receivers) {
      receiver.closeSync();
    }
    ehClient.closeSync();
    executorService.shutdown();
    System.exit(0);
  }
}

现在,即使两个发布者同时运行,我也试图弄清楚如何从发布者1接收消息。预先感谢。

0 个答案:

没有答案