Header Image - Kilo Charlie 4 Romeo Charlie Romeo

Category Archives

8 Articles

Direwolf APRS Setup for the Raspberry Pi

Written with the Grok engine from xAI. A beginner’s walk-through of building a fill-in APRS digipeater and IGate on a Raspberry Pi, with the AURSINC VHF node and Direwolf. Each step says what to do and why it matters.

This is a recount of the build that worked, rewritten for doing it the first time. I asked Grok to write down everything I did on the path to successfully building this node. It certainly took a lot of trial and error, so this summary boils that lengthy process down.

Start with the basic information: Callsign, location, and the APRS-IS passcode are placeholders. Put your own in.

  • YOURCALL — your amateur callsign
  • YOURCALL-10 — the SSID used for this node. I used the suffix -10 here
  • YOURPASSCODE — the APRS-IS passcode for your base callsign
  • The latitude and longitude of the beacon — your location

What you are building, and why

APRS is a system that sends short position and status packets over a radio, usually on 144.390 MHz in North America. A digipeater hears a packet and retransmits it, so it can travel farther. An IGate hears a packet on the radio and uploads it to the internet, where sites like aprs.fi show it on a map.

A “fill-in” is the small, local version of that. It answers one hop, for stations that cannot quite reach a big digipeater, and it uploads what it hears. It does not take packets from the internet and put them back on the air. That matters on a 1 watt node. A wide digipeater is supposed to be high, loud, and carefully filtered. This one is meant to fill a gap, not cover a county.

The computer is a Raspberry Pi. The radio is the AURSINC VHF APRS RF node, which is a small 136–174 MHz module of about 1 watt, with a USB sound chip for the audio and a way to program the radio over serial. Direwolf is the software that turns audio into APRS packets and back again. It is a sound-card TNC. There is no separate TNC box.

Raspberry Pi 3 Model B
The computer in this build, a Raspberry Pi 3. Any Pi 2, 3, 4, or 5 works. Photo: Raspberry Pi. raspberrypi.com
CM108 USB sound module
A typical CM108 USB sound module. The black chip in the middle is the CM108. Direwolf uses this kind of chip for audio, and one of its pins for push-to-talk. The AURSINC node has the same chip built in. Photo: Online Amateur Radio Community Wiki. wiki.oarc.uk

The AURSINC node itself is the board this article was built around. It combines the CM108 sound and PTT path with a serial path for the SR110v radio. Product page: AURSINC VHF APRS RF Node on Amazon. Also listed at aursinc.com. Note: Although advertised as 1W, it rarely produced more than a few hundred milliwatts.

Why the USB cable has two positions

The board has two chips on one plug. One is a CM108 sound chip. That is what Direwolf uses for audio, and one of its GPIO pins keys the transmitter. The other is a serial chip, used only to program the radio’s frequency and settings.

The USB-C connector is wired so that rotating it 180 degrees selects which chip the Pi talks to. The LEDs tell you which one you have.

What you seeWhat the Pi seesWhy you want it
Green LED onlyA serial port, /dev/ttyUSB0Programming the radio, done once
Green and yellow LEDsA sound card and a PTT deviceNormal operation

If you start Direwolf and it cannot find an audio device, the cable is almost certainly in serial mode-you want this for programming. If you are not in serial mode, unplug it, rotate the plug, and plug it back in. You will use serial mode once, then leave it in sound mode for good.

You can check the availability of sounds devices with arecord and aplay. You should not see them in serial mode. You should see the ttyUSB device, however.

arecord -l
aplay -l
ls /dev/ttyUSB*

arecord -l lists recording devices. In sound mode you should see a USB audio card.

ls /dev/ttyUSB* lists serial ports. In serial mode you should see /dev/ttyUSB0.

If you can’t access the sounds device, the user might need permission from a group setting (I found this when trying to use the dietpi operating system). To add the user to the audio group, try (dietpi being the test user here):

sudo adduser dietpi audio

Why you program the radio before anything else

