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 subscriptionListItems = new List(); public void OnConnectButton() { #if UNITY_WEBGL && !UNITY_EDITOR if (this.transportDropdown.value == 0) { AddText("TCP transport isn't available under WebGL!"); return; } #endif SetConnectingUI(); var host = this.hostInput.GetValue("broker.mqttdashboard.com"); AddText($"[{host}] Connecting with client id: {SessionHelper.Get(host).ClientId}"); 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: {code}, reason: {reason}"); } private void OnError(MQTTClient client, string reason) { AddText($"[{client.Options.Host}] OnError reason: {reason}"); } public void OnDisconnectButton() { this.connectButton.interactable = false; this.client?.CreateDisconnectPacketBuilder().BeginDisconnect(); } private void OnStateChanged(MQTTClient client, ClientStates oldState, ClientStates newState) { AddText($"[{client.Options.Host}] {oldState} => {newState}"); } 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}] Couldn't parse '#{colorValue}'"); 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 {topic} 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 {topic.Filter.OriginalFilter} returned with reason code: {reasonCode}"); } private void AddSubscriptionUI(string topic, string color) { var item = Instantiate(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 {topic} 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 {topic} returned with reason code: {reason}"); } 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}] [{topicName}] {contentType}{payload}"); } private SubscriptionListItem FindSubscriptionItem(string topicName) => this.subscriptionListItems.FirstOrDefault(s => s.Topic.IsMatching(topicName)); private void OnDestroy() { this.client?.CreateDisconnectPacketBuilder().BeginDisconnect(); } } }