Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added implementation of Rest Connector Basic Config #26

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
530 changes: 367 additions & 163 deletions src/app/gateway/assets/connector-default-configs/rest.json

Large diffs are not rendered by default.

37 changes: 33 additions & 4 deletions src/app/gateway/assets/locale/locale.constant-en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
"certificates": "Certificates"
}
},
"certificate": "Certificate",
"CA-certificate-path": "Path to CA certificate file",
"path-to-CA-cert-required": "Path to CA certificate file is required.",
"change-connector-title": "Confirm connector change",
Expand Down Expand Up @@ -185,7 +186,7 @@
"payload-type": "Payload type",
"platform-side": "Platform side",
"JSON": "JSON",
"JSON-hint": "Converter for this payload type processes MQTT messages in JSON format. It uses JSON Path expressions to extract vital details such as device names, device profile names, attributes, and time series from the message. And regular expressions to get device details from topics.",
"JSON-hint": "Converter for this payload type processes messages in JSON format. It uses JSON Path expressions to extract vital details such as device names, device profile names, attributes, and time series from the message. And regular expressions to get device details from topics.",
"byte": "Byte",
"bytes": "Bytes",
"bytes-hint": "Converter for this payload type designed for binary MQTT payloads, this converter directly interprets binary data to retrieve device names and device profile names, along with attributes and time series, using specific byte positions for data extraction.",
Expand Down Expand Up @@ -373,6 +374,28 @@
"retries": "Retries",
"retries-on-empty": "Retries on empty",
"retries-on-invalid": "Retries on invalid",
"response": "Response",
"rest": {
"add-http-header": "Add HTTP header",
"no-http-headers": "No HTTP headers",
"delete-http-header": "Delete HTTP header",
"ssl-verify": "SSLVerify",
"endpoint": "Endpoint",
"http-methods": "HTTP methods",
"on-error": "On error",
"on-success": "On success",
"tries": "Tries",
"http-headers": "HTTP headers",
"allow-redirects": "Allow redirects",
"request-url-expression": "Request URL expression",
"response-attribute": "Response attribute",
"response-expected": "Expected",
"response-type": {
"default": "Default",
"const": "Constant",
"advanced": "Advanced"
}
},
"rpc": {
"title": "{{type}} Connector RPC parameters",
"templates-title": "Connector RPC Templates",
Expand Down Expand Up @@ -476,7 +499,7 @@
"request-topic-expression": "Request topic expression",
"request-client-certificate": "Request client certificate",
"request-topic-expression-required": "Request topic expression is required.",
"response-timeout": "Response timeout (ms)",
"response-timeout": "Response timeout",
"response-timeout-required": "Response timeout is required.",
"response-timeout-limits-error": "Timeout must be more then {{min}} ms.",
"response-topic-Qos": "Response topic QoS",
Expand Down Expand Up @@ -628,6 +651,7 @@
"sqlite": "SQLITE"
},
"suffix": {
"s": "s",
"ms": "ms"
},
"report-strategy": {
Expand All @@ -644,7 +668,8 @@
"const": "Constant",
"identifier": "Identifier",
"path": "Path",
"expression": "Expression"
"expression": "Expression",
"request": "From request"
},
"workers-settings": "Workers settings",
"thingsboard": "ThingsBoard",
Expand All @@ -662,7 +687,7 @@
"thingsboard-port-required": "Port is required.",
"tidy": "Tidy",
"tidy-tip": "Tidy config JSON",
"timeout": "Timeout (ms)",
"timeout": "Timeout",
"timeout-error": "Timeout should be at least {{min}} (ms).",
"title-connectors-json": "Connector {{typeName}} configuration",
"type": "Type",
Expand Down Expand Up @@ -773,6 +798,10 @@
"poll-period-required": "Poll period is required.",
"report-period-required": "Report period is required.",
"report-period-range": "Report period must be greater than 100.",
"rest": {
"endpoint-required": "Endpoint is required.",
"http-methods-required": "HTTP methods are required."
},
"socket": {
"attribute-on-platform-required": "Attribute on platform is required",
"attribute-requests-type": "The type of requested attribute can be “shared” or “client.“",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
///
/// Copyright © 2016-2024 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, Input } from '@angular/core';
import { SharedModule } from '@shared/public-api';
import { CommonModule } from '@angular/common';

@Component({
selector: 'tb-error-icon',
template: `
<mat-icon
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="tooltipText"
class="tb-error">
warning
</mat-icon>
`,
standalone: true,
imports: [
SharedModule,
CommonModule,
],
styles: [`
:host {
display: flex;
width: 40px;
height: 40px;
padding: 10px;
}
mat-icon {
font-size: 20px;
}
`]
})
export class ErrorTooltipIconComponent {
@Input() tooltipText: string = '';
}
1 change: 1 addition & 0 deletions src/app/gateway/shared/components/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@
///
export * from './report-strategy/report-strategy.component';
export * from './gateway-status/gateway-status.component';
export * from './error-icon/error-icon.component';
20 changes: 19 additions & 1 deletion src/app/gateway/shared/models/gateway.models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
ConnectorBaseConfig_v3_5_2,
ConnectorBaseConfig_v3_6,
ConnectorBaseConfig_v3_6_2,
ConnectorBaseConfig_v3_7_0,
ConnectorLegacyConfig
} from '../../states/gateway-connectors/models/public-api';
import { ConfigurationModes, ReportStrategyConfig } from './report-strategy.models';
Expand All @@ -40,6 +41,7 @@ export enum GatewayLogLevel {
}

