diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.ts
index 7c96131fef..7dd934ccd9 100644
--- a/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.ts
+++ b/ui-ngx/src/app/modules/home/components/rule-node/external/azure-iot-hub-config.component.ts
@@ -53,6 +53,7 @@ export class AzureIotHubConfigComponent extends RuleNodeConfigurationComponent {
clientId: [configuration ? configuration.clientId : null, [Validators.required]],
cleanSession: [configuration ? configuration.cleanSession : false, []],
ssl: [configuration ? configuration.ssl : false, []],
+ protocolVersion: [configuration ? configuration.protocolVersion : null, []],
credentials: this.fb.group(
{
type: [configuration && configuration.credentials ? configuration.credentials.type : null, [Validators.required]],
diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html
index 090fea41f3..60adadd6bb 100644
--- a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html
+++ b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html
@@ -72,6 +72,7 @@
{{ 'rule-node-config.parse-to-plain-text' | translate }}
{{ "rule-node-config.parse-to-plain-text-hint" | translate }}
+
{{ 'rule-node-config.clean-session' | translate }}
diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts
index 00a95e5ce6..08c8e284a9 100644
--- a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts
+++ b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts
@@ -52,6 +52,7 @@ export class MqttConfigComponent extends RuleNodeConfigurationComponent {
cleanSession: [configuration ? configuration.cleanSession : false, []],
retainedMessage: [configuration ? configuration.retainedMessage : false, []],
ssl: [configuration ? configuration.ssl : false, []],
+ protocolVersion: [configuration ? configuration.protocolVersion : null, []],
credentials: [configuration ? configuration.credentials : null, []]
});
}
diff --git a/ui-ngx/src/app/shared/components/mqtt-version-select.component.html b/ui-ngx/src/app/shared/components/mqtt-version-select.component.html
new file mode 100644
index 0000000000..81029a3445
--- /dev/null
+++ b/ui-ngx/src/app/shared/components/mqtt-version-select.component.html
@@ -0,0 +1,30 @@
+
+
+ device-profile.mqtt-protocol-version
+
+ @for (version of mqttVersions; track version) {
+
+ {{ mqttVersionTranslation.get(version) }}
+
+ }
+
+
diff --git a/ui-ngx/src/app/shared/components/mqtt-version-select.component.ts b/ui-ngx/src/app/shared/components/mqtt-version-select.component.ts
new file mode 100644
index 0000000000..6bde856a7b
--- /dev/null
+++ b/ui-ngx/src/app/shared/components/mqtt-version-select.component.ts
@@ -0,0 +1,79 @@
+///
+/// Copyright © 2016-2025 The Thingsboard Authors
+///
+/// Licensed under the Apache License, Version 2.0 (the "License");
+/// you may not use this file except in compliance with the License.
+/// You may obtain a copy of the License at
+///
+/// http://www.apache.org/licenses/LICENSE-2.0
+///
+/// Unless required by applicable law or agreed to in writing, software
+/// distributed under the License is distributed on an "AS IS" BASIS,
+/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+/// See the License for the specific language governing permissions and
+/// limitations under the License.
+///
+
+import { Component, forwardRef, Input } from '@angular/core';
+import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
+import { coerceBoolean } from '@shared/decorators/coercion';
+import { SubscriptSizing, MatFormFieldAppearance } from '@angular/material/form-field';
+import { MqttVersionTranslation, MqttVersion } from '@shared/models/mqtt.models';
+
+@Component({
+ selector: 'tb-mqtt-version-select',
+ templateUrl: './mqtt-version-select.component.html',
+ styleUrls: [],
+ providers: [{
+ provide: NG_VALUE_ACCESSOR,
+ useExisting: forwardRef(() => MqttVersionSelectComponent),
+ multi: true
+ }]
+})
+export class MqttVersionSelectComponent implements ControlValueAccessor {
+
+ @Input()
+ disabled: boolean;
+
+ @Input()
+ subscriptSizing: SubscriptSizing = 'dynamic';
+
+ @Input()
+ appearance: MatFormFieldAppearance = 'fill';
+
+ mqttVersions = Object.values(MqttVersion);
+ mqttVersionTranslation = MqttVersionTranslation;
+ modelValue: MqttVersion;
+
+ @Input()
+ @coerceBoolean()
+ required = false;
+
+ private propagateChange = (v: any) => { };
+
+ constructor() {
+ }
+
+ registerOnChange(fn: any): void {
+ this.propagateChange = fn;
+ }
+
+ registerOnTouched(fn: any): void {
+ }
+
+ setDisabledState(isDisabled: boolean): void {
+ this.disabled = isDisabled;
+ }
+
+ writeValue(value: MqttVersion | null): void {
+ this.modelValue = value;
+ }
+
+ mqttVersionChanged() {
+ this.updateView();
+ }
+
+ private updateView() {
+ this.propagateChange(this.modelValue);
+ }
+}
diff --git a/ui-ngx/src/app/shared/models/mqtt.models.ts b/ui-ngx/src/app/shared/models/mqtt.models.ts
new file mode 100644
index 0000000000..2bd40f3681
--- /dev/null
+++ b/ui-ngx/src/app/shared/models/mqtt.models.ts
@@ -0,0 +1,29 @@
+///
+/// Copyright © 2016-2025 The Thingsboard Authors
+///
+/// Licensed under the Apache License, Version 2.0 (the "License");
+/// you may not use this file except in compliance with the License.
+/// You may obtain a copy of the License at
+///
+/// http://www.apache.org/licenses/LICENSE-2.0
+///
+/// Unless required by applicable law or agreed to in writing, software
+/// distributed under the License is distributed on an "AS IS" BASIS,
+/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+/// See the License for the specific language governing permissions and
+/// limitations under the License.
+///
+
+export enum MqttVersion {
+ MQTT_3_1 = 'MQTT_3_1',
+ MQTT_3_1_1 = 'MQTT_3_1_1',
+ MQTT_5 = 'MQTT_5'
+}
+
+export const DEFAULT_MQTT_VERSION = MqttVersion.MQTT_3_1_1;
+
+export const MqttVersionTranslation = new Map([
+ [MqttVersion.MQTT_3_1, 'MQTT 3.1'],
+ [MqttVersion.MQTT_3_1_1, 'MQTT 3.1.1'],
+ [MqttVersion.MQTT_5, 'MQTT 5.0']
+]);
diff --git a/ui-ngx/src/app/shared/shared.module.ts b/ui-ngx/src/app/shared/shared.module.ts
index 47a65631db..ec7219d78a 100644
--- a/ui-ngx/src/app/shared/shared.module.ts
+++ b/ui-ngx/src/app/shared/shared.module.ts
@@ -227,6 +227,7 @@ import { JsFuncModulesComponent } from '@shared/components/js-func-modules.compo
import { JsFuncModuleRowComponent } from '@shared/components/js-func-module-row.component';
import { EntityKeyAutocompleteComponent } from '@shared/components/entity/entity-key-autocomplete.component';
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
+import { MqttVersionSelectComponent } from '@shared/components/mqtt-version-select.component';
export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) {
return markedOptionsService;
@@ -439,6 +440,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
HexInputComponent,
ScadaSymbolInputComponent,
EntityKeyAutocompleteComponent,
+ MqttVersionSelectComponent,
],
imports: [
CommonModule,
@@ -702,6 +704,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
WidgetButtonComponent,
ScadaSymbolInputComponent,
EntityKeyAutocompleteComponent,
+ MqttVersionSelectComponent,
]
})
export class SharedModule { }
diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json
index e02095d6c3..cdc8fac5fe 100644
--- a/ui-ngx/src/assets/locale/locale.constant-en_US.json
+++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json
@@ -1919,6 +1919,7 @@
"mqtt-use-json-format-for-default-downlink-topics-hint": "When enabled, the platform will use Json payload format to push attributes and RPC via the following topics: v1/devices/me/attributes/response/$request_id, v1/devices/me/attributes, v1/devices/me/rpc/request/$request_id, v1/devices/me/rpc/response/$request_id. This setting does not impact attribute and rpc subscriptions sent using new (v2) topics: v2/a/res/$request_id, v2/a, v2/r/req/$request_id, v2/r/res/$request_id. Where $request_id is an integer request identifier.",
"mqtt-send-ack-on-validation-exception": "Send PUBACK on PUBLISH message validation failure",
"mqtt-send-ack-on-validation-exception-hint": "By default, the platform will close the MQTT session on message validation failure. When enabled, the platform will send publish acknowledgment instead of closing the session.",
+ "mqtt-protocol-version": "Protocol version",
"snmp-add-mapping": "Add SNMP mapping",
"snmp-mapping-not-configured": "No mapping for OID to time series/telemetry configured",
"snmp-timseries-or-attribute-name": "Time series/attribute name for mapping",