Files
Simulation/Assets/Generic Client/GenericClient.Logic.cs
2025-05-27 10:13:49 +09:00

232 lines
9.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Best.HTTP.Shared.PlatformSupport.Memory;
using Best.MQTT;
using Best.MQTT.Examples;
using Best.MQTT.Examples.Helpers;
using Best.MQTT.Packets;
using Best.MQTT.Packets.Builders;
using UnityEngine;
namespace Best.MQTT.Examples
{
public partial class GenericClient
{
private MQTTClient client;
// UI instances of SubscriptionListItem
private List<SubscriptionListItem> subscriptionListItems = new List<SubscriptionListItem>();
public void OnConnectButton()
{
#if UNITY_WEBGL && !UNITY_EDITOR
if (this.transportDropdown.value == 0)
{
AddText("<color=red>TCP transport isn't available under WebGL!</color>");
return;
}
#endif
SetConnectingUI();
var host = this.hostInput.GetValue("broker.mqttdashboard.com");
AddText($"[{host}] Connecting with client id: <color=green>{SessionHelper.Get(host).ClientId}</color>");
var options = new ConnectionOptions();
options.Host = host;
options.Port = this.portInput.GetIntValue(1883);
options.Transport = (SupportedTransports)this.transportDropdown.value;
options.UseTLS = this.isSecureToggle.GetBoolValue();
options.Path = this.pathInput.GetValue("/mqtt");
options.ProtocolVersion = (SupportedProtocolVersions)this.protocolVersionDropdown.value;
this.client = new MQTTClient(options);
this.client.OnConnected += OnConnected;
this.client.OnError += OnError;
this.client.OnDisconnect += OnDisconnected;
this.client.OnStateChanged += OnStateChanged;
this.client.BeginConnect(ConnectPacketBuilderCallback);
}
private void OnConnected(MQTTClient client)
{
SetConnectedUI();
}
private void OnDisconnected(MQTTClient client, DisconnectReasonCodes code, string reason)
{
SetDisconnectedUI();
AddText($"[{client.Options.Host}] OnDisconnected - code: <color=blue>{code}</color>, reason: <color=red>{reason}</color>");
}
private void OnError(MQTTClient client, string reason)
{
AddText($"[{client.Options.Host}] OnError reason: <color=red>{reason}</color>");
}
public void OnDisconnectButton()
{
this.connectButton.interactable = false;
this.client?.CreateDisconnectPacketBuilder().BeginDisconnect();
}
private void OnStateChanged(MQTTClient client, ClientStates oldState, ClientStates newState)
{
AddText($"[{client.Options.Host}] <color=yellow>{oldState}</color> => <color=green>{newState}</color>");
}
private ConnectPacketBuilder ConnectPacketBuilderCallback(MQTTClient client, ConnectPacketBuilder builder)
{
AddText($"[{client.Options.Host}] Creating connect packet.");
var userName = this.userNameInput.GetValue(null);
var password = this.passwordInput.GetValue(null);
var session = SessionHelper.HasAny(client.Options.Host) ? SessionHelper.Get(client.Options.Host) : SessionHelper.CreateNullSession(client.Options.Host);
builder.WithSession(session);
if (!string.IsNullOrEmpty(userName))
builder.WithUserName(userName);
if (!string.IsNullOrEmpty(password))
builder.WithPassword(password);
builder.WithKeepAlive((ushort)this.keepAliveInput.GetIntValue(60));
// setup last-will
var lastWillTopic = this.lastWill_TopicInput.GetValue(null);
var lastWillMessage = this.lastWill_MessageInput.GetValue(null);
var retain = this.lastWill_RetainToggle.GetBoolValue();
if (!string.IsNullOrEmpty(lastWillTopic) && !string.IsNullOrEmpty(lastWillMessage))
builder.WithLastWill(new LastWillBuilder()
.WithTopic(lastWillTopic)
.WithContentType("text/utf-8")
.WithPayload(Encoding.UTF8.GetBytes(lastWillMessage))
.WithQoS(this.lastWill_QoSDropdown.GetQoS())
.WithRetain(retain));
return builder;
}
public void OnPublishButtonClicked()
{
string topic = this.publish_TopicInput.GetValue("best_mqtt/test");
QoSLevels qos = this.publish_QoSDropdown.GetQoS();
bool retain = this.publish_RetainToggle.GetBoolValue();
string message = this.publish_MessageInput.GetValue("Hello MQTT World...");
this.client.CreateApplicationMessageBuilder(topic)
.WithQoS(qos)
.WithRetain(retain)
.WithPayload(message)
.BeginPublish();
}
public void OnSubscribeButtonClicked()
{
var colorValue = this.subscribe_ColorInput.GetValue("000000");
if (!ColorUtility.TryParseHtmlString("#" + colorValue, out var color))
{
AddText($"[{client.Options.Host}] <color=red>Couldn't parse '#{colorValue}'</color>");
return;
}
var qos = this.subscribe_QoSDropdown.GetQoS();
var topic = this.subscribe_TopicInput.GetValue("best_mqtt/#");
this.client?.CreateBulkSubscriptionBuilder()
.WithTopic(new SubscribeTopicBuilder(topic)
.WithMaximumQoS(qos)
.WithAcknowledgementCallback(OnSubscriptionAcknowledgement)
.WithMessageCallback(OnApplicationMessage))
.BeginSubscribe();
AddText($"[{client.Options.Host}] Subscribe request for topic <color=#{colorValue}>{topic}</color> sent...");
AddSubscriptionUI(topic, colorValue);
}
private void OnSubscriptionAcknowledgement(MQTTClient client, SubscriptionTopic topic, SubscribeAckReasonCodes reasonCode)
{
var subscription = FindSubscriptionItem(topic.Filter.OriginalFilter);
string reasonColor = reasonCode <= SubscribeAckReasonCodes.GrantedQoS2 ? "green" : "red";
AddText($"[{client.Options.Host}] Subscription request to topic <color=#{subscription.Color}>{topic.Filter.OriginalFilter}</color> returned with reason code: <color={reasonColor}>{reasonCode}</color>");
}
private void AddSubscriptionUI(string topic, string color)
{
var item = Instantiate<SubscriptionListItem>(this.subscription_ListItem, this.subscribe_ListItemRoot);
item.Set(this, topic, color);
this.subscriptionListItems.Add(item);
}
public void Unsubscribe(string topic)
{
this.client.CreateUnsubscribePacketBuilder(topic)
.WithAcknowledgementCallback(OnUnsubscribed)
.BeginUnsubscribe();
var subscription = FindSubscriptionItem(topic);
AddText($"[{client.Options.Host}] Unsubscribe request for topic <color=#{subscription.Color}>{topic}</color> sent...");
}
private void OnUnsubscribed(MQTTClient client, string topic, Best.MQTT.Packets.UnsubscribeAckReasonCodes reason)
{
var instance = this.subscriptionListItems.FirstOrDefault(s => s.Topic.OriginalFilter == topic);
this.subscriptionListItems.Remove(instance);
Destroy(instance.gameObject);
string reasonColor = reason == UnsubscribeAckReasonCodes.Success ? "green" : "red";
AddText($"[{client.Options.Host}] Unsubscription request to topic <color=#{instance.Color}>{topic}</color> returned with reason code: <color={reasonColor}>{reason}</color>");
}
private void OnApplicationMessage(MQTTClient client, SubscriptionTopic topic, string topicName, ApplicationMessage applicationMessage)
{
// find matching subscription for its color
var subscription = FindSubscriptionItem(topicName);
string payload = string.Empty;
// Here we going to try to convert the payload as an UTF-8 string. Note that it's not guaranteed that the payload is a string!
// While MQTT supports an additional Content-Type field in this demo we can't rely on its presense.
if (applicationMessage.Payload != BufferSegment.Empty)
{
payload = Encoding.UTF8.GetString(applicationMessage.Payload.Data, applicationMessage.Payload.Offset, applicationMessage.Payload.Count);
const int MaxPayloadLength = 512;
if (payload.Length > MaxPayloadLength)
payload = payload?.Remove(MaxPayloadLength);
}
// Display the Content-Type if present
string contentType = string.Empty;
if (applicationMessage.ContentType != null)
contentType = $" ({applicationMessage.ContentType}) ";
// Add the final text to the demo's log view.
AddText($"[{client.Options.Host}] <color=#{subscription.Color}>[{topicName}] {contentType}{payload}</color>");
}
private SubscriptionListItem FindSubscriptionItem(string topicName) => this.subscriptionListItems.FirstOrDefault(s => s.Topic.IsMatching(topicName));
private void OnDestroy()
{
this.client?.CreateDisconnectPacketBuilder().BeginDisconnect();
}
}
}