The SR110v does not know it is an APRS radio. Out of the box it may be on some other frequency, with VOX on, in low power. Direwolf cannot fix that. It only sends audio. The radio has to already be on 144.390, simplex, with VOX off, before Direwolf is useful.

Orient the cable so only the green LED is on and your tty device responds. Then install the python serial library.

ls /dev/ttyUSB*
sudo apt-get install -y python3-serial

python3-serial is the library that lets a short Python script talk to the radio. The radio speaks a simple text protocol at 9600 baud. Each command starts with AT+ and ends with a return. A reply ending in :0 means the radio accepted it.

python3 - <<'PY'
import serial, time
s = serial.Serial('/dev/ttyUSB0', 9600, timeout=2)

def cmd(c):
    s.reset_input_buffer()
    s.write((c + '\r\n').encode())
    time.sleep(1)
    print(c, '->', repr(s.read(200)))

cmd('AT+DMOCONNECT')
cmd('AT+DMOSETGROUP=1,144.3900,144.3900,00,0,00,0')
cmd('AT+DMOSETVOLUME=5')
cmd('AT+DMOSETVOX=0')
cmd('AT+DMOAUTOPOWCONTR=1')
PY

What each line is for:

  • DMOCONNECT — wake the radio up and confirm the serial link works.
  • DMOSETGROUP — set receive and transmit to 144.390, no CTCSS tone, squelch open, and the final 0 is the high-power flag. Both frequencies are the same because APRS is simplex. Everyone transmits and receives on one frequency.
  • DMOSETVOLUME=5 — set the audio level the radio sends to the sound chip. Too high and Direwolf sees distortion. Too low and it misses packets. Five is a starting point.
  • DMOSETVOX=0 — turn VOX off. VOX keys the transmitter when it hears audio. Direwolf keys it with a GPIO pin instead. If both are on, the radio keys at the wrong time.
  • DMOAUTOPOWCONTR=1 — leave automatic power control on.

The seven fields in the group command, in order:

AT+DMOSETGROUP = 1 , 144.3900 , 144.3900 , 00 , 0 , 00 , 0
#ValueMeaning
11Bandwidth. 1 is wide, 25 kHz. 0 is narrow, 12.5 kHz.
2144.3900Transmit frequency, in MHz.
3144.3900Receive frequency. Same as transmit, because APRS is simplex.
400Transmit CTCSS. 00 means no tone.
50Squelch. 0 is open, so the audio is never muted. Range is 0–8.
600Receive CTCSS. 00 means no tone is required to unmute.
70Power. 0 is high, 1 is low. This is the flag that survives a reboot.

APRS wants all of those: one frequency, no PL tone, squelch open so Direwolf hears everything, and high power if you are going to transmit. A reply of +DMOSETGROUP:0 means the radio stored it. :1 means a field was out of range or the wrong shape. Newer manuals call a similar command AT+DMOGRP and number the fields differently. This 7-field form is the one this firmware accepted.

The high-power flag is stored in the radio. It survives unplugging it. The shorter form of the group command failed on this firmware. The 7-field form is the one that returned :0.

When the replies look right, unplug the cable, rotate it, and plug it back in so both LEDs are on.

Why Direwolf has to be compiled, not just installed

The packaged Direwolf in some distributions is built without CM108 push-to-talk. PTT is how the software tells the radio to transmit. On this board that signal is a pin on the CM108 sound chip. If the program was built without the library that talks to that pin, it can decode packets all day and never key the transmitter. The instructions below detail how to build Direwolf with CM108 PTT support.

The library is libudev. Install the development package before you build.

sudo apt-get update
sudo apt-get install -y \
  git gcc g++ make cmake \
  libasound2-dev \
  libudev-dev \
  libavahi-client-dev \
  pkg-config

libasound2-dev is the sound system. libudev-dev is the one that enables CM108 PTT. The rest are ordinary build tools.

Then build from source, in a separate directory. CMake is a build helper. It has to be run from a build folder, looking up at the source. Running it in the source folder is what produces “does not appear to contain CMakeLists.txt.”

cd ~
git clone https://github.com/wb2osz/direwolf
cd direwolf
mkdir build
cd build
cmake ..
make -j4
sudo make install
make install-conf

