#8 camera

Merged
trungnd merged 9 commits from features/camera into master 1 year ago
  1. +1
    -1
      README.md
  2. +2
    -1
      angular.json
  3. +4
    -1
      package.json
  4. +3
    -14
      src/app/app.module.ts
  5. +2
    -6
      src/app/modules/overview/camera-stream/camera-stream.component.html
  6. +4
    -21
      src/app/modules/overview/camera-stream/camera-stream.component.scss
  7. +15
    -11
      src/app/modules/overview/camera-stream/camera-stream.component.ts
  8. +1
    -0
      src/app/modules/overview/overall-ground/overall-ground.component.ts
  9. +1
    -0
      src/app/modules/overview/overview.module.ts
  10. +0
    -18
      src/app/shared/services/app-init.service.ts
  11. +11
    -8
      src/app/shared/services/socket.service.ts
  12. +22
    -16
      src/server/server.js
  13. +0
    -4
      src/server/stream.sh

+ 1
- 1
README.md View File

@@ -1,4 +1,4 @@
# LotWebUi
# iotWebUi

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 16.2.14.


+ 2
- 1
angular.json View File

@@ -27,7 +27,8 @@
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/assets"
"src/assets",
"src/server"
],
"styles": [
"@angular/material/prebuilt-themes/indigo-pink.css",

+ 4
- 1
package.json View File

@@ -6,7 +6,8 @@
"start": "ng serve -o",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
"test": "ng test",
"camera-server": "node dist/lot-web-ui/server/server.js"
},
"private": true,
"dependencies": {
@@ -23,6 +24,8 @@
"@angular/router": "^16.2.0",
"@asymmetrik/ngx-leaflet": "^16.0.1",
"@asymmetrik/ngx-leaflet-markercluster": "^16.0.0",
"express": "^4.19.2",
"express-ws": "^5.0.2",
"leaflet": "^1.9.4",
"ngx-toastr": "^17.0.2",
"rtsp-relay": "^1.8.0",

+ 3
- 14
src/app/app.module.ts View File

@@ -1,4 +1,4 @@
import {APP_INITIALIZER, NgModule} from '@angular/core';
import { NgModule} from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
@@ -6,12 +6,9 @@ import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {SharedModule} from "./shared/shared.module";
import {HttpClientModule} from "@angular/common/http";
import {AppInitService} from "./shared/services/app-init.service";
import { ToastrModule } from 'ngx-toastr';

export function appInitializerFactory(appInitializerService: AppInitService): () => Promise<any> {
return () => appInitializerService.initializeApp();
}



@NgModule({
@@ -30,15 +27,7 @@ export function appInitializerFactory(appInitializerService: AppInitService): ()
autoDismiss: true
}), // ToastrModule added
],
providers: [

{
provide: APP_INITIALIZER,
useFactory: appInitializerFactory,
deps: [AppInitService],
multi: true
}
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

+ 2
- 6
src/app/modules/overview/camera-stream/camera-stream.component.html View File

@@ -1,6 +1,2 @@
<h3>Camera Stream</h3>
<!--<canvas #videoPlayer></canvas>-->

<video width="700" controls style="display: block; margin-left: auto; margin-right: auto">
<source src="assets/video/video.mp4" type="video/mp4">
</video>
<h3 style="text-align: center">Camera Stream</h3>
<canvas class="video" #videoPlayer></canvas>

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

@@ -1,22 +1,5 @@
.tooltip {
position: relative;
display: inline-block;
}

.tooltip .tooltiptext {
visibility: hidden;
width: 300px;
padding: 10px;
background-color: #fff;
color: black;
border-radius: 6px;
position: absolute;
z-index: 1;
bottom: 100%;
left: 50%;
margin-left: -60px;
}

.tooltip:hover .tooltiptext {
visibility: visible;
.video {
width: 78% !important;
display: block;
margin: 0 auto
}

+ 15
- 11
src/app/modules/overview/camera-stream/camera-stream.component.ts View File

@@ -9,21 +9,25 @@ import {loadPlayer, Player} from "rtsp-relay/browser";
export class CameraStreamComponent implements OnInit, AfterViewInit{
player?: Player;

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

constructor(private el: ElementRef, private renderer: Renderer2) {}

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);
const connect = async () => {
this.player = await loadPlayer({
url: 'ws://localhost:8080/stream',
canvas: this.videoPlayer!.nativeElement,
onDisconnect: () => {
setTimeout(connect, 5000); // reconnect after 5 seconds
},
});
};
connect();
}



+ 1
- 0
src/app/modules/overview/overall-ground/overall-ground.component.ts View File

@@ -3,6 +3,7 @@ import {SocketService} from "../../../shared/services/socket.service";
import {Subscription} from "rxjs";
import {ToastrService} from "ngx-toastr";


@Component({
selector: 'app-overall-ground',
templateUrl: './overall-ground.component.html',

+ 1
- 0
src/app/modules/overview/overview.module.ts View File

@@ -8,6 +8,7 @@ import {MapComponent} from "./map/map.component";
import {SharedMaterialModule} from "../../shared/shared-material.module";
import { CameraStreamComponent } from './camera-stream/camera-stream.component';


@NgModule({
declarations: [
OverallGroundComponent,

+ 0
- 18
src/app/shared/services/app-init.service.ts View File

@@ -1,18 +0,0 @@
import { Injectable } from '@angular/core';
import {config} from "../../../assets/config/config";

@Injectable({
providedIn: 'root'
})
export class AppInitService {
appConfig = config;

constructor() {}

initializeApp(): Promise<any> {
return new Promise((resolve, reject) => {
console.log('Loaded:', this.appConfig);
resolve(true);
});
}
}

+ 11
- 8
src/app/shared/services/socket.service.ts View File

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


@@ -10,8 +10,7 @@ import { config } from "../../../assets/config/config";
export class SocketService {
gateway = config.gateway;


websocket$!: WebSocketSubject<any> ;
websocket$: WebSocketSubject<any> | undefined ;
private isConnected: boolean = false;
private messagesSubject$ = new Subject();
public messages$ = this.messagesSubject$.asObservable();
@@ -20,22 +19,25 @@ 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…');

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

}

close() {
this.websocket$.complete();
this.websocket$?.complete();
this.websocket$ = undefined;
}

sendMessage(msg: any) {
this.websocket$.next(msg);
this.websocket$?.next(msg);
}

private getNewWebSocket() {
@@ -51,6 +53,7 @@ export class SocketService {
closeObserver: {
next: () => {
console.log('Connection closed');
this.websocket$ = undefined;
this.isConnected = false;
this.connect({reconnect: true});
this.statusSubject.next(this.isConnected);

+ 22
- 16
src/server/server.js View File

@@ -1,23 +1,29 @@
const WebSocket = require('ws');
const http = require('http');
const express = require('express');
const expressWs = require('express-ws');
const app = express();
expressWs(app);

const server = http.createServer();
const { proxy, scriptUrl } = require('rtsp-relay')(app);

const wss = new WebSocket.Server({ server });
const port = 8080;
const urlCamera = 'rtsp://admin:[email protected]:88/cam/realmonitor?channel=1&subtype=0';

wss.on('connection', function connection(ws) {
app.ws('/api/stream/:cameraIP', (ws, req) =>
proxy({
url: `rtsp://${req.params.cameraIP}:554/feed`,
})(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');
});
const handler = proxy({
url: urlCamera,
verbose: false,
transport: 'tcp'
});

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

app.ws('/stream', handler);

const server = app.listen(port, () => {
console.log(`RTSP Relay Server is listening on port ${port}`);
});


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

@@ -1,4 +0,0 @@
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