<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Skye HAN</title>
    <description>The latest articles on DEV Community by Skye HAN (@skyehan).</description>
    <link>https://dev.to/skyehan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F914365%2F5dbabe12-9b2c-4812-9761-28942e61414e.jpeg</url>
      <title>DEV Community: Skye HAN</title>
      <link>https://dev.to/skyehan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/skyehan"/>
    <language>en</language>
    <item>
      <title>Use JAVA to connect Azure Web Pub Sub Service to make a simple MQ Demo</title>
      <dc:creator>Skye HAN</dc:creator>
      <pubDate>Wed, 24 Aug 2022 04:12:00 +0000</pubDate>
      <link>https://dev.to/skyehan/azure-web-pub-sub-java-l1h</link>
      <guid>https://dev.to/skyehan/azure-web-pub-sub-java-l1h</guid>
      <description>&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;p&gt;Develop web applications with real-time messaging using Azure Web PubSub, a fully managed service that supports native and serverless WebSockets. Use the publish-subscribe messaging pattern to create loosely coupled, scalable applications - including chat, live streaming, and IoT dashboards. Developers can focus on functionality while Web PubSub manages the flow of data and content to your web pages and mobile applications.&lt;/p&gt;

&lt;h1&gt;
  
  
  concept
&lt;/h1&gt;

&lt;h2&gt;
  
  
  connect
&lt;/h2&gt;

&lt;p&gt;A connection, also known as a client or client connection, represents a single WebSocket connection to a Web PubSub service. After a successful connection, the Web PubSub service assigns a unique connection ID to the connection.&lt;/p&gt;

&lt;h2&gt;
  
  
  hub
&lt;/h2&gt;

&lt;p&gt;A hub is a logical concept for a set of client connections. Usually you use a hub for one purpose, for example, a chat hub or a notification hub. When a client connects, it connects to a hub, and for the life of its life, it belongs to that hub. Once a client connects to the hub, the hub exists. Different applications can share an Azure Web PubSub service using different hub names.&lt;/p&gt;

&lt;h2&gt;
  
  
  Group
&lt;/h2&gt;

&lt;p&gt;A group is a subset of connections to a hub. You can add client connections to or remove client connections from a group at any time. For example, when a customer joins a chat room, or when a customer leaves the chat room, the chat room can be considered a group. A client can join multiple groups, and a group can contain multiple clients. A group is like a group "conversation", a group conversation is created once someone joins the group, and the conversation disappears when there is no one in the group.&lt;/p&gt;

&lt;h2&gt;
  
  
  user
&lt;/h2&gt;

&lt;p&gt;A connection to Web PubSub can belong to a user. A user may have multiple connections, such as when a user connects across multiple devices or multiple browser tabs.&lt;/p&gt;

&lt;h2&gt;
  
  
  message
&lt;/h2&gt;

&lt;p&gt;When a client connects, it can send messages to, or receive messages from, upstream applications over the WebSocket connection.&lt;/p&gt;

