Browse Source

add stream camera and change icon

pull/5/head
PhamY0601 1 year ago
parent
commit
5e9f082613
17 changed files with 334 additions and 177 deletions
  1. +64
    -0
      src/app/app.constants.ts
  2. +3
    -0
      src/app/modules/overview/camera-stream/camera-stream.component.html
  3. +0
    -0
      src/app/modules/overview/camera-stream/camera-stream.component.scss
  4. +21
    -0
      src/app/modules/overview/camera-stream/camera-stream.component.spec.ts
  5. +30
    -0
      src/app/modules/overview/camera-stream/camera-stream.component.ts
  6. +2
    -1
      src/app/modules/overview/map/map.component.html
  7. +5
    -1
      src/app/modules/overview/map/map.component.scss
  8. +73
    -80
      src/app/modules/overview/map/map.component.ts
  9. +10
    -20
      src/app/modules/overview/overall-ground/overall-ground.component.html
  10. +77
    -71
      src/app/modules/overview/overall-ground/overall-ground.component.ts
  11. +5
    -2
      src/app/modules/overview/overview.module.ts
  12. +5
    -0
      src/app/modules/overview/overview.routing.ts
  13. +4
    -2
      src/app/shared/services/socket.service.ts
  14. +8
    -0
      src/assets/config/config.ts
  15. BIN
      src/assets/images/camera.png
  16. +23
    -0
      src/server/server.js
  17. +4
    -0
      src/server/stream.sh

+ 64
- 0
src/app/app.constants.ts View File

@@ -0,0 +1,64 @@
export const ICON = {
sensorOff: `<div style="display: flex; flex-direction: row; gap: 5px">
<img style="width: 30px; height: 30px;" src="assets/images/sensor-off.png">
<img style="width: 30px; height: 30px;" src="assets/images/camera.png">
</div>`,
sensorOn: `<div style="display: flex; flex-direction: row; gap: 5px">
<img style="width: 30px; height: 30px;" src="assets/images/sensor-on.png">
<img style="width: 30px; height: 30px;" src="assets/images/camera.png">
</div>`,
sensorActive: `<div>
<div style="width: 30px; height: 30px; position: absolute; display: flex; justify-content: center; align-items: center; border-radius: 50%; background: linear-gradient(#ff0000, #C70039);">
<div style="position: absolute !important; width: 100%; height: 100%; background: #ff0000; border-radius: 50%; z-index: 1; animation: sensor-on 2s ease-out infinite;"></div>
<div style="position: absolute !important; width: 100%; height: 100%; background: #ff0000; border-radius: 50%; z-index: 1; animation: sensor-on 2s ease-out infinite; animation-delay: 1s;"></div>
<img src="assets/images/sensor-on.png" style="width: 30px; height: 30px; z-index: 9;">
</div>
<img style="width: 30px; height: 30px;margin-left: 40px;" src="assets/images/camera.png">
<style>
@keyframes sensor-on {
100% {
transform: scale(2);
opacity: 0;
}
}
</style>
</div>`,
fireContent: `<div style="display: flex;
flex-direction: row;
justify-content: space-between;">
<div style="color: #F33152;
padding: 5px 13px;
background-color: rgba(243, 49, 82, 0.1);
border-radius: 20px;
text-align: center;
width: 100px;">Sự cố cháy</div>
<a href="/overview/camera-stream">
<svg width="24px" height="24px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none">
<g stroke="currentColor" stroke-width="2">
<path d="M16 16V8a1 1 0 00-1-1H5a1 1 0 00-1 1v8a1 1 0 001 1h10a1 1 0 001-1z"/>
<path stroke-linejoin="round" d="M20 7l-4 3v4l4 3V7z"/>
</g>
</svg>
</a>
</div>
<div><strong>Địa điểm:</strong> 120 Xa Lộ Hà Nội, Thành Phố, Thủ Đức, Thành phố Hồ Chí Minh</div>
<div><strong>Tọa độ:</strong> 10.8661° N, 106.8029° E</div>
<div><strong>Thời gian:</strong> 01:54, 16/05/2022</div>
<a href="/overview/overall-ground" target="_blank">Xem chi tiết</a>`,

sensorActiveBK: `
<div style="width: 30px; height: 30px; position: absolute; display: flex; justify-content: center; align-items: center; border-radius: 50%; background: linear-gradient(#ff0000, #C70039);">
<div style="position: absolute !important; width: 100%; height: 100%; background: #ff0000; border-radius: 50%; z-index: 1; animation: sensor-on 2s ease-out infinite;"></div>
<div style="position: absolute !important; width: 100%; height: 100%; background: #ff0000; border-radius: 50%; z-index: 1; animation: sensor-on 2s ease-out infinite; animation-delay: 1s;"></div>
<img src="assets/images/sensor-on.png" style="width: 30px; height: 30px; z-index: 9;">
</div>
<style>
@keyframes sensor-on {
100% {
transform: scale(2);
opacity: 0;
}
}
</style>
`,
}

