Browse Source

add loading, send message socket

pull/15/head
PhamY0601 1 year ago
parent
commit
0d9f87a306
12 changed files with 191 additions and 88 deletions
  1. +15
    -21
      src/app/modules/homepage/centralized-security-management/centralized-security-management.component.ts
  2. +4
    -5
      src/app/modules/homepage/homepage/home-page.component.html
  3. +43
    -2
      src/app/modules/homepage/homepage/home-page.component.ts
  4. +5
    -2
      src/app/modules/homepage/security-system-details/security-system-details.component.ts
  5. +14
    -9
      src/app/shared/component/camera-dialog/camera-dialog.component.html
  6. +27
    -0
      src/app/shared/component/camera-dialog/camera-dialog.component.scss
  7. +4
    -4
      src/app/shared/component/camera-dialog/camera-dialog.component.ts
  8. +9
    -5
      src/app/shared/component/confirm-dialog/confirm-dialog.component.html
  9. +30
    -15
      src/app/shared/component/confirm-dialog/confirm-dialog.component.ts
  10. +5
    -4
      src/app/shared/component/slider-range/slider-range.component.html
  11. +32
    -19
      src/app/shared/services/alarm-sound.service.ts
  12. +3
    -2
      src/app/shared/services/confirm-dialog.service.ts

+ 15
- 21
src/app/modules/homepage/centralized-security-management/centralized-security-management.component.ts View File

@@ -13,7 +13,6 @@ import { MatDialog } from '@angular/material/dialog';
import { AlarmSoundService } from '../../../shared/services/alarm-sound.service';
import { CameraDialogComponent } from '../../../shared/component/camera-dialog/camera-dialog.component';
import { alarmData, alarmDemo } from '../data/fake-data';
import { ConfirmDialogService } from '../../../shared/services/confirm-dialog.service';

