| @@ -25,6 +25,7 @@ | |||
| "@asymmetrik/ngx-leaflet-markercluster": "^16.0.0", | |||
| "leaflet": "^1.9.4", | |||
| "rxjs": "~7.8.0", | |||
| "rxjs-websockets": "^9.0.0", | |||
| "tslib": "^2.3.0", | |||
| "zone.js": "~0.13.0" | |||
| }, | |||
| @@ -10,3 +10,24 @@ | |||
| </div> | |||
| </div> | |||
| <div class="topnav"> | |||
| <h1>Test Socket</h1> | |||
| </div> | |||
| <div class="content"> | |||
| <div class="card-grid"> | |||
| <div class="card"> | |||
| <p>Connect</p> | |||
| <p class="state"><span id="Connect">{{ isConnected ? 'Online' : 'Offline' }}</span></p> | |||
| </div> | |||
| <div class="card"> | |||
| <p class="state" id="State1">{{ State1 == '' ? '%STATE%' : State1}}</p> | |||
| <p class="state" id="State2">{{ State2 == '' ? '%STATE%' : State2}}</p> | |||
| <p class="state" id="State3">{{ State3 == '' ? '%STATE%' : State3}}</p> | |||
| <p class="state" id="State4">{{ State4 == '' ? '%STATE%' : State4}}</p> | |||
| <p class="state" id="State5">{{ State5 == '' ? '%STATE%' : State5}}</p> | |||
| <p class="state" id="State6">{{ State6 == '' ? '%STATE%' : State6}}</p> | |||
| <p><button (click)="toggleState1()" id="SetState1" class="button">Set State 1 On</button></p> | |||
| <p><button (click)="toggleState2()" id="SetState2" class="button">Set State 2 On</button></p> | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -10,3 +10,92 @@ button { | |||
| background-color: green !important; | |||
| color: white !important; | |||
| } | |||
| h1 { | |||
| font-size: 1.8rem; | |||
| color: white; | |||
| } | |||
| .topnav { | |||
| overflow: hidden; | |||
| background-color: #0A1128; | |||
| } | |||
| body { | |||
| margin: 0; | |||
| } | |||
| p { | |||
| text-align: center; | |||
| } | |||
| .content { | |||
| padding: 50px; | |||
| } | |||
| .card-grid { | |||
| max-width: 800px; | |||
| margin: 0 auto; | |||
| display: grid; | |||
| grid-gap: 2rem; | |||
| grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); | |||
| } | |||
| .card { | |||
| background-color: white; | |||
| box-shadow: 2px 2px 12px 1px rgba(140, 140, 140, .5); | |||
| } | |||
| .card-title { | |||
| font-size: 1.2rem; | |||
| font-weight: bold; | |||
| color: #034078 | |||
| } | |||
| .reading { | |||
| font-size: 1.2rem; | |||
| color: #1282A2; | |||
| } | |||
| .button { | |||
| padding: 15px 50px; | |||
| font-size: 24px; | |||
| text-align: center; | |||
| outline: none; | |||
| color: #fff; | |||
| background-color: #0f8b8d; | |||
| border: none; | |||
| border-radius: 5px; | |||
| -webkit-touch-callout: none; | |||
| -webkit-user-select: none; | |||
| -khtml-user-select: none; | |||
| -moz-user-select: none; | |||
| -ms-user-select: none; | |||
| user-select: none; | |||
| -webkit-tap-highlight-color: rgba(0, 0, 0, 0); | |||
| } | |||
| /*.button:hover {background-color: #0f8b8d}*/ | |||
| .button:active { | |||
| background-color: #0f8b8d; | |||
| box-shadow: 2 2px #CDCDCD; | |||
| transform: translateY(2px); | |||
| } | |||
| .state { | |||
| font-size: 1.5rem; | |||
| color: #8c8c8c; | |||
| font-weight: bold; | |||
| text-align: center; | |||
| } | |||
| .content { | |||
| padding: 30px; | |||
| max-width: 600px; | |||
| margin: 0 auto; | |||
| } | |||
| .card { | |||
| background-color: #F8F7F9;; | |||
| box-shadow: 2px 2px 12px 1px rgba(140, 140, 140, .5); | |||
| padding-top: 10px; | |||
| padding-bottom: 20px; | |||
| } | |||
| @@ -1,14 +1,59 @@ | |||
| import { Component } from '@angular/core'; | |||
| import {Component, OnDestroy, OnInit} from '@angular/core'; | |||
| import {SocketService} from "../../../shared/services/socket.service"; | |||
| @Component({ | |||
| selector: 'app-overall-ground', | |||
| templateUrl: './overall-ground.component.html', | |||
| styleUrls: ['./overall-ground.component.scss'] | |||
| }) | |||
| export class OverallGroundComponent { | |||
| export class OverallGroundComponent implements OnInit, OnDestroy{ | |||
| isClicked = false; | |||
| isConnected: boolean = false; | |||
| State1: string = ''; | |||
| State2: string = ''; | |||
| State3: string = ''; | |||
| State4: string = ''; | |||
| State5: string = ''; | |||
| State6: string = ''; | |||
| constructor(private socketService$: SocketService) { | |||
| } | |||
| ngOnInit() { | |||
| this.socketService$.connect(); | |||
| this.isConnected = this.socketService$.getStatus(); | |||
| if(this.isConnected){ | |||
| this.socketService$.messages$.subscribe(message => { | |||
| this.onMessage(message); | |||
| }); | |||
| } | |||
| } | |||
| toggleColor(): void { | |||
| this.isClicked = !this.isClicked; | |||
| } | |||
| ngOnDestroy(): void { | |||
| this.socketService$.close(); | |||
| } | |||
| toggleState1() { | |||
| this.socketService$.sendMessage({ id: '0', type: 'cmd', state1: !this.State1 }); | |||
| } | |||
| toggleState2() { | |||
| this.socketService$.sendMessage({ id: '0', type: 'cmd', state2: !this.State2 }); | |||
| } | |||
| 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'; | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,57 @@ | |||
| import { Injectable } from '@angular/core'; | |||
| import { webSocket, WebSocketSubject } from 'rxjs/webSocket'; | |||
| import {catchError, delayWhen, Observable, retryWhen, Subject, tap, timer} from "rxjs"; | |||
| @Injectable({ | |||
| providedIn: 'root' | |||
| }) | |||
| export class SocketService { | |||
| gateway = 'ws://192.168.2.45/ws'; | |||
| websocket$!: WebSocketSubject<any> ; | |||
| private isConnected: boolean = false; | |||
| private messagesSubject$ = new Subject(); | |||
| public messages$ = this.messagesSubject$.asObservable(); | |||
| constructor() { | |||
| } | |||
| public connect(cfg: { reconnect: boolean } = {reconnect: false}): void { | |||
| if (!this.websocket$ || this.websocket$.closed) { | |||
| console.log('Trying to open a WebSocket connection…'); | |||
| this.websocket$ = this.getNewWebSocket(); | |||
| this.websocket$.subscribe((messages) => { | |||
| this.messagesSubject$.next(messages); | |||
| }); | |||
| } | |||
| } | |||
| getStatus(): boolean { | |||
| return this.isConnected; | |||
| } | |||
| close() { | |||
| this.websocket$.complete(); | |||
| } | |||
| sendMessage(msg: any) { | |||
| this.websocket$.next(msg); | |||
| } | |||
| private getNewWebSocket() { | |||
| return webSocket({ | |||
| url: this.gateway, | |||
| openObserver: { | |||
| next: () => { | |||
| console.log('Connection ok'); | |||
| this.isConnected = true; | |||
| } | |||
| }, | |||
| closeObserver: { | |||
| next: () => { | |||
| console.log('Connection closed'); | |||
| this.isConnected = false; | |||
| this.connect({reconnect: true}); | |||
| } | |||
| }, | |||
| }); | |||
| } | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| import { NgModule } from "@angular/core"; | |||
| import { FlexLayoutModule } from "@angular/flex-layout"; | |||
| import {MatButtonModule} from "@angular/material/button"; | |||
| import { MatButtonModule } from "@angular/material/button"; | |||
| @NgModule({ | |||
| exports: [ | |||