cmake .. means “the source is one directory up.” make -j4 compiles using four jobs. sudo make install copies the program into /usr/local/bin. make install-conf drops a sample config in your home directory.

Start it once and read the first lines. You want cm108-ptt in the banner. If it is missing, the udev package was not installed before the build, and you have to install it and rebuild. Validate success with the following commands:

cm108
arecord -l

cm108 is a small tool that comes with Direwolf. It lists CM108 sound cards and the PTT device that goes with each one. Write down the plughw:N,0 name and the /dev/hidraw device. On this build they were plughw:2,0 and /dev/hidraw0. The number changes if another USB sound device is plugged in. Use what your Pi reports.

plughw is an ALSA name. ALSA is the Linux sound system. plughw:2,0 means card 2, device 0, with a plugin layer that converts sample rates. Direwolf wants that form, not the raw hw: form.

Why the config looks the way it does

Direwolf’s config is a text file, usually ~/direwolf.conf. Most of the sample file can stay as it is. These are the lines that make it a fill-in.

Audio, identity, modem, and PTT:

ADEVICE plughw:2,0
ACHANNELS 1

CHANNEL 0
MYCALL YOURCALL-10
MODEM 1200
PTT CM108

ADEVICE is the sound card from the previous step. One channel, because this is a mono radio. MYCALL is how the node identifies itself. The -10 SSID is the usual convention for an IGate. MODEM 1200 is the standard VHF APRS speed, 1200 baud AFSK. PTT CM108 tells Direwolf to key the transmitter through the sound chip’s GPIO instead of a serial port. At startup it should print Using /dev/hidraw0 GPIO 3 for channel 0 PTT control.

The digipeater rules:

DIGIPEAT 0 0 ^TEST$ ^WIDE[12]-[12]$ TRACE
FILTER 0 0 t/p

A packet can ask to be repeated by putting aliases in its path, such as WIDE1-1 or WIDE2-1. A fill-in answers those. It does not answer WIDE3-3 or a packet aliased to TEST.

  • DIGIPEAT 0 0 — hear on channel 0, transmit on channel 0. There is only one radio.
  • ^TEST$ — never repeat a packet whose alias is TEST. That is a debugging alias, not a real path.
  • ^WIDE[12]-[12]$ — only repeat a packet that still has an unused WIDE1 or WIDE2 hop. The brackets are a pattern, not something you type on the air.
  • TRACE — when you hop a packet, put your own call in the path with a star, so the path shows YOURCALL-10*. That is how other stations know you handled it.
  • FILTER 0 0 t/p — only digipeat position packets. Messages, status, and weather are still uploaded to the internet. They are not retransmitted on the radio. That keeps a small node from repeating everything it hears.

The IGate:

IGSERVER noam.aprs2.net
IGLOGIN YOURCALL-10 YOURPASSCODE
IGTXLIMIT 6 10

APRS-IS is the internet side of APRS. noam.aprs2.net is a rotating name for the North American Tier 2 servers. You do not pick a server. The name hands you one, and the log shows which one after logresp … verified.

The passcode is a number derived from your callsign. It is how the server knows you are allowed to send. Generate it from your base callsign. Do not share it, and do not invent one.

IGTXVIA is left commented out on purpose. That line is what would let the node transmit packets that arrived from the internet. Leaving it off means the node is receive-only toward the internet and transmit-only for what it heard on the radio, plus its own beacon. IGTXLIMIT is a safety cap, in case that line is enabled later.

The beacon:

PBEACON delay=0:20 every=05:00 symbol="igate" lat=39^26.74N long=123^53.93W comment="SR110v fill-in" via=WIDE1-1

A beacon is how the node tells the network where it is. Without one, aprs.fi may show the packets you gate and never show the node itself.

  • delay=0:20 — wait 20 seconds after start, so the IGate login can finish first.
  • every=05:00 — then every 5 minutes. Often enough to be seen, not often enough to be rude.
  • symbol="igate" — the icon. A digipeater can use symbol="digi" instead.
  • lat and long — your location, in degrees and decimal minutes. Replace the example.
  • via=WIDE1-1 — ask for one hop, so a nearby digipeater can hear you. Remove it if you only care that your own IGate uploads the beacon.

