Compare commits
No commits in common. "e975585f5784c7bed9f9bdca7c38bd7ca36d6dd2" and "a857f870a579356b7429f5b3531e7f38e9de24c1" have entirely different histories.
e975585f57
...
a857f870a5
@ -10,7 +10,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="item-robotText">
|
<div class="item-robotText">
|
||||||
<div *ngIf="!(robotIsReady$ | async)" id="robotIsOnTour">Robot is on Tour</div>
|
<div *ngIf="robotStateChange$ | async" id="robotIsOnTour">Robot is on Tour</div>
|
||||||
<div *ngIf="(robotIsReady$ | async)" id="robotIsReady">Robot is Ready</div>
|
<div *ngIf="!(robotStateChange$ | async)" id="robotIsReady">Robot is Ready</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -8,8 +8,7 @@ import { StoreService } from '../Service/store.service';
|
|||||||
styleUrls: ['./home.component.css']
|
styleUrls: ['./home.component.css']
|
||||||
})
|
})
|
||||||
export class HomeComponent {
|
export class HomeComponent {
|
||||||
// Aktueller RobotStatus wird subscribed
|
robotStateChange$: Observable<boolean> = this.storeService.currentRobotReady;
|
||||||
robotIsReady$: Observable<boolean> = this.storeService.currentRobotReady;
|
|
||||||
|
|
||||||
constructor(private storeService: StoreService) {
|
constructor(private storeService: StoreService) {
|
||||||
}
|
}
|
||||||
|
@ -15,43 +15,36 @@ export class InputComponent implements OnInit, OnDestroy {
|
|||||||
subscription: Subscription;
|
subscription: Subscription;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public speechService: SpeechService,
|
public service: SpeechService,
|
||||||
private mqttRequestService: MqttRequestService
|
private mqttRequestService: MqttRequestService
|
||||||
) {
|
) {
|
||||||
if (!this.speechService.initSpeechServiceStarted) {
|
if (!this.service.initSpeechServiceStarted) {
|
||||||
this.speechService.init();
|
this.service.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
// subscribe auf die eingegebene Spracheingabe, gibt als response einen string
|
this.subscription = this.service.currentApprovalStageMessage.subscribe(msg => {
|
||||||
this.subscription = this.speechService.currentApprovalStageMessage.subscribe(msg => {
|
|
||||||
this.text = msg;
|
this.text = msg;
|
||||||
if (this.text !== '') {
|
if (this.text !== '') {
|
||||||
this.micIsClicked = false;
|
this.micIsClicked = false;
|
||||||
this.mqttRequestService.publishToINPUT(this.text); // msg wird hier den Request Service weitergeleitet
|
this.mqttRequestService.publishToINPUT(this.text);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Beim klick auf das Mikrofon, wird die Spracheingabe gestartet. Beim 2ten klick auf das
|
|
||||||
* Mikrofon wird die Spracheingabe gestoppt
|
|
||||||
*/
|
|
||||||
startStopService() {
|
startStopService() {
|
||||||
//
|
|
||||||
if (this.micIsClicked) {
|
if (this.micIsClicked) {
|
||||||
this.micIsClicked = false;
|
this.micIsClicked = false;
|
||||||
this.speechService.stop(); // Spracheingabe stoppen
|
this.service.stop();
|
||||||
} else {
|
} else {
|
||||||
this.micIsClicked = true;
|
this.micIsClicked = true;
|
||||||
this.speechService.start(); //Spracheingabe starten
|
this.service.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.subscription.unsubscribe()
|
this.subscription.unsubscribe()
|
||||||
this.speechService.onDestory();
|
this.service.onDestory();
|
||||||
this.text = '';
|
this.text = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import { MqttRequestService } from 'src/app/Service/Mqtt/mqtt-request.service';
|
import { MqttRequestService } from 'src/app/Service/Mqtt/mqtt-request.service';
|
||||||
|
|
||||||
declare var speechSynthesis: any;
|
declare var speechSynthesis: any;
|
||||||
@ -15,7 +16,6 @@ export class OutputComponent implements OnInit, OnDestroy {
|
|||||||
constructor(private mqttRequestService: MqttRequestService) { }
|
constructor(private mqttRequestService: MqttRequestService) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
// subsribe auf "responseMessage", sie wird jedes mal getriggert wenn eine Spracheingabe statt findet
|
|
||||||
this.subscription = this.mqttRequestService.responseMessage.subscribe(msg => {
|
this.subscription = this.mqttRequestService.responseMessage.subscribe(msg => {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.outputText = msg;
|
this.outputText = msg;
|
||||||
@ -24,11 +24,6 @@ export class OutputComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Methode spricht das übergeben string aus --> Sprachausgabe
|
|
||||||
* @method speak
|
|
||||||
* @param string
|
|
||||||
*/
|
|
||||||
speak(text: string) {
|
speak(text: string) {
|
||||||
const utterance = new SpeechSynthesisUtterance(text);
|
const utterance = new SpeechSynthesisUtterance(text);
|
||||||
utterance.lang = 'en-US';
|
utterance.lang = 'en-US';
|
||||||
@ -39,4 +34,5 @@ export class OutputComponent implements OnInit, OnDestroy {
|
|||||||
this.subscription.unsubscribe();
|
this.subscription.unsubscribe();
|
||||||
this.mqttRequestService.onDestroy();
|
this.mqttRequestService.onDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,8 @@ declare var webkitSpeechRecognition: any;
|
|||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class SpeechService {
|
export class SpeechService {
|
||||||
/*
|
|
||||||
* currentApprovalStageMessage wird als observable festgelegt,
|
|
||||||
* damit man aus anderen Komponenten die änderungen mitbekommt!
|
|
||||||
*/
|
|
||||||
private approvalStageMessage = new BehaviorSubject('');
|
private approvalStageMessage = new BehaviorSubject('');
|
||||||
currentApprovalStageMessage = this.approvalStageMessage.asObservable();
|
currentApprovalStageMessage = this.approvalStageMessage.asObservable();
|
||||||
|
|
||||||
initSpeechServiceStarted: boolean = false;
|
initSpeechServiceStarted: boolean = false;
|
||||||
|
|
||||||
recognition = new webkitSpeechRecognition();
|
recognition = new webkitSpeechRecognition();
|
||||||
@ -23,6 +18,8 @@ export class SpeechService {
|
|||||||
tempWords: string | undefined;
|
tempWords: string | undefined;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this.recognition.pitch = 10;
|
||||||
|
this.recognition.rate = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@ -36,19 +33,22 @@ export class SpeechService {
|
|||||||
.map((result) => result.transcript)
|
.map((result) => result.transcript)
|
||||||
.join('');
|
.join('');
|
||||||
this.tempWords = transcript;
|
this.tempWords = transcript;
|
||||||
|
console.log('init:' + transcript);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
this.text = '';
|
this.text = '';
|
||||||
this.isStoppedSpeechRecog = false;
|
this.isStoppedSpeechRecog = false;
|
||||||
this.recognition.start(); // Start der Sprachaufnahme
|
this.recognition.start();
|
||||||
|
console.log("Speech recognition started")
|
||||||
this.recognition.addEventListener('end', () => {
|
this.recognition.addEventListener('end', () => {
|
||||||
this.wordConcat()
|
this.wordConcat()
|
||||||
this.recognition.stop(); // Ende der Sprachaufnahme
|
this.recognition.stop();
|
||||||
if (!this.isStoppedSpeechRecog) {
|
if (!this.isStoppedSpeechRecog) {
|
||||||
this.isStoppedSpeechRecog = true;
|
this.isStoppedSpeechRecog = true;
|
||||||
this.approvalStageMessage.next(this.text); // String was eingelesen wurde, wird mit der Methode "next(..)" an alle subsriber weitergeleitet!
|
console.log("End speech recognition");
|
||||||
|
this.approvalStageMessage.next(this.text);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -62,7 +62,6 @@ export class SpeechService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// addiert die Wörter bei der Sprachaufnahme zusammen
|
|
||||||
wordConcat() {
|
wordConcat() {
|
||||||
this.text = this.text + ' ' + this.tempWords;
|
this.text = this.text + ' ' + this.tempWords;
|
||||||
this.tempWords = '';
|
this.tempWords = '';
|
||||||
|
@ -18,19 +18,10 @@ export class PlantCardComponent {
|
|||||||
constructor(public dialog: MatDialog, private mqttRequestService: MqttRequestService) {
|
constructor(public dialog: MatDialog, private mqttRequestService: MqttRequestService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Methode wird in der HTML datei verwendet damit der Wert nicht undefined ist.
|
|
||||||
* @method
|
|
||||||
*/
|
|
||||||
getFormattedLastRequestedTimestamp(): Observable<string> {
|
getFormattedLastRequestedTimestamp(): Observable<string> {
|
||||||
return of(this.calculateTimestamp(this.plant.Timestamp))
|
return of(this.calculateTimestamp(this.plant.Timestamp))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Methode dividiert den Timestamp der Pflanze mit der aktuellen Zeit. Die Zeit wird dann in Tagen, Stunden, Minuten, Sekunden angezeigt
|
|
||||||
* @method
|
|
||||||
* @return string wie z.B "1 hour ago"
|
|
||||||
*/
|
|
||||||
calculateTimestamp(timestamp: string): string {
|
calculateTimestamp(timestamp: string): string {
|
||||||
const datePlant = new Date(timestamp);
|
const datePlant = new Date(timestamp);
|
||||||
this.currentDate = new Date();
|
this.currentDate = new Date();
|
||||||
@ -52,10 +43,6 @@ export class PlantCardComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Methode öffnet den Dialog "DeleteConfirmDialogComponent"
|
|
||||||
* @method
|
|
||||||
*/
|
|
||||||
onDeletePlant() {
|
onDeletePlant() {
|
||||||
this.dialog.open(DeleteConfirmDialogComponent, {
|
this.dialog.open(DeleteConfirmDialogComponent, {
|
||||||
data: this.plant,
|
data: this.plant,
|
||||||
@ -63,10 +50,6 @@ export class PlantCardComponent {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Methode öffnet den Dialog "ConfigurePlantDialogComponent"
|
|
||||||
* @method
|
|
||||||
*/
|
|
||||||
onConfigurePlant() {
|
onConfigurePlant() {
|
||||||
this.dialog.open(ConfigurePlantDialogComponent, {
|
this.dialog.open(ConfigurePlantDialogComponent, {
|
||||||
data: {
|
data: {
|
||||||
@ -75,4 +58,5 @@ export class PlantCardComponent {
|
|||||||
width: '400px',
|
width: '400px',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,6 @@ export class PlantsComponent {
|
|||||||
|
|
||||||
|
|
||||||
constructor(public dialog: MatDialog, public storeService: StoreService, private mqttRequestService: MqttRequestService) {
|
constructor(public dialog: MatDialog, public storeService: StoreService, private mqttRequestService: MqttRequestService) {
|
||||||
// sobald es eine änderung bei den pflanzenNamen gibt, wird bei der suchleiste ein neuer filter eingesetzt
|
|
||||||
this.options$.subscribe(response => {
|
this.options$.subscribe(response => {
|
||||||
this.filteredOptions = this.myControl.valueChanges.pipe(
|
this.filteredOptions = this.myControl.valueChanges.pipe(
|
||||||
startWith(''),
|
startWith(''),
|
||||||
@ -31,39 +30,24 @@ export class PlantsComponent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* es wird nach dem Pflanzen Namen gesucht.
|
|
||||||
* @method
|
|
||||||
* @return Pflant
|
|
||||||
*/
|
|
||||||
onSearchPlant(plantName: string): Observable<Plant> {
|
onSearchPlant(plantName: string): Observable<Plant> {
|
||||||
return this.storeService.getPlant(plantName);
|
return this.storeService.getPlant(plantName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Methode öffnet das Dialog "AddPlantDialogComponent"
|
|
||||||
* @method
|
|
||||||
*/
|
|
||||||
onNewPlant() {
|
onNewPlant() {
|
||||||
this.dialog.open(AddPlantDialogComponent, {
|
this.dialog.open(AddPlantDialogComponent, {
|
||||||
width: '420px',
|
width: '420px',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* die ausgewählte Pflanze wird in "selectedPlant" geschrieben
|
|
||||||
* @method
|
|
||||||
*/
|
|
||||||
onOptionSelect(value: string) {
|
onOptionSelect(value: string) {
|
||||||
this.selectedPlant = value;
|
this.selectedPlant = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
onOptionDefault() {
|
onOptionDefault() {
|
||||||
this.selectedPlant = 'undefined';
|
this.selectedPlant = 'undefined';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private _filter(value: string, options: string[]): string[] {
|
private _filter(value: string, options: string[]): string[] {
|
||||||
const filterValue = value.toLowerCase();
|
const filterValue = value.toLowerCase();
|
||||||
|
|
||||||
|
@ -17,32 +17,18 @@ export class RobotComponent {
|
|||||||
constructor(private storeService: StoreService) {
|
constructor(private storeService: StoreService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Methode setzt die Farbe der LoadingBar auf Rot ("warn") oder Blau ("Primary")
|
|
||||||
* @method
|
|
||||||
* @return warn oder primary
|
|
||||||
*/
|
|
||||||
getLoadingBarColor(): Observable<ThemePalette> {
|
getLoadingBarColor(): Observable<ThemePalette> {
|
||||||
return this.batteryChargingStatus$.pipe(
|
return this.batteryChargingStatus$.pipe(
|
||||||
map(chargingStatus => chargingStatus < 20 ? "warn" : "primary")
|
map(chargingStatus => chargingStatus < 20 ? "warn" : "primary")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Methode wird in der HTML datei verwendet damit der Wert nicht undefined ist.
|
|
||||||
* @method
|
|
||||||
*/
|
|
||||||
getFormattedLastRequestedBatteryState(): Observable<string> {
|
getFormattedLastRequestedBatteryState(): Observable<string> {
|
||||||
return this.requestTimestamp$.pipe(
|
return this.requestTimestamp$.pipe(
|
||||||
map(timestamp => this.formatLastRequestedBatteryState(timestamp))
|
map(timestamp => this.formatLastRequestedBatteryState(timestamp))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Methode dividiert den Timestamp der Pflanze mit der aktuellen Zeit. Die Zeit wird dann in Tagen, Stunden, Minuten, Sekunden angezeigt
|
|
||||||
* @method
|
|
||||||
* @return string wie z.B "1 hour ago"
|
|
||||||
*/
|
|
||||||
formatLastRequestedBatteryState(timestamp: string): string {
|
formatLastRequestedBatteryState(timestamp: string): string {
|
||||||
const datePlant = new Date(timestamp);
|
const datePlant = new Date(timestamp);
|
||||||
const currentDate = new Date();
|
const currentDate = new Date();
|
||||||
@ -63,4 +49,5 @@ export class RobotComponent {
|
|||||||
return `${seconds} second${seconds !== 1 ? 's' : ''} ago`;
|
return `${seconds} second${seconds !== 1 ? 's' : ''} ago`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { BehaviorSubject, Subscription } from 'rxjs';
|
import { BehaviorSubject, Subscription } from 'rxjs';
|
||||||
import { take } from 'rxjs/operators';
|
|
||||||
import { ErrorDialogComponent } from 'src/app/dialog/error-dialog/error-dialog.component';
|
import { ErrorDialogComponent } from 'src/app/dialog/error-dialog/error-dialog.component';
|
||||||
import { Plant } from 'src/app/models/plant.model';
|
import { Plant } from 'src/app/models/plant.model';
|
||||||
import { PlantCount } from 'src/app/models/plantCount.model';
|
import { PlantCount } from 'src/app/models/plantCount.model';
|
||||||
|
import { Position } from 'src/app/models/position.model';
|
||||||
import { RobotBattery } from 'src/app/models/robotBattery.model';
|
import { RobotBattery } from 'src/app/models/robotBattery.model';
|
||||||
import { StoreService } from '../store.service';
|
import { StoreService } from '../store.service';
|
||||||
import { MqttSetDataService } from './mqtt-set-data.service';
|
import { MqttSetDataService } from './mqtt-set-data.service';
|
||||||
@ -14,7 +14,6 @@ import { MqttService } from './mqtt.service';
|
|||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class MqttRequestService {
|
export class MqttRequestService {
|
||||||
// wird für die Sprachausgabe verwendet
|
|
||||||
private sourceMessage = new BehaviorSubject('');
|
private sourceMessage = new BehaviorSubject('');
|
||||||
responseMessage = this.sourceMessage.asObservable();
|
responseMessage = this.sourceMessage.asObservable();
|
||||||
|
|
||||||
@ -23,7 +22,6 @@ export class MqttRequestService {
|
|||||||
constructor(private mqttService: MqttService,
|
constructor(private mqttService: MqttService,
|
||||||
private mqttSetDataService: MqttSetDataService,
|
private mqttSetDataService: MqttSetDataService,
|
||||||
private storeService: StoreService, public dialog: MatDialog) {
|
private storeService: StoreService, public dialog: MatDialog) {
|
||||||
|
|
||||||
//Subscribe to the Topics
|
//Subscribe to the Topics
|
||||||
this.mqttService.subscribeToTopic("BACKEND/DATA/SENSORDATA_ALL").subscribe(data => {
|
this.mqttService.subscribeToTopic("BACKEND/DATA/SENSORDATA_ALL").subscribe(data => {
|
||||||
if (typeof data !== "object") {
|
if (typeof data !== "object") {
|
||||||
@ -38,10 +36,11 @@ export class MqttRequestService {
|
|||||||
console.error('Error:', err);
|
console.error('Error:', err);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.mqttService.subscribeToTopic("BACKEND/DATA/ERROR").subscribe(errorMsg => {
|
this.mqttService.subscribeToTopic("BACKEND/DATA/ERROR").subscribe(data => {
|
||||||
if (typeof errorMsg !== "object") {
|
if (typeof data !== "object") {
|
||||||
|
const payload = JSON.parse(data) as string;
|
||||||
this.dialog.open(ErrorDialogComponent, {
|
this.dialog.open(ErrorDialogComponent, {
|
||||||
data: errorMsg,
|
data: payload,
|
||||||
width: '400px',
|
width: '400px',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -66,18 +65,18 @@ export class MqttRequestService {
|
|||||||
console.error('Error:', err);
|
console.error('Error:', err);
|
||||||
});
|
});
|
||||||
|
|
||||||
// this.mqttService.subscribeToTopic("BACKEND/DATA/POSITION").subscribe(data => {
|
this.mqttService.subscribeToTopic("BACKEND/DATA/POSITION").subscribe(data => {
|
||||||
// if (typeof data !== "object") {
|
if (typeof data !== "object") {
|
||||||
// const payload = JSON.parse(data) as Position;
|
const payload = JSON.parse(data) as Position;
|
||||||
// this.mqttSetDataService.setRobotPosition(payload);
|
this.mqttSetDataService.setRobotPosition(payload);
|
||||||
// }
|
}
|
||||||
// }, err => {
|
}, err => {
|
||||||
// this.dialog.open(ErrorDialogComponent, {
|
this.dialog.open(ErrorDialogComponent, {
|
||||||
// data: err,
|
data: err,
|
||||||
// width: '400px',
|
width: '400px',
|
||||||
// });
|
});
|
||||||
// console.error('Error:', err);
|
console.error('Error:', err);
|
||||||
// });
|
});
|
||||||
|
|
||||||
this.mqttService.subscribeToTopic("BACKEND/DATA/BATTERY").subscribe(data => {
|
this.mqttService.subscribeToTopic("BACKEND/DATA/BATTERY").subscribe(data => {
|
||||||
if (typeof data !== "object") {
|
if (typeof data !== "object") {
|
||||||
@ -93,10 +92,9 @@ export class MqttRequestService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.mqttService.subscribeToTopic("BACKEND/DATA/ROBOTREADY").subscribe(data => {
|
this.mqttService.subscribeToTopic("BACKEND/DATA/ROBOTREADY").subscribe(data => {
|
||||||
if (data === "False") {
|
if (typeof data !== "object") {
|
||||||
this.mqttSetDataService.setRobotReady(false);
|
const payload = JSON.parse(data) as boolean;
|
||||||
} else if (data === "True") {
|
this.mqttSetDataService.setRobotReady(payload);
|
||||||
this.mqttSetDataService.setRobotReady(true);
|
|
||||||
}
|
}
|
||||||
}, err => {
|
}, err => {
|
||||||
this.dialog.open(ErrorDialogComponent, {
|
this.dialog.open(ErrorDialogComponent, {
|
||||||
@ -118,7 +116,14 @@ export class MqttRequestService {
|
|||||||
});
|
});
|
||||||
console.error('Error:', err);
|
console.error('Error:', err);
|
||||||
});
|
});
|
||||||
|
// this.mqttService.subscribeToTopic("BACKEND/DATA/POSITION").subscribe(data => {
|
||||||
|
// if (typeof data !== "object") {
|
||||||
|
// const payload = JSON.parse(data) as Plant[];
|
||||||
|
// this.mqttSetDataService.setDataAllPlants(payload);
|
||||||
|
// }
|
||||||
|
// }, err => {
|
||||||
|
// console.error('Error:', err);
|
||||||
|
// });
|
||||||
// this.mqttService.subscribeToTopic("BACKEND/DATA/PICTURE").subscribe(data => {
|
// this.mqttService.subscribeToTopic("BACKEND/DATA/PICTURE").subscribe(data => {
|
||||||
// if (typeof data !== "object") {
|
// if (typeof data !== "object") {
|
||||||
// const payload = JSON.parse(data) as Plant;
|
// const payload = JSON.parse(data) as Plant;
|
||||||
@ -173,15 +178,10 @@ export class MqttRequestService {
|
|||||||
publishToPLANTCOUNT() {
|
publishToPLANTCOUNT() {
|
||||||
this.mqttService.publishToTopic('BACKEND/ACTION/PLANTCOUNT');
|
this.mqttService.publishToTopic('BACKEND/ACTION/PLANTCOUNT');
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* publishToINPUT wird die Spracheingabe übermittelt, die dann mit
|
|
||||||
* mehreren if else anweisungen einen Request an das Backend sendet und
|
|
||||||
* die Sprachausgabe mit next(..) triggert
|
|
||||||
* @method
|
|
||||||
*/
|
|
||||||
publishToINPUT(message: string) {
|
publishToINPUT(message: string) {
|
||||||
message = message.replace(/\s/g, ""); //entfernt alle leerzeichen
|
message = message.replace(/\s/g, "");
|
||||||
console.log(":" + message + ":"); //Nachricht die übermittel wurde, wird ausgegeben auf der Konsole
|
console.log(":" + message + ":");
|
||||||
let msgFound: boolean = false;
|
let msgFound: boolean = false;
|
||||||
|
|
||||||
if (message === "whereismyrobot") {
|
if (message === "whereismyrobot") {
|
||||||
@ -194,11 +194,10 @@ export class MqttRequestService {
|
|||||||
this.sourceMessage.next("The data is being collected and you can view it under the 'Robot' tab");
|
this.sourceMessage.next("The data is being collected and you can view it under the 'Robot' tab");
|
||||||
} else if (message === "howaremyplants") {
|
} else if (message === "howaremyplants") {
|
||||||
msgFound = true;
|
msgFound = true;
|
||||||
this.mqttService.publishToTopic('BACKEND/ACTION/DRIVEALL');
|
// this.mqttService.publishToTopic('BACKEND/ACTION/DRIVEALL');
|
||||||
this.sourceMessage.next("Robot is driving to all plants");
|
this.sourceMessage.next("Robot is driving to all plants");
|
||||||
} else {
|
} else {
|
||||||
// schickt den Roboter zur eingegeben Pflanze..
|
this.storeService.getAllPlantNames().subscribe(result =>
|
||||||
this.storeService.getAllPlantNames().pipe(take(1)).subscribe(result =>
|
|
||||||
result.forEach((element: string) => {
|
result.forEach((element: string) => {
|
||||||
let msgPlantName = "howismyplant".concat(element.toLowerCase())
|
let msgPlantName = "howismyplant".concat(element.toLowerCase())
|
||||||
if (message === msgPlantName) {
|
if (message === msgPlantName) {
|
||||||
@ -211,9 +210,7 @@ export class MqttRequestService {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wenn kein case eintrifft, wird "Please try again" ausgegeben
|
|
||||||
if (!msgFound) {
|
if (!msgFound) {
|
||||||
msgFound = false;
|
|
||||||
this.sourceMessage.next("Please try again");
|
this.sourceMessage.next("Please try again");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,12 +6,12 @@ import { Observable } from 'rxjs';
|
|||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class MqttService {
|
export class MqttService {
|
||||||
|
|
||||||
private client: MqttClient;
|
private client: MqttClient;
|
||||||
|
|
||||||
// Connection zu dem MQTT Broker
|
|
||||||
constructor() {
|
constructor() {
|
||||||
// this.client = connect('wss://mqtt.eclipseprojects.io:443/mqtt'); //Je nachdem welchen Link der Broker hat
|
this.client = connect('wss://mqtt.eclipseprojects.io:443/mqtt'); //Je nachdem welchen Link der Broker hat
|
||||||
this.client = connect('mqtt://192.168.137.197:1883', { clientId: 'kemal' });
|
// this.client = connect('mqtt://192.168.137.197:1883', { clientId: 'kemal' });
|
||||||
}
|
}
|
||||||
|
|
||||||
public subscribeToTopic(topic: string): Observable<any> {
|
public subscribeToTopic(topic: string): Observable<any> {
|
||||||
|
@ -8,8 +8,6 @@ import { RobotBattery } from '../models/robotBattery.model';
|
|||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
export class StoreService {
|
export class StoreService {
|
||||||
positionRobot: Position;
|
positionRobot: Position;
|
||||||
plantCount: PlantCount;
|
plantCount: PlantCount;
|
||||||
|
@ -11,7 +11,6 @@ import { MqttRequestService } from './Service/Mqtt/mqtt-request.service';
|
|||||||
export class AppComponent {
|
export class AppComponent {
|
||||||
header: string;
|
header: string;
|
||||||
constructor(private mqttRequestService: MqttRequestService, private location: Location) {
|
constructor(private mqttRequestService: MqttRequestService, private location: Location) {
|
||||||
// Header in der Leiste zu bestimmen
|
|
||||||
const actualRoute = this.location.path().slice(1);
|
const actualRoute = this.location.path().slice(1);
|
||||||
const lastParam = actualRoute.charAt(0).toUpperCase() + actualRoute.slice(1);
|
const lastParam = actualRoute.charAt(0).toUpperCase() + actualRoute.slice(1);
|
||||||
if (lastParam === "") {
|
if (lastParam === "") {
|
||||||
|
@ -17,11 +17,13 @@
|
|||||||
Soil Moisture: <br>
|
Soil Moisture: <br>
|
||||||
<img class="icons-measurements" src="assets/images/Icons-Card/brightness_icon.png" alt="not available">
|
<img class="icons-measurements" src="assets/images/Icons-Card/brightness_icon.png" alt="not available">
|
||||||
Brightness:<br>
|
Brightness:<br>
|
||||||
|
<!-- <img class="icons-measurements" src="assets/images/Icons-Card/Timestamp_icon.png" alt="not available">
|
||||||
|
Timestamp: -->
|
||||||
</div>
|
</div>
|
||||||
<div class="item-Measurements-Values">
|
<div class="item-Measurements-Values">
|
||||||
<mat-form-field class="item-option" appearance="fill">
|
<mat-form-field class="item-option" appearance="fill">
|
||||||
<mat-label>Choose an ID</mat-label>
|
<mat-label>Choose an ID</mat-label>
|
||||||
<mat-select [(value)]="selected" (closed)="onOptionSelected()">
|
<mat-select [(value)]="selected" (closed)="onOptionSelected(selected)">
|
||||||
<mat-option *ngFor="let option of options$ | async" [value]="option">
|
<mat-option *ngFor="let option of options$ | async" [value]="option">
|
||||||
{{option}}
|
{{option}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
@ -12,17 +12,13 @@ import { MapPlantDialogComponent } from '../map-plant-dialog/map-plant-dialog.co
|
|||||||
templateUrl: './add-plant-dialog.component.html',
|
templateUrl: './add-plant-dialog.component.html',
|
||||||
styleUrls: ['./add-plant-dialog.component.css']
|
styleUrls: ['./add-plant-dialog.component.css']
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
|
||||||
* @description
|
|
||||||
* Mit diesem Dialog "AddPlantDialogComponent" wird eine neue Pflanze erstellt und in das Backend geschickt.
|
|
||||||
*/
|
|
||||||
export class AddPlantDialogComponent implements OnInit {
|
export class AddPlantDialogComponent implements OnInit {
|
||||||
selected: number;
|
selected: number;
|
||||||
options$: Observable<number[]>;
|
options$: Observable<number[]>;
|
||||||
plantNames: string[];
|
plantNames: string[];
|
||||||
plant = {} as Plant;
|
plant = {} as Plant;
|
||||||
buttonSavedisabled: boolean;
|
buttonSavedisabled: boolean;
|
||||||
|
number: number[];
|
||||||
|
|
||||||
constructor(public dialogRef: MatDialogRef<AddPlantDialogComponent>,
|
constructor(public dialogRef: MatDialogRef<AddPlantDialogComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||||
@ -32,26 +28,16 @@ export class AddPlantDialogComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.buttonSavedisabled = true; //Button "Save" wird disabled
|
this.buttonSavedisabled = true;
|
||||||
this.mqttRequestService.publishToPLANTCOUNT(); // Pflanzen anzahl wird angefordet#
|
this.mqttRequestService.publishToPLANTCOUNT();
|
||||||
|
|
||||||
// ID's bei denen noch keine Pflanze sind, werden in "option$" rein geschrieben
|
|
||||||
this.storeService.currentPlants.subscribe(response => {
|
this.storeService.currentPlants.subscribe(response => {
|
||||||
this.options$ = this.storeService.getIDsWithoutPlant(response);
|
this.options$ = this.storeService.getIDsWithoutPlant(response);
|
||||||
})
|
})
|
||||||
|
|
||||||
// Alle aktuellen Pflanzen Namen werden in "plantNames" geschrieben
|
|
||||||
this.storeService.getAllPlantNames().subscribe(result => {
|
this.storeService.getAllPlantNames().subscribe(result => {
|
||||||
this.plantNames = result
|
this.plantNames = result
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Nach dem der Button "Save" geklickt wurde, werden die Daten in die Pflanze geschrieben
|
|
||||||
* die anschließend geprüft wird auf zulässige Werte, falls unzulässige werte vorhanden sind,
|
|
||||||
* wird eine Fehlermeldung angezeigt
|
|
||||||
* @method onSaveDialog
|
|
||||||
*/
|
|
||||||
onSaveDialog() {
|
onSaveDialog() {
|
||||||
this.plant.PlantName = (<HTMLInputElement>document.getElementById("inputName")).value;
|
this.plant.PlantName = (<HTMLInputElement>document.getElementById("inputName")).value;
|
||||||
this.plant.AirTemperature = +(<HTMLInputElement>document.getElementById("inputAirTemperature")).value;
|
this.plant.AirTemperature = +(<HTMLInputElement>document.getElementById("inputAirTemperature")).value;
|
||||||
@ -62,7 +48,6 @@ export class AddPlantDialogComponent implements OnInit {
|
|||||||
|
|
||||||
const plantInputString: string = this.plantInputTestFails();
|
const plantInputString: string = this.plantInputTestFails();
|
||||||
|
|
||||||
// bei unzulässigen Werten --> Dialog, bei zulässigen Wertden --> Pflanze wird an das Backend geschickt
|
|
||||||
if (plantInputString) {
|
if (plantInputString) {
|
||||||
this.dialog.open(ErrorDialogComponent, {
|
this.dialog.open(ErrorDialogComponent, {
|
||||||
data: "Error: " + plantInputString,
|
data: "Error: " + plantInputString,
|
||||||
@ -70,16 +55,11 @@ export class AddPlantDialogComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.mqttRequestService.publishToNEWPLANT(this.plant);
|
this.mqttRequestService.publishToNEWPLANT(this.plant);
|
||||||
this.mqttRequestService.publishToGETALLDATA(); // Daten werden aus dem Backend angefragt
|
this.mqttRequestService.publishToGETALLDATA();
|
||||||
window.location.reload(); // Seite neu laden
|
window.location.reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Methode prüft ob die Werte die eingegeben wurden, korrekt sind.
|
|
||||||
* @method
|
|
||||||
* @return Bei einem Fehler --> Fehlermeldung; wenn es passt --> string oder leeren string
|
|
||||||
*/
|
|
||||||
plantInputTestFails(): string {
|
plantInputTestFails(): string {
|
||||||
|
|
||||||
if (this.plantNames.indexOf(this.plant.PlantName) > -1) {
|
if (this.plantNames.indexOf(this.plant.PlantName) > -1) {
|
||||||
@ -97,16 +77,12 @@ export class AddPlantDialogComponent implements OnInit {
|
|||||||
if (this.plant.SoilMoisture > 100) {
|
if (this.plant.SoilMoisture > 100) {
|
||||||
return "Soil Moisture is to high";
|
return "Soil Moisture is to high";
|
||||||
}
|
}
|
||||||
if (this.plant.Brightness > 40000) {
|
if (this.plant.Brightness > 100) {
|
||||||
return "Brightness is to high";
|
return "Brightness is to high";
|
||||||
}
|
}
|
||||||
return ""; //Empty string is a Boolean false!
|
return ""; //Empty string is a Boolean false!
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* beim klick auf den Button, wird das Dialog "MapPlantDialogComponent" geöffnet
|
|
||||||
* @method
|
|
||||||
*/
|
|
||||||
onOpenMap() {
|
onOpenMap() {
|
||||||
this.dialog.open(MapPlantDialogComponent, {
|
this.dialog.open(MapPlantDialogComponent, {
|
||||||
width: '400px',
|
width: '400px',
|
||||||
@ -114,11 +90,11 @@ export class AddPlantDialogComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
onOptionSelected(numb: number) {
|
||||||
* nach der Auswahl der ID, wird der Button "Save" enabled
|
let num: number = numb;
|
||||||
* @method
|
if (num < 7 && num > 0) { //TODOO anzahl der Pflanzen IDS variable machen statt 7 evtl. eine variable
|
||||||
*/
|
this.buttonSavedisabled = false;
|
||||||
onOptionSelected() {
|
}
|
||||||
this.buttonSavedisabled = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject, OnInit } from '@angular/core';
|
||||||
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
|
||||||
import { MqttRequestService } from 'src/app/Service/Mqtt/mqtt-request.service';
|
import { MqttRequestService } from 'src/app/Service/Mqtt/mqtt-request.service';
|
||||||
import { Plant } from 'src/app/models/plant.model';
|
import { Plant } from 'src/app/models/plant.model';
|
||||||
@ -9,7 +9,7 @@ import { ErrorDialogComponent } from '../error-dialog/error-dialog.component';
|
|||||||
templateUrl: './configure-plant-dialog.component.html',
|
templateUrl: './configure-plant-dialog.component.html',
|
||||||
styleUrls: ['./configure-plant-dialog.component.css']
|
styleUrls: ['./configure-plant-dialog.component.css']
|
||||||
})
|
})
|
||||||
export class ConfigurePlantDialogComponent {
|
export class ConfigurePlantDialogComponent implements OnInit {
|
||||||
plant: Plant;
|
plant: Plant;
|
||||||
|
|
||||||
constructor(public dialogRef: MatDialogRef<ConfigurePlantDialogComponent>,
|
constructor(public dialogRef: MatDialogRef<ConfigurePlantDialogComponent>,
|
||||||
@ -19,12 +19,9 @@ export class ConfigurePlantDialogComponent {
|
|||||||
this.plant = data.plant;
|
this.plant = data.plant;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
ngOnInit(): void {
|
||||||
* Nach dem der Button "Save" geklickt wurde, werden die Daten in die Pflanze geschrieben
|
}
|
||||||
* die anschließend geprüft wird auf zulässige Werte, falls unzulässige werte vorhanden sind,
|
|
||||||
* wird eine Fehlermeldung angezeigt
|
|
||||||
* @method onSaveDialog
|
|
||||||
*/
|
|
||||||
onSaveDialog() {
|
onSaveDialog() {
|
||||||
this.plant.AirTemperature = +(<HTMLInputElement>document.getElementById("inputAirTemperature")).value;
|
this.plant.AirTemperature = +(<HTMLInputElement>document.getElementById("inputAirTemperature")).value;
|
||||||
this.plant.AirHumidity = +(<HTMLInputElement>document.getElementById("inputAirHumidity")).value;
|
this.plant.AirHumidity = +(<HTMLInputElement>document.getElementById("inputAirHumidity")).value;
|
||||||
@ -32,25 +29,19 @@ export class ConfigurePlantDialogComponent {
|
|||||||
this.plant.Brightness = +(<HTMLInputElement>document.getElementById("inputBrightness")).value;
|
this.plant.Brightness = +(<HTMLInputElement>document.getElementById("inputBrightness")).value;
|
||||||
|
|
||||||
const plantInputString: string = this.plantInputTestFails();
|
const plantInputString: string = this.plantInputTestFails();
|
||||||
|
|
||||||
// bei unzulässigen Werten --> Dialog, bei zulässigen Wertden --> Pflanze wird an das Backend geschickt
|
|
||||||
if (plantInputString) {
|
if (plantInputString) {
|
||||||
this.dialog.open(ErrorDialogComponent, {
|
this.dialog.open(ErrorDialogComponent, {
|
||||||
data: "Error: " + plantInputString,
|
data: "Error: " + plantInputString,
|
||||||
width: '400px',
|
width: '400px',
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.mqttRequestService.publishToCONFIGUREPLANT(this.plant); //Request to the Backend, to change the data of the plant
|
//Request to the Backend, to change the data of the plant
|
||||||
this.mqttRequestService.publishToGETALLDATA(); // Daten werden aus dem Backend angefragt
|
this.mqttRequestService.publishToCONFIGUREPLANT(this.plant);
|
||||||
window.location.reload(); // Seite neu laden
|
this.mqttRequestService.publishToGETALLDATA();
|
||||||
|
window.location.reload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Methode prüft ob die Werte die eingegeben wurden, korrekt sind.
|
|
||||||
* @method
|
|
||||||
* @return Bei einem Fehler --> Fehlermeldung; wenn es passt --> string oder leeren string
|
|
||||||
*/
|
|
||||||
plantInputTestFails(): string {
|
plantInputTestFails(): string {
|
||||||
if (this.plant.AirTemperature > 100) {
|
if (this.plant.AirTemperature > 100) {
|
||||||
return "Air Temperature is to high";
|
return "Air Temperature is to high";
|
||||||
@ -61,7 +52,7 @@ export class ConfigurePlantDialogComponent {
|
|||||||
if (this.plant.SoilMoisture > 100) {
|
if (this.plant.SoilMoisture > 100) {
|
||||||
return "Soil Moisture is to high";
|
return "Soil Moisture is to high";
|
||||||
}
|
}
|
||||||
if (this.plant.Brightness > 40000) {
|
if (this.plant.Brightness > 100) {
|
||||||
return "Brightness is to high";
|
return "Brightness is to high";
|
||||||
}
|
}
|
||||||
return ""; //Empty string is a Boolean false!
|
return ""; //Empty string is a Boolean false!
|
||||||
|
@ -11,15 +11,12 @@ import { ConfigurePlantDialogComponent } from '../configure-plant-dialog/configu
|
|||||||
})
|
})
|
||||||
export class DeleteConfirmDialogComponent {
|
export class DeleteConfirmDialogComponent {
|
||||||
plant: Plant;
|
plant: Plant;
|
||||||
|
|
||||||
constructor(public dialogRef: MatDialogRef<ConfigurePlantDialogComponent>,
|
constructor(public dialogRef: MatDialogRef<ConfigurePlantDialogComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: Plant, private mqttRequestService: MqttRequestService) {
|
@Inject(MAT_DIALOG_DATA) public data: Plant, private mqttRequestService: MqttRequestService) {
|
||||||
this.plant = data;
|
this.plant = data;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* beim Click auf "Delete" wird eine anfrage an das Backend geschickt um die Pflanze zu löschen.
|
|
||||||
* @method
|
|
||||||
*/
|
|
||||||
onDelete() {
|
onDelete() {
|
||||||
this.mqttRequestService.publishToDELETEPLANT(this.plant.PlantID);
|
this.mqttRequestService.publishToDELETEPLANT(this.plant.PlantID);
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject, OnInit } from '@angular/core';
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
import { ConfigurePlantDialogComponent } from '../configure-plant-dialog/configure-plant-dialog.component';
|
import { ConfigurePlantDialogComponent } from '../configure-plant-dialog/configure-plant-dialog.component';
|
||||||
|
|
||||||
@ -7,15 +7,19 @@ import { ConfigurePlantDialogComponent } from '../configure-plant-dialog/configu
|
|||||||
templateUrl: './error-dialog.component.html',
|
templateUrl: './error-dialog.component.html',
|
||||||
styleUrls: ['./error-dialog.component.css']
|
styleUrls: ['./error-dialog.component.css']
|
||||||
})
|
})
|
||||||
export class ErrorDialogComponent {
|
export class ErrorDialogComponent implements OnInit {
|
||||||
text: string = "";
|
|
||||||
|
|
||||||
|
text: string = "";
|
||||||
constructor(public dialogRef: MatDialogRef<ConfigurePlantDialogComponent>,
|
constructor(public dialogRef: MatDialogRef<ConfigurePlantDialogComponent>,
|
||||||
@Inject(MAT_DIALOG_DATA) public data: any) {
|
@Inject(MAT_DIALOG_DATA) public data: any) {
|
||||||
this.text = data;
|
this.text = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
onClose() {
|
ngOnInit(): void {
|
||||||
window.location.reload(); // Seite neu laden
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onClose() {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-map-plant-dialog',
|
selector: 'app-map-plant-dialog',
|
||||||
templateUrl: './map-plant-dialog.component.html',
|
templateUrl: './map-plant-dialog.component.html',
|
||||||
styleUrls: ['./map-plant-dialog.component.css']
|
styleUrls: ['./map-plant-dialog.component.css']
|
||||||
})
|
})
|
||||||
export class MapPlantDialogComponent {
|
export class MapPlantDialogComponent implements OnInit {
|
||||||
|
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user