Skip to content

Commit

Permalink
- Support for multiple input and output units. Defaults are for input…
Browse files Browse the repository at this point in the history
… m/s and output bft.

- Changed look of the windspeedbar.
- Option to render all speed ranges in the bar or only till the highest measured speed.
- New example screencapture.
  • Loading branch information
aukedejong committed Feb 4, 2023
1 parent bbc6c80 commit e1c5344
Show file tree
Hide file tree
Showing 16 changed files with 429 additions and 115 deletions.
31 changes: 17 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,23 @@ Else, if you prefer the graphical editor, use the menu to add the resource:

### Card options

| Name | Type | Default | Required | Description |
|----------------------------|:------:|:-------:|:--------:|----------------------------------------------------------------------------------------------------|
| type | string | | x | `custom:windrose-card`. |
| title | string | | - | The card title. |
| wind_direction_entity | string | | x | The wind direction entity, having directing in degrees as the state. |
| windspeed_entities | object | | x | One are more windspeed entities. Only the first is used for the windrose. (for now) |
| refresh_interval | number | 300 | - | Refresh interval in seconds |
| hours_to_show | number | 4 | - | Show winddata for the last number of hours. |
| max_width | number | null | - | Use to limit the with (and height) of the windrose. |
| windspeed_bar_location | string | bottom | - | Location of the speed bar graph: `bottom`, `right` |
| wind_direction_unit | string | degrees | - | Wind direction unit, options: `degrees`, `letters`. Where letters being N, NE upto 32 directions. |
| direction_compensation | number | 0 | - | Compensate the measured direction in degrees. |
| cardinal_direction_letters | string | NESW | - | The cardinal letters used in the windrose. |
| wind_direction_count | string | 16 | - | How many wind direction the windrose can display, min. 4 max. 32 |
| Name | Type | Default | Required | Description |
|----------------------------|:-------:|:-------:|:--------:|------------------------------------------------------------------------------------------------------|
| type | string | | x | `custom:windrose-card`. |
| title | string | | - | The card title. |
| wind_direction_entity | string | | x | The wind direction entity, having directing in degrees as the state. |
| windspeed_entities | object | | x | One are more windspeed entities. Only the first is used for the windrose. (for now) |
| refresh_interval | number | 300 | - | Refresh interval in seconds |
| hours_to_show | number | 4 | - | Show winddata for the last number of hours. |
| max_width | number | null | - | Use to limit the with (and height) of the windrose. |
| windspeed_bar_location | string | bottom | - | Location of the speed bar graph: `bottom`, `right` |
| windspeed_bar_full | boolean | true | - | When true, renders all wind ranges, when false, doesn't render the speed range without measurements. |
| wind_direction_unit | string | degrees | - | Wind direction unit, options: `degrees`, `letters`. Where letters being N, NE upto 32 directions. |
| input_speed_unit | string | mps | - | Windspeed unit of measurement, options: `mps`, `kph`, `mph`, `knots`. |
| output_speed_unit | string | bft | - | Windspeed unit used on card, options: `mps`, `kph`, `mph`, `knots`, `bft`. |
| direction_compensation | number | 0 | - | Compensate the measured direction in degrees. |
| cardinal_direction_letters | string | NESW | - | The cardinal letters used in the windrose. |
| wind_direction_count | string | 16 | - | How many wind direction the windrose can display, min. 4 max. 32 |

#### Object windspeed_entities