Do not add a second beacon with sendto=IG and the same position. Your own IGate already uploads the RF beacon. Two copies look like duplicates on aprs.fi.

Why the first run is done by hand

Run it in a terminal the first time, so you can see the banner and the login.

direwolf -t 0 -c ~/direwolf.conf

-t 0 turns on color. -c points at the config. You want, in order:

  1. The banner includes cm108-ptt. The PTT support was compiled in.
  2. The audio device is the plughw you wrote down.
  3. A line about /dev/hidraw0 GPIO 3. The PTT pin was found.
  4. logresp YOURCALL-10 verified. The IGate server accepted you.

Then the tags on each packet tell you what the node did with it.

  • [0L] — something you transmitted, such as your beacon.
  • [0H] — something you digipeated. The path will contain YOURCALL-10*.
  • [0.n] — something you received. The number is how many bits Direwolf corrected.

Direwolf also prints an audio level for each station. Most of them should be around 50. If it says the level is too high, the radio is sending too much audio into the sound chip. Drop AT+DMOSETVOLUME by one and try again. Distorted audio decodes worse, not better.

How you know it is actually working

Three different checks, because each one proves a different thing.

  • A second radio on 144.390 hears your beacon when the PTT LED lights. That proves the transmitter, the frequency, and the PTT pin.
  • aprs.fi shows your beacon. That proves the IGate login and the upload. The path will be TCPIP* or qAC, because your own IGate uploaded it.
  • A station you heard shows qAR,YOURCALL-10 or qAO,YOURCALL-10 on aprs.fi. That proves you gated someone else’s packet. Your call with a star appears only if some other IGate heard your retransmission. Your own IGate uploads the original, before the hop stamp.

Why it should run as a service

A program started in a terminal dies when you log out. A systemd service starts at boot and restarts if it crashes. Change the user and the path if yours are different.

sudo tee /etc/systemd/system/direwolf.service >/dev/null <<'EOF'
[Unit]
Description=Direwolf APRS fill-in IGate
After=network-online.target sound.target
Wants=network-online.target

[Service]
Type=simple
User=pi
ExecStart=/usr/local/bin/direwolf -t 0 -c /home/pi/direwolf.conf
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now direwolf

After=network-online.target waits for the network, because the IGate has nowhere to go without it. Restart=on-failure brings it back if it exits.

What might go wrong the first time, and why

IssueWhat happened
cm108 said PTT was disabledDirewolf was built before libudev-dev was installed. The PTT code was left out. Install the package and rebuild.
cmake could not find CMakeLists.txtcmake was run in the source directory. It has to be run from build/, with .. pointing at the source.
No audio deviceThe USB-C cable was in serial mode. Rotate it until both LEDs are on.
Beacons in the log, nothing on aprs.fiThe packet was sent before the server login finished, or that Tier 2 server was not passing traffic. Restart, wait for verified, then wait for the next beacon.
PTT LED on, no RF on the meterThe radio was still in low power, or not on 144.390. Re-run the group command with the final 0.
Audio level warningThe SR110v volume was too high, so the sound chip was clipping. Lower AT+DMOSETVOLUME.

Appendix: harmonics, and why the antenna needs a filter

After the node was on the air, a wattmeter on the antenna jack with a dummy load did not show 144.390. It showed about 288.781 MHz. That is the second harmonic:

144.390 × 2 = 288.780

The radio was transmitting on 144.390. A strong copy of that signal was also leaving on 288.78 MHz. A nearby radio on 144.390 could hear the APRS audio, so the fundamental was there. The meter locked onto the harmonic because, on this module, the harmonic was strong enough to dominate the reading.

Why it happens: a clean transmitter produces a sine wave at the frequency you asked for, and very little else. A cheap single-chip module does not. Its output is closer to a distorted square wave, and a distorted wave is the fundamental plus a series of harmonics. The second is at twice the frequency, the third at three times. Turning the high-power flag on made it worse. More drive, more distortion, more harmonic. Both units we tried did this. It is the module, not a bad sample.