+ 3
- 0
src/app/modules/overview/camera-stream/camera-stream.component.html View File

@@ -0,0 +1,3 @@
<h3>Camera Stream</h3>
<canvas #videoPlayer></canvas>


+ 0
- 0
src/app/modules/overview/camera-stream/camera-stream.component.scss View File


+ 21
- 0
src/app/modules/overview/camera-stream/camera-stream.component.spec.ts View File

@@ -0,0 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { CameraStreamComponent } from './camera-stream.component';

describe('CameraStreamComponent', () => {
let component: CameraStreamComponent;
let fixture: ComponentFixture<CameraStreamComponent>;

beforeEach(() => {
TestBed.configureTestingModule({
declarations: [CameraStreamComponent]
});
fixture = TestBed.createComponent(CameraStreamComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 30
- 0
src/app/modules/overview/camera-stream/camera-stream.component.ts View File

@@ -0,0 +1,30 @@
import {Component, OnInit, ViewChild, ElementRef, AfterViewInit, Renderer2} from '@angular/core';
import {loadPlayer, Player} from "rtsp-relay/browser";

@Component({
selector: 'app-camera-stream',
templateUrl: './camera-stream.component.html',
styleUrls: ['./camera-stream.component.scss']
})
export class CameraStreamComponent implements OnInit, AfterViewInit{
player?: Player;

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

ngOnInit() {
}
constructor(private el: ElementRef, private renderer: Renderer2) {}
async ngAfterViewInit() {
this.player = await loadPlayer({
url: 'ws://localhost:8081',
canvas: this.videoPlayer!.nativeElement,

onDisconnect: () => console.log('Connection lost!'),
});

console.log('Connected!', this.player);
}


}

+ 2
- 1
src/app/modules/overview/map/map.component.html View File

@@ -1,6 +1,7 @@
<div class="map-container">
<h2>ATMs Security Monitoring and Control</h2>
<div class="map-frame">
<div id="map"></div> <!-- Ensure no extra space after "map" -->
<div id="map"></div>
</div>
</div>


+ 5
- 1
src/app/modules/overview/map/map.component.scss View File

@@ -9,7 +9,7 @@

.map-frame {
border: 2px solid black;
height: 100%;
height: 90%;
}

#map {
@@ -23,3 +23,7 @@ p {
padding: 3px 2px;
background-color: rbg(243,49,82,0.1);
}
.hidden-background{
background: transparent;
border: none;
}

+ 73
- 80
src/app/modules/overview/map/map.component.ts View File

@@ -1,7 +1,8 @@
import {AfterViewInit, Component, OnDestroy, OnInit} from '@angular/core';
import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core';
import * as L from 'leaflet';
import {Subscription} from "rxjs";
import {SocketService} from "../../../shared/services/socket.service";
import { Subscription } from 'rxjs';
import { SocketService } from '../../../shared/services/socket.service';
import {ICON} from "../../../app.constants";

@Component({
selector: 'app-map',
@@ -9,124 +10,106 @@ import {SocketService} from "../../../shared/services/socket.service";
styleUrls: ['./map.component.scss']
})
export class MapComponent implements OnInit, AfterViewInit, OnDestroy {
private map: any;
houseIcon = L.icon({
iconUrl: '../../../../assets/images/icon.png',
iconSize: [38, 48],
shadowSize: [50, 64],
});
fireIcon = L.icon({
iconUrl: '../../../../assets/images/fire.gif',
iconSize: [38, 48],
})
sensorOnIcon = L.divIcon({
className: '',
html:'<div style="width: 30px; height: 30px; position: absolute; display: flex; justify-content: center; align-items: center; border-radius: 50%; background: linear-gradient(#ff0000, #C70039);">'+
' <div style="position: absolute !important; width: 100%; height: 100%; background: #ff0000; border-radius: 50%; z-index: 1; animation: sensor-on 2s ease-out infinite;"></div>'+
' <div style="position: absolute !important; width: 100%; height: 100%; background: #ff0000; border-radius: 50%; z-index: 1; animation: sensor-on 2s ease-out infinite; animation-delay: 1s;"></div>'+
' <img src="assets/images/sensor-on.png" style="width: 30px; height: 30px; z-index: 9;">'+
'</div>'+
'<style>'+
'@keyframes sensor-on {'+
' 100% {'+
' transform: scale(2);'+
' opacity: 0;'+
' }'+
'}'+
'</style>',
iconSize: [38, 48]
private map!: L.Map;
private featureGroup!: L.FeatureGroup;
private statusSubscription?: Subscription;
private messageSubscription?: Subscription;
sensorOff = ICON.sensorOff;
sensorOn = ICON.sensorOn;
sensorActive = ICON.sensorActiveBK;

sensorActiveIcon = L.divIcon({
html: this.sensorActive,
iconSize: [38, 48],
className: 'hidden-background'
});

//
// sensorOffIcon = L.divIcon({
// html: this.sensorOff,
// iconSize: [38, 38],
// className: 'hidden-background'
// });

// sensorOnIcon = L.divIcon({
// html: this.sensorOn,
// iconSize: [38, 38],
// className: 'hidden-background'
// });
sensorOffIcon = L.icon({
iconUrl: '../../../../assets/images/sensor-off.png',
iconSize: [38, 38],
})
});

state5 = false;
state6 = false;
sensorOnIcon = L.icon({
iconUrl: '../../../../assets/images/sensor-on.png',
iconSize: [38, 38],
});

private statusSubscription?: Subscription;
private messageSubscription?: Subscription;

constructor(private socketService$: SocketService) {}
state5 = false;
state6 = false;

constructor(private socketService$: SocketService) { }

ngOnInit() {
this.statusSubscription = this.socketService$.status$.subscribe(isConnected => {
if (isConnected) {
this.messageSubscription = this.socketService$.messages$.subscribe(message => {
this.messageSubscription = this.socketService$.messages$.subscribe(message => {
this.onMessage(message);
});
}
});
}
ngOnDestroy(): void {
if (this.statusSubscription) {
this.statusSubscription.unsubscribe();
}
if (this.messageSubscription) {
this.messageSubscription.unsubscribe();
}

this.socketService$.close();
}

onMessage(message: any) {
if (message.id == '0' && message.type === 'get') {
this.state5 = message.state5 === '1';
this.state6 = message.state6 === '1' ;
this.updateIcons();
}
}

ngAfterViewInit(): void {
this.initMap();
}

ngOnDestroy(): void {
this.statusSubscription?.unsubscribe();
this.messageSubscription?.unsubscribe();
this.socketService$.close();
}

private initMap(): void {
const mapContainer = document.getElementById('map');
if (mapContainer) {
this.map = L.map('map', {
center: [10.8494, 106.7537 ],
center: [10.8494, 106.7537],
zoom: 12
});

const tiles = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
minZoom: 3,
attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
});
}).addTo(this.map);

tiles.addTo(this.map);
this.addIconToMap()
this.featureGroup = L.featureGroup().addTo(this.map);
this.addIconToMap();
} else {
console.error('Map container not found');
}
}

onMessage(message: any) {
if (message.id == '0' && message.type === 'get') {
this.state5 = message.state5 === '1';
this.state6 = message.state6 === '1';
this.updateIcons();
}
}

addIconToMap() {
//add marker
let popupContent = `<div>Vinhome quận 9</div>
<a href="/overview/overall-ground" target="_blank">Xem chi tiết</a>`;

let fireContent = `<div style="color: #F33152;
padding: 2px 13px;
background-color: rgba(243, 49, 82, 0.1);
border-radius: 20px;
text-align: center;
width: 100px;">
Sự cố cháy
</div>
<div><strong>Địa điểm:</strong> 120 Xa Lộ Hà Nội, Thành Phố, Thủ Đức, Thành phố Hồ Chí Minh</div>

<div><strong>Tọa độ:</strong> 10.8661° N, 106.8029° E</div>
<div><strong>Thời gian:</strong> 01:54, 16/05/2022</div>

<a href="/overview/overall-ground" target="_blank">Xem chi tiết</a>`
L.marker([10.8356, 106.8300], {icon: this.state5 ? this.sensorOnIcon : this.sensorOffIcon})
const popupContent = `<div>Vinhome quận 9</div>
<a href="/overview/overall-ground" target="_blank">Xem chi tiết</a>`;

const fireContent = ICON.fireContent;

L.marker([10.8356, 106.8300], {icon: this.applyIcon(this.state5, this.state6)})
.addTo(this.map)
.bindPopup(popupContent);
L.marker([10.8661, 106.8029], {icon: this.state6 ? this.sensorOnIcon : this.sensorOffIcon})
L.marker([10.8661, 106.8029], {icon: this.applyIcon(this.state5, this.state6)})
.addTo(this.map)
.bindPopup(fireContent);
}
@@ -140,4 +123,14 @@ export class MapComponent implements OnInit, AfterViewInit, OnDestroy {

this.addIconToMap();
}

applyIcon(state1: boolean, state2: boolean): L.Icon | L.DivIcon {
if (state1 && state2) {
return this.sensorActiveIcon;
}
if (state1) {
return this.sensorOnIcon;
}
return this.sensorOffIcon;
}
}

+ 10
- 20
src/app/modules/overview/overall-ground/overall-ground.component.html View File

@@ -3,29 +3,19 @@
<div class="card-state">
<img src="assets/images/ground.png">

<p class="state t1" id="State1" [ngClass]="{'sensor-on': state1 === 'ON'}">
<img [src]="getImageSource(state1)" style="width: 30px; height: 30px">
</p>
<p class="state t2" id="State2" [ngClass]="{'sensor-on': state2 === 'ON'}">
<img [src]="getImageSource(state2)" style="width: 30px; height: 30px">
</p>
<p class="state t3" id="State3" [ngClass]="{'sensor-on': state3 === 'ON'}">
<img [src]="getImageSource(state3)" style="width: 30px; height: 30px">
</p>
<p class="state t4" id="State4" [ngClass]="{'sensor-on': state4 === 'ON'}">
<img [src]="getImageSource(state4)" style="width: 30px; height: 30px">
</p>
<p class="state t5" id="State5" [ngClass]="{'sensor-on': state5 === 'ON'}">
<img [src]="getImageSource(state5)" style="width: 30px; height: 30px">
</p>
<p class="state t6" id="State6" [ngClass]="{'sensor-on': state6 === 'ON'}">
<img [src]="getImageSource(state6)" style="width: 30px; height: 30px">
</p>
<div *ngFor="let state of states; let i = index"
[ngClass]="{'sensor-on': Sstate1 && Sstate2}"
class="state t{{i + 1}}"
id="State{{i + 1}}">
<img [src]="getImageSource()" style="width: 30px; height: 30px">
</div>

</div>
</div>
<div fxFlex="30" fxLayout="column" fxLayoutGap="50px">
<div>Công tắc 1 <button [disabled]="!isConnected" mat-flat-button color="{{Sstate1 ? 'accent' : 'primary'}}" (click)="toggleState1()">{{ Sstate1 ? 'ON' : 'OFF'}}</button></div>
<div>Công tắc 2 <button [disabled]="!isConnected" mat-flat-button color="{{Sstate2 ? 'accent' : 'primary'}}" (click)="toggleState2()">{{ Sstate2 ? 'ON' : 'OFF'}}</button></div>
<div>Công tắc 1 <button [disabled]="!isConnected" mat-flat-button color="{{Sstate1 ? 'accent' : 'primary'}}" (click)="toggleState1()">{{ Sstate1 ? 'DISARM' : 'ARM'}}</button></div>
<div>Công tắc 2 <button [disabled]="!isConnected" mat-flat-button color="{{Sstate2 ? 'accent' : 'primary'}}" (click)="toggleState2()">{{ Sstate2 ? 'TẮT CẢNH BÁO' : 'BẬT CẢNH BÁO'}}</button></div>
<div>Live Camera <button mat-stroked-button color="primary" [routerLink]="'/overview/camera-stream'"> Xem chi tiết </button></div>

</div>
</div>

+ 77
- 71
src/app/modules/overview/overall-ground/overall-ground.component.ts View File

@@ -1,90 +1,96 @@
import {ChangeDetectorRef, Component, OnChanges, OnDestroy, OnInit, SimpleChanges} from '@angular/core';
import {SocketService} from "../../../shared/services/socket.service";
import {Subscription} from "rxjs";
import * as L from "leaflet";

@Component({
selector: 'app-overall-ground',
templateUrl: './overall-ground.component.html',
styleUrls: ['./overall-ground.component.scss']
selector: 'app-overall-ground',
templateUrl: './overall-ground.component.html',
styleUrls: ['./overall-ground.component.scss']
})
export class OverallGroundComponent implements OnInit, OnDestroy{
isClicked = false;
isConnected = false;
state1 = '';
state2 = '';
state3 = '';
state4 = '';
state5 = '';
state6 = '';
Sstate1 = false;
Sstate2 = false;
private statusSubscription?: Subscription;
private messageSubscription?: Subscription;
private intervalId: any;
export class OverallGroundComponent implements OnInit, OnDestroy {
isClicked = false;
isConnected = false;
states = Array(6).fill(0);
state1 = '';
state2 = '';
state3 = '';
state4 = '';
state5 = '';
state6 = '';
Sstate1 = false;
Sstate2 = false;
imageIcon = 'assets/images/sensor-off.png';
private statusSubscription?: Subscription;
private messageSubscription?: Subscription;
private intervalId: any;


constructor(private socketService$: SocketService) {
}
constructor(private socketService$: SocketService) {
}

ngOnInit() {
this.socketService$.connect();
this.statusSubscription = this.socketService$.status$.subscribe(isConnected => {
this.isConnected = isConnected;
if (this.isConnected) {
this.intervalId = setInterval(() => this.getReadings(), 2000);
this.messageSubscription = this.socketService$.messages$.subscribe(message => {
this.onMessage(message);
});
}
ngOnInit() {
// this.socketService$.connect();
this.statusSubscription = this.socketService$.status$.subscribe(isConnected => {
this.isConnected = isConnected;
if (this.isConnected) {
this.intervalId = setInterval(() => this.getReadings(), 2000);
this.messageSubscription = this.socketService$.messages$.subscribe(message => {
this.onMessage(message);
});
}
}
});
}

toggleColor(): void {
this.isClicked = !this.isClicked;
}
toggleColor(): void {
this.isClicked = !this.isClicked;
}

ngOnDestroy(): void {
if (this.statusSubscription) {
this.statusSubscription.unsubscribe();
}
if (this.messageSubscription) {
this.messageSubscription.unsubscribe();
}
if (this.intervalId) {
clearInterval(this.intervalId);
}
this.socketService$.close();
ngOnDestroy(): void {
if (this.statusSubscription) {
this.statusSubscription.unsubscribe();
}

getReadings(){
let str = { id: '0', type: 'get' };
this.socketService$.sendMessage(str);
if (this.messageSubscription) {
this.messageSubscription.unsubscribe();
}
toggleState1() {
this.Sstate1 = !this.Sstate1;
let str = { id: '0', type: 'cmd', state1: this.Sstate1.toString() };
this.socketService$.sendMessage(str);
if (this.intervalId) {
clearInterval(this.intervalId);
}
this.socketService$.close();
}

toggleState2() {
this.Sstate2 = !this.Sstate2;
let str = { id: '0', type: 'cmd', state2: this.Sstate2.toString() };
this.socketService$.sendMessage(str);
}
getReadings() {
let str = {id: '0', type: 'get'};
this.socketService$.sendMessage(str);
}

getImageSource(state: string): string {
return state === 'ON' ? 'assets/images/sensor-on.png' : 'assets/images/sensor-off.png';
}
onMessage(message: any) {
if (message.id == '0' && message.type === 'get') {
this.state1 = message.state1 === '1' ? 'ON' : 'OFF';
this.state2 = message.state2 === '1' ? 'ON' : 'OFF';
this.state3 = message.state3 === '1' ? 'ON' : 'OFF';
this.state4 = message.state4 === '1' ? 'ON' : 'OFF';
this.state5 = message.state5 === '1' ? 'ON' : 'OFF';
this.state6 = message.state6 === '1' ? 'ON' : 'OFF';
}
this.Sstate1 = this.state5 === 'ON';
this.Sstate2 = this.state6 === 'ON';
toggleState1() {
this.Sstate1 = !this.Sstate1;
let str = {id: '0', type: 'cmd', state1: this.Sstate1.toString()};
this.socketService$.sendMessage(str);
}

toggleState2() {
this.Sstate2 = !this.Sstate2;
let str = {id: '0', type: 'cmd', state2: this.Sstate2.toString()};
this.socketService$.sendMessage(str);
}

getImageSource(): string {
return (this.Sstate1 && this.Sstate2) || this.Sstate1 ? 'assets/images/sensor-on.png' : 'assets/images/sensor-off.png';
}

onMessage(message: any) {
if (message.id == '0' && message.type === 'get') {
this.state1 = message.state1 === '1' ? 'ON' : 'OFF';
this.state2 = message.state2 === '1' ? 'ON' : 'OFF';
this.state3 = message.state3 === '1' ? 'ON' : 'OFF';
this.state4 = message.state4 === '1' ? 'ON' : 'OFF';
this.state5 = message.state5 === '1' ? 'ON' : 'OFF';
this.state6 = message.state6 === '1' ? 'ON' : 'OFF';
}
this.Sstate1 = this.state5 === 'ON';
this.Sstate2 = this.state6 === 'ON';
}

}

+ 5
- 2
src/app/modules/overview/overview.module.ts View File

@@ -7,17 +7,20 @@ import {overviewRoutes} from "./overview.routing";
import {MapComponent} from "./map/map.component";
import {SharedMaterialModule} from "../../shared/shared-material.module";
import {MatIconModule} from "@angular/material/icon";
import { CameraStreamComponent } from './camera-stream/camera-stream.component';
import {FormsModule} from "@angular/forms";

@NgModule({
declarations: [
OverallGroundComponent,
MapComponent
MapComponent,
CameraStreamComponent
],
imports: [
CommonModule,
RouterModule.forChild(overviewRoutes),
SharedMaterialModule,
MatIconModule
]
})
export class OverviewModule { }

+ 5
- 0
src/app/modules/overview/overview.routing.ts View File

@@ -1,6 +1,7 @@
import {Routes} from "@angular/router";
import {MapComponent} from "./map/map.component";
import {OverallGroundComponent} from "./overall-ground/overall-ground.component";
import {CameraStreamComponent} from "./camera-stream/camera-stream.component";

export const overviewRoutes: Routes = [
{
@@ -10,6 +11,10 @@ export const overviewRoutes: Routes = [
{
path: 'overall-ground',
component: OverallGroundComponent
},
{
path: 'camera-stream',
component: CameraStreamComponent
}

];

+ 4
- 2
src/app/shared/services/socket.service.ts View File

@@ -1,13 +1,16 @@
import { Injectable } from '@angular/core';
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';
import { BehaviorSubject, Subject } from "rxjs";
import { config } from "../../../config";
import { config } from "../../../assets/config/config";


@Injectable({
providedIn: 'root'
})
export class SocketService {
gateway = config.gateway;


websocket$!: WebSocketSubject<any> ;
private isConnected: boolean = false;
private messagesSubject$ = new Subject();
@@ -17,7 +20,6 @@ export class SocketService {

constructor() {
}

public connect(cfg: { reconnect: boolean } = {reconnect: false}): void {
if (!this.websocket$ || this.websocket$.closed) {
console.log('Trying to open a WebSocket connection…');

+ 8
- 0
src/assets/config/config.ts View File

@@ -0,0 +1,8 @@
export const config = {
gateway: 'wss:/socket.aztrace.vn/ws'
};
// export function loadConfig() {
// return {
// gateway: 'wss:/socket.aztrace.vn/ws'
// };
// }

BIN
src/assets/images/camera.png View File

Before After
Width: 576  |  Height: 570  |  Size: 19KB

+ 23
- 0
src/server/server.js View File

@@ -0,0 +1,23 @@
const WebSocket = require('ws');
const http = require('http');

const server = http.createServer();

const wss = new WebSocket.Server({ server });

wss.on('connection', function connection(ws) {

ws.on('message', function incoming(message) {
// Log tin nhắn nhận được
console.log('Nhận được: %s', message);
});

// Bắt sự kiện khi kết nối đóng
ws.on('close', function close() {
console.log('Client đã ngắt kết nối');
});
});

server.listen(8081, function listening() {
console.log('WebSocket server đang lắng nghe trên cổng 8081');
});

+ 4
- 0
src/server/stream.sh View File

@@ -0,0 +1,4 @@
ffmpeg -rtsp_transport tcp -i rtsp://admin:hd543211@@xuanphuong32.dyndns.org:8001/cam/realmonitor?channel=7&subtype=0 ^
-f mpegts -codec:v mpeg1video -s 640x480 -b:v 800k -r 30 ^
-codec:a mp2 -b:a 128k ^
http://localhost:8081

Loading…
Cancel
Save