&lt;h1&gt;
  
  
  work process
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;The client connects to the service/client endpoint using the WebSocket transport. The service forwards each WebSocket frame to the configured upstream (server). WebSocket connections can connect with any custom subprotocol for server processing, or with the subprotocol json.webpubsub.azure.v1 supported by the service, which enables clients to pub/sub directly. Details are described in Client Protocol.&lt;/li&gt;
&lt;li&gt;The service calls the server using the CloudEvents HTTP protocol on different client events. CloudEvents is a standardized, protocol-agnostic definition of the structure and metadata description of events hosted by the Cloud Native Computing Foundation (CNCF). Details are described in the server protocol.&lt;/li&gt;
&lt;li&gt;The server can use the REST API to call services to send messages to clients or manage connected clients. Details are described in the server protocol&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Create a web pub sub service
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Connect to webPubSubServiceClient
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Import maven
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;com.azure&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;azure-messaging-webpubsub&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.1.4&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Get connectionString from Azure and determine Hub
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WebPubSubServiceClient webPubSubServiceClient = new WebPubSubServiceClientBuilder()
        .connectionString(" ")
        .hub(" ")
        .buildClient();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Connect to webSocket
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create token
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GetClientAccessTokenOptions getClientAccessTokenOptions = new GetClientAccessTokenOptions();
getClientAccessTokenOptions.addRole("webpubsub.sendToGroup");
getClientAccessTokenOptions.addRole("webpubsub.joinLeaveGroup");
WebPubSubClientAccessToken token = webPubSubServiceClient.getClientAccessToken(getClientAccessTokenOptions);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a WebSocket and determine the data transfer protocol used
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String url = token.getUrl();
ws = HttpClient.newHttpClient().newWebSocketBuilder().subprotocols("json.webpubsub.azure.v1")
        .buildAsync(URI.create(url), new WebSocketClient()).join();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Implement WebSocket message listener (depending on the WebSocket used, the implementation method is also different)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private static final class WebSocketClient implements WebSocket.Listener {
    private WebSocketClient() {
    }

    @Override
    public void onOpen(WebSocket webSocket) {
        log.info("subscriber open");
        WebSocket.Listener.super.onOpen(webSocket);
    }

    @Override
    public CompletionStage&amp;lt;?&amp;gt; onText(WebSocket webSocket, CharSequence data, boolean last) {
        log.info("Message received:{}", data);
        return WebSocket.Listener.super.onText(webSocket, data, last);
    }

    @Override
    public void onError(WebSocket webSocket, Throwable error) {
        System.out.println("Bad day! " + webSocket.toString());
        WebSocket.Listener.super.onError(webSocket, error);
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Information
&lt;/h2&gt;

&lt;h3&gt;
  
  
  AckId
&lt;/h3&gt;

&lt;p&gt;When using ackId, you can receive an acknowledgment response message when your request is processed. You can choose to omit the ackId in fire-and-forget scenarios.&lt;br&gt;
The Web PubSub service will send an ack response for each request with an ackId.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class AckResponseMessage {
    private String type;
    private String ackId;
    private boolean success;
    private Error error;

    public static class Error{
        private String name;
        private String message;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Send to group
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class SendGroupMessage {
    public final String type = "sendToGroup";
    public String data;
    public int ackId;
    public String group;
    public boolean noEcho;
    public DataType dataType;

    public SendGroupMessage(String data, int ackId, String group, boolean noEcho, DataType dataType) {
        this.data = data;
        this.ackId = ackId;
        this.group = group;
        this.noEcho = noEcho;
        this.dataType = dataType;
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Join a group
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class JoinGroupMessage {
    public int ackId;
    public final String type = "joinGroup";
    public String group;

    public JoinGroupMessage(int ackId, String group){
        this.ackId = ackId;
        this.group = group;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Leave a Group
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class LeaveGroupMessage {
    public int ackId;
    public final String type = "leaveGroup";
    public String group;

    public LeaveGroupMessage(int ackId, String group){
        this.ackId = ackId;
        this.group = group;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Receiving messages from groups
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ReceivedGroupMessage {
    private String type;
    private String from;
    private String fromUserId;
    private String group;
    private DataType dataType;
    private String data;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Receiving a message from the server
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ReceivedServerMessage {
    private String type;
    private String from;
    private DataType dataType;
    private String data;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  System response
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ConnectedSystemMessage {
    private String type;
    private String event;
    private String userId;
    private String connectionId;
}

public class DisConnectedSystemMessage {
     private String type;
     private String event;
     private String message;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Publish and subscribe
&lt;/h3&gt;

&lt;p&gt;Publish&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void sendToGroup(String data,String group) {
     ++ackId;
     GroupMessage groupMessage = new GroupMessage(data, ackId, group);
     String string = null;
     try {
         string = objectMapper.writeValueAsString(groupMessage);
     } catch (JsonProcessingException e) {
         e.printStackTrace();
     }
     ws.sendText(string,true);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Subscribe&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Override
public CompletionStage&amp;lt;?&amp;gt; onText(WebSocket webSocket, CharSequence data, boolean last) {
     try {
         String message = String.valueOf(data);
         handleData(message);
     } catch (Exception e) {
         log.warn("e:{}", e.getMessage());
     }
     return WebSocket.Listener.super.onText(webSocket, data, last);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>java</category>
      <category>azure</category>
      <category>pubsub</category>
    </item>
    <item>
      <title>Common services and methods of openTCS</title>
      <dc:creator>Skye HAN</dc:creator>
      <pubDate>Wed, 24 Aug 2022 03:14:21 +0000</pubDate>
      <link>https://dev.to/skyehan/common-services-and-methods-of-opentcs-4jld</link>
      <guid>https://dev.to/skyehan/common-services-and-methods-of-opentcs-4jld</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;openTCS is a vendor-independent and flexibly usable control system software for automated guided vehicle systems (AGVS) and other non-continuous conveyors like electric monorail conveyors and mobile assembly platforms. It was originally developed during a publicly funded project. Now the code base is being maintained and development continued by Fraunhofer Institute for Material Flow and Logistics (IML) in Dortmund, Germany.&lt;/p&gt;

&lt;h1&gt;
  
  
  Services and methods
&lt;/h1&gt;

&lt;h2&gt;
  
  
  plantModelService
&lt;/h2&gt;

&lt;p&gt;Create model, get model information, etc.&lt;br&gt;
Create a new model&lt;br&gt;
plantModelService.createPlantModel();&lt;br&gt;
Get model properties, such as modification time&lt;br&gt;
plantModelService.getModelProperties();&lt;br&gt;
get model name&lt;br&gt;
plantModelService.getModelName();&lt;br&gt;
Get the elements on the model: point, car, order, etc.&lt;br&gt;
plantModelService.fetchObjects();&lt;/p&gt;

&lt;h2&gt;
  
  
  transportOrderService
&lt;/h2&gt;

&lt;p&gt;After the order is created, the initial status of the order is RAW&lt;br&gt;
Create Order&lt;br&gt;
transportOrderService.createTransportOrder();&lt;br&gt;
Create order sequence&lt;br&gt;
transportOrderService.createOrderSequence();&lt;br&gt;
Mark order sequence complete&lt;br&gt;
transportOrderService.markOrderSequenceComplete();&lt;/p&gt;

&lt;p&gt;After the order is created, set the properties, such as the expected execution trolley, deadline, etc. Order status changed to ACTIVE&lt;/p&gt;

&lt;h2&gt;
  
  
  routerService
&lt;/h2&gt;

&lt;p&gt;The router checks whether each destination can be reached, and can modify the order status to dispatchable. If not, change the order status to UNrouteable&lt;br&gt;
routerService.updatePathLock();&lt;br&gt;
routerService.updateRoutingTopology();&lt;/p&gt;

&lt;h2&gt;
  
  
  dispatcherService
&lt;/h2&gt;

&lt;p&gt;The dispatcher assigns the trolley to execute the corresponding order, and when the trolley starts to execute, it changes the order status to be processed&lt;br&gt;
Allocate orders&lt;br&gt;
dispatcherService.dispatch();&lt;br&gt;
Cancellation by car&lt;br&gt;
dispatcherService.withdrawByVehicle();&lt;br&gt;
Cancellation by order&lt;br&gt;
dispatcherService.withdrawByTransportOrder();&lt;/p&gt;

&lt;h2&gt;
  
  
  vehicleService
&lt;/h2&gt;

&lt;p&gt;Services for trolleys, mainly including communication adapters&lt;br&gt;
Update cart integration&lt;br&gt;
vehicleService.updateVehicleIntegrationLevel();&lt;br&gt;
get processModel&lt;br&gt;
vehicleService.fetchProcessModel();&lt;br&gt;
vehicleService.sendCommAdapterCommand();&lt;br&gt;
vehicleService.attachCommAdapter();&lt;br&gt;
vehicleService.disableCommAdapter();&lt;br&gt;
vehicleService.enableCommAdapter();&lt;br&gt;
vehicleService.fetchAttachmentInformation();&lt;br&gt;
vehicleService.updateVehicleAllowedOrderTypes();&lt;br&gt;
vehicleService.sendCommAdapterMessage();&lt;/p&gt;

&lt;h2&gt;
  
  
  schedulerService
&lt;/h2&gt;

&lt;p&gt;schedule&lt;br&gt;
schedulerService.fetchSchedulerAllocations()&lt;/p&gt;

&lt;h2&gt;
  
  
  notificationService
&lt;/h2&gt;

&lt;p&gt;Notice&lt;br&gt;
notificationService.fetchUserNotifications();&lt;br&gt;
notificationService.publishUserNotification();&lt;/p&gt;

</description>
      <category>opentcs</category>
      <category>java</category>
    </item>
  </channel>
</rss>