Why it matters: 288 MHz is not a 2 meter frequency. Energy there is outside the amateur band, and it has to be suppressed. The usual expectation is harmonics at least 40 dB down. A watt of harmonic is still a watt in the wrong place, and it steals power from the signal you meant to send.

The fix is a low-pass filter between the radio and the antenna. A low-pass filter lets the 144 MHz signal through and cuts everything above it. For a 1 watt node it does not need to be large.

Mini-Circuits filter family
Mini-Circuits filter modules. The part for this node is the VLF-180+, a low-pass filter that passes DC to 180 MHz and cuts the harmonics above it. Photo: Mini-Circuits. VLF-180+ product page
  • A commercial 2 meter low-pass filter rated for a few watts is enough. Radio, then filter, then antenna.
  • A 7-pole 144 MHz low-pass filter, the classic design for the band, puts the second harmonic down about 40 dB when it is built carefully.
  • Do not skip it because the node is “only 1 watt.” That is exactly the power level where a harmonic is still loud and easy to ignore.

Check it the same way it was found. Dummy load, and a meter that can read past 300 MHz, or a receiver on 288.78. With the filter in line the 288 MHz reading should collapse. Until that filter is in the antenna line, the node is not finished.

That is the whole path. A running Pi, the cable in the right orientation, a radio programmed for 144.390, Direwolf built with the PTT support this board needs, and a short config that makes it a fill-in instead of a wide.

Index: 130

440 Repeater Build

The KC4RCR 440 Repeater!

Front View
Side View

Current status: completed T-MARC frequency coordination for 444.300/449.300 frequency pair with 141.3 Hz CTCSS.

Raspberry Pi repeater controller running AllStar with a Repeater Builder RIM_Lite USB interface with custom cable (9 pin to 25 pin).

Connect with All Star Node #58830 or Echolink Node # 527721 (KC4RCR-R)

Index: 3

Lightning Detector and Email Notifier

I decided to post a draft of this page since I keep referencing it on a few nets. Watch for updates as I continue to update and refine the build and this page. Updated 16 July 2023.

This how-to instruction set will build a local lightning detection notification system which will send an email via Python script running on a Raspberry Pi. This of course, could be adapted to run on other hardware platforms easily.

Here’s my list of items:

* In 2022 Google stopped allowing “less secure apps” to access email. When they removed allowing the user to decide for themself to enable or disable, it rendered the email for many Raspberry Pi users to non-functioning (this would apply in other builds as well). It appears a work around was found, though I have not tried it. You can read about it here: G-Mail and less secure sign-in technology.

First, set up your Raspberry Pi if you have not already. There are many instruction sets on the Internet including this one: https://www.raspberrypi.com/tutorials/how-to-set-up-raspberry-pi/. Also, any Debian-based Operating System should work fine if you can’t source a Raspberry Pi. In my case I am using the Raspberry Pi 4 Model B Rev 1.2 running Raspbian GNU/Linux 10 (buster). I do plan to move this over to an Ubuntu machine one day to free this Pi up for other experiments.

Check and see if you have Python2 installed by running Python -V at the command prompt. You can use newer versions if you wish, but my code snippets in this example were written for the version noted below.

$ python -V
Python 2.7.16

If you do not have Python, it can be installed with:

$ sudo apt update
$ sudo apt-get install python2

