22 changed files with 846 additions and 43 deletions
@ -0,0 +1,226 @@ |
|||||
|
<!-- |
||||
|
|
||||
|
Copyright © 2016-2023 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. |
||||
|
|
||||
|
--> |
||||
|
<mat-toolbar color="primary"> |
||||
|
<h2 translate>device.connectivity.check-connectivity</h2> |
||||
|
<span fxFlex></span> |
||||
|
<!-- <div [tb-help]="'check-connectivity'"></div>--> |
||||
|
<button mat-icon-button |
||||
|
(click)="close()" |
||||
|
type="button"> |
||||
|
<mat-icon class="material-icons">close</mat-icon> |
||||
|
</button> |
||||
|
</mat-toolbar> |
||||
|
<div mat-dialog-content> |
||||
|
<section *ngIf="loadedCommand; else loadingCommand" class="tb-form-panel no-padding no-border"> |
||||
|
<tb-toggle-header #transportProtocol |
||||
|
value="{{ selectTransportType }}" |
||||
|
name="TransportProtocol" |
||||
|
useSelectOnMdLg="false" |
||||
|
appearance="fill" |
||||
|
[fxHide]="allowTransportType.size < 2"> |
||||
|
<tb-toggle-option |
||||
|
*ngIf="allowTransportType.has(BasicTransportType.HTTP)" |
||||
|
[value]="BasicTransportType.HTTP"> |
||||
|
{{ deviceTransportTypeTranslationMap.get(BasicTransportType.HTTP) | translate }} |
||||
|
</tb-toggle-option> |
||||
|
<tb-toggle-option |
||||
|
*ngIf="allowTransportType.has(DeviceTransportType.MQTT)" |
||||
|
[value]="DeviceTransportType.MQTT"> |
||||
|
{{ deviceTransportTypeTranslationMap.get(DeviceTransportType.MQTT) | translate }} |
||||
|
</tb-toggle-option> |
||||
|
<tb-toggle-option |
||||
|
*ngIf="allowTransportType.has(DeviceTransportType.COAP)" |
||||
|
[value]="DeviceTransportType.COAP"> |
||||
|
{{ deviceTransportTypeTranslationMap.get(DeviceTransportType.COAP) | translate }} |
||||
|
</tb-toggle-option> |
||||
|
<tb-toggle-option |
||||
|
*ngIf="allowTransportType.has(DeviceTransportType.SNMP)" |
||||
|
[value]="DeviceTransportType.SNMP"> |
||||
|
{{ deviceTransportTypeTranslationMap.get(DeviceTransportType.SNMP) | translate }} |
||||
|
</tb-toggle-option> |
||||
|
<tb-toggle-option |
||||
|
*ngIf="allowTransportType.has(DeviceTransportType.LWM2M)" |
||||
|
[value]="DeviceTransportType.LWM2M"> |
||||
|
{{ deviceTransportTypeTranslationMap.get(DeviceTransportType.LWM2M) | translate }} |
||||
|
</tb-toggle-option> |
||||
|
</tb-toggle-header> |
||||
|
<div class="tb-form-panel stroked" [fxHide]="!allowTransportType.size"> |
||||
|
<ng-container [ngSwitch]="transportProtocol.value"> |
||||
|
<ng-template [ngSwitchCase]="BasicTransportType.HTTP"> |
||||
|
<div class="tb-form-panel-hint tb-font-14" translate>device.connectivity.use-following-instructions</div> |
||||
|
<div class="tb-hint-instruction"> |
||||
|
<span class="content tb-form-panel-hint" translate>device.connectivity.install-curl</span> |
||||
|
<span tb-help-popup="device/install_curl" |
||||
|
tb-help-popup-placement="bottom" |
||||
|
trigger-style="letter-spacing:0.25px; font-size: 12px" |
||||
|
[tb-help-popup-style]="{maxWidth: '800px'}" |
||||
|
trigger-text="{{ 'action.see-documentation' | translate }}"></span> |
||||
|
</div> |
||||
|
<div *ngIf="commands.http"> |
||||
|
<div class="tb-form-panel-hint tb-font-14" translate>device.connectivity.http-command</div> |
||||
|
<tb-markdown usePlainMarkdown containerClass="tb-command-code" |
||||
|
[data]=createMarkDownCommand(commands.http)></tb-markdown> |
||||
|
</div> |
||||
|
<div *ngIf="commands.https"> |
||||
|
<div class="tb-form-panel-hint tb-font-14" translate>device.connectivity.https-command</div> |
||||
|
<tb-markdown usePlainMarkdown containerClass="tb-command-code" |
||||
|
[data]=createMarkDownCommand(commands.https)></tb-markdown> |
||||
|
</div> |
||||
|
</ng-template> |
||||
|
<ng-template [ngSwitchCase]="DeviceTransportType.MQTT"> |
||||
|
<div *ngIf="!(commands.mqtts && commands.mqtts === 'Check documentation')" class="tb-form-panel no-padding no-border"> |
||||
|
<div class="tb-form-panel-hint tb-font-14" translate>device.connectivity.use-following-instructions</div> |
||||
|
<div class="tb-hint-instruction"> |
||||
|
<span class="content tb-form-panel-hint" translate>device.connectivity.install-mqtt-client</span> |
||||
|
<span tb-help-popup="device/install_mqtt_client" |
||||
|
tb-help-popup-placement="bottom" |
||||
|
trigger-style="letter-spacing:0.25px; font-size: 12px" |
||||
|
[tb-help-popup-style]="{maxWidth: '800px'}" |
||||
|
trigger-text="{{ 'action.see-documentation' | translate }}"></span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div *ngIf="commands.mqtt"> |
||||
|
<div class="tb-form-panel-hint tb-font-14" translate>device.connectivity.mqtt-command</div> |
||||
|
<tb-markdown usePlainMarkdown containerClass="tb-command-code" |
||||
|
[data]=createMarkDownCommand(commands.mqtt)></tb-markdown> |
||||
|
</div> |
||||
|
<div *ngIf="commands.mqtts"> |
||||
|
<div *ngIf="commands.mqtts !== 'Check documentation'; else mqttCertificate"> |
||||
|
<div class="tb-form-panel-hint tb-font-14" translate>device.connectivity.mqtts-command</div> |
||||
|
<tb-markdown usePlainMarkdown containerClass="tb-command-code" |
||||
|
[data]=createMarkDownCommand(commands.mqtts)></tb-markdown> |
||||
|
</div> |
||||
|
<ng-template #mqttCertificate> |
||||
|
<div class="tb-form-panel-hint tb-font-14" translate>device.connectivity.mqtts-x509-command</div> |
||||
|
<div> |
||||
|
<a mat-button color="primary" href="https://thingsboard.io/docs/user-guide/certificates/?ubuntuThingsboardX509=x509Chain" target="_blank"> |
||||
|
<span> |
||||
|
{{ 'action.see-documentation' | translate }} |
||||
|
<mat-icon class="tb-mat-18">open_in_new</mat-icon> |
||||
|
</span> |
||||
|
</a> |
||||
|
</div> |
||||
|
</ng-template> |
||||
|
</div> |
||||
|
</ng-template> |
||||
|
<ng-template [ngSwitchCase]="DeviceTransportType.COAP"> |
||||
|
<div *ngIf="!(commands.coaps && commands.coaps === 'Check documentation')" class="tb-form-panel no-padding no-border"> |
||||
|
<div class="tb-form-panel-hint tb-font-14" translate>device.connectivity.use-following-instructions</div> |
||||
|
<div class="tb-hint-instruction"> |
||||
|
<span class="content tb-form-panel-hint" translate>device.connectivity.install-coap-cli</span> |
||||
|
<span tb-help-popup="device/install_coap_client" |
||||
|
tb-help-popup-placement="bottom" |
||||
|
trigger-style="letter-spacing:0.25px; font-size: 12px" |
||||
|
[tb-help-popup-style]="{maxWidth: '800px'}" |
||||
|
trigger-text="{{ 'action.see-documentation' | translate }}"></span> |
||||
|
</div> |
||||
|
</div> |
||||
|
<div *ngIf="commands.coap"> |
||||
|
<div class="tb-form-panel-hint tb-font-14" translate>device.connectivity.coap-command</div> |
||||
|
<tb-markdown usePlainMarkdown containerClass="tb-command-code" |
||||
|
[data]=createMarkDownCommand(commands.coap)></tb-markdown> |
||||
|
</div> |
||||
|
<div *ngIf="commands.coaps"> |
||||
|
<div *ngIf="commands.coaps !== 'Check documentation'; else coapCertificate"> |
||||
|
<div class="tb-form-panel-hint tb-font-14" translate>device.connectivity.coaps-command</div> |
||||
|
<tb-markdown usePlainMarkdown containerClass="tb-command-code" |
||||
|
[data]=createMarkDownCommand(commands.coaps)></tb-markdown> |
||||
|
</div> |
||||
|
<ng-template #coapCertificate> |
||||
|
<div class="tb-form-panel-hint tb-font-14" translate>device.connectivity.coaps-x509-command</div> |
||||
|
<div> |
||||
|
<a mat-button color="primary" href="https://thingsboard.io/docs/user-guide/ssl/coap-x509-certificates/" target="_blank"> |
||||
|
<span> |
||||
|
{{ 'action.see-documentation' | translate }} |
||||
|
<mat-icon class="tb-mat-18">open_in_new</mat-icon> |
||||
|
</span> |
||||
|
</a> |
||||
|
</div> |
||||
|
</ng-template> |
||||
|
</div> |
||||
|
</ng-template> |
||||
|
<ng-template [ngSwitchCase]="DeviceTransportType.SNMP"> |
||||
|
<div class="tb-form-panel-hint tb-font-14" translate>device.connectivity.snmp-command</div> |
||||
|
<div> |
||||
|
<a mat-button color="primary" href="https://thingsboard.io/docs/reference/snmp-api/" target="_blank"> |
||||
|
<span> |
||||
|
{{ 'action.see-documentation' | translate }} |
||||
|
<mat-icon class="tb-mat-18">open_in_new</mat-icon> |
||||
|
</span> |
||||
|
</a> |
||||
|
</div> |
||||
|
</ng-template> |
||||
|
<ng-template [ngSwitchCase]="DeviceTransportType.LWM2M"> |
||||
|
<div class="tb-form-panel-hint tb-font-14" translate>device.connectivity.lwm2m-command</div> |
||||
|
<div> |
||||
|
<a mat-button color="primary" href="https://thingsboard.io/docs/reference/lwm2m-api/" target="_blank"> |
||||
|
<span> |
||||
|
{{ 'action.see-documentation' | translate }} |
||||
|
<mat-icon class="tb-mat-18">open_in_new</mat-icon> |
||||
|
</span> |
||||
|
</a> |
||||
|
</div> |
||||
|
</ng-template> |
||||
|
</ng-container> |
||||
|
</div> |
||||
|
<div class="tb-form-panel stroked"> |
||||
|
<div fxFlex fxLayout="row"> |
||||
|
<div class="tb-form-panel-title" translate>device.state</div> |
||||
|
<div class="status" [ngClass]="{'inactive': !status}"> |
||||
|
{{ (status ? 'device.active' : 'device.inactive') | translate }} |
||||
|
</div> |
||||
|
</div> |
||||
|
<div class="tb-form-panel-hint tb-font-14" translate>attribute.latest-telemetry</div> |
||||
|
<div class="tb-form-table"> |
||||
|
<div class="tb-form-table-header"> |
||||
|
<div class="tb-form-table-header-cell" fxFlex translate>device.time</div> |
||||
|
<div class="tb-form-table-header-cell" fxFlex translate>attribute.key</div> |
||||
|
<div class="tb-form-table-header-cell" fxFlex translate>attribute.value</div> |
||||
|
</div> |
||||
|
<div *ngIf="latestTelemetry.length; else noData" class="tb-form-table-body"> |
||||
|
<div class="tb-form-table-row" *ngFor="let telemetry of latestTelemetry"> |
||||
|
<div class="tb-form-table-row-cell" fxFlex>{{ telemetry.lastUpdateTs | date: 'yyyy-MM-dd HH:mm:ss' }}</div> |
||||
|
<div class="tb-form-table-row-cell" fxFlex>{{ telemetry.key }}</div> |
||||
|
<div class="tb-form-table-row-cell" fxFlex>{{ telemetry.value }}</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
</div> |
||||
|
<div mat-dialog-actions class="tb-dialog-actions"> |
||||
|
<mat-slide-toggle fxShow="{{ showDontShowAgain }}" [(ngModel)]="notShowAgain">{{ 'action.dont-show-again' | translate}}</mat-slide-toggle> |
||||
|
<span fxFlex></span> |
||||
|
<button mat-button |
||||
|
[disabled]="(isLoading$ | async)" |
||||
|
(click)="close()">{{ 'action.cancel' | translate }}</button> |
||||
|
</div> |
||||
|
<ng-template #loadingCommand> |
||||
|
<div class="tb-loader"> |
||||
|
<mat-spinner color="accent" diameter="65" strokeWidth="4"></mat-spinner> |
||||
|
<span class="mat-subtitle-1 label"> |
||||
|
{{ 'device.connectivity.loading-check-connectivity-command' | translate }} |
||||
|
</span> |
||||
|
</div> |
||||
|
</ng-template> |
||||
|
<ng-template #noData> |
||||
|
<div class="tb-no-data-available"> |
||||
|
<div class="tb-no-data-bg"></div> |
||||
|
<div class="tb-no-data-text" translate>attribute.no-latest-telemetry</div> |
||||
|
</div> |
||||
|
</ng-template> |
||||
@ -0,0 +1,151 @@ |
|||||
|
/** |
||||
|
* Copyright © 2016-2023 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 "../../../../../scss/constants"; |
||||
|
|
||||
|
:host { |
||||
|
height: 100%; |
||||
|
max-height: 100vh; |
||||
|
display: grid; |
||||
|
grid-template-rows: min-content minmax(auto, 1fr) min-content; |
||||
|
|
||||
|
.tb-loader { |
||||
|
display: flex; |
||||
|
flex-direction: column; |
||||
|
align-items: center; |
||||
|
justify-content: center; |
||||
|
gap: 16px; |
||||
|
height: 300px; |
||||
|
max-height: 100%; |
||||
|
|
||||
|
.label { |
||||
|
margin-bottom: 0; |
||||
|
text-align: center; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.status { |
||||
|
margin-left: 12px; |
||||
|
border-radius: 12px; |
||||
|
height: 24px; |
||||
|
line-height: 24px; |
||||
|
padding: 0 8px; |
||||
|
width: fit-content; |
||||
|
color: #198038; |
||||
|
background-color: rgba(25, 128, 56, 0.08); |
||||
|
font-size: 14px; |
||||
|
|
||||
|
&.inactive { |
||||
|
color: #d12730; |
||||
|
background-color: rgba(209, 39, 48, 0.08); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.tb-hint-instruction { |
||||
|
border-radius: 6px; |
||||
|
background-color: rgba(48, 86, 128, 0.04); |
||||
|
padding: 6px 16px; |
||||
|
|
||||
|
.content { |
||||
|
vertical-align: middle; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.tb-font-14 { |
||||
|
font-size: 14px; |
||||
|
} |
||||
|
|
||||
|
.tb-form-table-body { |
||||
|
max-height: 88px; |
||||
|
overflow-y: auto; |
||||
|
scrollbar-gutter: stable; |
||||
|
|
||||
|
.tb-form-table-row { |
||||
|
min-height: 38px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
.tb-no-data-available { |
||||
|
.tb-no-data-bg { |
||||
|
min-height: 68px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@media #{$mat-sm} { |
||||
|
width: 470px; |
||||
|
} |
||||
|
|
||||
|
@media #{$mat-gt-sm} { |
||||
|
width: 720px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
:host-context(.mat-mdc-dialog-container) { |
||||
|
.tb-dialog-actions { |
||||
|
display: flex; |
||||
|
gap: 8px; |
||||
|
padding: 8px 16px; |
||||
|
} |
||||
|
|
||||
|
.mat-mdc-dialog-content { |
||||
|
max-height: 80vh; |
||||
|
padding: 16px; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
:host ::ng-deep { |
||||
|
.tb-markdown-view { |
||||
|
.tb-command-code { |
||||
|
.code-wrapper { |
||||
|
padding: 0; |
||||
|
pre[class*=language-] { |
||||
|
background: #F3F6FA; |
||||
|
border-color: #305680; |
||||
|
} |
||||
|
} |
||||
|
button.clipboard-btn { |
||||
|
right: 0; |
||||
|
p { |
||||
|
color: #305680; |
||||
|
} |
||||
|
p, div { |
||||
|
background-color: #F3F6FA; |
||||
|
} |
||||
|
div { |
||||
|
img { |
||||
|
display: none; |
||||
|
} |
||||
|
&:after { |
||||
|
content: ""; |
||||
|
position: initial; |
||||
|
display: block; |
||||
|
width: 18px; |
||||
|
height: 18px; |
||||
|
background: #305680; |
||||
|
mask-image: url(/assets/copy-code-icon.svg); |
||||
|
mask-repeat: no-repeat; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
.mdc-button__label > span { |
||||
|
.mat-icon { |
||||
|
vertical-align: text-bottom; |
||||
|
box-sizing: initial; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,170 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2023 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, Inject, NgZone, OnDestroy, OnInit } from '@angular/core'; |
||||
|
import { DialogComponent } from '@shared/components/dialog.component'; |
||||
|
import { select, Store } from '@ngrx/store'; |
||||
|
import { AppState } from '@core/core.state'; |
||||
|
import { Router } from '@angular/router'; |
||||
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; |
||||
|
import { DeviceService } from '@core/http/device.service'; |
||||
|
import { FormBuilder } from '@angular/forms'; |
||||
|
import { |
||||
|
AttributeData, |
||||
|
AttributeScope, |
||||
|
AttributesSubscriptionCmd, |
||||
|
LatestTelemetry, |
||||
|
TelemetrySubscriber |
||||
|
} from '@shared/models/telemetry/telemetry.models'; |
||||
|
import { TelemetryWebsocketService } from '@core/ws/telemetry-websocket.service'; |
||||
|
import { EntityId } from '@shared/models/id/entity-id'; |
||||
|
import { EntityType } from '@shared/models/entity-type.models'; |
||||
|
import { selectPersistDeviceStateToTelemetry } from '@core/auth/auth.selectors'; |
||||
|
import { take } from 'rxjs/operators'; |
||||
|
import { |
||||
|
BasicTransportType, |
||||
|
DeviceTransportType, |
||||
|
deviceTransportTypeTranslationMap, |
||||
|
NetworkTransportType |
||||
|
} from '@shared/models/device.models'; |
||||
|
import { UserSettingsService } from '@core/http/user-settings.service'; |
||||
|
import { ActionPreferencesUpdateUserSettings } from '@core/auth/auth.actions'; |
||||
|
|
||||
|
export interface DeviceCheckConnectivityDialogData { |
||||
|
deviceId: EntityId; |
||||
|
showDontShowAgain: boolean; |
||||
|
} |
||||
|
@Component({ |
||||
|
selector: 'tb-device-check-connectivity-dialog', |
||||
|
templateUrl: './device-check-connectivity-dialog.component.html', |
||||
|
styleUrls: ['./device-check-connectivity-dialog.component.scss'] |
||||
|
}) |
||||
|
export class DeviceCheckConnectivityDialogComponent extends |
||||
|
DialogComponent<DeviceCheckConnectivityDialogComponent> implements OnInit, OnDestroy { |
||||
|
|
||||
|
loadedCommand = false; |
||||
|
|
||||
|
status: boolean; |
||||
|
|
||||
|
latestTelemetry: Array<AttributeData> = []; |
||||
|
|
||||
|
commands: {[key: string]: string}; |
||||
|
|
||||
|
allowTransportType = new Set<NetworkTransportType>(); |
||||
|
selectTransportType: NetworkTransportType; |
||||
|
|
||||
|
BasicTransportType = BasicTransportType; |
||||
|
DeviceTransportType = DeviceTransportType; |
||||
|
deviceTransportTypeTranslationMap = deviceTransportTypeTranslationMap; |
||||
|
|
||||
|
showDontShowAgain = this.data.showDontShowAgain; |
||||
|
|
||||
|
notShowAgain = false; |
||||
|
|
||||
|
private telemetrySubscriber: TelemetrySubscriber; |
||||
|
|
||||
|
private currentTime = Date.now(); |
||||
|
|
||||
|
private transportTypes = [...Object.keys(BasicTransportType), ...Object.keys(DeviceTransportType)] as Array<NetworkTransportType>; |
||||
|
|
||||
|
constructor(protected store: Store<AppState>, |
||||
|
protected router: Router, |
||||
|
@Inject(MAT_DIALOG_DATA) private data: DeviceCheckConnectivityDialogData, |
||||
|
public dialogRef: MatDialogRef<DeviceCheckConnectivityDialogComponent>, |
||||
|
private fb: FormBuilder, |
||||
|
private deviceService: DeviceService, |
||||
|
private telemetryWsService: TelemetryWebsocketService, |
||||
|
private userSettingsService: UserSettingsService, |
||||
|
private zone: NgZone) { |
||||
|
super(store, router, dialogRef); |
||||
|
} |
||||
|
|
||||
|
ngOnInit() { |
||||
|
this.loadCommands(); |
||||
|
this.subscribeToLatestTelemetry(); |
||||
|
} |
||||
|
|
||||
|
ngOnDestroy() { |
||||
|
super.ngOnDestroy(); |
||||
|
this.telemetrySubscriber?.complete(); |
||||
|
this.telemetrySubscriber?.unsubscribe(); |
||||
|
} |
||||
|
|
||||
|
close(): void { |
||||
|
if (this.notShowAgain && this.showDontShowAgain) { |
||||
|
this.store.dispatch(new ActionPreferencesUpdateUserSettings({ notDisplayConnectivityAfterAddDevice: true })); |
||||
|
this.dialogRef.close(null); |
||||
|
} else { |
||||
|
this.dialogRef.close(null); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
createMarkDownCommand(command: string): string { |
||||
|
return '```bash\n' + |
||||
|
command + |
||||
|
'{:copy-code}\n' + |
||||
|
'```'; |
||||
|
} |
||||
|
|
||||
|
private loadCommands() { |
||||
|
this.deviceService.getDevicePublishTelemetryCommands(this.data.deviceId.id).subscribe( |
||||
|
commands => { |
||||
|
this.commands = commands; |
||||
|
const commandsProtocols = Object.keys(commands); |
||||
|
this.transportTypes.forEach(transport => { |
||||
|
const findCommand = commandsProtocols.find(item => item.toUpperCase().startsWith(transport)); |
||||
|
if (findCommand) { |
||||
|
this.allowTransportType.add(transport); |
||||
|
} |
||||
|
}); |
||||
|
this.selectTransportType = this.allowTransportType.values().next().value; |
||||
|
this.loadedCommand = true; |
||||
|
} |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
private subscribeToLatestTelemetry() { |
||||
|
this.store.pipe(select(selectPersistDeviceStateToTelemetry)).pipe( |
||||
|
take(1) |
||||
|
).subscribe(persistToTelemetry => { |
||||
|
this.telemetrySubscriber = TelemetrySubscriber.createEntityAttributesSubscription( |
||||
|
this.telemetryWsService, this.data.deviceId, LatestTelemetry.LATEST_TELEMETRY, this.zone); |
||||
|
if (!persistToTelemetry) { |
||||
|
const subscriptionCommand = new AttributesSubscriptionCmd(); |
||||
|
subscriptionCommand.entityType = this.data.deviceId.entityType as EntityType; |
||||
|
subscriptionCommand.entityId = this.data.deviceId.id; |
||||
|
subscriptionCommand.scope = AttributeScope.SERVER_SCOPE; |
||||
|
subscriptionCommand.keys = 'active'; |
||||
|
this.telemetrySubscriber.subscriptionCommands.push(subscriptionCommand); |
||||
|
} |
||||
|
|
||||
|
this.telemetrySubscriber.subscribe(); |
||||
|
this.telemetrySubscriber.attributeData$().subscribe( |
||||
|
(data) => { |
||||
|
this.latestTelemetry = data.reduce<Array<AttributeData>>((accumulator, item) => { |
||||
|
if (item.key === 'active') { |
||||
|
this.status = item.value; |
||||
|
} else if (item.lastUpdateTs > this.currentTime) { |
||||
|
accumulator.push(item); |
||||
|
} |
||||
|
return accumulator; |
||||
|
}, []); |
||||
|
} |
||||
|
); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
#### CoAP installation instructions |
||||
|
--- |
||||
|
<br /> |
||||
|
|
||||
|
Install coap client tool on your **Linux/macOS**: |
||||
|
|
||||
|
```bash |
||||
|
git clone https://github.com/obgm/libcoap --recursive |
||||
|
{:copy-code} |
||||
|
``` |
||||
|
<br /> |
||||
|
|
||||
|
```bash |
||||
|
cd libcoap |
||||
|
{:copy-code} |
||||
|
``` |
||||
|
<br /> |
||||
|
|
||||
|
```bash |
||||
|
./autogen.sh |
||||
|
{:copy-code} |
||||
|
``` |
||||
|
<br /> |
||||
|
|
||||
|
```bash |
||||
|
./configure --with-openssl --disable-doxygen --disable-manpages --disable-shared |
||||
|
{:copy-code} |
||||
|
``` |
||||
|
<br /> |
||||
|
|
||||
|
```bash |
||||
|
make |
||||
|
{:copy-code} |
||||
|
``` |
||||
|
<br /> |
||||
|
|
||||
|
```bash |
||||
|
sudo make install |
||||
|
{:copy-code} |
||||
|
``` |
||||
@ -0,0 +1,34 @@ |
|||||
|
#### cURL installation instructions |
||||
|
--- |
||||
|
<section style="margin: 18px 0"> |
||||
|
<div style="margin: 0 32px"> |
||||
|
<tb-toggle-header #publishCommandSteps value="ubuntu" name="publishCommandSteps" useSelectOnMdLg="false" appearance="fill"> |
||||
|
<tb-toggle-option value="ubuntu">Ubuntu</tb-toggle-option> |
||||
|
<tb-toggle-option value="macos">MacOS</tb-toggle-option> |
||||
|
<tb-toggle-option value="windows">Windows</tb-toggle-option> |
||||
|
</tb-toggle-header> |
||||
|
</div> |
||||
|
<ng-container [ngSwitch]="publishCommandSteps.value"> |
||||
|
<ng-template [ngSwitchCase]="'ubuntu'"> |
||||
|
<p style="margin-top: 18px; padding: 0 32px">Install cURL tool:</p> |
||||
|
<tb-markdown usePlainMarkdown containerClass="tb-getting-started-code" data=" |
||||
|
```bash |
||||
|
sudo apt-get install curl |
||||
|
{:copy-code} |
||||
|
``` |
||||
|
"></tb-markdown> |
||||
|
</ng-template> |
||||
|
<ng-template [ngSwitchCase]="'macos'"> |
||||
|
<p style="margin-top: 18px; padding: 0 32px">Install cURL tool:</p> |
||||
|
<tb-markdown usePlainMarkdown containerClass="tb-getting-started-code" data=" |
||||
|
```bash |
||||
|
brew install curl |
||||
|
{:copy-code} |
||||
|
``` |
||||
|
"></tb-markdown> |
||||
|
</ng-template> |
||||
|
<ng-template [ngSwitchCase]="'windows'"> |
||||
|
<div style="margin-top: 18px; padding: 0 32px; width: 404px;">Starting Windows 10 b17063, cURL is available by default.</div> |
||||
|
</ng-template> |
||||
|
</ng-container> |
||||
|
</section> |
||||
@ -0,0 +1,38 @@ |
|||||
|
#### MQTT client tool installation instructions |
||||
|
--- |
||||
|
<section style="margin: 18px 0"> |
||||
|
<div style="margin: 0 32px"> |
||||
|
<tb-toggle-header #publishCommandSteps value="ubuntu" name="publishCommandSteps" useSelectOnMdLg="false" appearance="fill"> |
||||
|
<tb-toggle-option value="ubuntu">Ubuntu</tb-toggle-option> |
||||
|
<tb-toggle-option value="macos">MacOS</tb-toggle-option> |
||||
|
<tb-toggle-option value="windows">Windows</tb-toggle-option> |
||||
|
</tb-toggle-header> |
||||
|
</div> |
||||
|
<ng-container [ngSwitch]="publishCommandSteps.value"> |
||||
|
<ng-template [ngSwitchCase]="'ubuntu'"> |
||||
|
<p style="margin-top: 18px; padding: 0 32px">Install mqtt client tool:</p> |
||||
|
<tb-markdown usePlainMarkdown containerClass="tb-getting-started-code" data=" |
||||
|
```bash |
||||
|
sudo apt-get install curl mosquitto-clients |
||||
|
{:copy-code} |
||||
|
``` |
||||
|
"></tb-markdown> |
||||
|
</ng-template> |
||||
|
<ng-template [ngSwitchCase]="'macos'"> |
||||
|
<p style="margin-top: 18px; padding: 0 32px">Install mqtt client tool:</p> |
||||
|
<tb-markdown usePlainMarkdown containerClass="tb-getting-started-code" data=" |
||||
|
```bash |
||||
|
brew install mosquitto-clients |
||||
|
{:copy-code} |
||||
|
``` |
||||
|
"></tb-markdown> |
||||
|
</ng-template> |
||||
|
<ng-template [ngSwitchCase]="'windows'"> |
||||
|
<p style="margin-top: 18px; padding: 0 32px">Install mqtt client tool:</p> |
||||
|
<a mat-stroked-button color="primary" class="ignore-style-a" |
||||
|
style="margin: 8px 32px" |
||||
|
href="https://thingsboard.io/docs/getting-started-guides/helloworld/?connectdevice=mqtt-windows#step-2-connect-device" target="_blank"> |
||||
|
<mat-icon>description</mat-icon>How to install MQTT Box</a> |
||||
|
</ng-template> |
||||
|
</ng-container> |
||||
|
</section> |
||||
@ -0,0 +1,21 @@ |
|||||
|
///
|
||||
|
/// Copyright © 2016-2023 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.
|
||||
|
///
|
||||
|
|
||||
|
type NestedKeyOf<ObjectType extends object> = |
||||
|
{[Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends object |
||||
|
? `${Key}` | `${Key}.${NestedKeyOf<ObjectType[Key]> extends infer U extends string ? U : never}` |
||||
|
: `${Key}` |
||||
|
}[keyof ObjectType & (string | number)]; |
||||
Loading…
Reference in new issue