static void printHelp() {
   System.out.format(
       "Argument error.\n"
           + " Call: ClientPublisher \n"
           + "[OPC Server string] - OPC server,e.g. [opc.tcp://server:51210/UA/SampleServer]\n"
           + "[Device connection string] - String containing Hostname, Device Id & Device Key in the following format: HostName=<iothub_host_name>;DeviceId=<device_id>;SharedAccessKey=<device_key>\n"
           + "[Protocol] - (https | amqps | mqtt | amqps_ws).\n");
   System.exit(1);
 }
  public static void main(String[] args) throws Exception {

    System.out.println("Starting ClientPublisher sample");

    if (args.length < 2 || args.length > 3) {
      printHelp();
      return;
    }

    String opcUrl = args[0];
    String connString = args[1];
    IotHubClientProtocol protocol = IotHubClientProtocol.AMQPS;
    if (args.length > 2) {
      String protocolStr = args[2].toLowerCase();
      if (protocolStr.equals("https")) {
        protocol = IotHubClientProtocol.HTTPS;
      } else if (protocolStr.equals("amqps")) {
        protocol = IotHubClientProtocol.AMQPS;
      } else if (protocolStr.equals("mqtt")) {
        protocol = IotHubClientProtocol.MQTT;
      } else if (protocolStr.equals("amqps_ws")) {
        protocol = IotHubClientProtocol.AMQPS_WS;
      } else {
        System.out.format("Protocol: %s not found, using AMQPS instead\n", protocolStr);
      }
    }

    System.out.format("OPC Server: %s\n", opcUrl);
    System.out.format("IoT Hub ConnectionString: %s\n", connString);
    System.out.format("Start communication using protocol %s.\n", protocol.name());

    //////////////  CLIENT  //////////////
    // Load Client's Application Instance Certificate from file
    KeyPair myClientApplicationInstanceCertificate = getOPCCert("ClientPublisher");
    // Create Client
    Client myClient = Client.createClientApplication(myClientApplicationInstanceCertificate);

    ////////// DISCOVER ENDPOINT /////////
    // Discover server's endpoints, and choose one
    String publicHostname = InetAddress.getLocalHost().getHostName();

    EndpointDescription[] endpoints = myClient.discoverEndpoints(opcUrl);
    // Filter out all but opc.tcp protocol endpoints
    if (opcUrl.startsWith("opc.tcp")) {
      endpoints = selectByProtocol(endpoints, "opc.tcp");
      // Filter out all but Signed & Encrypted endpoints
      endpoints = selectByMessageSecurityMode(endpoints, MessageSecurityMode.SignAndEncrypt);
      // Filter out all but Basic128 cryption endpoints
      endpoints = selectBySecurityPolicy(endpoints, SecurityPolicy.BASIC128RSA15);
      // Sort endpoints by security level. The lowest level at the
      // beginning, the highest at the end of the array
      endpoints = sortBySecurityLevel(endpoints);
    } else {
      // we don't have a valid https cert for now
      System.out.format("HTTPS protocol not suported.\n");
      System.exit(0);
      endpoints = selectByProtocol(endpoints, "https");
    }

    // Choose one endpoint
    EndpointDescription endpoint = endpoints[endpoints.length - 1];

    // fix connection issue on localhost
    if (endpoint.getEndpointUrl().contains(publicHostname)) {
      endpoint.setEndpointUrl(endpoint.getEndpointUrl().replace(publicHostname, "localhost"));
    } else {
      // fix .Net UA Server bug, patch localhost with hostname of server
      if (endpoint.getEndpointUrl().contains("localhost")) {
        URL opcURL = new URL(opcUrl.replace("opc.tcp", "http"));
        endpoint.setEndpointUrl(endpoint.getEndpointUrl().replace("localhost", opcURL.getHost()));
      }
    }

    ////////////////////// AZURE IotHub ////////////////////////////
    // connect to Azure IotHub with connection string and protocol
    // see http://www.github.com/Azure/azure-iot-sdks/java
    //
    DeviceClient client = new DeviceClient(connString, protocol);

    System.out.println("Successfully created an IoT Hub client.");

    if (protocol == IotHubClientProtocol.MQTT) {
      MessageCallbackMqtt callback = new MessageCallbackMqtt();
      Counter counter = new Counter(0);
      client.setMessageCallback(callback, counter);
    } else {
      MessageCallback callback = new MessageCallback();
      Counter counter = new Counter(0);
      client.setMessageCallback(callback, counter);
    }
    System.out.println("Successfully set message callback.");

    client.open();

    System.out.println("Opened connection to IoT Hub.");

    System.out.println("Beginning to receive messages...");

    ////////////  SESSION  ////////////
    // Create Session
    SessionChannel mySession = myClient.createSessionChannel(endpoint);
    mySession.activate();

    System.out.println("Opened session to OPC Server.");

    /////////////  EXECUTE  //////////////
    // Browse Root
    BrowseDescription browse = new BrowseDescription();
    browse.setNodeId(Identifiers.RootFolder);
    browse.setBrowseDirection(BrowseDirection.Forward);
    browse.setIncludeSubtypes(true);
    browse.setNodeClassMask(NodeClass.Object, NodeClass.Variable);
    browse.setResultMask(BrowseResultMask.All);
    BrowseResponse browseResponse = mySession.Browse(null, null, null, browse);
    System.out.println(browseResponse);

    /////////////  PUBLISH  /////////////
    // Poll OPC server and publish to Azure IotHub

    int count = 0;
    while (count++ < 100) {
      // Read current time
      NodeId nodeId = Identifiers.Server_ServerStatus_CurrentTime;
      ReadResponse opcCurrentTime =
          mySession.Read(
              null,
              500.0,
              TimestampsToReturn.Both,
              new ReadValueId(nodeId, Attributes.Value, null, null));

      // convert node to JSON
      JSONObject obj = new JSONObject();
      obj.put("Id", nodeId.toString());
      obj.put("Uri", endpoints[0].getServer().getApplicationUri());

      JSONObject value = new JSONObject();
      value.put("Value", opcCurrentTime.getResults()[0].getValue().toString());
      value.put("SourceTimestamp", opcCurrentTime.getResults()[0].getSourceTimestamp().toString());
      value.put("ServerTimestamp", opcCurrentTime.getResults()[0].getServerTimestamp().toString());

      JSONObject monitoredItem = new JSONObject();
      monitoredItem.put("MonitoredItem", obj);
      monitoredItem.put("ClientHandle", 2);
      monitoredItem.put("Value", value);

      // publish JSON string to IotHub
      String msgStr = monitoredItem.toString();
      try {
        Message msg = new Message(msgStr);
        msg.setProperty("messageCount", Integer.toString(count));
        msg.setExpiryTime(5000);
        System.out.println(msgStr);
        EventCallback eventCallback = new EventCallback();
        client.sendEventAsync(msg, eventCallback, count);
      } catch (Exception e) {
        e.printStackTrace();
      }

      try {
        System.out.println(opcCurrentTime);
        System.out.println(msgStr);
        Thread.sleep(2000);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    /////////////  SHUTDOWN  /////////////
    mySession.close();
    mySession.closeAsync();
    //////////////////////////////////////

    client.close();

    //////////////////////////////////////
    System.exit(0);
  }