| @@ -1 +1,2 @@ | |||
| <router-outlet></router-outlet> | |||
| <audio #audioPlayer src="assets/sound/alarm2.mp3" loop muted style="display: none"></audio> | |||
| @@ -1,5 +1,6 @@ | |||
| import {Component, OnInit} from '@angular/core'; | |||
| import {Component, ElementRef, OnInit, ViewChild} from '@angular/core'; | |||
| import {SocketService} from "./shared/services/socket.service"; | |||
| import {AlarmSoundService} from "./shared/services/alarm-sound.service"; | |||
| @Component({ | |||
| selector: 'app-root', | |||
| @@ -8,9 +9,12 @@ import {SocketService} from "./shared/services/socket.service"; | |||
| }) | |||
| export class AppComponent implements OnInit{ | |||
| title = 'Iot-web-ui'; | |||
| constructor(private socketService$: SocketService) { | |||
| @ViewChild('audioPlayer', { static: true }) audioPlayer!: ElementRef<HTMLAudioElement>; | |||
| constructor(private socketService$: SocketService, | |||
| private alarmSoundService$: AlarmSoundService) { | |||
| } | |||
| ngOnInit() { | |||
| this.socketService$.connect(); | |||
| this.alarmSoundService$.setSound(this.audioPlayer); | |||
| } | |||
| } | |||
| @@ -0,0 +1 @@ | |||
| <h2 style="text-align: center; padding: 3rem">Centralized Security Management Dashboard</h2> | |||
| @@ -0,0 +1,21 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { CentralizedSecurityManagementComponent } from './centralized-security-management.component'; | |||
| describe('CentralizedSecurityManagementComponent', () => { | |||
| let component: CentralizedSecurityManagementComponent; | |||
| let fixture: ComponentFixture<CentralizedSecurityManagementComponent>; | |||
| beforeEach(() => { | |||
| TestBed.configureTestingModule({ | |||
| declarations: [CentralizedSecurityManagementComponent] | |||
| }); | |||
| fixture = TestBed.createComponent(CentralizedSecurityManagementComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,10 @@ | |||
| import { Component } from '@angular/core'; | |||
| @Component({ | |||
| selector: 'app-centralized-security-management', | |||
| templateUrl: './centralized-security-management.component.html', | |||
| styleUrls: ['./centralized-security-management.component.scss'] | |||
| }) | |||
| export class CentralizedSecurityManagementComponent { | |||
| } | |||
| @@ -5,15 +5,21 @@ import {RouterModule} from "@angular/router"; | |||
| import {SharedMaterialModule} from "../../shared/shared-material.module"; | |||
| import { HomePageComponent } from './homepage/home-page.component'; | |||
| import {homePageRoutes} from "./home-page.routing"; | |||
| import {SharedModule} from "../../shared/shared.module"; | |||
| import { CentralizedSecurityManagementComponent } from './centralized-security-management/centralized-security-management.component'; | |||
| import { SecuritySystemDetailsComponent } from './security-system-details/security-system-details.component'; | |||
| @NgModule({ | |||
| declarations: [ | |||
| HomePageComponent | |||
| HomePageComponent, | |||
| CentralizedSecurityManagementComponent, | |||
| SecuritySystemDetailsComponent | |||
| ], | |||
| imports: [ | |||
| CommonModule, | |||
| RouterModule.forChild(homePageRoutes), | |||
| SharedMaterialModule,] | |||
| SharedMaterialModule, | |||
| SharedModule,] | |||
| }) | |||
| export class HomePageModule { } | |||
| @@ -1,12 +1,22 @@ | |||
| import {Routes} from "@angular/router"; | |||
| import {HomePageComponent} from "./homepage/home-page.component"; | |||
| import { | |||
| CentralizedSecurityManagementComponent | |||
| } from "./centralized-security-management/centralized-security-management.component"; | |||
| export const homePageRoutes: Routes = [ | |||
| { | |||
| path: '', | |||
| component: HomePageComponent, | |||
| }, | |||
| { | |||
| path: 'centralized-security-management', | |||
| component: CentralizedSecurityManagementComponent | |||
| }, | |||
| { | |||
| path: 'security-system-details', | |||
| component: CentralizedSecurityManagementComponent | |||
| } | |||
| ]; | |||
| @@ -1,3 +1,19 @@ | |||
| <div> | |||
| <div fxLayout="row" fxLayoutGap="30px" style="padding: 3rem 3rem 0"> | |||
| <button mat-stroked-button routerLink="./centralized-security-management">Centralized Security Management</button> | |||
| <button mat-stroked-button routerLink="./security-system-details">Security System Details </button> | |||
| </div> | |||
| <div class="sound-group"> | |||
| <h2>WHISTLE TIME: {{timeEffect1}}s</h2> | |||
| <div class="volume-group"> | |||
| <app-silder-range [value]="timeEffect1" (valueChange)="timeEffect1 = $event" ></app-silder-range> | |||
| </div> | |||
| </div> | |||
| <div class="sound-group"> | |||
| <h2>24-HOUR ZONE ALARM TIME: {{timeEffect2}}s</h2> | |||
| <div class="volume-group"> | |||
| <app-silder-range [value]="timeEffect2" (valueChange)="timeEffect2 = $event" ></app-silder-range> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -0,0 +1,7 @@ | |||
| .sound-group{ | |||
| padding: 3rem; | |||
| width: 70% | |||
| } | |||
| button{ | |||
| color: #ff7723 !important; | |||
| } | |||
| @@ -6,5 +6,6 @@ import { Component } from '@angular/core'; | |||
| styleUrls: ['./home-page.component.scss'] | |||
| }) | |||
| export class HomePageComponent { | |||
| timeEffect1: any = 10; | |||
| timeEffect2: any = 30; | |||
| } | |||
| @@ -0,0 +1 @@ | |||
| <h2 style="text-align: center; padding: 3rem">Security System Details Dashboard</h2> | |||
| @@ -0,0 +1,21 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { SecuritySystemDetailsComponent } from './security-system-details.component'; | |||
| describe('SecuritySystemDetailsComponent', () => { | |||
| let component: SecuritySystemDetailsComponent; | |||
| let fixture: ComponentFixture<SecuritySystemDetailsComponent>; | |||
| beforeEach(() => { | |||
| TestBed.configureTestingModule({ | |||
| declarations: [SecuritySystemDetailsComponent] | |||
| }); | |||
| fixture = TestBed.createComponent(SecuritySystemDetailsComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,10 @@ | |||
| import { Component } from '@angular/core'; | |||
| @Component({ | |||
| selector: 'app-security-system-details', | |||
| templateUrl: './security-system-details.component.html', | |||
| styleUrls: ['./security-system-details.component.scss'] | |||
| }) | |||
| export class SecuritySystemDetailsComponent { | |||
| } | |||
| @@ -10,6 +10,7 @@ import { Subscription } from 'rxjs'; | |||
| import { SocketService } from '../../../shared/services/socket.service'; | |||
| import {MatDialog} from "@angular/material/dialog"; | |||
| import {CameraDialogComponent} from "../camera-dialog/camera-dialog.component"; | |||
| import {AlarmSoundService} from "../../../shared/services/alarm-sound.service"; | |||
| const alarmData = [ | |||
| @@ -193,7 +194,7 @@ export class MapComponent implements OnInit, AfterViewInit, OnDestroy { | |||
| constructor(private socketService$: SocketService, | |||
| private dialog: MatDialog, | |||
| private renderer: Renderer2, | |||
| private audioService: AudioService) { } | |||
| private alarmSoundService$: AlarmSoundService) { } | |||
| ngOnInit() { | |||
| this.statusSubscription = this.socketService$.status$.subscribe(isConnected => { | |||
| @@ -221,6 +222,7 @@ export class MapComponent implements OnInit, AfterViewInit, OnDestroy { | |||
| this.statusSubscription?.unsubscribe(); | |||
| this.messageSubscription?.unsubscribe(); | |||
| this.socketService$.close(); | |||
| this.alarmSoundService$.stopAlarm() | |||
| } | |||
| initMap(): void { | |||
| @@ -249,6 +251,7 @@ export class MapComponent implements OnInit, AfterViewInit, OnDestroy { | |||
| this.state2 = message.state2 === '0'; // 1 OFF // alarm 1h | |||
| 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.updateIcons(); | |||
| } | |||
| } | |||
| @@ -346,4 +349,5 @@ export class MapComponent implements OnInit, AfterViewInit, OnDestroy { | |||
| } | |||
| return this.createIcon(false); | |||
| } | |||
| } | |||
| @@ -2,9 +2,8 @@ | |||
| <div class="header mat-elevation-z1"> | |||
| <img src="../../../../../../assets/images/logo.png" > | |||
| <div> | |||
| <button mat-button routerLink="/home">Home</button> | |||
| <button mat-button routerLink="/overview">Overview</button> | |||
| <button mat-button>Setting</button> | |||
| <button mat-button routerLink="/homepage" routerLinkActive="active">Home</button> | |||
| <button mat-button routerLink="/overview" routerLinkActive="active">Overview</button> | |||
| </div> | |||
| </div> | |||
| <div> | |||
| @@ -15,6 +15,9 @@ | |||
| button { | |||
| width: 5rem; | |||
| } | |||
| .active { | |||
| color: #ff7723 !important; | |||
| } | |||
| } | |||
| } | |||
| @@ -3,20 +3,25 @@ import {CommonModule} from "@angular/common"; | |||
| import {SharedMaterialModule} from "../shared-material.module"; | |||
| import {RouterModule} from "@angular/router"; | |||
| import { LayoutComponent } from './layout/layout.component'; | |||
| import { SliderRangeComponent } from './slider-range/slider-range.component'; | |||
| import {FormsModule} from "@angular/forms"; | |||
| @NgModule({ | |||
| declarations: [ | |||
| LayoutComponent | |||
| LayoutComponent, | |||
| SliderRangeComponent | |||
| ], | |||
| imports: [ | |||
| CommonModule, | |||
| SharedMaterialModule, | |||
| RouterModule, | |||
| ], | |||
| FormsModule, | |||
| ], | |||
| exports: [ | |||
| LayoutComponent | |||
| LayoutComponent, | |||
| SliderRangeComponent | |||
| ], | |||
| providers: [] | |||
| }) | |||
| @@ -0,0 +1,64 @@ | |||
| <ng-content></ng-content> | |||
| <div class="volume-group"> | |||
| <div class="speaker" *ngIf="value>0; else valueMin"> | |||
| <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/sound</title> | |||
| <g id="Icons/sound" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> | |||
| <g id="SpeakerLow"> | |||
| <path | |||
| d="M19.500001,12 C19.5006623,12.9135698 19.1672238,13.7958481 18.5625,14.480625 C18.2868064,14.7835586 17.8190602,14.8092747 17.5118188,14.5383902 C17.2045774,14.2675057 17.1714919,13.8002229 17.4375,13.48875 C18.185902,12.6387624 18.185902,11.3649876 17.4375,10.515 C17.1714919,10.2035271 17.2045774,9.73624429 17.5118188,9.46535978 C17.8190602,9.19447528 18.2868064,9.22019142 18.5625,9.523125 C19.1658428,10.2072505 19.4991441,11.0878325 19.500001,12 Z M15,3 L15,21 C14.9997852,21.2863161 14.8365765,21.5475297 14.5793423,21.6732576 C14.3221081,21.7989856 14.0157342,21.7672891 13.7896875,21.5915625 L7.2421875,16.5 L3,16.5 C2.17157288,16.5 1.5,15.8284271 1.5,15 L1.5,9 C1.5,8.17157288 2.17157288,7.5 3,7.5 L7.2421875,7.5 L13.7896875,2.4084375 C14.0157342,2.23271088 14.3221081,2.20101442 14.5793423,2.32674236 C14.8365765,2.4524703 14.9997852,2.71368392 15,3 Z M6.75,9 L3,9 L3,15 L6.75,15 L6.75,9 Z" | |||
| id="Shape" fill="currentColor" fill-rule="nonzero"></path> | |||
| <rect id="Rectangle" x="0" y="0" width="24" height="24"></rect> | |||
| </g> | |||
| </g> | |||
| </svg> | |||
| </div> | |||
| <ng-template #valueMin> | |||
| <div class="speaker"> | |||
| <svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> | |||
| <path | |||
| d="M12.1657 2.14424C12.8728 2.50021 13 3.27314 13 3.7446V20.2561C13 20.7286 12.8717 21.4998 12.1656 21.8554C11.416 22.2331 10.7175 21.8081 10.3623 21.4891L4.95001 16.6248H3.00001C1.89544 16.6248 1.00001 15.7293 1.00001 14.6248L1 9.43717C1 8.3326 1.89543 7.43717 3 7.43717H4.94661L10.3623 2.51158C10.7163 2.19354 11.4151 1.76635 12.1657 2.14424Z" | |||
| fill="currentColor"/> | |||
| <path | |||
| d="M21.8232 15.6767C21.4327 16.0673 20.7995 16.0673 20.409 15.6768L18.5 13.7678L16.591 15.6768C16.2005 16.0673 15.5673 16.0673 15.1768 15.6767L14.8233 15.3232C14.4327 14.9327 14.4327 14.2995 14.8233 13.909L16.7322 12L14.8232 10.091C14.4327 9.70044 14.4327 9.06727 14.8232 8.67675L15.1767 8.3232C15.5673 7.93267 16.2004 7.93267 16.591 8.32319L18.5 10.2322L20.409 8.32319C20.7996 7.93267 21.4327 7.93267 21.8233 8.3232L22.1768 8.67675C22.5673 9.06727 22.5673 9.70044 22.1768 10.091L20.2678 12L22.1767 13.909C22.5673 14.2995 22.5673 14.9327 22.1767 15.3232L21.8232 15.6767Z" | |||
| fill="currentColor"/> | |||
| </svg> | |||
| </div> | |||
| </ng-template> | |||
| <button class="volume-control" (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> | |||
| <g id="Icons/Minus-square-fill" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> | |||
| <g id="MinusSquare"> | |||
| <path | |||
| d="M19.5,3 L4.5,3 C3.67157288,3 3,3.67157288 3,4.5 L3,19.5 C3,20.3284271 3.67157288,21 4.5,21 L19.5,21 C20.3284271,21 21,20.3284271 21,19.5 L21,4.5 C21,3.67157288 20.3284271,3 19.5,3 Z M15.75,12.75 L8.25,12.75 C7.83578644,12.75 7.5,12.4142136 7.5,12 C7.5,11.5857864 7.83578644,11.25 8.25,11.25 L15.75,11.25 C16.1642136,11.25 16.5,11.5857864 16.5,12 C16.5,12.4142136 16.1642136,12.75 15.75,12.75 Z" | |||
| id="Shape" fill="currentColor" fill-rule="nonzero"></path> | |||
| <rect id="Rectangle" x="0" y="0" width="24" height="24"></rect> | |||
| </g> | |||
| </g> | |||
| </svg> | |||
| </button> | |||
| <div class="volume-control" style="padding: 1rem 0"> | |||
| <div class="volume-slider"> | |||
| <input type="range" [(ngModel)]="value" (input)="onSliderChange($event)" | |||
| [ngStyle]="onSliderChangeBackground()" | |||
| [max]="max"> | |||
| </div> | |||
| </div> | |||
| <button class="volume-control" (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> | |||
| <g id="Icons/Plus-square-fill" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> | |||
| <g id="Plus"> | |||
| <path | |||
| d="M19.5,3 L4.5,3 C3.67157288,3 3,3.67157288 3,4.5 L3,19.5 C3,20.3284271 3.67157288,21 4.5,21 L19.5,21 C20.3284271,21 21,20.3284271 21,19.5 L21,4.5 C21,3.67157288 20.3284271,3 19.5,3 Z M17.25,12.75 L12.75,12.75 L12.75,17.25 C12.75,17.6642136 12.4142136,18 12,18 C11.5857864,18 11.25,17.6642136 11.25,17.25 L11.25,12.75 L6.75,12.75 C6.33578644,12.75 6,12.4142136 6,12 C6,11.5857864 6.33578644,11.25 6.75,11.25 L11.25,11.25 L11.25,6.75 C11.25,6.33578644 11.5857864,6 12,6 C12.4142136,6 12.75,6.33578644 12.75,6.75 L12.75,11.25 L17.25,11.25 C17.6642136,11.25 18,11.5857864 18,12 C18,12.4142136 17.6642136,12.75 17.25,12.75 Z" | |||
| id="Shape" fill="currentColor" fill-rule="nonzero"></path> | |||
| <rect id="Rectangle" x="0" y="0" width="24" height="24"></rect> | |||
| </g> | |||
| </g> | |||
| </svg> | |||
| </button> | |||
| </div> | |||
| @@ -0,0 +1,148 @@ | |||
| .volume-group { | |||
| margin-top: 1.5rem; | |||
| display: flex; | |||
| flex-direction: row; | |||
| gap: 1.5rem; | |||
| align-items: center; | |||
| justify-content: space-between; | |||
| .speaker { | |||
| background: transparent; | |||
| padding: 1rem; | |||
| clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%); | |||
| position: relative; | |||
| &:before { | |||
| content: ""; | |||
| position: absolute; | |||
| top: 0; | |||
| left: 0; | |||
| width: 100%; | |||
| height: 100%; | |||
| clip-path: polygon( | |||
| 50% 0, | |||
| 100% 25%, | |||
| 100% 75%, | |||
| 50% 100%, | |||
| 0 75%, | |||
| 0 25%, | |||
| 50% 0, | |||
| 50% 1px, | |||
| 1px calc(25% + .5px), | |||
| 1px calc(75% - .5px), | |||
| 50% calc(100% - 1px), | |||
| calc(100% - 1px) calc(75% - .5px), | |||
| calc(100% - 1px) calc(25% + .5px), | |||
| 50% 1px | |||
| ); | |||
| background-color: #ff7723; | |||
| } | |||
| } | |||
| .volume-control { | |||
| padding: .63rem; | |||
| border-top: solid .06rem #ff7723; | |||
| border-bottom: solid .06rem #ff7723; | |||
| background-color: transparent; | |||
| border-left: none; | |||
| border-right: none; | |||
| svg { | |||
| cursor: pointer; | |||
| width: 1.5rem; | |||
| height: 1.5rem; | |||
| } | |||
| } | |||
| .volume-slider { | |||
| border: .06rem solid #eed3c2; | |||
| height: .75rem; | |||
| width: 39rem; | |||
| position: relative; | |||
| input[type="range"] { | |||
| position: relative; | |||
| -webkit-appearance: none; | |||
| -moz-appearance: none; | |||
| display: block; | |||
| outline: none; | |||
| height: 4px; | |||
| width: 38.5rem; | |||
| appearance: none; | |||
| background-color: transparent; | |||
| margin: .25rem; | |||
| &::-webkit-slider-thumb { | |||
| -webkit-appearance: none; | |||
| appearance: none; | |||
| background: #ff7723 | |||
| ; | |||
| border: .06rem solid #ff7723; | |||
| height: .88rem; | |||
| width: .88rem; | |||
| padding: 2px; | |||
| background-clip: content-box; | |||
| transition: transform .2s ease; | |||
| &:focus { | |||
| cursor: pointer; | |||
| border: .12rem solid #ff7723; | |||
| transform: scale(1.2); | |||
| } | |||
| &:hover { | |||
| cursor: pointer; | |||
| border: .12rem solid #ff7723; | |||
| transform: scale(1.2); | |||
| } | |||
| } | |||
| &::-moz-range-thumb { | |||
| border-radius: 0; | |||
| background: #ff7723; | |||
| border: .06rem solid #ff7723; | |||
| height: .5rem; | |||
| width: .5rem ; | |||
| padding: 3px; | |||
| background-clip: content-box; | |||
| &:focus { | |||
| cursor: pointer; | |||
| border: .14rem solid #ff7723; | |||
| transform: scale(1); | |||
| } | |||
| &:hover { | |||
| cursor: pointer; | |||
| border: .14rem solid #ff7723; | |||
| transform: scale(1); | |||
| } | |||
| } | |||
| &::-ms-thumb { | |||
| -webkit-appearance: none; | |||
| appearance: none; | |||
| background: #ff7723; | |||
| border: .06rem solid #ff7723; | |||
| height: .88rem; | |||
| width: .88rem; | |||
| padding: 3px; | |||
| background-clip: content-box; | |||
| &:focus { | |||
| cursor: pointer; | |||
| border: .12rem solid #ff7723; | |||
| transform: scale(1.2); | |||
| } | |||
| &:hover { | |||
| cursor: pointer; | |||
| border: .12rem solid #ff7723; | |||
| transform: scale(1.2); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| svg{ | |||
| color: #ff7723; | |||
| } | |||
| @@ -0,0 +1,21 @@ | |||
| import { ComponentFixture, TestBed } from '@angular/core/testing'; | |||
| import { SliderRangeComponent } from './slider-range.component'; | |||
| describe('SilderRangeComponent', () => { | |||
| let component: SliderRangeComponent; | |||
| let fixture: ComponentFixture<SliderRangeComponent>; | |||
| beforeEach(() => { | |||
| TestBed.configureTestingModule({ | |||
| declarations: [SliderRangeComponent] | |||
| }); | |||
| fixture = TestBed.createComponent(SliderRangeComponent); | |||
| component = fixture.componentInstance; | |||
| fixture.detectChanges(); | |||
| }); | |||
| it('should create', () => { | |||
| expect(component).toBeTruthy(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,65 @@ | |||
| import {Component, EventEmitter, Input, Output} from '@angular/core'; | |||
| @Component({ | |||
| selector: 'app-slider-range', | |||
| templateUrl: './slider-range.component.html', | |||
| styleUrls: ['./slider-range.component.scss'] | |||
| }) | |||
| export class SliderRangeComponent { | |||
| @Input() value: number = 10; | |||
| @Input() max: number = 300; | |||
| @Output() valueChange = new EventEmitter<number>(); | |||
| constructor() {} | |||
| onSliderChange(event: any) { | |||
| this.value = event.target.value; | |||
| this.valueChange.emit(this.value); | |||
| } | |||
| onSliderChangeBackground() { | |||
| let valPercent = (this.value / this.max) * 100; | |||
| // Adjust valPercent based on your conditions | |||
| switch (true) { | |||
| case (valPercent > 10 && valPercent <= 30): | |||
| valPercent -= 0.5; | |||
| break; | |||
| case (valPercent > 30 && valPercent <= 50): | |||
| valPercent -= 1; | |||
| break; | |||
| case (valPercent > 50 && valPercent <= 70): | |||
| valPercent -= 1.5; | |||
| break; | |||
| case (valPercent > 70 && valPercent <= 90): | |||
| valPercent -= 2; | |||
| break; | |||
| case (valPercent > 90 && valPercent <= 100): | |||
| valPercent -= 2.3; | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| // Return CSS object with background style | |||
| return { | |||
| 'background': `linear-gradient(to right, #ff7723 ${valPercent}%, transparent ${valPercent}%)` | |||
| }; | |||
| } | |||
| increaseVolume() { | |||
| if (this.value < this.max) { | |||
| this.value += 10; | |||
| this.valueChange.emit(this.value); | |||
| } | |||
| } | |||
| decreaseVolume() { | |||
| if (this.value > 0) { | |||
| this.value -= 10; | |||
| this.valueChange.emit(this.value); | |||
| } | |||
| } | |||
| } | |||
| @@ -1,29 +1,43 @@ | |||
| import { Injectable } from '@angular/core'; | |||
| import {ElementRef, Injectable} from '@angular/core'; | |||
| @Injectable({ | |||
| providedIn: 'root' | |||
| }) | |||
| export class AlarmSoundService { | |||
| private audioPlayer!: HTMLAudioElement; | |||
| private alertInterval: any; | |||
| private alertDuration: number = 30000; | |||
| private audio: HTMLAudioElement; | |||
| constructor() { } | |||
| constructor() { | |||
| this.audio = new Audio('assets/sound/alarm.mp3'); | |||
| this.audio.loop = true; | |||
| setSound(audioPlayer: ElementRef<HTMLAudioElement>): void { | |||
| this.audioPlayer = audioPlayer.nativeElement; | |||
| } | |||
| playAlertSound() { | |||
| this.audio.play(); | |||
| playSound(): void { | |||
| if (this.audioPlayer) { | |||
| this.audioPlayer.play().catch(error => console.error('Error playing sound:', error)); | |||
| } | |||
| } | |||
| stopAlertSound() { | |||
| this.audio.pause(); | |||
| this.audio.currentTime = 0; | |||
| stopSound(): void { | |||
| if (this.audioPlayer) { | |||
| this.audioPlayer.pause(); | |||
| this.audioPlayer.currentTime = 0; | |||
| } | |||
| } | |||
| setVolume(volume: number) { | |||
| if (volume >= 0 && volume <= 1) { | |||
| this.audio.volume = volume; | |||
| startAlarm(state5: boolean, isReady: boolean, state1: boolean, state2: boolean): void { | |||
| if (state5 && isReady && (state1 || state2)) { | |||
| this.playSound(); | |||
| this.alertInterval = setInterval(() => { | |||
| this.stopAlarm() | |||
| }, this.alertDuration); | |||
| } | |||
| } | |||
| stopAlarm(): void { | |||
| this.stopSound() | |||
| clearInterval(this.alertInterval); | |||
| } | |||
| } | |||
| @@ -1,13 +1,14 @@ | |||
| import { NgModule } from '@angular/core'; | |||
| import { CommonModule } from '@angular/common'; | |||
| import {SharedComponentModule} from "./component/shared-component.module"; | |||
| import {FormsModule} from "@angular/forms"; | |||
| @NgModule({ | |||
| declarations: [], | |||
| imports: [ | |||
| CommonModule, | |||
| SharedComponentModule, | |||
| FormsModule | |||
| ], | |||
| exports: [ | |||
| SharedComponentModule, | |||