Expand Down
Binary file modified example/windrose-example-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/CardConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ export interface CardConfig {
wind_direction_entity: string;
windspeed_entities: {entity: string, name: string}[];
wind_direction_unit: string;
input_speed_unit: string;
output_speed_unit: string;

direction_compensation: number;
windspeed_bar_location: string;
windspeed_bar_full: boolean;
cardinal_direction_letters: string;
wind_direction_count: number;
}
53 changes: 52 additions & 1 deletion src/CardConfigWrapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@ export class CardConfigWrapper {
windspeedEntities: {entity: string, name: string}[];
directionCompensation: number;
windspeedBarLocation: string;
windspeedBarFull: boolean;
cardinalDirectionLetters: string;
windDirectionCount: number;
windDirectionUnit: string;
inputSpeedUnit: string;
outputSpeedUnit: string;

entities: string[];
filterEntitiesQueryParameter: string;
Expand All @@ -25,6 +28,7 @@ export class CardConfigWrapper {
max_width: 400,
refresh_interval: GlobalConfig.defaultRefreshInterval,
windspeed_bar_location: GlobalConfig.defaultWindspeedBarLocation,
windspeed_bar_full: 'true',
wind_direction_entity: '',
windspeed_entities: [
{
Expand All @@ -33,6 +37,8 @@ export class CardConfigWrapper {
}
],
wind_direction_unit: GlobalConfig.defaultWindDirectionUnit,
input_speed_unit: GlobalConfig.defaultInputSpeedUnit,
output_speed_unit: GlobalConfig.defaultOutputSpeedUnit,
direction_compensation: 0,
cardinal_direction_letters: GlobalConfig.defaultCardinalDirectionLetters
};
Expand All @@ -47,9 +53,12 @@ export class CardConfigWrapper {
this.windspeedEntities = this.checkWindspeedEntities();
this.directionCompensation = this.checkDirectionCompensation();
this.windspeedBarLocation = this.checkWindspeedBarLocation();
this.windspeedBarFull = this.checkWindspeedBarFull();
this.cardinalDirectionLetters = this.checkCardinalDirectionLetters();
this.windDirectionCount = this.checkWindDirectionCount();
this.windDirectionUnit = this.checkWindDirectionUnit();
this.inputSpeedUnit = this.checkInputSpeedUnit();
this.outputSpeedUnit = this.checkOutputSpeedUnit();
this.filterEntitiesQueryParameter = this.createEntitiesQueryParameter();
this.entities = this.createEntitiesArray();
}
Expand Down Expand Up @@ -112,7 +121,6 @@ export class CardConfigWrapper {

private checkWindspeedBarLocation(): string {
if (this.cardConfig.windspeed_bar_location) {

if (this.cardConfig.windspeed_bar_location !== 'bottom' && this.cardConfig.windspeed_bar_location !== 'right') {
throw new Error('Invalid windspeed bar location ' + this.cardConfig.windspeed_bar_location +
'. Valid options: bottom, right');
Expand All @@ -122,6 +130,18 @@ export class CardConfigWrapper {
return GlobalConfig.defaultWindspeedBarLocation;
}

private checkWindspeedBarFull(): boolean {
return this.cardConfig.windspeed_bar_full;
// if (this.cardConfig.windspeed_bar_full) {
// // if (this.cardConfig.windspeed_bar_full !== 'true' && this.cardConfig.windspeed_bar_full !== 'false') {
// // throw new Error('Invalid windspeed bar full config ' + this.cardConfig.windspeed_bar_full +
// // '. Valid options: true, false');
// // }
// return this.cardConfig.windspeed_bar_full === 'true';
// }
// return GlobalConfig.defaultWindspeedBarFull;
}

private checkCardinalDirectionLetters(): string {
if (this.cardConfig.cardinal_direction_letters) {
if (this.cardConfig.cardinal_direction_letters.length !== 4) {
Expand Down Expand Up @@ -154,6 +174,37 @@ export class CardConfigWrapper {
}
return GlobalConfig.defaultWindDirectionUnit;
}

private checkInputSpeedUnit(): string {
if (this.cardConfig.input_speed_unit) {
if (this.cardConfig.input_speed_unit !== 'mps'
&& this.cardConfig.input_speed_unit !== 'kph'
&& this.cardConfig.input_speed_unit !== 'mph'
&& this.cardConfig.input_speed_unit !== 'fps'
&& this.cardConfig.input_speed_unit !== 'knots') {
throw new Error('Invalid input windspeed unit configured: ' + this.cardConfig.input_speed_unit +
'. Valid options: mps, fps, kph, mph, knots');
}
return this.cardConfig.input_speed_unit;
}
return GlobalConfig.defaultInputSpeedUnit;
}

private checkOutputSpeedUnit(): string {
if (this.cardConfig.output_speed_unit) {
if (this.cardConfig.output_speed_unit !== 'mps'
&& this.cardConfig.output_speed_unit !== 'kph'
&& this.cardConfig.output_speed_unit !== 'mph'
&& this.cardConfig.output_speed_unit !== 'fps'
&& this.cardConfig.output_speed_unit !== 'knots'
&& this.cardConfig.output_speed_unit !== 'bft') {
throw new Error('Invalid output windspeed unit configured: ' + this.cardConfig.output_speed_unit +
'. Valid options: mps, fps, kph, mph, knots, bft');
}
return this.cardConfig.output_speed_unit;
}
return GlobalConfig.defaultOutputSpeedUnit;
}

private createEntitiesQueryParameter() {
return this.windDirectionEntity + ',' + this.windspeedEntities
Expand Down
5 changes: 4 additions & 1 deletion src/GlobalConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ export class GlobalConfig {
static defaultRefreshInterval = 300;
static defaultWindDirectionCount = 16;
static defaultWindDirectionUnit = 'degrees';
static defaultInputSpeedUnit = 'mps';
static defaultOutputSpeedUnit = 'bft';
static defaultWindspeedBarFull = true;

static verticalBarHeight = 16;
static verticalBarHeight = 30;
static horizontalBarHeight = 15;

static getTextColor() {
Expand Down
2 changes: 1 addition & 1 deletion src/MeasurementMatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export class MeasurementMatcher {
match(): DirectionSpeed[] {
const matchedData: DirectionSpeed[] = [];
this.directionData.forEach((direction) => {
let speed = this.findMatchingSpeed(direction.lu);
const speed = this.findMatchingSpeed(direction.lu);
if (speed) {
matchedData.push(new DirectionSpeed(direction.s, speed.s));
}
Expand Down
25 changes: 20 additions & 5 deletions src/WindBarCalculator.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
import {WindSpeedConverter} from "./WindSpeedConverter";
import {SpeedUnits, WindSpeedConverter} from "./WindSpeedConverter";
import {WindBarData} from "./WindBarData";
import {WindBarConfig} from "./WindBarConfig";

export class WindBarCalculator {

readonly windSpeedConverter = new WindSpeedConverter();
readonly config: WindBarConfig;
speeds: number[] = [];
modified = false;

speedRangePercentages: number[] = []

speedRangeFunction: (speed: number) => number;
speedConverterFunction: (speed: number) => number;
rangeCount: number;

constructor(config: WindBarConfig) {
this.config = config;
this.speedRangeFunction = this.windSpeedConverter.getRangeFunction(this.config.outputUnit);
this.speedConverterFunction = this.windSpeedConverter.getSpeedConverter(this.config.inputUnit,
this.config.outputUnit);
this.rangeCount = SpeedUnits.getSpeedUnit(this.config.outputUnit).speedRanges.length;
}

addSpeeds(speeds: number[]) {
this.speeds = this.speeds.concat(speeds);
for (const speed of speeds) {
this.speeds.push(this.speedConverterFunction(speed));
}
this.modified = true;
}

Expand All @@ -22,9 +38,9 @@ export class WindBarCalculator {
}

private calculateSpeedRangePercentages(): void {
const speedRangeCounts = Array(13).fill(0);
const speedRangeCounts = Array(this.rangeCount).fill(0);
for (const speed of this.speeds) {
const windBft = this.windSpeedConverter.getByMeterPerSecond(speed)?.getBft();
const windBft = this.speedRangeFunction(speed);
if (windBft !== undefined && windBft >= 0) {
speedRangeCounts[windBft]++;
} else {
Expand All @@ -35,6 +51,5 @@ export class WindBarCalculator {
for (const speedRangeCount of speedRangeCounts) {
this.speedRangePercentages.push(speedRangeCount / (this.speeds.length / 100));
}
// console.log('BAR - Calculated speed range percentages', this.speedRangePercentages, this.speeds);
}
}
Loading

0 comments on commit e1c5344

Please sign in to comment.