@ -15,15 +15,11 @@
///
///
import { ChangeDetectorRef , Component , Input , OnInit } from '@angular/core' ;
import { ChangeDetectorRef , Component , Input , OnInit } from '@angular/core' ;
import { Store } from '@ngrx/store' ;
import { AppState } from '@core/core.state' ;
import { Router } from '@angular/router' ;
import {
import {
FormArray ,
FormArray ,
FormBuilder ,
FormBuilder ,
FormControl ,
FormControl ,
FormGroup ,
FormGroup ,
UntypedFormGroup ,
ValidationErrors ,
ValidationErrors ,
ValidatorFn ,
ValidatorFn ,
Validators
Validators
@ -41,79 +37,18 @@ import { Observable, of } from 'rxjs';
import { mergeMap } from 'rxjs/operators' ;
import { mergeMap } from 'rxjs/operators' ;
import { DeviceCredentials , DeviceCredentialsType } from '@shared/models/device.models' ;
import { DeviceCredentials , DeviceCredentialsType } from '@shared/models/device.models' ;
import { NULL_UUID } from '@shared/models/id/has-uuid' ;
import { NULL_UUID } from '@shared/models/id/has-uuid' ;
import {
export enum StorageTypes {
GatewayLogLevel ,
MEMORY = 'memory' ,
GecurityTypesTranslationsMap ,
FILE = 'file' ,
LocalLogsConfigTranslateMap ,
SQLITE = 'sqlite'
LocalLogsConfigs ,
}
LogSavingPeriod ,
LogSavingPeriodTranslations ,
export enum GatewayLogLevel {
SecurityTypes ,
none = 'NONE' ,
StorageTypes ,
critical = 'CRITICAL' ,
StorageTypesTranslationMap
error = 'ERROR' ,
} from './gateway-widget.models' ;
warning = 'WARNING' ,
import { deepTrim } from '@core/utils' ;
info = 'INFO' ,
debug = 'DEBUG'
}
export enum LogSavingPeriod {
days = 'D' ,
hours = 'H' ,
minutes = 'M' ,
seconds = 'S'
}
export enum LocalLogsConfigs {
service = 'service' ,
connector = 'connector' ,
converter = 'converter' ,
tb_connection = 'tb_connection' ,
storage = 'storage' ,
extension = 'extension'
}
export const localLogsConfigLabels = new Map < LocalLogsConfigs , string > ( [
[ LocalLogsConfigs . service , 'Service' ] ,
[ LocalLogsConfigs . connector , 'Connector' ] ,
[ LocalLogsConfigs . converter , 'Converter' ] ,
[ LocalLogsConfigs . tb_connection , 'TB Connection' ] ,
[ LocalLogsConfigs . storage , 'Storage' ] ,
[ LocalLogsConfigs . extension , 'Extension' ]
] ) ;
export const logSavingPeriodTranslations = new Map < LogSavingPeriod , string > (
[
[ LogSavingPeriod . days , 'gateway.logs.days' ] ,
[ LogSavingPeriod . hours , 'gateway.logs.hours' ] ,
[ LogSavingPeriod . minutes , 'gateway.logs.minutes' ] ,
[ LogSavingPeriod . seconds , 'gateway.logs.seconds' ]
]
) ;
export const storageTypesTranslations = new Map < StorageTypes , string > (
[
[ StorageTypes . MEMORY , 'gateway.storage-types.memory-storage' ] ,
[ StorageTypes . FILE , 'gateway.storage-types.file-storage' ] ,
[ StorageTypes . SQLITE , 'gateway.storage-types.sqlite' ]
]
) ;
export enum SecurityTypes {
ACCESS_TOKEN = 'accessToken' ,
USERNAME_PASSWORD = 'usernamePassword' ,
TLS_ACCESS_TOKEN = 'tlsAccessToken' ,
TLS_PRIVATE_KEY = 'tlsPrivateKey'
}
export const securityTypesTranslationsMap = new Map < SecurityTypes , string > (
[
[ SecurityTypes . ACCESS_TOKEN , 'gateway.security-types.access-token' ] ,
[ SecurityTypes . USERNAME_PASSWORD , 'gateway.security-types.username-password' ] ,
[ SecurityTypes . TLS_ACCESS_TOKEN , 'gateway.security-types.tls-access-token' ] ,
// [SecurityTypes.TLS_PRIVATE_KEY, 'gateway.security-types.tls-private-key'],
]
) ;
@Component ( {
@Component ( {
selector : 'tb-gateway-configuration' ,
selector : 'tb-gateway-configuration' ,
@ -124,13 +59,16 @@ export class GatewayConfigurationComponent implements OnInit {
gatewayConfigGroup : FormGroup ;
gatewayConfigGroup : FormGroup ;
storageTypes = storageTypesTranslations ;
StorageTypes = StorageTypes ;
storageTypes = Object . values ( StorageTypes ) as StorageTypes [ ] ;
storageTypesTranslationMap = StorageTypesTranslationMap ;
logSavingPeriods = logSavingPeriodTranslations ;
logSavingPeriods = L ogSavingPeriodTranslations;
localLogsConfigLabels = localLogsConfigLabels ;
localLogsConfigs = Object . keys ( LocalLogsConfigs ) as LocalLogsConfigs [ ] ;
localLogsConfigTranslateMap = LocalLogsConfigTranslateMap ;
securityTypes = s ecurityTypesTranslationsMap;
securityTypes = G ecurityTypesTranslationsMap;
gatewayLogLevel = Object . values ( GatewayLogLevel ) ;
gatewayLogLevel = Object . values ( GatewayLogLevel ) ;
@ -142,24 +80,19 @@ export class GatewayConfigurationComponent implements OnInit {
logSelector : FormControl ;
logSelector : FormControl ;
securityType : SecurityType s;
private initialCredentials : DeviceCredential s;
initialCredentials : DeviceCredentials ;
constructor ( private fb : FormBuilder ,
private attributeService : AttributeService ,
private deviceService : DeviceService ,
constructor ( protected router : Router ,
protected store : Store < AppState > ,
protected fb : FormBuilder ,
protected attributeService : AttributeService ,
protected deviceService : DeviceService ,
private cd : ChangeDetectorRef ,
private cd : ChangeDetectorRef ,
public dialog : MatDialog ) {
private dialog : MatDialog ) {
}
}
ngOnInit() {
ngOnInit() {
this . gatewayConfigGroup = this . fb . group ( {
this . gatewayConfigGroup = this . fb . group ( {
thingsboard : this.fb.group ( {
thingsboard : this.fb.group ( {
host : [ window . location . hostname , [ Validators . required ] ] ,
host : [ window . location . hostname , [ Validators . required , Validators . pattern ( /^[^\s]+$/ ) ] ] ,
port : [ 1883 , [ Validators . required , Validators . min ( 1 ) , Validators . max ( 65535 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ] ,
port : [ 1883 , [ Validators . required , Validators . min ( 1 ) , Validators . max ( 65535 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ] ,
remoteShell : [ false , [ ] ] ,
remoteShell : [ false , [ ] ] ,
remoteConfiguration : [ true , [ ] ] ,
remoteConfiguration : [ true , [ ] ] ,
@ -175,30 +108,30 @@ export class GatewayConfigurationComponent implements OnInit {
handleDeviceRenaming : [ true , [ ] ] ,
handleDeviceRenaming : [ true , [ ] ] ,
checkingDeviceActivity : this.fb.group ( {
checkingDeviceActivity : this.fb.group ( {
checkDeviceInactivity : [ false , [ ] ] ,
checkDeviceInactivity : [ false , [ ] ] ,
inactivityTimeoutSeconds : [ 200 , [ Validators . min ( 1 ) ] ] ,
inactivityTimeoutSeconds : [ 200 , [ Validators . min ( 1 ) , Validators . pattern ( /^[^.\s]+$/ ) ] ] ,
inactivityCheckPeriodSeconds : [ 500 , [ Validators . min ( 1 ) ] ]
inactivityCheckPeriodSeconds : [ 500 , [ Validators . min ( 1 ) , Validators . pattern ( /^[^.\s]+$/ ) ] ]
} ) ,
} ) ,
security : this.fb.group ( {
security : this.fb.group ( {
type : [ SecurityTypes . ACCESS_TOKEN , [ Validators . required ] ] ,
type : [ SecurityTypes . ACCESS_TOKEN , [ Validators . required ] ] ,
accessToken : [ null , [ Validators . required ] ] ,
accessToken : [ null , [ Validators . required , Validators . pattern ( /^[^.\s]+$/ ) ] ] ,
clientId : [ null , [ ] ] ,
clientId : [ null , [ Validators . pattern ( /^[^.\s]+$/ ) ] ] ,
username : [ null , [ ] ] ,
username : [ null , [ Validators . pattern ( /^[^.\s]+$/ ) ] ] ,
password : [ null , [ ] ] ,
password : [ null , [ Validators . pattern ( /^[^.\s]+$/ ) ] ] ,
caCert : [ null , [ ] ] ,
caCert : [ null , [ ] ] ,
cert : [ null , [ ] ] ,
cert : [ null , [ ] ] ,
privateKey : [ null , [ ] ] ,
privateKey : [ null , [ ] ] ,
} ) ,
} ) ,
qos : [ 1 , [ Validators . min ( 0 ) , Validators . max ( 1 ) , Validators . required ] ]
qos : [ 1 , [ Validators . min ( 0 ) , Validators . max ( 1 ) , Validators . required , Validators . pattern ( /^[^.\s]+$/ ) ] ]
} ) ,
} ) ,
storage : this.fb.group ( {
storage : this.fb.group ( {
type : [ StorageTypes . MEMORY , [ Validators . required ] ] ,
type : [ StorageTypes . MEMORY , [ Validators . required ] ] ,
read_records_count : [ 100 , [ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required ] ] ,
read_records_count : [ 100 , [ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required , Validators . pattern ( /^[^.\s]+$/ ) ] ] ,
max_records_count : [ 100000 , [ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required ] ] ,
max_records_count : [ 100000 , [ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required , Validators . pattern ( /^[^.\s]+$/ ) ] ] ,
data_folder_path : [ './data/' , [ ] ] ,
data_folder_path : [ './data/' , [ Validators . pattern ( /^[^\s]+$/ ) ] ] ,
max_file_count : [ 10 , [ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ] ,
max_file_count : [ 10 , [ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ] ,
max_read_records_count : [ 10 , [ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ] ,
max_read_records_count : [ 10 , [ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ] ,
max_records_per_file : [ 10000 , [ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ] ,
max_records_per_file : [ 10000 , [ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ] ,
data_file_path : [ './data/data.db' , [ ] ] ,
data_file_path : [ './data/data.db' , [ Validators . pattern ( /^[^\s]+$/ ) ] ] ,
messages_ttl_check_in_hours : [ 1 , [ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ] ,
messages_ttl_check_in_hours : [ 1 , [ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ] ,
messages_ttl_in_days : [ 7 , [ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ] ,
messages_ttl_in_days : [ 7 , [ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ] ,
@ -215,13 +148,13 @@ export class GatewayConfigurationComponent implements OnInit {
} ) ,
} ) ,
connectors : this.fb.array ( [ ] ) ,
connectors : this.fb.array ( [ ] ) ,
logs : this.fb.group ( {
logs : this.fb.group ( {
dateFormat : [ '%Y-%m-%d %H:%M:%S' , [ Validators . required ] ] ,
dateFormat : [ '%Y-%m-%d %H:%M:%S' , [ Validators . required , Validators . pattern ( /^[^\s].*[^\s]$/ ) ] ] ,
logFormat : [ '%(asctime)s - |%(levelname)s| - [%(filename)s] - %(module)s - %(funcName)s - %(lineno)d - %(message)s' ,
logFormat : [ '%(asctime)s - |%(levelname)s| - [%(filename)s] - %(module)s - %(funcName)s - %(lineno)d - %(message)s' ,
[ Validators . required ] ] ,
[ Validators . required , Validators . pattern ( /^[^\s].*[^\s]$/ ) ] ] ,
type : [ 'remote' , [ Validators . required ] ] ,
type : [ 'remote' , [ Validators . required ] ] ,
remote : this.fb.group ( {
remote : this.fb.group ( {
enabled : [ false ] ,
enabled : [ false ] ,
logLevel : [ GatewayLogLevel . info , [ Validators . required ] ] ,
logLevel : [ GatewayLogLevel . INFO , [ Validators . required ] ] ,
} ) ,
} ) ,
local : this.fb.group ( { } )
local : this.fb.group ( { } )
} )
} )
@ -231,7 +164,7 @@ export class GatewayConfigurationComponent implements OnInit {
if ( password && password !== '' ) {
if ( password && password !== '' ) {
this . gatewayConfigGroup . get ( 'thingsboard.security.username' ) . setValidators ( [ Validators . required ] ) ;
this . gatewayConfigGroup . get ( 'thingsboard.security.username' ) . setValidators ( [ Validators . required ] ) ;
} else {
} else {
this . gatewayConfigGroup . get ( 'thingsboard.security.username' ) . setValidators ( [ ] ) ;
this . gatewayConfigGroup . get ( 'thingsboard.security.username' ) . clearValidators ( ) ;
}
}
this . gatewayConfigGroup . get ( 'thingsboard.security.username' ) . updateValueAndValidity ( { emitEvent : false } ) ;
this . gatewayConfigGroup . get ( 'thingsboard.security.username' ) . updateValueAndValidity ( { emitEvent : false } ) ;
} ) ;
} ) ;
@ -258,10 +191,10 @@ export class GatewayConfigurationComponent implements OnInit {
checkingDeviceActivityGroup . get ( 'inactivityCheckPeriodSeconds' ) . setValidators ( [ Validators . min ( 1 ) , Validators . required ] ) ;
checkingDeviceActivityGroup . get ( 'inactivityCheckPeriodSeconds' ) . setValidators ( [ Validators . min ( 1 ) , Validators . required ] ) ;
} else {
} else {
checkingDeviceActivityGroup . get ( 'inactivityTimeoutSeconds' ) . clearValidators ( ) ;
checkingDeviceActivityGroup . get ( 'inactivityTimeoutSeconds' ) . clearValidators ( ) ;
checkingDeviceActivityGroup . get ( 'inactivityTimeoutSeconds' ) . setErrors ( null ) ;
checkingDeviceActivityGroup . get ( 'inactivityCheckPeriodSeconds' ) . clearValidators ( ) ;
checkingDeviceActivityGroup . get ( 'inactivityCheckPeriodSeconds' ) . clearValidators ( ) ;
checkingDeviceActivityGroup . get ( 'inactivityCheckPeriodSeconds' ) . setErrors ( null ) ;
}
}
checkingDeviceActivityGroup . get ( 'inactivityTimeoutSeconds' ) . updateValueAndValidity ( { emitEvent : false } ) ;
checkingDeviceActivityGroup . get ( 'inactivityCheckPeriodSeconds' ) . updateValueAndValidity ( { emitEvent : false } ) ;
} ) ;
} ) ;
this . gatewayConfigGroup . get ( 'grpc.enabled' ) . valueChanges . subscribe ( value = > {
this . gatewayConfigGroup . get ( 'grpc.enabled' ) . valueChanges . subscribe ( value = > {
@ -272,7 +205,7 @@ export class GatewayConfigurationComponent implements OnInit {
securityGroup . get ( 'type' ) . valueChanges . subscribe ( type = > {
securityGroup . get ( 'type' ) . valueChanges . subscribe ( type = > {
this . removeAllSecurityValidators ( ) ;
this . removeAllSecurityValidators ( ) ;
if ( type === SecurityTypes . ACCESS_TOKEN ) {
if ( type === SecurityTypes . ACCESS_TOKEN ) {
securityGroup . get ( 'accessToken' ) . addValidators ( [ Validators . required ] ) ;
securityGroup . get ( 'accessToken' ) . addValidators ( [ Validators . required , Validators . pattern ( /^[^.\s]+$/ ) ] ) ;
securityGroup . get ( 'accessToken' ) . updateValueAndValidity ( ) ;
securityGroup . get ( 'accessToken' ) . updateValueAndValidity ( ) ;
} else if ( type === SecurityTypes . TLS_PRIVATE_KEY ) {
} else if ( type === SecurityTypes . TLS_PRIVATE_KEY ) {
securityGroup . get ( 'caCert' ) . addValidators ( [ Validators . required ] ) ;
securityGroup . get ( 'caCert' ) . addValidators ( [ Validators . required ] ) ;
@ -282,21 +215,19 @@ export class GatewayConfigurationComponent implements OnInit {
securityGroup . get ( 'cert' ) . addValidators ( [ Validators . required ] ) ;
securityGroup . get ( 'cert' ) . addValidators ( [ Validators . required ] ) ;
securityGroup . get ( 'cert' ) . updateValueAndValidity ( ) ;
securityGroup . get ( 'cert' ) . updateValueAndValidity ( ) ;
} else if ( type === SecurityTypes . TLS_ACCESS_TOKEN ) {
} else if ( type === SecurityTypes . TLS_ACCESS_TOKEN ) {
securityGroup . get ( 'accessToken' ) . addValidators ( [ Validators . required ] ) ;
securityGroup . get ( 'accessToken' ) . addValidators ( [ Validators . required , Validators . pattern ( /^[^.\s]+$/ ) ] ) ;
securityGroup . get ( 'accessToken' ) . updateValueAndValidity ( ) ;
securityGroup . get ( 'accessToken' ) . updateValueAndValidity ( ) ;
securityGroup . get ( 'caCert' ) . addValidators ( [ Validators . required ] ) ;
securityGroup . get ( 'caCert' ) . addValidators ( [ Validators . required ] ) ;
securityGroup . get ( 'caCert' ) . updateValueAndValidity ( ) ;
securityGroup . get ( 'caCert' ) . updateValueAndValidity ( ) ;
} else if ( type === SecurityTypes . USERNAME_PASSWORD ) {
} else if ( type === SecurityTypes . USERNAME_PASSWORD ) {
securityGroup . addValidators ( [ this . atLeastOneRequired ( Validators . required , [ 'clientId' , 'username' ] ) ] )
securityGroup . addValidators ( [ this . atLeastOneRequired ( Validators . required , [ 'clientId' , 'username' ] ) ] ) ;
// securityGroup.get('password').addValidators([Validators.required]);
// securityGroup.get('password').updateValueAndValidity();
}
}
securityGroup . updateValueAndValidity ( ) ;
securityGroup . updateValueAndValidity ( ) ;
} ) ;
} ) ;
securityGroup . get ( 'caCert' ) . valueChanges . subscribe ( _ = > this . cd . detectChanges ( ) ) ;
securityGroup . get ( 'caCert' ) . valueChanges . subscribe ( ( ) = > this . cd . detectChanges ( ) ) ;
securityGroup . get ( 'privateKey' ) . valueChanges . subscribe ( _ = > this . cd . detectChanges ( ) ) ;
securityGroup . get ( 'privateKey' ) . valueChanges . subscribe ( ( ) = > this . cd . detectChanges ( ) ) ;
securityGroup . get ( 'cert' ) . valueChanges . subscribe ( _ = > this . cd . detectChanges ( ) ) ;
securityGroup . get ( 'cert' ) . valueChanges . subscribe ( ( ) = > this . cd . detectChanges ( ) ) ;
const storageGroup = this . gatewayConfigGroup . get ( 'storage' ) as FormGroup ;
const storageGroup = this . gatewayConfigGroup . get ( 'storage' ) as FormGroup ;
storageGroup . get ( 'type' ) . valueChanges . subscribe ( type = > {
storageGroup . get ( 'type' ) . valueChanges . subscribe ( type = > {
@ -306,28 +237,37 @@ export class GatewayConfigurationComponent implements OnInit {
[ Validators . required , Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ) ;
[ Validators . required , Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ) ;
storageGroup . get ( 'max_records_count' ) . addValidators (
storageGroup . get ( 'max_records_count' ) . addValidators (
[ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required ] ) ;
[ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required ] ) ;
storageGroup . get ( 'read_records_count' ) . updateValueAndValidity ( { emitEvent : false } ) ;
storageGroup . get ( 'max_records_count' ) . updateValueAndValidity ( { emitEvent : false } ) ;
} else if ( type === StorageTypes . FILE ) {
} else if ( type === StorageTypes . FILE ) {
storageGroup . get ( 'data_folder_path' ) . addValidators ( [ Validators . required ] ) ;
storageGroup . get ( 'data_folder_path' ) . addValidators ( [ Validators . required , Validators . pattern ( /^[^.\s]+$/ ) ] ) ;
storageGroup . get ( 'max_file_count' ) . addValidators (
storageGroup . get ( 'max_file_count' ) . addValidators (
[ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required ] ) ;
[ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required ] ) ;
storageGroup . get ( 'max_read_records_count' ) . addValidators (
storageGroup . get ( 'max_read_records_count' ) . addValidators (
[ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required ] ) ;
[ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required ] ) ;
storageGroup . get ( 'max_records_per_file' ) . addValidators (
storageGroup . get ( 'max_records_per_file' ) . addValidators (
[ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required ] ) ;
[ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required ] ) ;
storageGroup . get ( 'data_folder_path' ) . updateValueAndValidity ( { emitEvent : false } ) ;
storageGroup . get ( 'max_file_count' ) . updateValueAndValidity ( { emitEvent : false } ) ;
storageGroup . get ( 'max_read_records_count' ) . updateValueAndValidity ( { emitEvent : false } ) ;
storageGroup . get ( 'max_records_per_file' ) . updateValueAndValidity ( { emitEvent : false } ) ;
} else if ( type === StorageTypes . SQLITE ) {
} else if ( type === StorageTypes . SQLITE ) {
storageGroup . get ( 'data_file_path' ) . addValidators ( [ Validators . required ] ) ;
storageGroup . get ( 'data_file_path' ) . addValidators ( [ Validators . required , Validators . pattern ( /^[^.\s]+$/ ) ] ) ;
storageGroup . get ( 'messages_ttl_check_in_hours' ) . addValidators (
storageGroup . get ( 'messages_ttl_check_in_hours' ) . addValidators (
[ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required ] ) ;
[ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required ] ) ;
storageGroup . get ( 'messages_ttl_in_days' ) . addValidators (
storageGroup . get ( 'messages_ttl_in_days' ) . addValidators (
[ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required ] ) ;
[ Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . required ] ) ;
storageGroup . get ( 'data_file_path' ) . updateValueAndValidity ( { emitEvent : false } ) ;
storageGroup . get ( 'messages_ttl_check_in_hours' ) . updateValueAndValidity ( { emitEvent : false } ) ;
storageGroup . get ( 'messages_ttl_in_days' ) . updateValueAndValidity ( { emitEvent : false } ) ;
}
}
} ) ;
} ) ;
this . fetchConfigAttribute ( this . device ) ;
this . fetchConfigAttribute ( this . device ) ;
}
}
atLeastOneRequired ( validator : ValidatorFn , controls : string [ ] = null ) {
private atLeastOneRequired ( validator : ValidatorFn , controls : string [ ] = null ) {
return ( group : Untyped FormGroup) : ValidationErrors | null = > {
return ( group : FormGroup ) : ValidationErrors | null = > {
if ( ! controls ) {
if ( ! controls ) {
controls = Object . keys ( group . controls ) ;
controls = Object . keys ( group . controls ) ;
}
}
@ -337,22 +277,10 @@ export class GatewayConfigurationComponent implements OnInit {
} ;
} ;
}
}
updateSecurityValidators ( value : SecurityTypes ) {
private fetchConfigAttribute ( entityId : EntityId ) {
this . gatewayConfigGroup . get ( 'thingsboard.security.type' ) . setValue ( value , { emitEvent : true } ) ;
if ( entityId . id === NULL_UUID ) {
this . gatewayConfigGroup . get ( 'thingsboard.security.type' ) . markAsDirty ( ) ;
return ;
}
}
updateLogType ( value : LocalLogsConfigs ) {
this . logSelector . setValue ( value ) ;
}
updateStorageType ( value : StorageTypes ) {
this . gatewayConfigGroup . get ( 'storage.type' ) . setValue ( value , { emitEvent : true } ) ;
this . gatewayConfigGroup . get ( 'storage.type' ) . markAsDirty ( ) ;
}
fetchConfigAttribute ( entityId : EntityId ) {
if ( entityId . id === NULL_UUID ) return ;
this . attributeService . getEntityAttributes ( entityId , AttributeScope . CLIENT_SCOPE ,
this . attributeService . getEntityAttributes ( entityId , AttributeScope . CLIENT_SCOPE ,
[ 'general_configuration' , 'grpc_configuration' , 'logs_configuration' , 'storage_configuration' , 'RemoteLoggingLevel' ] ) . pipe (
[ 'general_configuration' , 'grpc_configuration' , 'logs_configuration' , 'storage_configuration' , 'RemoteLoggingLevel' ] ) . pipe (
mergeMap ( attributes = > attributes . length ? of ( attributes ) : this . attributeService . getEntityAttributes (
mergeMap ( attributes = > attributes . length ? of ( attributes ) : this . attributeService . getEntityAttributes (
@ -397,24 +325,26 @@ export class GatewayConfigurationComponent implements OnInit {
if ( remoteLoggingLevel ) {
if ( remoteLoggingLevel ) {
const remoteLogsFormGroup = this . gatewayConfigGroup . get ( 'logs.remote' ) ;
const remoteLogsFormGroup = this . gatewayConfigGroup . get ( 'logs.remote' ) ;
remoteLogsFormGroup . patchValue ( {
remoteLogsFormGroup . patchValue ( {
enabled : remoteLoggingLevel !== GatewayLogLevel . none ,
enabled : remoteLoggingLevel !== GatewayLogLevel . NONE ,
logLevel : remoteLoggingLevel
logLevel : remoteLoggingLevel
} , { emitEvent : false } ) ;
} , { emitEvent : false } ) ;
remoteLogsFormGroup . markAsPristine ( ) ;
remoteLogsFormGroup . markAsPristine ( ) ;
}
}
this . cd . detectChanges ( ) ;
this . cd . detectChanges ( ) ;
} else {
} else {
this . checkAndFetchCredentials ( { } ) ;
this . checkAndFetchCredentials ( ) ;
}
}
} ) ;
} ) ;
}
}
checkAndFetchCredentials ( security ) : void {
private checkAndFetchCredentials ( security : any = { } ) : void {
if ( security . type !== SecurityTypes . TLS_PRIVATE_KEY ) {
if ( security . type !== SecurityTypes . TLS_PRIVATE_KEY ) {
this . deviceService . getDeviceCredentials ( this . device . id ) . subscribe ( credentials = > {
this . deviceService . getDeviceCredentials ( this . device . id ) . subscribe ( credentials = > {
this . initialCredentials = credentials ;
this . initialCredentials = credentials ;
if ( credentials . credentialsType === DeviceCredentialsType . ACCESS_TOKEN || security . type === SecurityTypes . TLS_ACCESS_TOKEN ) {
if ( credentials . credentialsType === DeviceCredentialsType . ACCESS_TOKEN || security . type === SecurityTypes . TLS_ACCESS_TOKEN ) {
this . gatewayConfigGroup . get ( 'thingsboard.security.type' ) . setValue ( security . type === SecurityTypes . TLS_ACCESS_TOKEN ? SecurityTypes.TLS_ACCESS_TOKEN : SecurityTypes.ACCESS_TOKEN ) ;
this . gatewayConfigGroup . get ( 'thingsboard.security.type' ) . setValue ( security . type === SecurityTypes . TLS_ACCESS_TOKEN
? SecurityTypes . TLS_ACCESS_TOKEN
: SecurityTypes . ACCESS_TOKEN ) ;
this . gatewayConfigGroup . get ( 'thingsboard.security.accessToken' ) . setValue ( credentials . credentialsId ) ;
this . gatewayConfigGroup . get ( 'thingsboard.security.accessToken' ) . setValue ( credentials . credentialsId ) ;
if ( security . type === SecurityTypes . TLS_ACCESS_TOKEN ) {
if ( security . type === SecurityTypes . TLS_ACCESS_TOKEN ) {
this . gatewayConfigGroup . get ( 'thingsboard.security.caCert' ) . setValue ( security . caCert ) ;
this . gatewayConfigGroup . get ( 'thingsboard.security.caCert' ) . setValue ( security . caCert ) ;
@ -432,7 +362,7 @@ export class GatewayConfigurationComponent implements OnInit {
}
}
}
}
logsToObj ( logsConfig ) {
private logsToObj ( logsConfig : any ) {
const logsObject = {
const logsObject = {
local : { }
local : { }
} ;
} ;
@ -453,43 +383,42 @@ export class GatewayConfigurationComponent implements OnInit {
return { local : logsObject , logFormat , dateFormat } ;
return { local : logsObject , logFormat , dateFormat } ;
}
}
toggleRpcFields ( enable : boolean ) {
private toggleRpcFields ( enable : boolean ) {
const grpcGroup = this . gatewayConfigGroup . get ( 'grpc' ) as FormGroup ;
const grpcGroup = this . gatewayConfigGroup . get ( 'grpc' ) as FormGroup ;
if ( enable ) {
if ( enable ) {
grpcGroup . get ( 'serverPort' ) . enable ( ) ;
grpcGroup . get ( 'serverPort' ) . enable ( { emitEvent : false } ) ;
grpcGroup . get ( 'keepAliveTimeMs' ) . enable ( ) ;
grpcGroup . get ( 'keepAliveTimeMs' ) . enable ( { emitEvent : false } ) ;
grpcGroup . get ( 'keepAliveTimeoutMs' ) . enable ( ) ;
grpcGroup . get ( 'keepAliveTimeoutMs' ) . enable ( { emitEvent : false } ) ;
grpcGroup . get ( 'keepalivePermitWithoutCalls' ) . enable ( ) ;
grpcGroup . get ( 'keepalivePermitWithoutCalls' ) . enable ( { emitEvent : false } ) ;
grpcGroup . get ( 'maxPingsWithoutData' ) . enable ( ) ;
grpcGroup . get ( 'maxPingsWithoutData' ) . enable ( { emitEvent : false } ) ;
grpcGroup . get ( 'minTimeBetweenPingsMs' ) . enable ( ) ;
grpcGroup . get ( 'minTimeBetweenPingsMs' ) . enable ( { emitEvent : false } ) ;
grpcGroup . get ( 'minPingIntervalWithoutDataMs' ) . enable ( ) ;
grpcGroup . get ( 'minPingIntervalWithoutDataMs' ) . enable ( { emitEvent : false } ) ;
} else {
} else {
grpcGroup . get ( 'serverPort' ) . disable ( ) ;
grpcGroup . get ( 'serverPort' ) . disable ( { emitEvent : false } ) ;
grpcGroup . get ( 'keepAliveTimeMs' ) . disable ( ) ;
grpcGroup . get ( 'keepAliveTimeMs' ) . disable ( { emitEvent : false } ) ;
grpcGroup . get ( 'keepAliveTimeoutMs' ) . disable ( ) ;
grpcGroup . get ( 'keepAliveTimeoutMs' ) . disable ( { emitEvent : false } ) ;
grpcGroup . get ( 'keepalivePermitWithoutCalls' ) . disable ( ) ;
grpcGroup . get ( 'keepalivePermitWithoutCalls' ) . disable ( { emitEvent : false } ) ;
grpcGroup . get ( 'maxPingsWithoutData' ) . disable ( ) ;
grpcGroup . get ( 'maxPingsWithoutData' ) . disable ( { emitEvent : false } ) ;
grpcGroup . get ( 'minTimeBetweenPingsMs' ) . disable ( ) ;
grpcGroup . get ( 'minTimeBetweenPingsMs' ) . disable ( { emitEvent : false } ) ;
grpcGroup . get ( 'minPingIntervalWithoutDataMs' ) . disable ( ) ;
grpcGroup . get ( 'minPingIntervalWithoutDataMs' ) . disable ( { emitEvent : false } ) ;
}
}
}
}
addCommand ( command ? ) : void {
addCommand ( command : any = { } ) : void {
const data = command || { } ;
const commandsFormArray = this . commandFormArray ( ) ;
const commandsFormArray = this . commandFormArray ( ) ;
const commandFormGroup = this . fb . group ( {
const commandFormGroup = this . fb . group ( {
attributeOnGateway : [ data . attributeOnGateway || null , [ Validators . required ] ] ,
attributeOnGateway : [ comman d. attributeOnGateway || null , [ Validators . required , Validators . pattern ( /^[^.\s]+$/ ) ] ] ,
command : [ data . command || null , [ Validators . required ] ] ,
command : [ comman d. command || null , [ Validators . required , Validators . pattern ( /^[^.\s]+$/ ) ] ] ,
timeout : [ data . timeout || null , [ Validators . required , Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) ] ] ,
timeout : [ comman d. timeout || null , [ Validators . required , Validators . min ( 1 ) , Validators . pattern ( /^-?[0-9]+$/ ) , Validators . pattern ( /^[^.\s ]+$/ ) ] ] ,
} ) ;
} ) ;
commandsFormArray . push ( commandFormGroup ) ;
commandsFormArray . push ( commandFormGroup ) ;
}
}
addLocalLogConfig ( name , config ) : void {
private addLocalLogConfig ( name : string , config : any ) : void {
const localLogsFormGroup = this . gatewayConfigGroup . get ( 'logs.local' ) as FormGroup ;
const localLogsFormGroup = this . gatewayConfigGroup . get ( 'logs.local' ) as FormGroup ;
const configGroup = this . fb . group ( {
const configGroup = this . fb . group ( {
logLevel : [ config . logLevel || GatewayLogLevel . info , [ Validators . required ] ] ,
logLevel : [ config . logLevel || GatewayLogLevel . INFO , [ Validators . required ] ] ,
filePath : [ config . filePath || './logs' , [ Validators . required ] ] ,
filePath : [ config . filePath || './logs' , [ Validators . required ] ] ,
backupCount : [ config . backupCount || 7 , [ Validators . required , Validators . min ( 0 ) ] ] ,
backupCount : [ config . backupCount || 7 , [ Validators . required , Validators . min ( 0 ) ] ] ,
savingTime : [ config . savingTime || 3 , [ Validators . required , Validators . min ( 0 ) ] ] ,
savingTime : [ config . savingTime || 3 , [ Validators . required , Validators . min ( 0 ) ] ] ,
@ -507,12 +436,14 @@ export class GatewayConfigurationComponent implements OnInit {
}
}
removeCommandControl ( index : number , event : any ) : void {
removeCommandControl ( index : number , event : any ) : void {
if ( event . pointerType === '' ) return ;
if ( event . pointerType === '' ) {
return ;
}
this . commandFormArray ( ) . removeAt ( index ) ;
this . commandFormArray ( ) . removeAt ( index ) ;
this . gatewayConfigGroup . markAsDirty ( ) ;
this . gatewayConfigGroup . markAsDirty ( ) ;
}
}
removeAllSecurityValidators ( ) : void {
private removeAllSecurityValidators ( ) : void {
const securityGroup = this . gatewayConfigGroup . get ( 'thingsboard.security' ) as FormGroup ;
const securityGroup = this . gatewayConfigGroup . get ( 'thingsboard.security' ) as FormGroup ;
securityGroup . clearValidators ( ) ;
securityGroup . clearValidators ( ) ;
for ( const controlsKey in securityGroup . controls ) {
for ( const controlsKey in securityGroup . controls ) {
@ -524,7 +455,7 @@ export class GatewayConfigurationComponent implements OnInit {
}
}
}
}
removeAllStorageValidators ( ) : void {
private removeAllStorageValidators ( ) : void {
const storageGroup = this . gatewayConfigGroup . get ( 'storage' ) as FormGroup ;
const storageGroup = this . gatewayConfigGroup . get ( 'storage' ) as FormGroup ;
for ( const storageKey in storageGroup . controls ) {
for ( const storageKey in storageGroup . controls ) {
if ( storageKey !== 'type' ) {
if ( storageKey !== 'type' ) {
@ -535,7 +466,7 @@ export class GatewayConfigurationComponent implements OnInit {
}
}
}
}
removeEmpty ( obj ) {
private removeEmpty ( obj : any ) {
return Object . fromEntries (
return Object . fromEntries (
Object . entries ( obj )
Object . entries ( obj )
. filter ( ( [ _ , v ] ) = > v != null )
. filter ( ( [ _ , v ] ) = > v != null )
@ -543,7 +474,7 @@ export class GatewayConfigurationComponent implements OnInit {
) ;
) ;
}
}
generateLogsFile ( logsObj ) {
private generateLogsFile ( logsObj : any ) {
const logAttrObj = {
const logAttrObj = {
version : 1 ,
version : 1 ,
disable_existing_loggers : false ,
disable_existing_loggers : false ,
@ -591,7 +522,7 @@ export class GatewayConfigurationComponent implements OnInit {
return logAttrObj ;
return logAttrObj ;
}
}
createHandlerObj ( logObj , key ) {
private createHandlerObj ( logObj : any , key : string ) {
return {
return {
class : 'thingsboard_gateway.tb_utility.tb_handler.TimedRotatingFileHandler' ,
class : 'thingsboard_gateway.tb_utility.tb_handler.TimedRotatingFileHandler' ,
formatter : 'LogFormatter' ,
formatter : 'LogFormatter' ,
@ -603,7 +534,7 @@ export class GatewayConfigurationComponent implements OnInit {
} ;
} ;
}
}
createLoggerObj ( logObj , key ) {
private createLoggerObj ( logObj : any , key : string ) {
return {
return {
handlers : [ ` ${ key } Handler ` , 'consoleHandler' ] ,
handlers : [ ` ${ key } Handler ` , 'consoleHandler' ] ,
level : logObj.logLevel ,
level : logObj.logLevel ,
@ -612,12 +543,12 @@ export class GatewayConfigurationComponent implements OnInit {
}
}
saveConfig ( ) : void {
saveConfig ( ) : void {
const value = this . removeEmpty ( this . gatewayConfigGroup . value ) ;
const value = deepTrim ( this . removeEmpty ( this . gatewayConfigGroup . value ) ) ;
value . thingsboard . statistics . commands = Object . values ( value . thingsboard . statistics . commands ) ;
value . thingsboard . statistics . commands = Object . values ( value . thingsboard . statistics . commands ) ;
const attributes = [ ] ;
const attributes = [ ] ;
attributes . push ( {
attributes . push ( {
key : 'RemoteLoggingLevel' ,
key : 'RemoteLoggingLevel' ,
value : value.logs.remote.enabled ? value.logs.remote.logLevel : GatewayLogLevel.none
value : value.logs.remote.enabled ? value.logs.remote.logLevel : GatewayLogLevel.NONE
} ) ;
} ) ;
delete value . connectors ;
delete value . connectors ;
attributes . push ( {
attributes . push ( {
@ -642,18 +573,18 @@ export class GatewayConfigurationComponent implements OnInit {
this . attributeService . saveEntityAttributes ( this . device , AttributeScope . SHARED_SCOPE , attributes ) . subscribe ( _ = > {
this . attributeService . saveEntityAttributes ( this . device , AttributeScope . SHARED_SCOPE , attributes ) . subscribe ( _ = > {
this . updateCredentials ( value . thingsboard . security ) . subscribe ( _ = > {
this . updateCredentials ( value . thingsboard . security ) . subscribe ( ( ) = > {
if ( this . dialogRef ) {
if ( this . dialogRef ) {
this . dialogRef . close ( ) ;
this . dialogRef . close ( ) ;
} else {
} else {
this . gatewayConfigGroup . markAsPristine ( ) ;
this . gatewayConfigGroup . markAsPristine ( ) ;
this . cd . detectChanges ( ) ;
this . cd . detectChanges ( ) ;
}
}
} )
} ) ;
} ) ;
} ) ;
}
}
updateCredentials ( securityConfig ) : Observable < any > {
private updateCredentials ( securityConfig : any ) : Observable < any > {
let updateCredentials = false ;
let updateCredentials = false ;
let newCredentials = { } ;
let newCredentials = { } ;
if ( securityConfig . type === SecurityTypes . USERNAME_PASSWORD ) {
if ( securityConfig . type === SecurityTypes . USERNAME_PASSWORD ) {
@ -661,17 +592,26 @@ export class GatewayConfigurationComponent implements OnInit {
updateCredentials = true ;
updateCredentials = true ;
} else {
} else {
const parsedCredentials = JSON . parse ( this . initialCredentials . credentialsValue ) ;
const parsedCredentials = JSON . parse ( this . initialCredentials . credentialsValue ) ;
updateCredentials = ! ( parsedCredentials . clientId === securityConfig . clientId && parsedCredentials . userName === securityConfig . username && parsedCredentials . password === securityConfig . password ) ;
updateCredentials = ! (
parsedCredentials . clientId === securityConfig . clientId &&
parsedCredentials . userName === securityConfig . username &&
parsedCredentials . password === securityConfig . password ) ;
}
}
if ( updateCredentials ) {
if ( updateCredentials ) {
let credentialsValue : { clientId ? , userName ? , password ? } = { } ;
cons t credentialsValue : { clientId? : string ; userName? : string ; password? : string } = { } ;
const credentialsType = DeviceCredentialsType . MQTT_BASIC ;
const credentialsType = DeviceCredentialsType . MQTT_BASIC ;
if ( securityConfig . clientId ) credentialsValue . clientId = securityConfig . clientId ;
if ( securityConfig . clientId ) {
if ( securityConfig . username ) credentialsValue . userName = securityConfig . username ;
credentialsValue . clientId = securityConfig . clientId ;
if ( securityConfig . password ) credentialsValue . password = securityConfig . password ;
}
if ( securityConfig . username ) {
credentialsValue . userName = securityConfig . username ;
}
if ( securityConfig . password ) {
credentialsValue . password = securityConfig . password ;
}
newCredentials = {
newCredentials = {
credentialsType ,
credentialsType ,
credentialsValue : JSON.stringify ( credentialsValue )
credentialsValue : JSON.stringify ( credentialsValue )
} ;
} ;
}
}
} else if ( securityConfig . type === SecurityTypes . ACCESS_TOKEN || securityConfig . type === SecurityTypes . TLS_ACCESS_TOKEN ) {
} else if ( securityConfig . type === SecurityTypes . ACCESS_TOKEN || securityConfig . type === SecurityTypes . TLS_ACCESS_TOKEN ) {
@ -684,12 +624,12 @@ export class GatewayConfigurationComponent implements OnInit {
newCredentials = {
newCredentials = {
credentialsType : DeviceCredentialsType.ACCESS_TOKEN ,
credentialsType : DeviceCredentialsType.ACCESS_TOKEN ,
credentialsId : securityConfig.accessToken
credentialsId : securityConfig.accessToken
}
} ;
}
}
}
}
if ( updateCredentials ) {
if ( updateCredentials ) {
return this . deviceService . saveDeviceCredentials ( { . . . this . initialCredentials , . . . newCredentials } )
return this . deviceService . saveDeviceCredentials ( { . . . this . initialCredentials , . . . newCredentials } ) ;
}
}
return of ( null ) ;
return of ( null ) ;
}
}