/** * ============LICENSE_START======================================================================== * ONAP : ccsdk feature sdnr wt odlux * ================================================================================================= * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved. * ================================================================================================= * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. * ============LICENSE_END========================================================================== */ import * as React from "react"; import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect'; import { MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table'; import { TextField, Tabs, Tab, Typography, AppBar, Button, Tooltip, Checkbox, Table, TableCell, TableHead, TableRow, TableBody, Paper } from '@material-ui/core'; import './Style.scss' import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore"; import { UpdateFrequencyAction, UpdateLatLonAction, UpdateRainAttAction, UpdateRainValAction, UpdateFslCalculation, isCalculationServerReachableAction, UpdatePolAction, UpdateDistanceAction, updateAltitudeAction, UpdateAbsorptionLossAction, UpdateWorstMonthRainAction, UpdateTxPowerAction, UpdateRxSensitivityAction, UpdateEIRPAction, UpdateRxPowerAction, UpdateSomAction } from "../actions/commonLinkCalculationActions"; import { faPlaneArrival, faAlignCenter } from "@fortawesome/free-solid-svg-icons"; import ConnectionInfo from '../components/connectionInfo' import { red } from "@material-ui/core/colors"; import { Dvr } from "@material-ui/icons"; const mapProps = (state: IApplicationStoreState) => ({ linkId: state.linkCalculation.calculations.linkId, frequency: state.linkCalculation.calculations.frequency, lat1: state.linkCalculation.calculations.Lat1, lon1: state.linkCalculation.calculations.Lon1, lat2: state.linkCalculation.calculations.Lat2, lon2: state.linkCalculation.calculations.Lon2, rainAtt: state.linkCalculation.calculations.rainAtt, rainVal: state.linkCalculation.calculations.rainVal, formView: state.linkCalculation.calculations.formView, fsl: state.linkCalculation.calculations.fsl, siteA: state.linkCalculation.calculations.siteA, siteB: state.linkCalculation.calculations.siteB, distance: state.linkCalculation.calculations.distance, reachable: state.linkCalculation.calculations.reachable, polarization: state.linkCalculation.calculations.polarization, amslA: state.linkCalculation.calculations.amslA, amslB: state.linkCalculation.calculations.amslB, aglA: state.linkCalculation.calculations.aglA, aglB: state.linkCalculation.calculations.aglB, absorptionOxygen: state.linkCalculation.calculations.absorptionOxygen, absorptionWater: state.linkCalculation.calculations.absorptionWater, month: state.linkCalculation.calculations.month, eirpA: state.linkCalculation.calculations.eirpA, eirpB: state.linkCalculation.calculations.eirpB, antennaGainA: state.linkCalculation.calculations.antennaGainA, antennaGainB: state.linkCalculation.calculations.antennaGainB, antennaNameA: state.linkCalculation.calculations.antennaNameA, antennaNameB: state.linkCalculation.calculations.antennaNameB, systemOperatingMarginA: state.linkCalculation.calculations.systemOperatingMarginA, systemOperatingMarginB: state.linkCalculation.calculations.systemOperatingMarginB, waveguideLossA: state.linkCalculation.calculations.waveguideLossA, waveguideLossB: state.linkCalculation.calculations.waveguideLossB, rxPowerA: state.linkCalculation.calculations.rxPowerA, rxPowerB: state.linkCalculation.calculations.rxPowerB, txPowerA: state.linkCalculation.calculations.txPowerA, txPowerB: state.linkCalculation.calculations.txPowerB, rxSensitivityA: state.linkCalculation.calculations.rxSensitivityA, rxSensitivityB: state.linkCalculation.calculations.rxSensitivityB }); const BASE_URL = "/topology/linkcalculator" const mapDispatch = (dispatcher: IDispatcher) => ({ updateFrequency: (frequency: number) => { dispatcher.dispatch(new UpdateFrequencyAction(frequency)) }, updateLatLon: (Lat1: number, Lon1: number, Lat2: number, Lon2: number) => { dispatcher.dispatch(new UpdateLatLonAction(Lat1, Lon1, Lat2, Lon2)) }, updateRainValue: (rainVal: number) => { dispatcher.dispatch(new UpdateRainValAction(rainVal)) }, UpdateRainAtt: (rainAtt: number) => { dispatcher.dispatch(new UpdateRainAttAction(rainAtt)) }, specificRain: (rainAtt: number) => { dispatcher.dispatch(new UpdateRainAttAction(rainAtt)) }, FSL: (free: number) => { dispatcher.dispatch(new UpdateFslCalculation(free)) }, UpdateConectivity: (reachable: boolean) => { dispatcher.dispatch(new isCalculationServerReachableAction(reachable)) }, updatePolarization: (polarization: any) => { dispatcher.dispatch(new UpdatePolAction(polarization)) }, updateAutoDistance: (distance: number) => { dispatcher.dispatch(new UpdateDistanceAction(distance)) }, UpdateAbsorption: (OxLoss: number, WaterLoss: number) => { dispatcher.dispatch(new UpdateAbsorptionLossAction(OxLoss, WaterLoss)) }, UpdateWorstMonthRain: (month: string) => { dispatcher.dispatch(new UpdateWorstMonthRainAction(month)) }, UpdateEIRP: (eirpA: number, eirpB: number) => { dispatcher.dispatch(new UpdateEIRPAction(eirpA, eirpB)) }, UpdateRxPower: (rxPowerA: number, rxPowerB: number) => { dispatcher.dispatch(new UpdateRxPowerAction(rxPowerA, rxPowerB)) }, UpdateSom: (somA: number, somB: number) => { dispatcher.dispatch(new UpdateSomAction(somA, somB)) }, UpdateTxPower: (txPowerA: string | null, txPowerB: string | null) => { dispatcher.dispatch(new UpdateTxPowerAction(txPowerA, txPowerB)) }, UpdateRxSensitivity: (rxSensitivityA: string | null, rxSensitivityB: string | null) => { dispatcher.dispatch(new UpdateRxSensitivityAction(rxSensitivityA, rxSensitivityB)) } }); type linkCalculationProps = Connect; interface initialState { rainMethodDisplay: boolean, absorptionMethod: string; horizontalBoxChecked: boolean, latitude1Error: string, longitude1Error: string latitude2Error: string, longitude2Error: string, frequencyError: string, rainMethodError: string, antennaTypeError: string, attenuationMethodError: string, worstmonth: boolean, showWM: string, rainMethodErrorState: string } class LinkCalculation extends React.Component { constructor(props: any) { super(props); this.state = { rainMethodDisplay: false, horizontalBoxChecked: true, absorptionMethod: '0', latitude1Error: '', longitude1Error: '', latitude2Error: '', longitude2Error: '', frequencyError: '', rainMethodError: '', attenuationMethodError: '', antennaTypeError: '', worstmonth: false, showWM: '', rainMethodErrorState: '0' }; } updateAutoDistance = async (lat1: number, lon1: number, lat2: number, lon2: number) => { const result = await fetch(BASE_URL + '/distance/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2) const json = await result.json() return json.distanceInKm } updateLatLon = (e: any) => { e.target.id == 'Lat1' ? this.props.updateLatLon(e.target.value, this.props.lon1, this.props.lat2, this.props.lon2) : null e.target.id == 'Lon1' ? this.props.updateLatLon(this.props.lat1, e.target.value, this.props.lat2, this.props.lon2) : null e.target.id == 'Lat2' ? this.props.updateLatLon(this.props.lat1, this.props.lon1, e.target.value, this.props.lon2) : null e.target.id == 'Lon2' ? this.props.updateLatLon(this.props.lat1, e.target.value, this.props.lat2, e.target.value) : null } updatePoli = (val: string) => { this.setState({ horizontalBoxChecked: !this.state.horizontalBoxChecked }); this.props.updatePolarization(val); } LatLonToDMS = (value: number, isLon: boolean = false) => { const absoluteValue = Math.abs(value); const d = Math.floor(absoluteValue); const m = Math.floor((absoluteValue - d) * 60); const s = (absoluteValue - d - m / 60) * 3600; const dms = `${d}° ${m}' ${s.toFixed(2)}"`; const sign = Math.sign(value); if (isLon) { return (sign === -1 || sign === -0) ? dms + " W" : dms + " E"; } else { return (sign === -1 || sign === -0) ? dms + " S" : dms + " N"; } } rainAttCal = (lat1: any, lon1: any, lat2: any, lon2: any, frequency: any, distance: number, polarization: string, worstmonth: boolean) => { if (!worstmonth) { fetch(BASE_URL + '/rain/annual/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + frequency + '/' + distance + '/' + polarization.toUpperCase()) .then(res => res.json()) .then(result => { this.props.UpdateRainAtt(result.rainAttenuation); this.props.updateRainValue(result.rainFall.rainrate) }) } else { fetch(BASE_URL + '/rain/worstmonth/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + frequency + '/' + distance + '/' + polarization.toUpperCase()) .then(res => res.json()) .then(result => { this.props.UpdateRainAtt(result.rainAttenuation); this.props.updateRainValue(result.rainFall.rainrate); this.props.UpdateWorstMonthRain(result.rainFall.period); this.setState({ showWM: '- Wm is : ' }) }) } } manualRain = (rainfall: number, frequency: number, distance: number, polarization: string) => { fetch(BASE_URL + '/rain/' + rainfall + '/' + frequency + '/' + distance + '/' + polarization.toUpperCase()) .then(res => res.json()) .then(result => { this.props.specificRain(result.rainAttenuation) }) } FSL = (distance: number, frequency: number) => { fetch(BASE_URL + '/fsl/' + distance + '/' + frequency) .then(res => res.json()) .then(result => { this.props.FSL(result.fspl) }) } AbsorptionAtt = (lat1: number, lon1: number, lat2: number, lon2: number, distance: number, frequency: number, worstmonth: boolean, absorptionMethod: string) => { if (!worstmonth) { fetch(BASE_URL + '/absorption/annual/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + distance + '/' + frequency + '/' + absorptionMethod) .then(res => res.json()) .then(result => { this.props.UpdateAbsorption(result.oxygenLoss, result.waterLoss) }) } else { fetch(BASE_URL + '/absorption/annual/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + distance + '/' + frequency + '/' + absorptionMethod) .then(res => res.json()) .then(result => { this.props.UpdateAbsorption(result.oxygenLoss, result.waterLoss) }) } } linkBudget = (lat1: number, lon1: number, lat2: number, lon2: number, distance: number, frequency: number, absorptionMethod: string, polarization: string, antennaGainA: number, antennaGainB: number, waveguideLossA: number, waveguideLossB: number, transmissionPowerA: number, transmissionPowerB: number, rxSensitivityA: number, rxSensitivityB: number) => { fetch(BASE_URL + '/linkbudget/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + distance + '/' + frequency + '/' + absorptionMethod + '/' + polarization.toUpperCase() + '/' + antennaGainA + '/' + antennaGainB + '/' + waveguideLossA + '/' + waveguideLossB + '/' + transmissionPowerA + '/' + transmissionPowerB + '/' + rxSensitivityA + '/' + rxSensitivityB) .then(res => res.json()) .then(result => { this.props.UpdateEIRP(result.eirpA, result.eirpB); this.props.UpdateRxPower(result.receivedPowerA, result.receivedPowerB); this.props.UpdateSom(result.systemOperatingMarginA, result.systemOperatingMarginA) }) } formValid = () => { this.props.lat1 === 0 ? this.setState({ latitude1Error: 'Enter a number between -90 to 90' }) : null this.props.lat2 === 0 ? this.setState({ latitude2Error: 'Enter a number between -90 to 90' }) : null this.props.lon1 === 0 ? this.setState({ longitude1Error: 'Enter a number between -180 to 180' }) : null this.props.lon2 === 0 ? this.setState({ longitude2Error: 'Enter a number between -180 to 180' }) : null this.props.frequency === 0 ? this.setState({ frequencyError: 'Select a frequency' }) : this.setState({ frequencyError: '' }) // this.state.rainMethodDisplay === null && this.props.rainVal === 0 ? this.setState({ rainMethodError: 'Select the rain method' }) : this.setState({ rainMethodError: '' }) this.state.rainMethodErrorState === '0' ? this.setState({ rainMethodError: 'Select the rain method' }) : this.setState({ rainMethodError: '' }) this.state.absorptionMethod === '0' ? this.setState({ attenuationMethodError: 'Select the attenuation method' }) : this.setState({ attenuationMethodError: '' }) console.log(this.state); console.log(this.props.lat1 !== 0 && this.props.lat2 !== 0 && this.props.lon1 !== 0 && this.props.lon2 !== 0 && this.props.frequency !== 0 && this.state.rainMethodError === '' && this.state.attenuationMethodError === ''); return this.props.lat1 !== 0 && this.props.lat2 !== 0 && this.props.lon1 !== 0 && this.props.lon2 !== 0 && this.props.frequency !== 0 && this.state.rainMethodError === '' && this.state.attenuationMethodError === ''; } buttonHandler = async () => { if (this.formValid()) { this.props.updateAutoDistance(await this.updateAutoDistance(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2)) this.FSL(this.props.distance, this.props.frequency) if (this.state.worstmonth === false) { this.setState({ showWM: ' ' }) this.props.UpdateWorstMonthRain('') this.AbsorptionAtt(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.distance, this.props.frequency, this.state.worstmonth, this.state.absorptionMethod) this.linkBudget(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.distance, this.props.frequency, this.state.absorptionMethod, this.props.polarization!, this.props.antennaGainA, this.props.antennaGainB, this.props.waveguideLossA, this.props.waveguideLossB, Number(this.props.txPowerA), Number(this.props.txPowerB), Number(this.props.rxSensitivityA), Number(this.props.rxSensitivityB)) if (this.state.rainMethodDisplay === true) { this.manualRain(this.props.rainVal, this.props.frequency, this.props.distance, this.props.polarization!); } else { this.rainAttCal(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.frequency, this.props.distance, this.props.polarization!, this.state.worstmonth); } } else { this.AbsorptionAtt(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.distance, this.props.frequency, this.state.worstmonth, this.state.absorptionMethod) this.rainAttCal(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.frequency, this.props.distance, this.props.polarization!, this.state.worstmonth); } } else console.log('form is not valid') } componentDidMount = () => { fetch(BASE_URL + '/fsl/1/1') .then(res => { if (res.ok) { this.props.UpdateConectivity(true) } else { this.props.UpdateConectivity(false) } }) .catch(res => { this.props.UpdateConectivity(false) }) } handleChange = (e: any) => { switch (e.target.id) { case 'Lat1': if (e.target.value > 90 || e.target.value < -90) { this.setState({ latitude1Error: 'Enter a number between -90 to 90' }) } else { this.updateLatLon(e) this.setState({ latitude1Error: '' }) } break; case 'Lat2': if (e.target.value > 90 || e.target.value < -90) { this.setState({ latitude2Error: 'Enter a number between -90 to 90' }) } else { this.updateLatLon(e) this.setState({ latitude2Error: '' }) } break; case 'Lon1': if (e.target.value > 180 || e.target.value < -180) { this.setState({ longitude1Error: 'Enter a number between -180 to 180' }) } else { this.updateLatLon(e) this.setState({ longitude1Error: '' }) } break; case 'Lon2': if (e.target.value > 180 || e.target.value < -180) { this.setState({ longitude2Error: 'Enter a number between -180 to 180' }) } else { this.updateLatLon(e) this.setState({ longitude2Error: '' }) } break; } } render() { return (
{!this.props.formView &&
SiteA
SiteB
{this.state.latitude1Error}
{this.state.latitude2Error}
{this.state.longitude1Error}
{this.state.longitude2Error}
}
{
this.setState({ worstmonth: false })}>Annual this.setState({ worstmonth: true })}>WM
}
Site A
Site B
{/*
 
*/}
{(this.props.siteA.length > 0 || this.props.siteB.length > 0) &&
Site Name
}
{this.props.siteA}
{this.props.siteB}
Latitude
{this.props.lat1 && this.LatLonToDMS(this.props.lat1)}
{this.props.lat2 && this.LatLonToDMS(this.props.lat2)}
Longitude
{this.props.lon1 && this.LatLonToDMS(this.props.lon1)}
{this.props.lon2 && this.LatLonToDMS(this.props.lon2)}
Azimuth
0
0
Average Mean Sea Level
{this.props.amslA.toFixed(2)} m
{this.props.amslB.toFixed(2)} m
Antenna Height Above Ground
{this.props.aglA.toFixed(2)} m
{this.props.aglB.toFixed(2)} m
Distance
{this.props.distance?.toFixed(3)} km
Polarization
{
this.props.updatePolarization(e.target.value)}>Horizontal { this.props.updatePolarization(e.target.value) }}>Vertical
}
Frequency
{}
{this.state.frequencyError}
Free Space Loss
{this.props.fsl.toFixed(3)} dB
Rain Model
{}
{this.state.rainMethodError}
Rainfall Rate
{
{ this.props.updateRainValue(Number(e.target.value)) }} value={this.props.rainVal} disabled={this.state.rainMethodDisplay === false ? true : false}> mm/hr {this.state.showWM} {this.props.month}
}
Rain Loss
{this.props.rainAtt.toFixed(3)} dB
Absorption Model
{}
{this.state.attenuationMethodError}
Oxygen Specific Attenuation
{this.props.absorptionOxygen.toFixed(3)} dB
Water Vapor Specific Attenuation
{this.props.absorptionWater.toFixed(3)} dB
System Operating Margin
{this.props.systemOperatingMarginA.toFixed(3)} dB
{this.props.systemOperatingMarginB.toFixed(3)} dB
Radio Transmitted Power
{
{ if (e.target.value !== '') this.props.UpdateTxPower(e.target.value, null) }} > dBm
}
{
{ if (e.target.value !== '') this.props.UpdateTxPower(null, e.target.value) }} > dBm
}
RF Receiver Sensitivity
{
{ if (e.target.value !== '') this.props.UpdateRxSensitivity(e.target.value, null) }} > dBm
}
{
{ if (e.target.value !== '') this.props.UpdateRxSensitivity(null, e.target.value) }} > dBm
}
Rx power
{this.props.rxPowerA.toFixed(3)} dBm
{this.props.rxPowerB.toFixed(3)} dBm
Antenna Settings
Antenna
{this.props.antennaNameA}
{this.props.antennaNameB}
EIRP
{this.props.eirpA.toFixed(3)} dBm
{this.props.eirpB.toFixed(3)} dBm
Gain
{this.props.antennaGainA} dBi
{this.props.antennaGainB} dBi
Waveguide Loss
{this.props.waveguideLossA} dB
{this.props.waveguideLossB} dB
{}
) } } export default connect(mapProps, mapDispatch)(LinkCalculation);