@Component({
selector: 'app-centralized-security-management',
@@ -30,7 +29,9 @@ export class CentralizedSecurityManagementComponent
data = alarmData;
alarmDemo = alarmDemo;
state1 = false;
status1 = false;
state2 = false;
status2 = false;
state5 = false;
state6 = false;
isReady = true;
@@ -99,12 +100,13 @@ export class CentralizedSecurityManagementComponent
onMessage(message: any) {
if (message.id == '0' && message.type === 'get') {
this.state1 = message.state1 === '0'; // 1 OFF // alarm 12h
this.status1 = message.status1 === '1'; // 0 not, 1 ready, 2 error, 3 bypass
this.state2 = message.state2 === '0'; // 1 OFF // alarm 1h
this.status2 = message.status2 === '1'; // 0 not, 1 ready, 2 error, 3 bypass
this.state5 = message.state5 === '1'; // 1 ON, 0 OFF
this.isReady = message.ready === '1';
this.alarmSoundService$.startAlarm(this.state5, this.isReady, this.state1, this.state2);
this.alarmSoundService$.startAlarm(this.state5, this.state1,this.status1, this.state2, this.status2);
this.updateIcons();

}

}
@@ -117,8 +119,9 @@ export class CentralizedSecurityManagementComponent
}

addMarker(item: any, isDemo: boolean = false): void {
console.log(this.state5, this.state1, this.status1)
const icon = isDemo
? this.getIcon(this.state5, this.isReady, this.state1, this.state2)
? this.getIcon(this.state5, this.state1, this.status1, this.state2, this.status2)
: this.createIcon(item.warning);
const marker = L.marker(
[item.detail.coordinates.lat, item.detail.coordinates.lng],
@@ -164,11 +167,7 @@ export class CentralizedSecurityManagementComponent
</div>`;
}

createIcon(
active: boolean,
className: string = '',
text: any = [],
): L.Icon<L.IconOptions> | L.DivIcon {
createIcon(active: boolean, className: string = '', text: any = []): L.Icon<L.IconOptions> | L.DivIcon {
if (text.length < 1) {
return L.icon({
iconUrl: active
@@ -198,22 +197,17 @@ export class CentralizedSecurityManagementComponent
}
}

getIcon(
isTurnOn: boolean,
isReady: boolean,
fireArm: boolean,
fenceArm: boolean,
): L.Icon<L.IconOptions> | L.DivIcon {
if (isTurnOn && isReady) {
getIcon(isTurnOn: boolean, fireArm: boolean, fireStatus: boolean, fenceArm: boolean, fenceStatus: boolean): L.Icon<L.IconOptions> | L.DivIcon {
if (isTurnOn) {
let text = [];
if (fireArm && fenceArm) {
text.push('FIRE ALARM', 'FENCE ALARM');
} else if (fireArm) {
if (fireStatus && fireArm) {
text.push('FIRE ALARM');
} else if (fenceArm) {
}
if (fenceStatus && fenceArm) {
text.push('FENCE ALARM');
}
return this.createIcon(true, '', text);
return this.createIcon(true, '', text);

}
return this.createIcon(false);
}

+ 4
- 5
src/app/modules/homepage/homepage/home-page.component.html View File

@@ -7,7 +7,6 @@
</button>
</div>


<mat-card class="sound-group">
<mat-card-header>
<mat-card-title>WHISTLE TIME: {{whistle.time}}s</mat-card-title>
@@ -17,13 +16,13 @@
<app-slider-range
[value]="whistle.time"
[icon]="'access_alarm'"
(valueChange)="whistle.time = $event"
(valueChange)="emitSetting('whistle', $event)"
[disable]="!isConnected"
></app-slider-range>
</div>
</mat-card-content>
</mat-card>


<mat-card class="sound-group">
<mat-card-header>
<mat-card-title>24-HOUR ZONE ALARM TIME: {{alarm.time}}s</mat-card-title>
@@ -33,9 +32,9 @@
<app-slider-range
[value]="alarm.time"
[icon]="'access_alarm'"
(valueChange)="alarm.time = $event"
(valueChange)="emitSetting('alarm',$event)"
[disable]="!isConnected"
></app-slider-range>
</div>

</mat-card-content>
</mat-card>

+ 43
- 2
src/app/modules/homepage/homepage/home-page.component.ts View File

@@ -1,11 +1,13 @@
import { Component } from '@angular/core';
import {Component, OnDestroy, OnInit} from '@angular/core';
import {SocketService} from "../../../shared/services/socket.service";
import {Subscription} from "rxjs";

@Component({
selector: 'app-homepage',
templateUrl: './home-page.component.html',
styleUrls: ['./home-page.component.scss'],
})
export class HomePageComponent {
export class HomePageComponent implements OnInit,OnDestroy{
whistle = {
time: 10,
sound: 0,
@@ -14,4 +16,43 @@ export class HomePageComponent {
time: 30,
sound: 0,
};
private statusSubscription?: Subscription;
isConnected: boolean = false;
constructor(private socketService$: SocketService,) {
this.statusSubscription = this.socketService$.status$.subscribe(
(isConnected) => {
this.isConnected = isConnected;
},
);
}
ngOnInit() {
this.whistle.time = parseInt(localStorage.getItem('whistletime') ?? '10');
if (!localStorage.getItem('whistletime')) {
localStorage.setItem('whistletime', '10');
}
this.alarm.time = parseInt(localStorage.getItem('alarmtime') ?? '30');
if (!localStorage.getItem('alarmtime')) {
localStorage.setItem('alarmtime', '30');
}
}

emitSetting(type: string, event: any){
if (this.isConnected) {
if (type === 'whistle') {
this.whistle.time = event;
localStorage.setItem('whistletime', event);
this.socketService$.sendMessage({ id: '0', type: 'set', whistletime: event.toString() });
} else if (type === 'alarm') {
this.alarm.time = event;
localStorage.setItem('alarmtime', event);
this.socketService$.sendMessage({ id: '0', type: 'set', arlamtime: event.toString() });
}
}
}

ngOnDestroy(): void {
if (this.statusSubscription) {
this.statusSubscription.unsubscribe();
}
}
}

+ 5
- 2
src/app/modules/homepage/security-system-details/security-system-details.component.ts View File

@@ -5,6 +5,7 @@ import {ToastrService} from "ngx-toastr";
import {CameraDialogComponent} from "../../../shared/component/camera-dialog/camera-dialog.component";
import {MatDialog} from "@angular/material/dialog";
import { ConfirmDialogService } from '../../../shared/services/confirm-dialog.service';
import {AlarmSoundService} from "../../../shared/services/alarm-sound.service";

@Component({
selector: 'app-security-system-details',
@@ -31,9 +32,9 @@ export class SecuritySystemDetailsComponent implements OnInit, OnDestroy {

constructor(
private socketService$: SocketService,
private toastr: ToastrService,
private dialog: MatDialog,
private confirm$: ConfirmDialogService
private confirm$: ConfirmDialogService,
private alarmSoundService$: AlarmSoundService,
) {}

ngOnInit() {
@@ -61,6 +62,7 @@ export class SecuritySystemDetailsComponent implements OnInit, OnDestroy {
clearInterval(this.intervalId);
}
this.socketService$.close();
this.alarmSoundService$.stopAlarm();
}

getReadings() {
@@ -104,6 +106,7 @@ export class SecuritySystemDetailsComponent implements OnInit, OnDestroy {
this.confirm$.openDialog(data);
// this.toastr.warning('System not ready', 'Warning', {timeOut: 5000});
}
this.alarmSoundService$.startAlarm(this.state5, this.state1,this.status1, this.state2, this.status2);
}
}
openDialog(): void {

+ 14
- 9
src/app/shared/component/camera-dialog/camera-dialog.component.html View File

@@ -1,11 +1,16 @@
<div style="padding: 10px 20px" fxLayout="row" fxLayoutAlign="center">
<div style="text-align: center; font-size: 24px; width: 95%">Camera Stream</div>
<button mat-icon-button color="warn" (click)="onClose()">
<mat-icon>close</mat-icon>
</button>
</div>

<div style="padding: 10px 20px" fxLayout="row" fxLayoutAlign=" center">
<div style="text-align: center; font-size: 24px; width: 95%">Camera Stream</div>
<button mat-icon-button color="warn" (click)="onClose()">
<mat-icon>close</mat-icon>
</button>
<div mat-dialog-content>
<div fxLayout="row" fxLayoutAlign="space-around center" fxLayoutGap="10px"
style="height: 50%;"
*ngIf="!videoLoaded">
<div class="circle-loader"></div>
<div class="loader"></div>
</div>
<div mat-dialog-content>
<canvas class="video" #videoPlayer></canvas>
</div>

<canvas class="video" #videoPlayer [hidden]="!videoLoaded"></canvas>
</div>

+ 27
- 0
src/app/shared/component/camera-dialog/camera-dialog.component.scss View File

@@ -7,3 +7,30 @@
.mat-mdc-dialog-content{
max-height: unset;
}

.loader {
width: fit-content;
color: orange;
font-family: monospace;
font-size: 30px;
clip-path: inset(0 3ch 0 0);
animation: l4 1s steps(4) infinite;
}
.loader:before {
content:"Loading..."
}
@keyframes l4 {to{clip-path: inset(0 -1ch 0 0)}}

.circle-loader {
width: 50px;
aspect-ratio: 1;
border-radius: 50%;
background:
radial-gradient(farthest-side,#ffa516 94%,#0000) top/8px 8px no-repeat,
conic-gradient(#0000 30%,#ffa516);
-webkit-mask: radial-gradient(farthest-side,#0000 calc(100% - 8px),#000 0);
animation: l13 1s infinite linear;
}
@keyframes l13{
100%{transform: rotate(1turn)}
}

+ 4
- 4
src/app/shared/component/camera-dialog/camera-dialog.component.ts View File

@@ -10,9 +10,8 @@ import {loadPlayer, Player} from "rtsp-relay/browser";
export class CameraDialogComponent implements AfterViewInit{

player?: Player;
@ViewChild('videoPlayer')
videoPlayer?: ElementRef<HTMLCanvasElement>;

videoLoaded: boolean = false;
@ViewChild('videoPlayer') videoPlayer?: ElementRef<HTMLCanvasElement>;

constructor(public dialogRef: MatDialogRef<CameraDialogComponent>) { }

@@ -22,9 +21,10 @@ export class CameraDialogComponent implements AfterViewInit{
url: 'ws://localhost:8080/stream',
canvas: this.videoPlayer!.nativeElement,
onDisconnect: () => {
setTimeout(connect, 5000); // reconnect after 5 seconds
setTimeout(connect, 5000);
},
});
this.videoLoaded = true;
};
connect();
}

+ 9
- 5
src/app/shared/component/confirm-dialog/confirm-dialog.component.html View File

@@ -1,11 +1,15 @@
<h5 mat-dialog-title >CONFIRM TO IGNORE THE WARNING</h5>
<mat-dialog-content style="padding-bottom: 4px">
<div *ngFor="let item of data">
<mat-checkbox [(ngModel)]="item.value" (ngModelChange)="submitChange(item)" name="sensor">
{{ (item.key == 'status1' ? 'Fire' : 'ff')}}
</mat-checkbox>
</div>
<div *ngFor="let item of data">
<mat-checkbox [(ngModel)]="item.value"
(ngModelChange)="submitChange(item)"
[disabled]="isConnected && item.value"
name="sensor">
{{ (item.key == 'status1' ? 'Fire Alarm' : 'Fence Alarm') }}
</mat-checkbox>
</div>
</mat-dialog-content>

<mat-dialog-actions align="end">
<button mat-button mat-dialog-close cdkFocusInitial>Close</button>
</mat-dialog-actions>

+ 30
- 15
src/app/shared/component/confirm-dialog/confirm-dialog.component.ts View File

@@ -1,25 +1,40 @@
import { Component } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
import {Component, Inject, OnDestroy, OnInit} from '@angular/core';
import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog';
import {SocketService} from "../../services/socket.service";
import {Subscription} from "rxjs";

@Component({
selector: 'app-confirm-dialog',
templateUrl: './confirm-dialog.component.html',
styleUrls: ['./confirm-dialog.component.scss'],
})
export class ConfirmDialogComponent {
constructor(public dialogRef: MatDialogRef<ConfirmDialogComponent>) {}
data = [
{
key: 'status1',
value: false,
export class ConfirmDialogComponent implements OnDestroy{

private statusSubscription?: Subscription;
isConnected: boolean = false;

constructor(
@Inject(MAT_DIALOG_DATA) public data: any[],
private socketService$: SocketService,
) {
this.statusSubscription = this.socketService$.status$.subscribe(
(isConnected) => {
this.isConnected = isConnected;
},
{
name: 'status2',
value: false,
},
];
);
}

submitChange(item: any): void{
console.log(item);
// call socket here
if(this.isConnected) {
const position = item.key === 'status1' ? 1 : 2;
this.socketService$.sendMessage({ id: '0', type: 'bypass', state: position})
item.value = true;
}
}

ngOnDestroy() {
if (this.statusSubscription) {
this.statusSubscription.unsubscribe();
}
}
}

+ 5
- 4
src/app/shared/component/slider-range/slider-range.component.html View File

@@ -1,9 +1,9 @@
<ng-content></ng-content>
<div class="volume-group">
<div class="speaker">
<mat-icon>{{icon}}</mat-icon>
<mat-icon>{{ icon }}</mat-icon>
</div>
<button class="volume-control" (click)="decreaseVolume()">
<button class="volume-control" [disabled]="disable" (click)="decreaseVolume()">
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icons/Minus square fill</title>
@@ -21,10 +21,11 @@
<div class="volume-slider">
<input type="range" [(ngModel)]="value" (input)="onSliderChange($event)"
[ngStyle]="onSliderChangeBackground()"
[max]="max">
[max]="max"
[disabled]="disable">
</div>
</div>
<button class="volume-control" (click)="increaseVolume()">
<button class="volume-control" [disabled]="disable" (click)="increaseVolume()">
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Icons/Plus square fill</title>

+ 32
- 19
src/app/shared/services/alarm-sound.service.ts View File

@@ -1,4 +1,5 @@
import { Injectable } from '@angular/core';
import {max} from "rxjs";

@Injectable({
providedIn: 'root',
@@ -7,21 +8,18 @@ export class AlarmSoundService {
private alertInterval: any;
private alertDuration: number = 10000;
private audio = new Audio();
private isPlaying: boolean = false;
private isPlay: boolean = false;

constructor() {
this.audio.src = 'assets/sound/alarm_5m.mp3';
this.audio.load();
this.audio.onended = () => {
// Khi phát hết âm thanh, đặt biến isPlaying về false
this.isPlaying = false;
};

}

playSound(): void {
if (!this.isPlaying) {
if(!this.isPlay){
this.audio.play().then(() => {
this.isPlaying = true;
this.isPlay = true;
this.alertInterval = setInterval(() => {
this.stopAlarm();
}, this.alertDuration);
@@ -29,30 +27,45 @@ export class AlarmSoundService {
console.error('Error playing audio:', error);
});
}

}

stopSound(): void {
if (this.audio) {
this.audio.pause();
this.audio.currentTime = 0;
this.isPlaying = false;
startAlarm(isTurnOn: boolean, fireArm: boolean, fireStatus: boolean, fenceArm: boolean, fenceStatus: boolean): void {
if (!isTurnOn) {
this.stopAlarm();
return;
}
}

startAlarm( isTurnOn: boolean, isReady: boolean, fireArm: boolean, fenceArm: boolean): void {
if (isTurnOn && isReady && (fireArm || fenceArm)) {
//this.alertDuration = // setting time
this.playSound();
}else{
const alarmTime = this.getTimeDuration('alarmtime');
const whistleTime = this.getTimeDuration('whistletime');

if (fireArm && fireStatus && fenceArm && fenceStatus) {
this.alertDuration = Math.max(alarmTime, whistleTime);
} else if (fireArm && fireStatus) {
this.alertDuration = alarmTime;
} else if (fenceArm && fenceStatus) {
this.alertDuration = whistleTime;
} else {
this.stopAlarm();
return;
}

this.playSound();
}

stopAlarm(): void {
this.stopSound();
if (this.audio) {
this.audio.pause();
this.audio.currentTime = 0;
this.isPlay = false;
}
if (this.alertInterval){
clearInterval(this.alertInterval);
}
}

getTimeDuration(key: string) {
return parseInt(localStorage.getItem(key) ?? '0') * 100;
}
}

+ 3
- 2
src/app/shared/services/confirm-dialog.service.ts View File

@@ -14,8 +14,9 @@ export class ConfirmDialogService {
openDialog(data: any[]): void {
if (!this.isDialogOpen) {
this.isDialogOpen = true;
const dialogRef = this.dialog.open(ConfirmDialogComponent);

const dialogRef = this.dialog.open(ConfirmDialogComponent, {
data: data
});
dialogRef
.afterClosed()
.pipe(take(1))

Loading…
Cancel
Save