diff --git a/src/app/applications/bulk-import/bulk-import.component.ts b/src/app/applications/bulk-import/bulk-import.component.ts index c39bf3f54..1fbebd7bb 100644 --- a/src/app/applications/bulk-import/bulk-import.component.ts +++ b/src/app/applications/bulk-import/bulk-import.component.ts @@ -9,7 +9,6 @@ import { import { IoTDeviceService } from '@applications/iot-devices/iot-device.service'; import { faDownload, faTrash } from '@fortawesome/free-solid-svg-icons'; import { TranslateService } from '@ngx-translate/core'; -import { OrganizationAccessScope } from '@shared/enums/access-scopes'; import { ErrorMessageService } from '@shared/error-message.service'; import { splitList } from '@shared/helpers/array.helper'; import { Download } from '@shared/helpers/download.helper'; @@ -20,7 +19,7 @@ import { Papa } from 'ngx-papaparse'; import { Observable, Subject } from 'rxjs'; import { takeWhile } from 'rxjs/operators'; import { BulkImport } from './bulk-import.model'; -import { BulkMapping } from './bulkMapping'; +import { BulkMapping } from './bulk-mapping'; @Component({ selector: 'app-bulk-import', @@ -54,6 +53,14 @@ export class BulkImportComponent implements OnInit { name: 'lorawan-abp-sample.csv', url: '../../../assets/docs/iotdevice_lorawan_abp.csv', }, + { + name: 'mqtt-internal-broker-sample.csv', + url: '../../../assets/docs/mqtt_internal_broker_sample.csv', + }, + { + name: 'mqtt-external-broker-sample.csv', + url: '../../../assets/docs/mqtt_external_broker_sample.csv', + }, ]; download$: Observable; private bulkMapper = new BulkMapping(); diff --git a/src/app/applications/bulk-import/bulk-mapping.ts b/src/app/applications/bulk-import/bulk-mapping.ts new file mode 100644 index 000000000..1913265d0 --- /dev/null +++ b/src/app/applications/bulk-import/bulk-mapping.ts @@ -0,0 +1,131 @@ +import { IotDevice } from '@applications/iot-devices/iot-device.model'; +import { DeviceType } from '@shared/enums/device-type'; +import { Buffer } from 'buffer'; + +export class BulkMapping { + public dataMapper(data: IotDevice, applicationId: number): IotDevice { + switch (data.type.toUpperCase()) { + case DeviceType.LORAWAN: + return this.lorawanMapper(data, applicationId); + case DeviceType.MQTT_INTERNAL_BROKER: + return this.mqttInternalBrokerMapper(data, applicationId); + case DeviceType.MQTT_EXTERNAL_BROKER: + return this.mqttExternalBrokerMapper(data, applicationId); + case DeviceType.GENERIC_HTTP: + return this.baseMapper(data, applicationId); + default: + break; + } + } + + private lorawanMapper(data: any, applicationId): IotDevice { + const newDevice = this.baseMapper(data, applicationId); + newDevice.lorawanSettings = { + devEUI: data.devEUI, + skipFCntCheck: data.skipFCntCheck + ? this.convertToBoolean(data.skipFCntCheck) + : undefined, + activationType: data.activationType ? data.activationType : undefined, + OTAAapplicationKey: data.OTAAapplicationKey + ? data.OTAAapplicationKey + : undefined, + devAddr: data.devAddr ? data.devAddr : undefined, + networkSessionKey: data.networkSessionKey + ? data.networkSessionKey + : undefined, + applicationSessionKey: data.applicationSessionKey + ? data.applicationSessionKey + : undefined, + serviceProfileID: data.serviceProfileID + ? data.serviceProfileID + : undefined, + deviceProfileID: data.deviceProfileID ? data.deviceProfileID : undefined, + fCntUp: data.fCntUp ? +data.fCntUp : undefined, + nFCntDown: data.nFCntDown ? +data.nFCntDown : undefined, + deviceStatusBattery: undefined, + deviceStatusMargin: undefined, + }; + newDevice.type = DeviceType.LORAWAN; + return newDevice; + } + + private mqttInternalBrokerMapper(data: any, applicationId: number) { + const newDevice = this.baseMapper(data, applicationId); + newDevice.mqttInternalBrokerSettings = { + authenticationType: data.authenticationType, + caCertificate: undefined, + deviceCertificate: undefined, + deviceCertificateKey: undefined, + mqttPort: undefined, + mqttURL: undefined, + mqtttopicname: undefined, + mqttusername: data.mqttusername, + mqttpassword: data.mqttpassword, + }; + newDevice.type = DeviceType.MQTT_INTERNAL_BROKER; + return newDevice; + } + + private mqttExternalBrokerMapper(data: any, applicationId: number) { + const newDevice = this.baseMapper(data, applicationId); + newDevice.mqttExternalBrokerSettings = { + authenticationType: data.authenticationType, + caCertificate: this.base64Decode(data.caCertificate), + deviceCertificate: this.base64Decode(data.deviceCertificate), + deviceCertificateKey: this.base64Decode(data.deviceCertificateKey), + mqttPort: data.mqttPort ? Number(data.mqttPort) : undefined, + mqttURL: data.mqttURL, + mqtttopicname: data.mqtttopicname, + mqttpassword: data.mqttpassword, + mqttusername: data.mqttusername, + invalidMqttConfig: data.invalidMqttConfig, + }; + newDevice.type = DeviceType.MQTT_EXTERNAL_BROKER; + return newDevice; + } + + private base64Decode(input: string) { + if (!input) { + return undefined; + } + return Buffer.from(input, 'base64').toString('binary'); + } + + private convertToBoolean(text: string): boolean { + if (text.toUpperCase() === 'TRUE') { + return true; + } else { + return false; + } + } + + private baseMapper(data: any, applicationId: number): IotDevice { + return { + name: data.name, + application: undefined, + location: undefined, + commentOnLocation: data.commentOnLocation, + comment: data.comment, + type: DeviceType.GENERIC_HTTP, + receivedMessagesMetadata: undefined, + metadata: undefined, + apiKey: undefined, + id: undefined, + createdAt: undefined, + updatedAt: undefined, + applicationId: applicationId, + longitude: data.longitude ? Number(data.longitude) : 0, + latitude: data.latitude ? Number(data.latitude) : 0, + latestReceivedMessage: undefined, + lorawanSettings: undefined, + sigfoxSettings: undefined, + mqttInternalBrokerSettings: undefined, + mqttExternalBrokerSettings: undefined, + createdBy: undefined, + updatedBy: undefined, + updatedByName: undefined, + createdByName: undefined, + deviceModelId: data.deviceModelId != '' ? +data.deviceModelId : undefined, + }; + } +} diff --git a/src/app/applications/bulk-import/bulkMapping.ts b/src/app/applications/bulk-import/bulkMapping.ts deleted file mode 100644 index 5f7b66d60..000000000 --- a/src/app/applications/bulk-import/bulkMapping.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { IotDevice } from '@applications/iot-devices/iot-device.model'; -import { DeviceType } from '@shared/enums/device-type'; - -export class BulkMapping { - - public dataMapper(data: IotDevice, applicationId: number): IotDevice { - - switch (data.type.toUpperCase()) { - case DeviceType.LORAWAN: - return this.lorawanMapper(data, applicationId); - case DeviceType.GENERIC_HTTP: - return this.baseMapper(data, applicationId); - default: - break; - } - //return new IotDevice(); - } - - private lorawanMapper(data: any, applicationId): IotDevice { - const newDevice = this.baseMapper(data, applicationId); - newDevice.lorawanSettings = { - devEUI: data.devEUI, - skipFCntCheck: data.skipFCntCheck ? this.convertToBoolean(data.skipFCntCheck) : undefined, - activationType: data.activationType ? data.activationType : undefined, - OTAAapplicationKey: data.OTAAapplicationKey ? data.OTAAapplicationKey : undefined, - devAddr: data.devAddr ? data.devAddr : undefined, - networkSessionKey: data.networkSessionKey ? data.networkSessionKey : undefined, - applicationSessionKey: data.applicationSessionKey ? data.applicationSessionKey : undefined, - serviceProfileID: data.serviceProfileID ? data.serviceProfileID : undefined, - deviceProfileID: data.deviceProfileID ? data.deviceProfileID : undefined, - fCntUp: data.fCntUp ? +data.fCntUp : undefined, - nFCntDown: data.nFCntDown ? +data.nFCntDown : undefined, - deviceStatusBattery: undefined, - deviceStatusMargin: undefined - }; - newDevice.type = DeviceType.LORAWAN; - return newDevice; - } - - private convertToBoolean(text: string): boolean { - if (text.toUpperCase() === 'TRUE') { - return true; - } else { - return false; - } - - } - - private baseMapper(data: any, applicationId: number): IotDevice { - return { - name: data.name, - application: undefined, - location: undefined, - commentOnLocation: data.commentOnLocation, - comment: data.comment, - type: DeviceType.GENERIC_HTTP, - receivedMessagesMetadata: undefined, - metadata: undefined, - apiKey: undefined, - id: data.id ? data.id : undefined, - createdAt: undefined, - updatedAt: undefined, - applicationId: applicationId, - longitude: data.longitude ? Number(data.longitude) : 0, - latitude: data.latitude ? Number(data.latitude) : 0, - latestReceivedMessage: undefined, - lorawanSettings: undefined, - sigfoxSettings: undefined, - createdBy: undefined, - updatedBy: undefined, - updatedByName: undefined, - createdByName: undefined, - deviceModelId: data.deviceModelId != "" ? +data.deviceModelId : undefined, - }; - } -} diff --git a/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.html b/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.html index 1cab2bc81..d7f8f5ec6 100644 --- a/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.html +++ b/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.html @@ -2,43 +2,44 @@

{{ 'IOTDEVICE.DETAIL' | translate }}

-

{{ 'IOT-TABLE.APPLICATION' | translate }}{{device.application.name}}

+ + -
+

{{ 'IOT-TABLE.BATTERY' | translate }}

- - -
-

{{ 'IOTDEVICE-TABLE-ROW.NOT-SUPPORTED-SHORT' | translate }}

-
-
- - {{'IOTDEVICE-TABLE-ROW.NOT-AVAILABLE' | translate}} - -
+ +
+

{{ 'IOTDEVICE.TYPE' | translate }}{{ 'IOT-DEVICE-TYPES.' + device.type | translate}}

- + - + - +

{{ 'IOTDEVICE.GENERIC_HTTP.APIKEY' | translate }} {{ httpDeviceUrl }}

+ + + + +

{{ 'IOTDEVICE.MQTT.NOCONNECTION' | translate}}

+ +

diff --git a/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.scss b/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.scss index 6d2bcf418..8e0bf6a9a 100644 --- a/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.scss +++ b/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.scss @@ -4,3 +4,8 @@ white-space: -o-pre-wrap; font-family: monospace; } + +.alarmText{ + color: #ff0000; + font-size: 1em; +} diff --git a/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.ts b/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.ts index ac439b806..a2e2110d1 100644 --- a/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.ts +++ b/src/app/applications/iot-devices/iot-device-detail/iot-device-detail-generic/iot-device-detail-generic.component.ts @@ -14,6 +14,7 @@ import { environment } from '@environments/environment'; import { TranslateService } from '@ngx-translate/core'; import { jsonToList } from '@shared/helpers/json.helper'; import { KeyValue } from '@shared/types/tuple.type'; +import { DeviceType } from '@shared/enums/device-type'; @Component({ selector: 'app-iot-device-detail-generic', @@ -45,7 +46,6 @@ export class IotDeviceDetailGenericComponent ngOnChanges(changes: SimpleChanges): void { this.batteryStatusPercentage = this.getBatteryProcentage(); this.httpDeviceUrl = this.getGenericHttpDeviceUrl(); - if ( changes?.device?.previousValue?.metadata !== changes?.device?.currentValue?.metadata && @@ -83,4 +83,6 @@ export class IotDeviceDetailGenericComponent } ngOnDestroy(): void {} + + protected readonly DeviceType = DeviceType; } diff --git a/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-external-broker/iot-device-details-mqtt-external-broker.component.html b/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-external-broker/iot-device-details-mqtt-external-broker.component.html new file mode 100644 index 000000000..6aa1198ec --- /dev/null +++ b/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-external-broker/iot-device-details-mqtt-external-broker.component.html @@ -0,0 +1,11 @@ +

{{ 'IOTDEVICE.MQTT.URL' | translate }}{{ device.mqttExternalBrokerSettings.mqttURL }}

+

{{ 'IOTDEVICE.MQTT.PORT' | translate }}{{ device.mqttExternalBrokerSettings.mqttPort }}

+

{{ 'IOTDEVICE.MQTT.TOPIC_NAME' | translate }}{{ device.mqttExternalBrokerSettings.mqtttopicname }}

+ +

{{ 'QUESTION.MQTT.USERNAME-LABEL' | translate }}{{ device.mqttExternalBrokerSettings.mqttusername }}

+
+ +

{{ 'QUESTION.MQTT.CA-CERTIFICATE' | translate }}

+

{{ 'QUESTION.MQTT.DEVICE-CERTIFICATE' | translate }}

+

{{ 'QUESTION.MQTT.DEVICE-CERTIFICATE-KEY' | translate }}

+
diff --git a/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-external-broker/iot-device-details-mqtt-external-broker.component.scss b/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-external-broker/iot-device-details-mqtt-external-broker.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-external-broker/iot-device-details-mqtt-external-broker.component.ts b/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-external-broker/iot-device-details-mqtt-external-broker.component.ts new file mode 100644 index 000000000..e74f503fb --- /dev/null +++ b/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-external-broker/iot-device-details-mqtt-external-broker.component.ts @@ -0,0 +1,18 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { IotDevice } from '@applications/iot-devices/iot-device.model'; +import { AuthenticationType } from '@shared/enums/authentication-type'; + +@Component({ + selector: 'app-iot-device-details-mqtt-external-broker', + templateUrl: './iot-device-details-mqtt-external-broker.component.html', + styleUrls: ['./iot-device-details-mqtt-external-broker.component.scss'], +}) +export class IotDeviceDetailsMqttExternalBrokerComponent implements OnInit { + @Input() device: IotDevice; + + constructor() {} + + ngOnInit(): void {} + + protected readonly AuthenticationType = AuthenticationType; +} diff --git a/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-internal-broker/iot-device-details-mqtt-internal-broker.component.html b/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-internal-broker/iot-device-details-mqtt-internal-broker.component.html new file mode 100644 index 000000000..cf321b63f --- /dev/null +++ b/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-internal-broker/iot-device-details-mqtt-internal-broker.component.html @@ -0,0 +1,23 @@ +

{{ 'IOTDEVICE.MQTT.URL' | translate }}{{ device.mqttInternalBrokerSettings.mqttURL }}

+

{{ 'IOTDEVICE.MQTT.PORT' | translate }}{{ device.mqttInternalBrokerSettings.mqttPort }}

+

{{ 'IOTDEVICE.MQTT.TOPIC_NAME' | translate }}{{device.mqttInternalBrokerSettings.mqtttopicname}}

+ + +

{{ 'QUESTION.MQTT.USERNAME-LABEL' | translate }}{{ device.mqttInternalBrokerSettings.mqttusername }}

+
+

{{ 'QUESTION.MQTT.CA-CERTIFICATE' | translate }} + + +

+ +

{{ 'QUESTION.MQTT.DEVICE-CERTIFICATE' | translate }} + + + +

+

{{ 'QUESTION.MQTT.DEVICE-CERTIFICATE-KEY' | translate }} + + + +

+
diff --git a/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-internal-broker/iot-device-details-mqtt-internal-broker.component.scss b/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-internal-broker/iot-device-details-mqtt-internal-broker.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-internal-broker/iot-device-details-mqtt-internal-broker.component.ts b/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-internal-broker/iot-device-details-mqtt-internal-broker.component.ts new file mode 100644 index 000000000..03a0c5312 --- /dev/null +++ b/src/app/applications/iot-devices/iot-device-detail/iot-device-details-mqtt-internal-broker/iot-device-details-mqtt-internal-broker.component.ts @@ -0,0 +1,23 @@ +import { Component, Input, OnInit } from '@angular/core'; +import { IotDevice } from '@applications/iot-devices/iot-device.model'; +import { AuthenticationType } from '@shared/enums/authentication-type'; +import { simpleDownload } from '@shared/helpers/download.helper'; + +@Component({ + selector: 'app-iot-device-details-mqtt-internal-broker', + templateUrl: './iot-device-details-mqtt-internal-broker.component.html', + styleUrls: ['./iot-device-details-mqtt-internal-broker.component.scss'], +}) +export class IotDeviceDetailsMqttInternalBrokerComponent implements OnInit { + @Input() device: IotDevice; + + constructor() {} + + ngOnInit(): void {} + + protected readonly AuthenticationType = AuthenticationType; + + downloadCaCertificate(caCertificate: string, filename: string) { + simpleDownload(caCertificate, filename); + } +} diff --git a/src/app/applications/iot-devices/iot-device-edit/iot-device-edit.component.html b/src/app/applications/iot-devices/iot-device-edit/iot-device-edit.component.html index 0a0ab24ca..02b91ff21 100644 --- a/src/app/applications/iot-devices/iot-device-edit/iot-device-edit.component.html +++ b/src/app/applications/iot-devices/iot-device-edit/iot-device-edit.component.html @@ -1,4 +1,5 @@ - +
@@ -12,11 +13,11 @@
+ [ngClass]="{'is-invalid' : formFailedSubmit && errorFields.includes('type'), 'is-valid' : formFailedSubmit && !errorFields.includes('type')}">
+
+
+