I created a solution for folks whom may want river flood information in their dashboards. It all came from a question posted here:
I decided that the best solution for my needs was to extract the data from NOAA posted CSV files using curl
to grab the data piped to jq
raw to create targeted JSON with the information I need. The below example uses my specific river monitor, you can easily change to yours. The sensor is:
##
## water.weather.gov CSV
##
- platform: command_line
scan_interval: 3600
name: Russian River Flood Info
command: "curl -s 'https://www.cnrfc.noaa.gov/graphicalRVF_csv.php?id=GUEC1' | jq --raw-input '{flooddata: [inputs | split(\",\") | {issued: .[0], valid: .[1] | strptime(\"%m/%d/%Y %I %p\") | strftime(\"%m/%d/%Y %I:%M %p\"), validts: .[1] | strptime(\"%m/%d/%Y %I %p\") | strftime(\"%Y-%d-%m %H:%M:%S\"), level: .[2] | tonumber, trend: .[3], status: .[4], mode: .[5] | gsub(\"[\\r]\"; \"\") }]| .[2:999] }'"
value_template: "{{ now() }}"
json_attributes:
- flooddata
This grabs the data from NOAA for GUEC1 in CSV format and then uses that jq command to structure it how I want it to be. The scan_interval
is set to every hour because it is not needed more often than that and likely could be greater as they update data every 4 to 6 hours. The only real tricks employed here in jq
is to parse NOAA date/times for charting purposes and excluding the first row of data as it is the header.
The result is like this:
So to put that data onto a dashboard, I chose to use custom:flex-table-card
and custom:apexcharts-card
. The YAML for these are:
type: custom:apexcharts-card
header:
show: true
title: Russian River Level
standard_format: true
span:
start: hour
offset: '-2d'
experimental:
color_threshold: true
brush: true
brush:
selection_span: 6d
now:
show: true
update_delay: 3000ms
graph_span: 5d
series:
- entity: sensor.russian_river_flood_info
type: area
stroke_width: 2
data_generator: |-
return entity.attributes.flooddata.map((point) =>
{ return [new Date(point.valid).getTime(), point.level]; });
color_threshold:
- value: 0
color: '#3399ff'
- value: 29
color: '#3399ff'
- value: 29
color: '#e67300'
- value: 32
color: '#e67300'
- value: 32
color: '#cc3300'
- value: 100
color: '#cc3300'
show:
in_brush: true
type: custom:flex-table-card
entities:
include: sensor.russian_river_flood_info
columns:
- name: Date/Time
data: flooddata
modify: x.valid
- name: Level
data: flooddata
modify: |-
switch(x.status){
case 'Above Monitor':
'<div style="background-color: #e67300;">' + parseFloat(x.level).toFixed(1) + ' ft</div>';
break;
case 'Above Flood':
'<div style="background-color: #cc0000;">' + parseFloat(x.level).toFixed(1) + ' ft</div>';
break;
default:
parseFloat(x.level).toFixed(1) + ' ft';
}
align: center
- name: Trend
data: flooddata
modify: |-
switch(x.trend){
case '+':
'<ha-icon icon="mdi:arrow-up" style="color: #e67300;">';
break;
case '-':
'<ha-icon icon="mdi:arrow-down" style="color: #3399ff;">';
break;
default:
'<ha-icon icon="mdi:arrow-all">';
}
align: center
css:
table+: 'padding: 0px'
card_mod:
style: |
ha-card {
overflow: auto;
max-height: 60vh;
}
Only a few tricks employed to color cells based on flood level and replace trend with icons.
The final result is like this:
in the future I plan to expand this from NOAA to include rainfall and winds and eliminate other weather information as NOAA to me is the best source.