</div> | </div> | ||||
</div> | </div> | ||||
<div class="item-robotText"> | <div class="item-robotText"> | ||||
<div *ngIf="robotStateChange$ | async" id="robotIsOnTour">Robot is on Tour</div> | |||||
<div *ngIf="!(robotStateChange$ | async)" id="robotIsReady">Robot is Ready</div> | |||||
<div *ngIf="!(robotIsReady$ | async)" id="robotIsOnTour">Robot is on Tour</div> | |||||
<div *ngIf="(robotIsReady$ | async)" id="robotIsReady">Robot is Ready</div> | |||||
</div> | </div> | ||||
</div> | </div> |
styleUrls: ['./home.component.css'] | styleUrls: ['./home.component.css'] | ||||
}) | }) | ||||
export class HomeComponent { | export class HomeComponent { | ||||
robotStateChange$: Observable<boolean> = this.storeService.currentRobotReady; | |||||
// Aktueller RobotStatus wird subscribed | |||||
robotIsReady$: Observable<boolean> = this.storeService.currentRobotReady; | |||||
constructor(private storeService: StoreService) { | constructor(private storeService: StoreService) { | ||||
} | } |
subscription: Subscription; | subscription: Subscription; | ||||
constructor( | constructor( | ||||
public service: SpeechService, | |||||
public speechService: SpeechService, | |||||
private mqttRequestService: MqttRequestService | private mqttRequestService: MqttRequestService | ||||
) { | ) { | ||||
if (!this.service.initSpeechServiceStarted) { | |||||
this.service.init(); | |||||
if (!this.speechService.initSpeechServiceStarted) { | |||||
this.speechService.init(); | |||||
} | } | ||||
} | } | ||||
ngOnInit(): void { | ngOnInit(): void { | ||||
this.subscription = this.service.currentApprovalStageMessage.subscribe(msg => { | |||||
// subscribe auf die eingegebene Spracheingabe, gibt als response einen string | |||||
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); | |||||
this.mqttRequestService.publishToINPUT(this.text); // msg wird hier den Request Service weitergeleitet | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
/** | |||||
* 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.service.stop(); | |||||
this.speechService.stop(); // Spracheingabe stoppen | |||||
} else { | } else { | ||||
this.micIsClicked = true; | this.micIsClicked = true; | ||||
this.service.start(); | |||||
this.speechService.start(); //Spracheingabe starten | |||||
} | } | ||||
} | } | ||||
ngOnDestroy() { | ngOnDestroy() { | ||||
this.subscription.unsubscribe() | this.subscription.unsubscribe() | ||||
this.service.onDestory(); | |||||
this.speechService.onDestory(); | |||||
this.text = ''; | this.text = ''; | ||||
} | } | ||||
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; | ||||
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; | ||||
}); | }); | ||||
} | } | ||||
/** | |||||
* 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'; | ||||
this.subscription.unsubscribe(); | this.subscription.unsubscribe(); | ||||
this.mqttRequestService.onDestroy(); | this.mqttRequestService.onDestroy(); | ||||
} | } | ||||
} | } |
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(); | ||||
tempWords: string | undefined; | tempWords: string | undefined; | ||||
constructor() { | constructor() { | ||||
this.recognition.pitch = 10; | |||||
this.recognition.rate = 3; | |||||
} | } | ||||
init() { | init() { | ||||
.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(); | |||||
console.log("Speech recognition started") | |||||
this.recognition.start(); // Start der Sprachaufnahme | |||||
this.recognition.addEventListener('end', () => { | this.recognition.addEventListener('end', () => { | ||||
this.wordConcat() | this.wordConcat() | ||||
this.recognition.stop(); | |||||
this.recognition.stop(); // Ende der Sprachaufnahme | |||||
if (!this.isStoppedSpeechRecog) { | if (!this.isStoppedSpeechRecog) { | ||||
this.isStoppedSpeechRecog = true; | this.isStoppedSpeechRecog = true; | ||||
console.log("End speech recognition"); | |||||
this.approvalStageMessage.next(this.text); | |||||
this.approvalStageMessage.next(this.text); // String was eingelesen wurde, wird mit der Methode "next(..)" an alle subsriber weitergeleitet! | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// 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 = ''; |
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(); | ||||
} | } | ||||
} | } | ||||
/** | |||||
* Methode öffnet den Dialog "DeleteConfirmDialogComponent" | |||||
* @method | |||||
*/ | |||||
onDeletePlant() { | onDeletePlant() { | ||||
this.dialog.open(DeleteConfirmDialogComponent, { | this.dialog.open(DeleteConfirmDialogComponent, { | ||||
data: this.plant, | data: this.plant, | ||||
}); | }); | ||||
} | } | ||||
/** | |||||
* Methode öffnet den Dialog "ConfigurePlantDialogComponent" | |||||
* @method | |||||
*/ | |||||
onConfigurePlant() { | onConfigurePlant() { | ||||
this.dialog.open(ConfigurePlantDialogComponent, { | this.dialog.open(ConfigurePlantDialogComponent, { | ||||
data: { | data: { | ||||
width: '400px', | width: '400px', | ||||
}); | }); | ||||
} | } | ||||
} | } |
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(''), | ||||
}) | }) | ||||
} | } | ||||
/** | |||||
* 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(); | ||||
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(); | ||||
return `${seconds} second${seconds !== 1 ? 's' : ''} ago`; | return `${seconds} second${seconds !== 1 ? 's' : ''} ago`; | ||||
} | } | ||||
} | } | ||||
} | } |
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'; | ||||
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(); | ||||
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") { | ||||
console.error('Error:', err); | console.error('Error:', err); | ||||
}); | }); | ||||
this.mqttService.subscribeToTopic("BACKEND/DATA/ERROR").subscribe(data => { | |||||
if (typeof data !== "object") { | |||||
const payload = JSON.parse(data) as string; | |||||
this.mqttService.subscribeToTopic("BACKEND/DATA/ERROR").subscribe(errorMsg => { | |||||
if (typeof errorMsg !== "object") { | |||||
this.dialog.open(ErrorDialogComponent, { | this.dialog.open(ErrorDialogComponent, { | ||||
data: payload, | |||||
data: errorMsg, | |||||
width: '400px', | width: '400px', | ||||
}); | }); | ||||
} | } | ||||
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 Position; | |||||
this.mqttSetDataService.setRobotPosition(payload); | |||||
} | |||||
}, err => { | |||||
this.dialog.open(ErrorDialogComponent, { | |||||
data: err, | |||||
width: '400px', | |||||
}); | |||||
console.error('Error:', err); | |||||
}); | |||||
// this.mqttService.subscribeToTopic("BACKEND/DATA/POSITION").subscribe(data => { | |||||
// if (typeof data !== "object") { | |||||
// const payload = JSON.parse(data) as Position; | |||||
// this.mqttSetDataService.setRobotPosition(payload); | |||||
// } | |||||
// }, err => { | |||||
// this.dialog.open(ErrorDialogComponent, { | |||||
// data: err, | |||||
// width: '400px', | |||||
// }); | |||||
// 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") { | ||||
}); | }); | ||||
this.mqttService.subscribeToTopic("BACKEND/DATA/ROBOTREADY").subscribe(data => { | this.mqttService.subscribeToTopic("BACKEND/DATA/ROBOTREADY").subscribe(data => { | ||||
if (typeof data !== "object") { | |||||
const payload = JSON.parse(data) as boolean; | |||||
this.mqttSetDataService.setRobotReady(payload); | |||||
if (data === "False") { | |||||
this.mqttSetDataService.setRobotReady(false); | |||||
} else if (data === "True") { | |||||
this.mqttSetDataService.setRobotReady(true); | |||||
} | } | ||||
}, err => { | }, err => { | ||||
this.dialog.open(ErrorDialogComponent, { | this.dialog.open(ErrorDialogComponent, { | ||||
}); | }); | ||||
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; | ||||
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, ""); | |||||
console.log(":" + message + ":"); | |||||
message = message.replace(/\s/g, ""); //entfernt alle leerzeichen | |||||
console.log(":" + message + ":"); //Nachricht die übermittel wurde, wird ausgegeben auf der Konsole | |||||
let msgFound: boolean = false; | let msgFound: boolean = false; | ||||
if (message === "whereismyrobot") { | if (message === "whereismyrobot") { | ||||
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 { | ||||
this.storeService.getAllPlantNames().subscribe(result => | |||||
// schickt den Roboter zur eingegeben Pflanze.. | |||||
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) { | ||||
) | ) | ||||
} | } | ||||
// 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"); | ||||
} | } | ||||
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('mqtt://192.168.137.197:1883', { clientId: 'kemal' }); | |||||
// 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' }); | |||||
} | } | ||||
public subscribeToTopic(topic: string): Observable<any> { | public subscribeToTopic(topic: string): Observable<any> { |
@Injectable({ | @Injectable({ | ||||
providedIn: 'root' | providedIn: 'root' | ||||
}) | }) | ||||
export class StoreService { | export class StoreService { | ||||
positionRobot: Position; | positionRobot: Position; | ||||
plantCount: PlantCount; | plantCount: PlantCount; |
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 === "") { |
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(selected)"> | |||||
<mat-select [(value)]="selected" (closed)="onOptionSelected()"> | |||||
<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> |
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, | ||||
} | } | ||||
ngOnInit(): void { | ngOnInit(): void { | ||||
this.buttonSavedisabled = true; | |||||
this.mqttRequestService.publishToPLANTCOUNT(); | |||||
this.buttonSavedisabled = true; //Button "Save" wird disabled | |||||
this.mqttRequestService.publishToPLANTCOUNT(); // Pflanzen anzahl wird angefordet# | |||||
// 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; | ||||
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, | ||||
}); | }); | ||||
} else { | } else { | ||||
this.mqttRequestService.publishToNEWPLANT(this.plant); | this.mqttRequestService.publishToNEWPLANT(this.plant); | ||||
this.mqttRequestService.publishToGETALLDATA(); | |||||
window.location.reload(); | |||||
this.mqttRequestService.publishToGETALLDATA(); // Daten werden aus dem Backend angefragt | |||||
window.location.reload(); // Seite neu laden | |||||
} | } | ||||
} | } | ||||
/** | |||||
* 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) { | ||||
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 > 100) { | |||||
if (this.plant.Brightness > 40000) { | |||||
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', | ||||
}); | }); | ||||
} | } | ||||
onOptionSelected(numb: number) { | |||||
let num: number = numb; | |||||
if (num < 7 && num > 0) { //TODOO anzahl der Pflanzen IDS variable machen statt 7 evtl. eine variable | |||||
this.buttonSavedisabled = false; | |||||
} | |||||
/** | |||||
* nach der Auswahl der ID, wird der Button "Save" enabled | |||||
* @method | |||||
*/ | |||||
onOptionSelected() { | |||||
this.buttonSavedisabled = false; | |||||
} | } | ||||
} | } |
import { Component, Inject, OnInit } from '@angular/core'; | |||||
import { Component, Inject } 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'; | ||||
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 implements OnInit { | |||||
export class ConfigurePlantDialogComponent { | |||||
plant: Plant; | plant: Plant; | ||||
constructor(public dialogRef: MatDialogRef<ConfigurePlantDialogComponent>, | constructor(public dialogRef: MatDialogRef<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; | ||||
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 { | ||||
//Request to the Backend, to change the data of the plant | |||||
this.mqttRequestService.publishToCONFIGUREPLANT(this.plant); | |||||
this.mqttRequestService.publishToGETALLDATA(); | |||||
window.location.reload(); | |||||
this.mqttRequestService.publishToCONFIGUREPLANT(this.plant); //Request to the Backend, to change the data of the plant | |||||
this.mqttRequestService.publishToGETALLDATA(); // Daten werden aus dem Backend angefragt | |||||
window.location.reload(); // Seite neu laden | |||||
} | } | ||||
} | } | ||||
/** | |||||
* 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"; | ||||
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 > 100) { | |||||
if (this.plant.Brightness > 40000) { | |||||
return "Brightness is to high"; | return "Brightness is to high"; | ||||
} | } | ||||
return ""; //Empty string is a Boolean false! | return ""; //Empty string is a Boolean false! |
}) | }) | ||||
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); | ||||
} | } |
import { Component, Inject, OnInit } from '@angular/core'; | |||||
import { Component, Inject } 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'; | ||||
templateUrl: './error-dialog.component.html', | templateUrl: './error-dialog.component.html', | ||||
styleUrls: ['./error-dialog.component.css'] | styleUrls: ['./error-dialog.component.css'] | ||||
}) | }) | ||||
export class ErrorDialogComponent implements OnInit { | |||||
export class ErrorDialogComponent { | |||||
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; | ||||
} | } | ||||
ngOnInit(): void { | |||||
} | |||||
onClose() { | onClose() { | ||||
window.location.reload(); | |||||
window.location.reload(); // Seite neu laden | |||||
} | } | ||||
} | } |
import { Component, OnInit } from '@angular/core'; | |||||
import { Component } 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 implements OnInit { | |||||
export class MapPlantDialogComponent { | |||||
constructor() { } | constructor() { } | ||||
ngOnInit(): void { | |||||
} | |||||
} | } |