import { pond } from "protobuf-ts/pond"; import { quack } from "protobuf-ts/pond"; import { or } from "utils/types"; import { clone, cloneDeep } from "lodash"; import { Component } from "models"; import { describeMeasurement } from "pbHelpers/MeasurementDescriber"; import { extractGrainCable } from "pbHelpers/ComponentTypes"; export class GrainCable { public settings: pond.ComponentSettings = pond.ComponentSettings.create(); public status: pond.ComponentStatus = pond.ComponentStatus.create(); public lastReading: string = ""; public temperatures: number[] = []; public humidities: number[] = []; public grainMoistures: number[] = []; public topNode: number = 0; public static create(comp: Component): GrainCable { let my = new GrainCable(); my.settings = comp.settings; my.status = comp.status; let temps: number[] = []; let hums: number[] = []; let emc: number[] = []; let lastReading = ""; if (comp.status.measurement.length > 0) { comp.status.measurement.forEach(um => { if (um.timestamps[0]) { lastReading = um.timestamps[0]; } if (um.values[0] && um.values[0].values.length > 0) { if (um.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE) { let revTemps = clone(um.values[0].values); temps = revTemps.reverse(); } if (um.type === quack.MeasurementType.MEASUREMENT_TYPE_PERCENT) { let revHums = clone(um.values[0].values); hums = revHums.reverse(); } if (um.type === quack.MeasurementType.MEASUREMENT_TYPE_GRAIN_EMC) { let revMoist = clone(um.values[0].values); emc = revMoist.reverse(); } } }); } else { let nodes = extractGrainCable(comp.status.lastMeasurement?.measurement?.grainCable).reverse(); if (nodes.length > 0) { nodes.forEach(node => { hums.push(node.humidity); temps.push(node.temperature); }); } } my.temperatures = temps; my.humidities = hums; my.grainMoistures = emc; my.lastReading = lastReading; my.topNode = comp.settings.grainFilledTo; return my; } public static createPond(comp: pond.Component): GrainCable { let my = new GrainCable(); my.settings = comp.settings ? comp.settings : pond.ComponentSettings.create(); my.status = comp.status ? comp.status : pond.ComponentStatus.create(); let temps: number[] = []; let hums: number[] = []; if (comp.lastMeasurement.length > 0) { comp.lastMeasurement.forEach(um => { if (um.values[0]) { if (um.type === quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE) { temps = um.values[0].values.reverse(); } if (um.type === quack.MeasurementType.MEASUREMENT_TYPE_PERCENT) { hums = um.values[0].values.reverse(); } //TODO-CS: could expand this to have the emc in the cable model as well // if (um.type === quack.MeasurementType.MEASUREMENT_TYPE_EMC){ // emc = um.values[0].values // } } }); } else { let nodes = extractGrainCable( comp?.status?.lastMeasurement?.measurement?.grainCable ).reverse(); if (nodes.length > 0) { nodes.forEach(node => { hums.push(node.humidity); temps.push(node.temperature); }); } } my.temperatures = temps; my.humidities = hums; return my; } public static any(data: any): GrainCable { let comp = pond.Component.fromObject(cloneDeep(data)); let my = GrainCable.createPond(comp); if (data && data.status && data.status.lastMeasurement) { my.status.lastMeasurement = data.status.lastMeasurement; } return my; } public update(other: GrainCable) { this.settings = other.settings; this.status = other.status; } public humidColour() { return describeMeasurement( quack.MeasurementType.MEASUREMENT_TYPE_PERCENT, quack.ComponentType.COMPONENT_TYPE_DHT ).colour(); } private farenheit(temp: number) { return temp * (9 / 5) + 32; } public tempColour() { return describeMeasurement(quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE).colour(); } public minTemp(unit = pond.TemperatureUnit.TEMPERATURE_UNIT_CELSIUS) { if (unit === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) return this.farenheit(Math.min(...this.temperatures)); return Math.min(...this.temperatures); } public minHumidity() { return Math.min(...this.humidities); } public minMoisture() { return Math.min(...this.grainMoistures); } public aveTemp(unit = pond.TemperatureUnit.TEMPERATURE_UNIT_CELSIUS) { if (unit === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) return this.farenheit( this.temperatures.reduce((p: any, c: any) => p + c, 0) / this.temperatures.length ); return this.temperatures.reduce((p: any, c: any) => p + c, 0) / this.temperatures.length; } public aveHumidity() { return this.humidities.reduce((p: any, c: any) => p + c, 0) / this.humidities.length; } public maxTemp(unit = pond.TemperatureUnit.TEMPERATURE_UNIT_CELSIUS) { if (unit === pond.TemperatureUnit.TEMPERATURE_UNIT_FAHRENHEIT) return this.farenheit(Math.max(...this.temperatures)); return Math.max(...this.temperatures); } public maxHumidity() { return Math.max(...this.humidities); } public maxMoisture() { return Math.min(...this.grainMoistures); } public name(): string { return this.settings.name !== "" ? this.settings.name : "Component " + this.key(); } public key(): string { return this.settings.key; } public location(): quack.ComponentID { return quack.ComponentID.fromObject({ type: this.settings.type, addressType: this.settings.addressType, address: this.settings.address }); } public locationString(): string { return ( or(this.settings.type, 0).toString() + "-" + or(this.settings.addressType, 0).toString() + "-" + or(this.settings.address, 0).toString() ); } public type(): quack.ComponentType { return this.settings.type; } public subType(): number { return this.settings.subtype; } //return the grain cable as a component public asComponent(): Component { let component = Component.create(); component.settings = this.settings; component.status = this.status; //this section of the function will be deprecated as the last measurement in the new structure is in the status again let lastMeasurements = []; let lastTemp = pond.UnitMeasurementsForComponent.create(); lastTemp.componentId = this.settings.key; lastTemp.timestamps = [this.lastReading]; lastTemp.type = quack.MeasurementType.MEASUREMENT_TYPE_TEMPERATURE; lastTemp.values = [pond.ValueArray.create()]; lastTemp.values[0].values = this.temperatures; lastMeasurements.push(lastTemp); let lastHum = pond.UnitMeasurementsForComponent.create(); lastHum.componentId = this.settings.key; lastHum.timestamps = [this.lastReading]; lastHum.type = quack.MeasurementType.MEASUREMENT_TYPE_PERCENT; lastHum.values = [pond.ValueArray.create()]; lastHum.values[0].values = this.humidities; lastMeasurements.push(lastHum); if (this.grainMoistures.length > 0) { let lastEMC = pond.UnitMeasurementsForComponent.create(); lastEMC.componentId = this.settings.key; lastEMC.timestamps = [this.lastReading]; lastEMC.type = quack.MeasurementType.MEASUREMENT_TYPE_GRAIN_EMC; lastEMC.values = [pond.ValueArray.create()]; lastEMC.values[0].values = this.grainMoistures; lastMeasurements.push(lastEMC); } component.lastMeasurement = lastMeasurements; return component; } }