My goal of this project was to be able to receive the NOAA weather radio, decode alerts and trigger webhooks and stream the audio from the SDR.
- RTL-SDR Dongle (with antenna)
- Device to host dongle
- Running Home Assistant instance
This project is made possible mainly by the rtl_sdr package as well as multimon-ng and dsame. Thank you to the creators and contributors of these projects.
To start we'll need some apt packages
sudo apt-get install rtl-sdr sox lame ezstream icecast2
NOTE: At some point along installing the apt packages it will ask you to configure icecast. You can do this now or later by following icecast documentation. Be sure to remember the passwords you set as the "source" one will be needed later.
sudo nano /etc/ezstream.xml
Use the example here and paste it into nano but change the source password to the icecast source password. You should also change the mount_point to something such as /noaa and Ogg to MP3.
At this point with the SDR plugged in you can run rtl_test to see if it is being recognized. If it shows on the list we can run a command to stream our audio. Be sure to change the frequency (-f 162.40M) to your local NOAA weather radio.
rtl_fm -f 162.40M -s 48000 -l 0 -d 0 -g 45 | lame -s 48000 --lowpass 3200 --abr 64 --scale 9 -r -m m - - | ezstream -c /etc/ezstream.xml -v -r
Using a browser or a program like VLC we can then navigate to the IP of the device hosting the SDR along with the port for icecast and the mount_point path from our ezstream config.
eg http://192.168.1.10:8000/noaa
This should load a media player (if using a browser) that will play the radio frequency tuned. From here if all you wish to do is hear the radio then you're all set. I wanted to take it a step further and integrate this into Home Assistant to alert me when there are EAS messages.
You can play the audio stream on a Home Assistant media_player with something like:
action: media_player.play_media
target:
entity_id: media_player.my_media_player
data:
media_content_id: http://192.168.1.10:8000/noaa
media_content_type: audio/mpeg
enqueue: playStart by downloading the required projects
sudo apt-get install python3-pip cmake
wget -O dsame-master.zip https://github.com/cuppa-joe/dsame/archive/refs/heads/master.zip
wget -O multimon-ng-master.zip https://github.com/EliasOenal/multimon-ng/archive/refs/heads/master.zip
Run the following commands found from the projects git page. This converts the digital information stored in the infamous EAS sound.
unzip ~/multimon-ng-master.zip
cd ~/multimon-ng-master
mkdir build
cd build
cmake ..
make
sudo make install
You can use sox to play an audio file that contains an EAS message and pipe it into multimon-ng to test the output with the following command to decode it.
sox | multimon-ng -t raw -a EAS -q -
This will "translate" the EAS text string from multimon-ng into understandable information. Extract the dsame zip.
unzip ~/dsame-master.zip
Test it's functioning by running the following command
python3 ~/dsame-master/dsame.py --msg "ZCZC-WXR-RWT-020103-020209-020091-020121-029047-029165-029095-029037+0030-1051700-KEAX/NWS"
Create the following file in your home directory. Replace the end of each curl command with a webhook generated by adding a webhook trigger to an automation. The script offers place for running separate webhooks for a Test, Warnings and general Messages. I like to keep track of the date of the last test to ensure that everything is still operating properly. Warnings can be set to automatically play the message sent in the webhook payload or the media stream as shown above. The data sent by the webhook can be accessed by {{ trigger.json.<key> }} within an action of the automation.
~/ha-webhook.sh
#!/bin/sh
echo HA Webhook: running 1>&2
EVENT_CODE=$2
TYPE="${11}"
URL_PREFIX=https://homeassistant.local/api/webhook
LOG_DIR=~/events
JSON_STRING="{\"org_code\": \"${1}\", \"event_code\": \"${2}\", \"same\": \"${3}\", \"purge_time_code\": \"${4}\", \"date_code\": \"${5}\", \"originator_code\": \"${6}\", \"country\": \"${7}\", \"organization\": \"${8}\", \"location\": \"${9}\", \"event\": \"${10}\", \"type\": \"${11}\", \"start\": \"${12}\", \"end\": \"${13}\", \"length\": \"${14}\", \"seconds\": \"${15}\", \"date\": \"${16}\", \"message\": \"${17}\"}"
# Write to json file as way to log events
echo $JSON_STRING >> $LOG_DIR/$EVENT_CODE-$(date -d "today" +"%Y%m%d%H%M").json
# Trigger HA webhooks
if [ "$TYPE" = "T" ]; then
echo HA Webhook: Test
curl -H "Content-Type: application/json" --request POST -d "${JSON_STRING}" $URL_PREFIX/my-webhook_test
elif [ "$TYPE" = "W" ] || [ "$TYPE" = "A" ] || [ "$TYPE" = "E" ] || [ "$TYPE" = "R" ]; then
echo HA Webhook: Alert
curl -H "Content-Type: application/json" --request POST -d "${JSON_STRING}" $URL_PREFIX/my-webhook_alert
else
echo HA Webhook: Message
curl -H "Content-Type: application/json" --request POST -d "${JSON_STRING}" $URL_PREFIX/my-webhook_message
fiAfter creating the script file be sure to add the ability to execute.
chmod +x ~/ha-webhook.sh
You can test dsame with HA webhooks with the following command.
python3 ~/dsame-master/dsame.py --msg "ZCZC-WXR-RWT-020103-020209-020091-020121-029047-029165-029095-029037+0030-1051700-KEAX/NWS" --call ~/ha-webhook.sh --command "{ORG}" "{EEE}" "{PSSCCC}" "{TTTT}" "{JJJHHMM}" "{LLLLLLLL}" "{COUNTRY}" "{organization}" "{location}" "{event}" "{type}" "{start}" "{end}" "{length}" "{seconds}" "{date}" "{MESSAGE}"
This command will continuously monitor the SDR feed for decodeable information and run the script.
rtl_fm -f 162.40M -s 22050 -l 0 -d 0 -g 45 | multimon-ng -t raw -a EAS -q - | python3 ~/dsame-master/dsame.py --no-text --call ~/ha-webhook.sh --command "{ORG}" "{EEE}" "{PSSCCC}" "{TTTT}" "{JJJHHMM}" "{LLLLLLLL}" "{COUNTRY}" "{organization}" "{location}" "{event}" "{type}" "{start}" "{end}" "{length}" "{seconds}" "{date}" "{MESSAGE}"
To bring together our audio stream and our EAS alerts we'll make a couple more scripts and a service to keep it running in the background.
~/source.sh
#!/bin/bash
echo INPUT: rtl_fm Device 1>&2
PPM=0
FREQ=162.400M
GAIN=42
until rtl_fm -f ${FREQ} -M fm -s 22050 -E dc -p ${PPM} -g ${GAIN} -| tee >(lame -s 22050 --lowpass 3200 --abr 64 --scale 9 -r -m m - - | ezstream -c /etc/ezstream.xml) | multimon-ng -t raw -a EAS /dev/stdin; do
echo Restarting... >&2
sleep 2
done~/weather_radio.sh
#!bin/sh
python3 /home/radio/dsame-master/dsame.py --source /home/radio/source.sh --call /home/radio/ha-webhook.sh --command "{ORG}" "{EEE}" "{PSSCCC}" "{TTTT}" "{JJJHHMM}" "{LLLLLLLL}" "{COUNTRY}" "{organization}" "{location}" "{event}" "{type}" "{start}" "{end}" "{length}" "{seconds}" "{date}" "{MESSAGE}"NOTE: Notice the fully declared file paths in this file. This is because it will be called by a service which will not have an associated user thus no associated home directory. Please update this to reflect the user that you have created these files under. Same goes for the service created in the next step.
We'll want both these new files to be executable
chmod +x source.sh
chmod +x weather_radio.sh
Next we'll create a service to run our weather alert scripts
sudo nano /lib/systemd/system/weather_radio.service
/lib/systemd/system/weather_radio.service
[Unit]
Description=Weather Radio with Alerts for Home Assistant
Before=multi-user.target
[Service]
Type=simple
ExecStart=/home/radio/weather_radio.sh
Restart=on-abort
[Install]
WantedBy=multi-user.target
Then run the following commands to get it running
sudo systemctl daemon-reload
sudo systemctl enable weather_radio.service
sudo systemctl start weather_radio.service
You can check to see if it is running smoothly with:
sudo systemctl status weather_radio.service