Now install the rtl_433 code (see official source code instructions here: https://github.com/merbanan/rtl_433/).

 $ sudo apt-get install rtl_433

rtl_433 is a very powerful tool! It can interpret numerous devices so be sure to check out the link above. Did you realize most cars can be tracked via the tire sensors which is now government mandated in many areas? Well now you do and this tool will also read cars as they drive by on the street! It’s all open and unencrypted. I make this point not to encourage snooping but to make folks aware of a pet peeve of mine which are new cars spewing data without knowledge or consent of most owners. Anyway, back to the lightning sensor discussion…

You will also need the msmtp package if you wish to send email notifications. Another package called mailutils is also helpful along with the mail transport agent. Those can be installed by running:

$ sudo apt-get install msmtp
$ sudo apt-get install mailutils
$ sudo apt-get install msmtp-mta

Which can also be combined as:
$ sudo apt-get install msmtp mailutils msmtp-mta

Here is the final setup of the Raspberry Pi with power (white cable), network (orange cable) and RTL-SDR Dongle in one of the USB ports. I also have a small band pass filter on the antenna connection (black cable at bottom with SMA connector). This additional filter isn’t generally needed but since I have a lot of radio activity going on in the area, I figured it couldn’t hurt. It doesn’t have great reviews but I tested it and it was a bit off frequency but not enough to impact my setup. Here is the link: https://www.amazon.com/Interface-Bandpass-Receiver-Dedicated-422-446MHz/dp/B0B1QSBZKR

Acurite 6045M Sensor placed outdoors. This can be found at: https://www.amazon.com/gp/product/B01LNALL6C/

The good thing about using this particular SDR Dongle is that it should be recognized by the Pi’s Operating System without installing anything additional. You can use the command ‘lsusb’ to be sure. Here you see it on the second output line below (Bus 001 Device 003).

$ lsusb
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 0bda:2838 Realtek Semiconductor Corp. RTL2838 DVB-T
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

If you run rtl_433 with no options, you will start getting a lot of data displayed continuously until you press Ctrl-C in the terminal. Below you will see two different Acurite-6045M devices running (id 85 and id 127). There was no modification to the Acurite devices. This is right out of the box with batteries installed.

Screen capture of rtl_433 running

A couple things of note. Acurite appears to send the data three times. I presume this is their standard to ensure the transmission is received properly. Second, the lightning strike count is a rolling counter which wraps from 255 back to 0. That becomes important in the Python code because you will need to look for a change in the counter, not an absolute number. I also restrict the data collected to only the Acurite protocol needed (thus not filling up my log with tire sensors and many others). The -R option allows that selection. The protocol needed for the Acurite 6045M is “40”, i.e. running as this command only reads the Acurite 6045M and similar sensors and outputs formats (via -F option) json and http (more on that below). The protocol list can be found at https://github.com/merbanan/rtl_433.

/usr/local/bin/rtl_433 -R 40 -F json -F http

Another fun aspect of the rtl_433 package is the ability to format the output as json, csv, http, syslog and a few others. It has an integrated http server which defaults to port 8433 when invoked with rtl_433 -F http. Point your web browser to http://127.0.0.1:8433 or whatever your Raspberry Pi’s IP is (if not local).

Screen capture of http data on port 8433

Now if all you want to do is view the data, you can stop here. The next steps are if you want to set up the Raspberry Pi to notify you via email or text that the lightning count has changed. I was hoping that the “active” tag in the data would be enough, but testing shows it is not. In my tests, the Acurite sensor goes into active mode regularly for unknown reasons. I suspect some is RFI, but I have not done enough testing. Ideally if the RFI field were true, the sensor should not go into active mode, but it’s hard to say what the thinking was in the design of the sensor. Even the author of rtl_433 states there are some transmitted bits in the message that have not been found to correlate to useful data. Check out the acurite.c code for an in-depth analysis.

For email sending, you use msmtp. I have never enjoyed working with msmtp. I find it rather clunky and usually have to fiddle around with it a bit. You must create a config file name msmtprc. For lots more information, try searching for msmtprc configuration. Here’s one example: https://centurio.net/2020/09/21/configure-mail-transport-agent-on-raspbian-with-external-smtp-server/. My example config file is below, redacted of real account login information of course. Make sure you have the /etc/ssl/certs/ca-certificates.crt as well. If you don’t have it properly installed, you might have to research how to get it on your particular system. My hosted email account has port 465 available for sending mail. You will have to modify the settings below based on your email provider.

$ cat /etc/msmtprc
defaults
auth on
tls on
tls_starttls off
tls_trust_file /etc/ssl/certs/ca-certificates.crt
logfile /var/log/msmtp.log
aliases /etc/aliases
auto_from off
# Account details
account yourusername
host mail.yourserver.com
port 465
from yourusername@yourserver.com
user yourusername@yourserver.com
password S0m3P@$$w0RD
# Default Account
account default : yourusername

You can try a test email using the following (this is one line, be careful with copy paste):

$ echo "Notification System Test" | mail --debug-level=6 -s "Test" -a "From:Notification System sendinguser@domain.com" recievinguser@domain.com

I find the “-a From” header helps get though some spam filters, especially to a cellular phone text gateway. You should see the following output after sending the mail command and get an email for the specified recipient.

mail: sendmail binary: /usr/sbin/sendmail
mail: mu_mailer_send_message(): using From: sendinguser@domain.com
mail: Sending headers…
mail: Sending body…
mail: /usr/sbin/sendmail exited with: 0

Now we move on to the Python code. Let me be clear here! This code will work but it is a quick approach. You can tailor it anyway you want and certainly clean it up to be more efficient. I am still working on the code to add other features and multiple sensors, etc. What that means is this is an earlier version that ran for many months. It does work, just not as clean and neat as it could be. Remember, be careful with copy and paste.

import json
import sys
import datetime
import subprocess

k = 0
start = 0
strike_count_old = 0

outputfile = open(r"/home/pi/lightning.txt", "a")

try:
   for line in iter(sys.stdin.readline, b''):
      k = k + 1
      if k > 9:
          signal_string = json.loads(line)
          if signal_string["model"] == "Acurite-6045M":
               #print signal_string
               strike_count_new = signal_string["strike_count"]
               if strike_count_new != strike_count_old:
                    distance = signal_string["storm_dist"]
                    text = "{} - LIGHTNING STRIKE {} mi away. Historical count is now {}.".format(datetime.datetime.now().strftime("%m/%d/%Y %H:%M:%S"), distance, strike_count_new)
                    if start > 0:
                        outputfile.write(text)
                        outputfile.write("\n")
                        outputfile.flush()
			subprocess.call(['echo "{}" | mail -s "LIGHTNING STRIKE" -a "From:Notification System <sendinguser@domain.com>" receipient@domain.com'.format(text)], shell=True)
                    else:
                        start = 1
                    strike_count_old = strike_count_new
               else:
                    #text = "No strike at time but data is {}.\n".format(signal_string)
                    #outputfile.write(text)
                    #outputfile.flush()
                    pass

except KeyboardInterrupt:
   sys.stdout.flush()
   outputfile.close()
   pass

I’ve left some of the testing lines in there as well which are commented out plus I skip over the first number of lines read to make sure the input gets settled. (I will explain more on the code at a later time). This code reads the json format the rtl_433 will output from “-F json”. I saved this in a file called lightning.py in /home/pi. You will pipe the output from rtl_433 via the -F json command. In my example, I am also running the http server so I can view live data in a web browser. This code will send an email for every strike with the calculated distance (presumed in miles) along with the current rolling strike counter. With this snippet, it only looks for a device named “Acurite-6045M”. It would need more specificity if used with multiple sensors (what I am experimenting with now).

$ rtl_433 -R 40 -F json -F http | /usr/bin/python /home/pi/lightning.py

To run this at startup, you can add an entry in /etc/rc.local (on Raspian). If you are using Ubuntu 20.04+, rc.local is not enabled by default. If you wish to use this approach see https://marsown.com/wordpress/how-to-enable-etc-rc-local-with-systemd-on-ubuntu-20-04/. To use rc.local to start the script on boot, add the rtl_433 line below:

#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

/usr/local/bin/rtl_433 -R 40 -F json -F http | /usr/bin/python /home/pi/lightning.py

exit 0

One final comment about the code. This will send ALL detected lightning strikes to email. Depending on your area, this could be a lot! I will eventually modify the code to compile the data, but again, this is proof of concept at this point. Besides adding diversity of sensors, my other planned addition is a commanded visual cue when lightning in the area.


To be continued…

Index: 10
PHP Code Snippets Powered By : XYZScripts.com