This is the fourth article in my Bark series. If you have read the first three, you already have Bark on your phone and a relay Worker that works. You do not need to set them up again. A push before a pass helped, but I still had to sit by the computer to know if I actually recorded it. So I made the computer tell me when the file was done: a small script watches the recording folder, and pushes to my phone when a recording is finished.
You need the relay from Article 2, and nothing else from the earlier articles. If that test push has not arrived yet, do Article 2 first, then come back here. After this one, Article 5 is the same idea on a repeater, and Article 7 is the general version with disk checks.
I spent some time putting these steps together, so you can follow them once, from start to finish, and end up with a result you are happy with: a recording, and a push that matches it. If this one still feels like a lot, do Article 3 first. That one is just a satellite pass reminder on your phone, no recording, no script on your computer, and it is much simpler to get going.
One honest thing before you start: I ran this myself only once, it worked, and then I shared the whole process here. I have not tested it for a long time. If a step does not work for you, that does not mean you did it wrong. Your program may be different, and your folder may be different.
Before you start: tools, and how to check each one
Do not start the steps until every check below passes. I write them in this order because each later step depends on an earlier tool.
- Bark on your iPhone, notifications allowed. Check: send yourself a test push, as in Article 2. You will test the relay again with the script test in Step 3 below. If that test does not arrive, fix Bark and the relay first. Nothing in this article can fix a broken relay.
- Your relay Worker address and its shared passphrase, written on paper. Check: you can read both back without opening Cloudflare. If you lost the passphrase, replace it on the relay Worker first, and write the new one down.
- A computer that records from your SDR, and must not enter sleep mode during the pass. Check: in its power settings, sleep mode is disabled, or the sleep delay is set long enough to cover a pass plus recording. A computer in sleep mode runs no script and sends no push.
- Python on that same computer. Check: open a terminal and run
python --versionon Windows, orpython3 --versionon Mac and Linux. If a version number comes back, you are done. On Windows, if typingpythonopens a store page instead of running anything, usepyinstead. If not, install Python from python.org first, and on Windows tick the box that adds Python to PATH. - Your SDR recording program, already working by hand. Check: record ten seconds by hand and find the file. That check is also Step 1 below, so do not skip it.
- A text editor and a terminal on the recording computer. You already have both. No other software is needed for this article: no Git, no Cloudflare command line tool, no SDR library, no extra Python package.
SDR recording programs do not share the same menus. One calls it Record, another calls it Capture, and the folder setting may sit under a different menu. That does not matter here. What matters is the same three things in every program: start recording, choose where the file goes, and know what file ending it writes. Find those three in your own program, and set them to your own situation.
If you do not know how to open a terminal yet, jump to the skills section below, then come back here. The checklist above will still be here.
Code repository
I keep the script in two places, so you have a second copy if one fails. The full script is pasted in this article, below. The same file also lives in my public code repository, in the folder sdr-scripts/, as 01-satellite-recording.py. Open that folder in the repository, open the file, press Raw, select all, and copy. If you copy from the repository, you still change only the same five lines at the top. Do not copy any secret from anywhere: the script contains only placeholders, and you fill in your own relay address and passphrase.
One thing not to copy into the script: your Bark key. That stays in the relay. The script only needs the relay address and the passphrase.
Before you start, three things to know
These three come up in every SDR article after this one, so I will write them out here.
How to open a terminal. On Windows, press the Start key, type Terminal, and open it. On Mac, press Command and Space together, type Terminal, and open it. On Linux, open Terminal from your applications menu. A terminal is a black window where you type commands and press Enter.
How to save a Python file correctly. Use a plain text editor, not Word. On Windows, use Notepad. On Mac, use TextEdit, then choose Format, then Make Plain Text, before you save. Save the file with a name ending in .py, for example sat-record-watch.py. On Windows, turn on File name extensions in File Explorer first, then check the saved file is really sat-record-watch.py, not sat-record-watch.py.txt. If it ends in .txt, rename it and remove the .txt.
How to copy from the repository. On your computer browser, not on your phone, open the repository folder sdr-scripts/, open the file, press Raw at the top right, press Ctrl and A together to select all, press Ctrl and C together to copy, then paste into your text editor and save as above. If you see curly quotes in the pasted code, replace them with straight quotes. Python only accepts straight quotes.
How to install Python, if the version check fails. Open python.org in your browser, open Downloads, download the installer for your system, and run it. On Windows, tick the box that says Add Python to PATH, before you press Install. When it finishes, close the terminal, open a new terminal, and run the version check again. A version number must come back.
Step 1: Find where your recordings really go
Open your SDR recording program and record ten seconds of anything. Then find that file on disk. Write down the exact folder, and the file ending, for example .wav. Do not guess the folder from memory. Many programs save to a folder you did not choose.
Check point: you can point at one real recording file, in one folder, and read its name and size back to me. If you cannot, stop here and find it first.
If your program names the folder setting differently, use the setting that does the same thing in your program, and write down the folder you actually find.
Step 2: Copy the script
Save the code below as sat-record-watch.py, in a folder you will remember. Change only the five lines at the top, marked CONFIG. Replace the relay address with your own Worker address, and the passphrase with your own passphrase. Leave the rest alone.
import json
import os
import shutil
import sys
import time
import urllib.request
# CONFIG: change these five lines only.
RELAY_URL = "https://YOUR-WORKER.workers.dev/push"
RELAY_SECRET = "YOUR-PASSPHRASE"
WATCH_FOLDER = "C:/Recordings"
FILE_ENDING = ".wav"
STABLE_SECONDS = 60
# Pushes are title-only: on my phone, a push with a body is not
# spoken aloud, so everything goes into the title and there is no body.
def send_push(title):
data = json.dumps({"title": title, "group": "sdr-record"}).encode()
req = urllib.request.Request(RELAY_URL, data=data, method="POST")
req.add_header("Content-Type", "application/json")
req.add_header("X-Relay-Secret", RELAY_SECRET)
with urllib.request.urlopen(req, timeout=20) as resp:
print(resp.read().decode())
def main():
if len(sys.argv) > 1 and sys.argv[1] == "test":
send_push("Test push, relay path works")
return
seen = {}
while True:
for name in os.listdir(WATCH_FOLDER):
if not name.lower().endswith(FILE_ENDING):
continue
path = os.path.join(WATCH_FOLDER, name)
size = os.path.getsize(path)
if name not in seen:
seen[name] = (size, time.time())
elif seen[name][0] == size and time.time() - seen[name][1] >= STABLE_SECONDS:
free_gb = shutil.disk_usage(WATCH_FOLDER).free / 1024 / 1024 / 1024
send_push("Recording finished, %s, %.1f MB, %.1f GB free" % (name, size / 1024 / 1024, free_gb))
del seen[name]
else:
seen[name] = (size, time.time())
time.sleep(30)
if __name__ == "__main__":
main()
Check point: the file opens in a text editor, and the top five lines show your own relay address, your own passphrase, and your real recording folder. The relay address must end with /push, with no slash after it. For the folder path, use forward slashes even on Windows, for example C:/Recordings, not backslashes, because a backslash in a Python string can eat the next letter. Nothing else in the file needs your personal information.
Step 3: Test the push before a real pass
Open a terminal in the script folder and run:
python sat-record-watch.py test
Or python3 sat-record-watch.py test on Mac and Linux. On Windows, if typing python opens a store page instead of running anything, use py sat-record-watch.py test instead. Your phone should receive a test push within seconds, titled “Test push, relay path works”.
Check point: if the test push does not arrive, do not go on to a real pass. Check the relay address first, then the passphrase, then whether the computer can reach the internet. A test that fails now will also fail during a pass.
Worked example: ISS, 437.800 MHz, FM, step by step
Read this example first, then do Step 4 below with your own values. The example values are filled in, so you can see exactly what each line should look like.
This is a concrete example, not a placeholder. Follow it once, with your own relay lines, and you will know how to fill every parameter for any other satellite afterwards.
Example scenario: I record one ISS FM pass. Downlink 437.800 MHz, mode FM. My recording program saves to C:/Recordings, with files ending in .wav. I want a push when the recording file stops growing.
Step 1, fill the CONFIG lines like this, line by line. Only the first two lines are yours. The other three lines are the example.
RELAY_URL = "https://YOUR-WORKER.workers.dev/push"
RELAY_SECRET = "YOUR-PASSPHRASE"
WATCH_FOLDER = "C:/Recordings"
FILE_ENDING = ".wav"
STABLE_SECONDS = 60
Step 2, before the pass, set your SDR program to 437.800 MHz, mode FM, and arm the recorder. Check the status first, as in Article 3: if the ISS repeater is off for that pass, your recording will be silent, and the finished push will still arrive with a small file. That is a status check, not a script failure.
Step 3, start the script without the word test, and leave the terminal open. Record the pass as normal. Suppose the program saves a file named ISS-1030.wav. While it records, the file size grows. When the pass ends and the file stops growing for 60 seconds, allow up to two minutes in total, and your phone should receive a push that would read, in this example:
Recording finished, ISS-1030.wav, 45.2 MB, 120.3 GB free
The numbers 45.2 MB and 120.3 GB are example numbers only, to show the format. Your real push will show your real file size and your real free space. If the file name matches but the size is near zero, the pass was silent or the recorder was not armed in time. That check is in Step 1 of the main steps.
Step 4, for your next satellite, change only the satellite and the frequency in your SDR program. The script CONFIG stays the same, unless your recording folder or file ending changes. That is the whole point of the example: once you have filled it once, the next satellite is only a frequency change, not a new setup.
Step 4: Run the script, then record a pass
Start the script without the word test, and leave the terminal open. The script runs in the foreground, so closing the terminal stops it, and a reboot also stops it. For automatic restart after a reboot, see Article 7, Step 4. Then record a satellite pass as you normally do, for example an FM satellite downlink you already know. The script checks every 30 seconds, and waits 60 seconds of stable size, so allow up to two minutes after the recording stops growing before you conclude it failed. Then it pushes one title, “Recording finished” plus the file name, its size, and the free disk space, and no body. If your program writes in large chunks with long gaps, increase STABLE_SECONDS to 180 before a real pass.
Check point: after the pass, you have two things: the recording file on the computer, and a push on your phone with the same file name. If the file is there but no push came, read the terminal output. It shows each push attempt, or the error that stopped it.
Step 5: The push has no body
The push has no body at all. The title is the whole push: “Recording finished” plus the file name, its size, and the free disk space. I first put the details in the body, and then found that on my phone a push with a body is not spoken aloud, so now everything goes into the title.
When it does not push
Fix one thing at a time, then try again.
- Did the test push arrive? If not, the relay address or passphrase is wrong, or the computer has no internet. Fix that first.
- Is the script still running in an open terminal? If the terminal is closed, the script stopped. Start it again.
- Is the folder in CONFIG the real recording folder? Open that folder and look for a real file. If it is empty, the folder is wrong.
- Did you wait long enough? This script checks every 30 seconds and waits 60 seconds of stable size, so allow up to two minutes after the recording stops growing.
- Is the file name really ending in
.py, and does the code use straight quotes? If not, fix the file name and the quotes, then run the test again.
If a step still fails after the checks above, copy this whole article into an AI tool and let it read the article first. Then tell it your SDR program, your real recording folder and file ending, and the error you saw. Ask it to check your local variables against the article, and to adjust for your program. Do not paste your relay passphrase or your Bark key into any AI tool. Copy the article as published, with placeholders, not your filled-in script.
Appendix: three things that really stop people
- The recorder was never armed. If no file appears in the folder, no script can push. Arm the recorder before the pass, and check the folder after a short test recording, not after a real pass you cannot repeat.
- The disk fills during the pass. Check free space before the pass. The finished push reports free space, but that report comes too late if the recording already stopped early.
- The script watches the wrong folder. If your program saves to a different folder, the script sees nothing, forever. Step 1 exists for this reason: find one real file first, then point the script at that exact folder.
More in this series: iPhone Low-Power Instant Ham Radio Reminders; One App, Two Websites: Instant Ham Radio Reminders; Satellite Pass Reminders by Hand: Start at 30 Degrees; Bark + SDR: Get Pushed Only When the Repeater Talks; Bark + SDR: A Push When the Band Opens to You; Bark + SDR: Know When Recording Finishes or Fails.
这是我的 Bark 系列第 4 篇。如果你已经读过前三篇,你的手机上已经有 Bark,转发器也已经配置完成并通过测试,不用再搭一次。过顶前的提醒有用,但我还是得在电脑旁等待,才知道到底录下来没有。所以我让电脑自己告诉我:录音文件夹里文件一完,就向我的手机发送一条推送。
你只需要第 2 篇里的转发器,其他前面的文章不用重做。测试推送还没到,就先去做第 2 篇,再回来。做完这篇,第 5 篇是中继版,第 7 篇是加了磁盘检查的通用版。
这几步我花了点时间整理,就是想让你一遍走通,从头到尾做下来,最后拿到自己满意的结果:一个录音,和一个对得上的推送。如果这篇你觉得还是复杂,先做第 3 篇,那篇只是卫星过顶的手机提醒,不用录音、不用在电脑上跑脚本,设置简单得多,也没有这么多复杂的步骤。
开始之前还有一句老实话:这篇我自己也只是跑了一遍,跑通了,才把整个过程分享出来,没有长时间测试过。如果哪一步在你那里跑不通,不一定是你做错了,可能是你的程序不一样,文件夹也不一样。
开始前:工具准备,和每一件工具的检查
下面每一项检查都通过了,再开始后面的步骤。我按这个顺序写,是因为后面的每一步都依赖前面的工具。
- iPhone 上的 Bark,通知要允许。检查:用你已有的转发器给自己发一条测试推送。测试推送未送达,就先修复 Bark 和转发器,这篇里的方法无法修复一个已损坏的转发器。
- 你的转发器地址和共享口令,写在纸上。检查:不用打开 Cloudflare,你就能把这两样读出来。口令丢了,就先在转发器后台换一个新的,再写下来。
- 一台录 SDR 的电脑,过顶期间不得进入休眠状态。检查:在电源设置中禁用休眠功能,或将休眠延迟设为足以覆盖一次过顶加录音的时长。电脑进入休眠状态后,脚本将停止运行,推送也不会发送。
- 同一台电脑上的 Python。检查:打开终端,Windows 运行
python --version,Mac 和 Linux 运行python3 --version。有版本号回来就算有了。Windows 上如果输入python后打开的是应用商店页面而非执行程序,改用py。没有,就先去 python.org 装一个,Windows 装的时候勾上把 Python 加到 PATH 那一项。 - 你的 SDR 录音程序,已经能手动录制。检查:手动录制十秒并找到文件。这个检查也就是下面第 1 步,不要跳过。
- 录音电脑上的文本编辑器和终端。你本来就有这两样。这篇不需要其他软件:不用 Git,不用 Cloudflare 命令行工具,不用 SDR 库,不用任何额外的 Python 包。
录音程序的菜单各不相同,有的叫录音,有的叫捕获,存文件夹的设置也不在同一个菜单里。这不影响这篇的做法。要做的事情在每个程序里都是同一件:开始录音、选好文件存哪里、知道它写什么后缀。在你自己的程序里找到这三样,按你自己的情况设好就行。
如果还不知道怎么打开终端,先跳到下面技能那节,做完再回来,上面的清单还在。
代码仓库
脚本我放在两个地方,万一一个地方出问题,你还有另一个。完整脚本贴在这篇文章下面。同一份文件也放在我的公开代码仓库里,文件夹是 sdr-scripts/,文件名是 01-satellite-recording.py。打开仓库里那个文件夹,打开文件,按 Raw,全选,复制。就算从仓库复制,也只改上面同样的五行。不要从任何地方复制秘密:脚本里只有占位符,转发器地址和口令都填你自己的。
有一项内容不要抄进脚本:你的 Bark 密钥。它留在转发器里就行。脚本只要转发器地址和口令。
开始前先会这三样
这三样在后面的 SDR 篇里都会用到,我在这里写一次。
怎么打开终端。Windows:按开始键,输入 Terminal,打开它。Mac:同时按 Command 和空格,输入 Terminal,打开它。Linux:从应用菜单里打开 Terminal。终端就是一个黑窗口,你在里面输入命令、按回车。
怎么正确保存一个 Python 文件。用纯文本编辑器,不要用 Word。Windows 用记事本。Mac 用文本编辑,保存前先选格式,再选制作纯文本。文件名要以 .py 结尾,比如 sat-record-watch.py。Windows 上先在文件资源管理器里打开“文件扩展名”显示,再确认存下来的文件真的是 sat-record-watch.py,不是 sat-record-watch.py.txt。如果是 .txt,改名把 .txt 去掉。
怎么从仓库复制。在电脑浏览器上,不要在手机上,打开仓库里的 sdr-scripts/ 文件夹,打开文件,按右上角的 Raw,同时按 Ctrl 和 A 全选,同时按 Ctrl 和 C 复制,再粘贴到文本编辑器里,按上面办法保存。如果粘贴出来的代码里有弯引号,换成直引号。Python 只认直引号。
Python 没装上怎么办。浏览器打开 python.org,打开 Downloads,下载你那个系统的安装程序,运行它。Windows 上按安装之前,先勾上把 Python 加到 PATH 那一项。装完后关闭终端,再开一个新终端,重新运行版本检查,必须有版本号回来。
第 1 步:先找到录音真正存到哪里
打开你的 SDR 录音程序,随便录十秒。然后在磁盘上找到那个文件。把准确的文件夹和文件后缀写下来,比如 .wav。不要凭记忆猜文件夹,很多程序存的地方都不是你以为的那个。
核对点:你能指着一个真实的录音文件,说出它在哪个文件夹、叫什么、多大。说不出来就先停在这里,先找到它。
如果你的程序里存文件夹的设置名字不同,就用你程序里做同一件事的那一项,记下你实际找到的文件夹。
第 2 步:复制脚本
把下面的代码存成 sat-record-watch.py,放在一个你记得住的文件夹里。只改上面标着 CONFIG 的五行:把转发器地址换成你自己的 Worker 地址,口令换成你自己的口令。其余不要动。
代码见上面英文部分的同一段,配置说明相同。
核对点:文件能在文本编辑器里打开,上面五行是你自己的转发器地址、你自己的口令、你真实的录音文件夹。转发器地址必须以 /push 结尾,后面不要再加斜杠。文件夹路径哪怕在 Windows 上也要用正斜杠写,比如 C:/Recordings,不要用反斜杠,因为 Python 字符串里的反斜杠会吃掉下一个字母。文件里其他地方不需要你的个人信息。
第 3 步:真过顶之前先测推送
在脚本所在文件夹打开终端,运行:
python sat-record-watch.py test
Mac 和 Linux 用 python3 sat-record-watch.py test。Windows 上如果输入 python 后打开的是应用商店页面而非执行程序,就改用 py sat-record-watch.py test。几秒内你的手机应该收到一条标题为 “Test push, relay path works” 的测试推送。
核对点:如果测试推送未送达,不要去做真过顶。先查转发器地址,再查口令,再查这台电脑能不能上网。现在测不通,过顶时也一样不通。
具体实例:ISS,437.800 MHz,FM,一步一步
先读这个实例,再按下面第 4 步用你自己的值做一遍。实例里的值都已填好,你能看到每一行该长什么样。
这是一个具体实例,不是占位符。照着它做一次,转发器那两行填你自己的,其他参数照着填,你就知道以后任何卫星该怎么填了。
实例情景:我录一次 ISS 的 FM 过顶。下行 437.800 MHz,模式 FM。我的录音程序存到 C:/Recordings,文件后缀是 .wav。我想在录音文件不再变大时收到推送。
第 1 步,一行一行填 CONFIG。只有前两行是你自己的,后三行是这个实例:
RELAY_URL = "https://YOUR-WORKER.workers.dev/push"
RELAY_SECRET = "YOUR-PASSPHRASE"
WATCH_FOLDER = "C:/Recordings"
FILE_ENDING = ".wav"
STABLE_SECONDS = 60
第 2 步,过顶前,把 SDR 程序调到 437.800 MHz,模式 FM,把录音开好。先按第 3 篇的办法查状态:如果这次过顶 ISS 中继没开,你录下来也是静默的,完成推送还是会来,但文件很小。这是一个状态检查,不是脚本坏了。
第 3 步,不带 test 启动脚本,终端保持开启,按平常办法录这次过顶。假设程序存了一个叫 ISS-1030.wav 的文件。录的时候文件在变大。过顶结束、文件 60 秒不再变大,总共最多等两分钟,你的手机应该收到一条推送,这个实例里会是这样:
Recording finished, ISS-1030.wav, 45.2 MB, 120.3 GB free
45.2 MB 和 120.3 GB 只是示例数字,用来看格式。你真实的推送会显示你真实的文件大小和真实剩余空间。如果文件名对上了、大小却接近零,说明这次过顶是静默的,或者录音没及时按下开始。这个检查在主步骤第 1 步里。
第 4 步,下一次换卫星,只换 SDR 程序里的卫星和频率。脚本 CONFIG 不用动,除非你的录音文件夹或者后缀变了。这就是这个实例的用意:填过一次,下一次只换频率,不用重新搭。
第 4 步:启动脚本,再去录一次过顶
不带 test 这个词启动脚本,让终端保持开启。脚本在前台运行,关闭终端后,脚本将停止运行,重启也会停。重启后自动运行的办法见第 7 篇第 4 步。然后按你平常的办法录一次卫星过顶,比如一条你已经熟悉的 FM 卫星下行。脚本每 30 秒检查一次,又要等 60 秒大小不变,所以录音停止变大之后,最多等两分钟再下结论说它失败了。之后它就发送一条只有标题的推送:“Recording finished”加上文件名、大小和剩余磁盘空间,没有正文。如果你的程序采用大批量写入、写入间隔较长,过顶前先把 STABLE_SECONDS 改成 180。
核对点:过顶之后你手里应该有两样东西:电脑上的录音文件,和手机上一条同名文件的推送。文件在、推送没来,就看终端输出,上面会显示每一次推送尝试,或者拦住它的报错。
第 5 步:推送没有正文
推送根本没有正文。标题就是整条推送:“Recording finished”加上文件名、大小、剩余空间。我原来把细节放正文里,后来发现有正文我这手机就不播报,所以现在全放标题里。
运行失败时,先这样排查
一次只改一处,改完再测一次。
- 测试推送到了吗?没到,就是转发器地址或者口令错了,或者电脑没联网。先修这个。
- 脚本是否仍在保持开启的终端中运行?终端关了,脚本将停止运行。重新启动它。
- CONFIG 里写的文件夹真的是录音文件夹吗?打开那个文件夹,看看有没有真实文件。空的,就是文件夹错了。
- 等够时间了吗?这个脚本每 30 秒检查一次,又要等 60 秒大小不变,所以录音停止变大之后,最多等两分钟再下结论。
- 文件名真的是以
.py结尾吗?代码里是直引号吗?不是就改文件名、改引号,再次运行测试。
如果按上面的顺序查了还是不行,把整篇文章复制给 AI 工具,先让它读完文章。再告诉它你的 SDR 程序、你真实的录音文件夹和文件后缀、你看到的报错,让它对照文章检查你的本地变量对不对,按你的程序做相应的调整。不要把转发器口令和 Bark 密钥粘给任何 AI 工具,复制的是发表出来的文章(带占位符的那版),不是你填好值的那份脚本。
附录:真正会卡住人的三条
- 录音根本没按下开始。文件夹里没有文件,什么脚本都推不出来。过顶前先把录音开好,先用一次短测试录音查文件夹,不要等到一次无法重来的真过顶才发现。
- 录到一半磁盘满了。过顶前先看剩余空间。完成推送里虽然报剩余空间,但录音已经提前断了的话,这条报告来得太晚。
- 脚本指向了错误的文件夹。程序存到别的文件夹,脚本将始终无法获取文件。第 1 步就是为这个设的:先找到一个真实文件,再把脚本指到那个准确的文件夹。
这个系列里还有:第 1 篇:为什么用 Bark 做提醒、第 2 篇:一个 App、两个网站、第 3 篇:卫星过顶提醒、第 5 篇:中继守听、第 6 篇:波段打开、第 7 篇:录音状态。