export enum GatewayVersion {
v3_7_0 = '3.7',
v3_6_3 = '3.6.3',
v3_6_2 = '3.6.2',
v3_6_0 = '3.6',
Expand Down Expand Up @@ -85,7 +87,11 @@ export const GatewayConnectorDefaultTypesTranslatesMap = new Map<ConnectorType,
[ConnectorType.CUSTOM, 'CUSTOM']
]);

export type ConnectorBaseConfig = ConnectorBaseConfig_v3_6_2 | ConnectorBaseConfig_v3_6 | ConnectorBaseConfig_v3_5_2 | ConnectorLegacyConfig;
export type ConnectorBaseConfig = ConnectorLegacyConfig
| ConnectorBaseConfig_v3_6_2
| ConnectorBaseConfig_v3_6
| ConnectorBaseConfig_v3_5_2
| ConnectorBaseConfig_v3_7_0;

export interface GatewayConnector<BaseConfig = ConnectorBaseConfig> extends GatewayConnectorBase {
configurationJson: BaseConfig;
Expand Down Expand Up @@ -143,3 +149,15 @@ export interface GatewayConfigCommand {
timeout: number;
installCmd?: string;
}

export enum HTTPMethods {
CONNECT = 'CONNECT',
DELETE = 'DELETE',
GET = 'GET',
HEAD = 'HEAD',
OPTIONS = 'OPTIONS',
PATCH = 'PATCH',
POST = 'POST',
PUT = 'PUT',
TRACE = 'TRACE'
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ export * from './gateway-connector-basic-config.abstract';
export * from './socket-version-processor.abstract';
export * from './bacnet-version-processor.abstract';
export * from './basic-config-entity-table.abstract';
export * from './rest-version-processor.abstract';
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
///
/// Copyright © 2016-2024 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 {
RestBasicConfig,
RestBasicConfig_v3_7,
RestLegacyBasicConfig,
RestRequestsMapping,
RestRequestType,
} from '../models/public-api';
import { RestVersionMappingUtil } from '../utils/public-api';
import { GatewayConnectorVersionProcessor } from './gateway-connector-version-processor.abstract';
import { GatewayConnector } from '../../../shared/models/public-api';

export class RestVersionProcessor extends GatewayConnectorVersionProcessor<RestBasicConfig> {

private readonly restRequestTypeKeys = Object.values(RestRequestType);

constructor(
protected gatewayVersionIn: string,
protected connector: GatewayConnector<RestBasicConfig>
) {
super(gatewayVersionIn, connector);
}

getUpgradedVersion(): GatewayConnector<RestBasicConfig_v3_7> {
const {
attributeRequests = [],
attributeUpdates = [],
serverSideRpc = [],
mapping = [],
...server
} = this.connector.configurationJson as RestLegacyBasicConfig;
let configurationJson = {
server,
requestsMapping: { attributeRequests, attributeUpdates, serverSideRpc },
mapping: RestVersionMappingUtil.mapMappingToUpgradedVersion(mapping),
};

this.restRequestTypeKeys.forEach((key: RestRequestType) => {
const { [key]: removedValue, ...rest } = configurationJson as RestBasicConfig_v3_7 & RestLegacyBasicConfig;
configurationJson = { ...rest } as any;
});

return {
...this.connector,
configurationJson,
configVersion: this.gatewayVersionIn
} as GatewayConnector<RestBasicConfig_v3_7>;
}

getDowngradedVersion(): GatewayConnector<RestLegacyBasicConfig> {
const { requestsMapping, mapping, server, ...restConfig } = this.connector.configurationJson as RestBasicConfig_v3_7;
const { attributeRequests = [], attributeUpdates = [], serverSideRpc = [] } = requestsMapping as RestRequestsMapping;

return {
...this.connector,
configurationJson: {
...restConfig,
...server,
attributeRequests,
attributeUpdates,
serverSideRpc,
mapping: RestVersionMappingUtil.mapMappingToDowngradedVersion(mapping),
} as RestLegacyBasicConfig,
configVersion: this.gatewayVersionIn
} as GatewayConnector<RestLegacyBasicConfig>;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
export * from './application-config/bacnet-application-config.component';
export * from './device-data-keys-pannel/bacnet-device-data-keys-panel.component';
export * from './basic-config/bacnet-basic-config.component';
export * from './basic-config/bacnet-legacy-basic-config.component';
export * from './device-data-key/bacnet-device-data-key.component';
export * from './device-dialog/bacnet-device-dialog.component';
export * from './devices-config-table/bacnet-devices-config-table.component';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import {
MQTTSourceType,
SourceTypeTranslationsMap,
SourceType,
ConvertorType
ConverterType
} from '../../models/public-api';
import { coerceBoolean, PageComponent, SharedModule } from '@shared/public-api';
import { CommonModule } from '@angular/common';
Expand Down Expand Up @@ -93,7 +93,7 @@ export class DeviceInfoTableComponent extends PageComponent implements ControlVa

@Input() connectorType: ConnectorType = ConnectorType.MQTT;

@Input() convertorType: ConvertorType;
@Input() convertorType: ConverterType;

@Input()
sourceTypes: Array<SourceType> = Object.values(MQTTSourceType) as Array<SourceType>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import { Store } from '@ngrx/store';
import { PageComponent } from '@shared/public-api';
import { isDefinedAndNotNull, AppState } from '@core/public-api';
import {
ConvertorType,
MqttConverterType,
MappingDataKey,
MappingKeysType,
OPCUaSourceType,
Expand Down Expand Up @@ -76,7 +76,7 @@ export class MappingDataKeysPanelComponent extends PageComponent implements OnIn
@Input() keys: Array<MappingDataKey> | {[key: string]: any};
@Input() keysType: MappingKeysType;
@Input() connectorType: ConnectorType;
@Input() convertorType: ConvertorType;
@Input() convertorType: MqttConverterType;
@Input() sourceType: SourceType;
@Input() valueTypeEnum = MappingValueType;
@Input() valueTypes: Map<string, unknown> = mappingValueTypesMap;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -569,16 +569,13 @@ <h2>{{ MappingTypeTranslationsMap.get(this.data?.mappingType) | translate}}</h2>
<mat-form-field class="tb-flex" appearance="outline" subscriptSizing="dynamic">
<input matInput name="value" type="number" min="1" formControlName="responseTimeout"
placeholder="{{ 'gateway.set' | translate }}"/>
<mat-icon matSuffix
matTooltipPosition="above"
matTooltipClass="tb-error-tooltip"
[matTooltip]="responseTimeoutErrorTooltip"
*ngIf="(mappingForm.get('requestValue.serverSideRpc.responseTimeout').hasError('required') ||
mappingForm.get('requestValue.serverSideRpc.responseTimeout').hasError('min')) &&
mappingForm.get('requestValue.serverSideRpc.responseTimeout').touched"
class="tb-error">
warning
</mat-icon>
@if ((mappingForm.get('requestValue.serverSideRpc.responseTimeout').hasError('required')
|| mappingForm.get('requestValue.serverSideRpc.responseTimeout').hasError('min'))
&& mappingForm.get('requestValue.serverSideRpc.responseTimeout').touched) {
<tb-error-icon matSuffix [tooltipText]="responseTimeoutErrorTooltip"/>
} @else {
<span translate class="block pr-2" matSuffix>gateway.suffix.ms</span>
}
</mat-form-field>
</div>
</ng-container>
Expand Down
Loading