Skip to content

Commit 155421b

Browse files
Merge pull request #169 from OS2iot/feature/IoT-640_DownlinkQueue
Feature/IoT_640 - downlink queue
2 parents 8564edd + bf161e2 commit 155421b

21 files changed

+488
-152
lines changed

src/app/applications/iot-devices/iot-device-detail/downlink/downlink-dialog/downlink-dialog.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<h1 mat-dialog-title>{{ "IOTDEVICE.DOWNLINK.DIALOG-TITLE" | translate }}</h1>
1+
<h1 mat-dialog-title>{{ "IOTDEVICE.DOWNLINK.FLUSH-QUEUE" | translate }}</h1>
22
<div mat-dialog-content>
33
{{ "IOTDEVICE.DOWNLINK.DIALOG-MESSAGE" | translate }}
44
</div>

src/app/applications/iot-devices/iot-device-detail/downlink/downlink-dialog/downlink-dialog.component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Component, OnInit } from "@angular/core";
22
import { MatDialogRef } from "@angular/material/dialog";
33
import { TranslateService } from "@ngx-translate/core";
4-
import { DownlinkComponent } from "../downlink.component";
4+
import { DownlinkComponent } from "../downlinks/downlink.component";
55

66
@Component({
77
selector: "app-downlink-dialog",
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export class DownlinkQueueDto {
2+
fCntDown: number;
3+
payload: string;
4+
port: number;
5+
sendAt: Date;
6+
acknowledgedAt: Date;
7+
acknowledged: boolean;
8+
createdAt: Date;
9+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<div *ngIf="device.type === 'LORAWAN'" class="jumbotron jumbotron--full-width">
2+
<h3 class="headerStyle">{{ "IOTDEVICE.DOWNLINK.DOWNLINKQUEUE" | translate }}</h3>
3+
<div class="mat-elevation-z8">
4+
<table mat-table [dataSource]="downlinkQueue">
5+
<div class="loading-shade" *ngIf="isLoadingResults">
6+
<mat-spinner *ngIf="isLoadingResults"></mat-spinner>
7+
</div>
8+
<!-- Created At Column -->
9+
<ng-container matColumnDef="createdAt">
10+
<th mat-header-cell *matHeaderCellDef>
11+
{{ "IOTDEVICE.CREATED" | translate }}
12+
</th>
13+
<td mat-cell *matCellDef="let element">
14+
{{ element.createdAt | dkTimeWithSeconds }}
15+
</td>
16+
</ng-container>
17+
18+
<!-- fCntDown Column -->
19+
<ng-container matColumnDef="status">
20+
<th mat-header-cell *matHeaderCellDef>{{ "USERS.STATUS" | translate }}</th>
21+
<td mat-cell *matCellDef="let element">
22+
{{ getStatus(element) }}
23+
</td>
24+
</ng-container>
25+
26+
<!-- Payload Column -->
27+
<ng-container matColumnDef="payload">
28+
<th mat-header-cell *matHeaderCellDef>{{ "IOTDEVICE.DOWNLINK.PAYLOADTITLE" | translate }}</th>
29+
<td mat-cell *matCellDef="let element">
30+
{{ element.payload }}
31+
</td>
32+
</ng-container>
33+
34+
<!-- Port Column -->
35+
<ng-container matColumnDef="port">
36+
<th mat-header-cell *matHeaderCellDef>{{ "IOTDEVICE.MQTT.PORT" | translate }}</th>
37+
<td mat-cell *matCellDef="let element">
38+
{{ element.port }}
39+
</td>
40+
</ng-container>
41+
42+
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
43+
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
44+
</table>
45+
</div>
46+
<div class="mt-5 buttons">
47+
<button (click)="handleFlushQueue()" class="btn btn-secondary" type="button">
48+
{{ "IOTDEVICE.DOWNLINK.FLUSH-QUEUE" | translate }}
49+
</button>
50+
51+
<button (click)="handleReload()" class="btn btn-secondary" type="button">
52+
{{ "IOTDEVICE.DOWNLINK.RELOAD" | translate }}
53+
</button>
54+
</div>
55+
</div>
56+
57+
<div *ngIf="device.type === 'LORAWAN'" class="jumbotron jumbotron--full-width">
58+
<h3 class="headerStyle">{{ "IOTDEVICE.DOWNLINK.HISTORICQUEUE" | translate }}</h3>
59+
<div class="mat-elevation-z8">
60+
<table mat-table [dataSource]="downlinkHistoryQueue">
61+
<div class="loading-shade" *ngIf="isLoadingResults">
62+
<mat-spinner *ngIf="isLoadingResults"></mat-spinner>
63+
</div>
64+
<!-- Created At Column -->
65+
<ng-container matColumnDef="createdAt">
66+
<th mat-header-cell *matHeaderCellDef>
67+
{{ "IOTDEVICE.CREATED" | translate }}
68+
</th>
69+
<td mat-cell *matCellDef="let element">
70+
{{ element.createdAt | dkTimeWithSeconds }}
71+
</td>
72+
</ng-container>
73+
74+
<!-- Send At Column -->
75+
<ng-container matColumnDef="sendAt">
76+
<th mat-header-cell *matHeaderCellDef>
77+
{{ "IOTDEVICE.DOWNLINK.SENDAT" | translate }}
78+
</th>
79+
<td mat-cell *matCellDef="let element">
80+
{{ element.sendAt | dkTimeWithSeconds }}
81+
</td>
82+
</ng-container>
83+
84+
<!-- AcknowledgedAt Column -->
85+
<ng-container matColumnDef="acknowledgedAt">
86+
<th mat-header-cell *matHeaderCellDef>{{ "IOTDEVICE.DOWNLINK.RECEIVEDAT" | translate }}</th>
87+
<td mat-cell *matCellDef="let element">
88+
{{
89+
element.acknowledgedAt
90+
? (element.acknowledgedAt | dkTimeWithSeconds)
91+
: ("IOTDEVICE.DOWNLINK.NOT-RECEIVED" | translate)
92+
}}
93+
</td>
94+
</ng-container>
95+
96+
<!-- fCntDown Column -->
97+
<ng-container matColumnDef="status">
98+
<th mat-header-cell *matHeaderCellDef>{{ "USERS.STATUS" | translate }}</th>
99+
<td mat-cell *matCellDef="let element">
100+
{{ getStatus(element) }}
101+
</td>
102+
</ng-container>
103+
104+
<!-- fCntDown Column -->
105+
<ng-container matColumnDef="fCntDown">
106+
<th mat-header-cell *matHeaderCellDef>{{ "IOTDEVICE.DOWNLINK.FRAMECOUNTER" | translate }}</th>
107+
<td mat-cell *matCellDef="let element">
108+
{{ element.fCntDown }}
109+
</td>
110+
</ng-container>
111+
112+
<!-- Acknowledged Column -->
113+
<ng-container matColumnDef="acknowledged">
114+
<th mat-header-cell *matHeaderCellDef>{{ "IOTDEVICE.DOWNLINK.CONFIRMED" | translate }}</th>
115+
<td mat-cell *matCellDef="let element">
116+
{{ isAcknowledged(element) }}
117+
</td>
118+
</ng-container>
119+
120+
<!-- Payload Column -->
121+
<ng-container matColumnDef="payload">
122+
<th mat-header-cell *matHeaderCellDef>{{ "IOTDEVICE.DOWNLINK.PAYLOADTITLE" | translate }}</th>
123+
<td mat-cell *matCellDef="let element">
124+
{{ element.payload }}
125+
</td>
126+
</ng-container>
127+
128+
<!-- Port Column -->
129+
<ng-container matColumnDef="port">
130+
<th mat-header-cell *matHeaderCellDef>{{ "IOTDEVICE.MQTT.PORT" | translate }}</th>
131+
<td mat-cell *matCellDef="let element">
132+
{{ element.port }}
133+
</td>
134+
</ng-container>
135+
136+
<tr mat-header-row *matHeaderRowDef="displayedColumnsHistory"></tr>
137+
<tr mat-row *matRowDef="let row; columns: displayedColumnsHistory"></tr>
138+
</table>
139+
</div>
140+
<div class="mt-5 buttons">
141+
<button (click)="handleReload()" class="btn btn-secondary" type="button">
142+
{{ "IOTDEVICE.DOWNLINK.RELOAD" | translate }}
143+
</button>
144+
</div>
145+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.headerStyle {
2+
margin-bottom: 50px !important;
3+
}
4+
5+
.buttons {
6+
gap: 10px;
7+
display: flex;
8+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import { HttpErrorResponse } from "@angular/common/http";
2+
import { Component, Input, OnInit } from "@angular/core";
3+
import { MatDialog } from "@angular/material/dialog";
4+
import { MatSnackBar } from "@angular/material/snack-bar";
5+
import { IotDevice } from "@applications/iot-devices/iot-device.model";
6+
import { TranslateService } from "@ngx-translate/core";
7+
import { DeviceType } from "@shared/enums/device-type";
8+
import { ErrorMessageService } from "@shared/error-message.service";
9+
import { DownlinkService } from "@shared/services/downlink.service";
10+
import { DownlinkDialogComponent } from "../downlink-dialog/downlink-dialog.component";
11+
import { DownlinkQueueDto } from "../downlink-queue-dto";
12+
13+
@Component({
14+
selector: "app-downlink-tables",
15+
templateUrl: "./downlink-tables.component.html",
16+
styleUrls: ["./downlink-tables.component.scss"],
17+
})
18+
export class DownlinkTablesComponent implements OnInit {
19+
@Input() device: IotDevice;
20+
@Input() errorMessages: string[];
21+
@Input() downlinkQueue: DownlinkQueueDto[];
22+
public downlinkHistoryQueue: DownlinkQueueDto[];
23+
public isLoadingResults = false;
24+
public displayedColumns: string[] = ["createdAt", "status", "payload", "port"];
25+
public displayedColumnsHistory: string[] = [
26+
"createdAt",
27+
"sendAt",
28+
"acknowledgedAt",
29+
"status",
30+
"fCntDown",
31+
"acknowledged",
32+
"payload",
33+
"port",
34+
];
35+
36+
constructor(
37+
private snackBar: MatSnackBar,
38+
private translate: TranslateService,
39+
private downlinkService: DownlinkService,
40+
public dialog: MatDialog,
41+
private errorMessageService: ErrorMessageService
42+
) {}
43+
44+
ngOnInit(): void {
45+
this.errorMessages = [];
46+
47+
this.getDownlinksQueue();
48+
this.getHistoricalDownlinksQueue();
49+
}
50+
51+
getDownlinksQueue() {
52+
this.isLoadingResults = true;
53+
this.downlinkService.getDownlinkQueue(this.device.id).subscribe(
54+
(response: DownlinkQueueDto[]) => {
55+
this.downlinkQueue = response;
56+
this.isLoadingResults = false;
57+
},
58+
error => {
59+
this.handleError(error);
60+
this.isLoadingResults = false;
61+
}
62+
);
63+
}
64+
65+
getHistoricalDownlinksQueue() {
66+
this.isLoadingResults = true;
67+
this.downlinkService.getHistoricalDownlinkQueue(this.device.id).subscribe(
68+
(response: DownlinkQueueDto[]) => {
69+
this.downlinkHistoryQueue = response;
70+
this.isLoadingResults = false;
71+
},
72+
error => {
73+
this.handleError(error);
74+
this.isLoadingResults = false;
75+
}
76+
);
77+
}
78+
79+
handleReload() {
80+
this.getDownlinksQueue();
81+
this.getHistoricalDownlinksQueue();
82+
}
83+
84+
handleFlushQueue() {
85+
this.openDownlinkDialog();
86+
}
87+
88+
private handleError(error: HttpErrorResponse) {
89+
this.errorMessages = this.errorMessageService.handleErrorMessage(error);
90+
}
91+
92+
openDownlinkDialog() {
93+
const dialog = this.dialog.open(DownlinkDialogComponent, {});
94+
95+
dialog.afterClosed().subscribe(result => {
96+
if (result === true) {
97+
this.downlinkService.flushQueue(this.device.id).subscribe(
98+
response => {
99+
this.snackBar.open(
100+
this.translate.instant("IOTDEVICE.DOWNLINK.QUEUE-FLUSHED"),
101+
this.translate.instant("DIALOG.OK"),
102+
{
103+
duration: 10000,
104+
}
105+
);
106+
this.getDownlinksQueue();
107+
},
108+
error => {
109+
this.handleError(error);
110+
}
111+
);
112+
}
113+
});
114+
}
115+
116+
getStatus(downlink: DownlinkQueueDto) {
117+
if (!downlink.acknowledgedAt && !downlink.sendAt) {
118+
return this.translate.instant("IOTDEVICE.DOWNLINK.IN-QUEUE");
119+
}
120+
if (downlink.acknowledgedAt) {
121+
return this.translate.instant("IOTDEVICE.DOWNLINK.RECEIVEDAT");
122+
}
123+
124+
return this.translate.instant("IOTDEVICE.DOWNLINK.SENDAT");
125+
}
126+
127+
isAcknowledged(downlink: DownlinkQueueDto) {
128+
return !downlink.acknowledged ? this.translate.instant("false") : this.translate.instant("true");
129+
}
130+
}

src/app/applications/iot-devices/iot-device-detail/downlink/downlink.component.html

Lines changed: 0 additions & 58 deletions
This file was deleted.

src/app/applications/iot-devices/iot-device-detail/downlink/downlink.component.scss

Whitespace-only changes.

0 commit comments

Comments
 (0)