9 个版本

0.4.0 2024年2月24日
0.3.0 2023年4月23日
0.2.5 2023年2月26日
0.2.3 2022年9月23日
0.1.0 2021年7月31日

#502硬件支持

Download history 1/week @ 2024-05-25 2/week @ 2024-06-01 23/week @ 2024-06-29 35/week @ 2024-07-27

57 每月下载量

MIT/Apache

350KB
5K SLoC

samedec: SAME/EAS 另一个解码器

为您的桌面或 RPi 提供空中天气警报。

这个二进制 crate 为特定区域消息编码(SAME)提供数字解调和解码程序。在大多数情况下,它可以作为 multimon-ng 的 EAS 模式的直接替换。

解调和解码功能作为 sameold 库 crate 单独发布。

背景

SAME 通常用于在美国和加拿大分发天气警报。它最初是为与携带模拟音频信号的广播电台一起使用而开发的,例如

这些电台参与一个称为紧急警报系统的紧急警报网络,该系统将警报传播给公众。

SAME 消息以音频消息的形式代替电台的正常节目传输。SAME 消息包括一个数字标题,用于将它们与电台的正常节目区分开来。数字标题也以带内方式发送——使用模拟调制来保留它。SAME 标题使用双极性移频键控(FSK)调制,以 520.83 Hz 的波特率发送。

免责声明

此 crate 以 MIT 和 Apache 2.0 许可证双重许可。请仔细阅读这些许可证,因为它们可能影响您的权利。

此 crate 未作为天气收音机接收器或其他任何目的进行认证。作者 强烈建议 不要将其用于任何安全关键的应用。始终至少使用两种方法接收天气警报。

入门

cargo install samedec

首先,您需要从广播SAME信号的无线电或电视台恢复基带音频。并非所有电台都传输SAME信号,也不是所有电台都一直在传输。

  • 在美国,NOAA气象无线电(NWR)电台可靠地传输SAME信号,用于像龙卷风和飓风这样的气象紧急情况。这些电台在公共安全VHF频段上运行,频率范围从162.400 MHz到162.550 MHz。

  • 在加拿大,Weatherradio Canada在相同的频段上提供类似的服务。

  • 一些美国广播电台为紧急警报系统(EAS)生成和/或重新传输SAME消息。要找到这些电台,您需要找到并阅读您州“紧急警报系统(EAS)计划”文件。EAS计划将列出本地主要和其他参与电台。广播电台没有义务转播每条消息,并且可以拒绝转播低严重性的消息。

NWR发射机不保证转播来自民事当局的消息,例如关于森林大火、火山活动或执法紧急情况的警告。您州的EAS计划文件可能指定NWR发射机是否会转播此类消息。

为了给samedec提供输入,获取您通常要听到的音频信号。您可以通过多种方式完成此操作

通过模拟音频

您可以使用硬件接收器的模拟音频“线路输出”,例如气象无线电、FM收音机或扫描仪。将“线路输出”端口连接到您的声卡的“线路输入”插孔。

您需要一种方法将音频从您的声卡传输到samedec。您可以在大多数平台上安装sox

rec -q -t raw -r 22.05k -e signed -b 16 -c 1 - | samedec --rate 22050

samedec以1通道(单声道)、有符号16位整数输入,格式为平台原生日照序。这相当于Rust的i16格式,有时在音频驱动程序中称为s16ne

您在samedec中设置的采样率--rate必须与您要传输的信号的采样率匹配。samedec的解调器将针对您请求的任何--rate进行设计,并且它可以与各种采样率一起工作。我们建议使用您声卡的本地采样率,这通常是44100 Hz或48000 Hz。

在Linux上,您可以使用pw-record(PipeWire)、parec(PulseAudio)或arecord(ALSA)获取管道音频。大多数桌面发行版都预装了其中之一。

pw-record --channels 1 --format s16 --rate 22050 -- - \
    | samedec -r 22050

通过软件定义无线电

使用任何兼容的SDR软件解调和恢复感兴趣电台的带通音频。您需要一种方法将带通音频传输到samedec

  • 一些程序,如rtl_fm,支持直接传输输出。

  • 一些程序,如gqrx,可以通过UDP输出音频。您可以使用netcatsocat获取UDP输入。

    nc -l -u 7355 | samedec -r 48000
    
  • 对于某些程序,您可能需要创建一个虚拟音频设备并将音频输出定向到该设备。PulseAudio可以通过module-null-sink“直接”完成此操作。

samedec不是FM解调器,也不能接受IQ样本。您需要解调带通音频信号并将其输入到samedec。

对于FM电台,您希望使用单声道解码(如果可用)和正确的去加重滤波器。

一般建议

无论输入方法如何,您都需要一个干净、噪声最小的音频输入。理想情况下,您应该有一个几乎“满静噪”的信号,没有噪声或静电。SAME缺乏现代的错误纠正技术,旨在在具有大量信噪比的链路上运行。如果您接收的电台听起来不好,看看是否可以找到一个更近的电台。

确保不要过载您的声卡或其他输入设备。检查您的声音控制面板或其他程序中的输入信号电平,以确保它们不会接近饱和。SAME数字头至少以80%的调制发送,它们可能比常规节目更响亮。

如果信号太弱,通常比使用声卡的大增益或音量级别命令更佳的是增加发送设备(即收音机)的音量。高音量级别可能会激活添加不需要噪声的放大器。您可能需要做一些实验以找到正确的音量级别。如果可用,请使用“线路输入”端口而不是麦克风或耳机端口。

始终测试您的解码设置!发送EAS消息的电台必须每周至少发送一条消息。如果在完整的一周内您没有收到至少一条消息,那么您的设置中可能存在问题。

控制台输出

从维基共享资源解码样本消息。运行

curl -C - -o Same.wav \
    https://upload.wikimedia.org/wikipedia/commons/2/25/Same.wav

sox 'Same.wav' -t raw -r 22.05k -e signed -b 16 -c 1 - | \
    samedec -r 22050

应产生以下输出

ZCZC-EAS-RWT-012057-012081-012101-012103-012115+0030-2780415-WTSP/TV-
NNNN

samedec收到SAME消息时,该消息将打印到标准输出。打印输出使用通过空中传输的SAME ASCII编码。

每行打印一条消息。只打印消息。

  • SAME 头部,指示消息的开始,前面加上ZCZC。会进行一些验证以确保头部格式正确,但它们可能仍然包含无效日期或未知事件代码。

  • SAME 尾部,指示消息的结束,输出为NNNN

dsame是一个Python解码器,可以从这种输出生成可读文本。该sameold包也了解如何解析消息字段。

调制解调器行为

突发次数 解码策略
1 快速EOM / 仅NNNN
2 错误检测(相等检查)
3 错误纠正(比特投票)

SAME消息总是以三个单独的“突发”形式重复发送,以提高冗余性。在解码消息头部ZCZC)时,如果可能的话,samedec将使用所有三个突发来提高解码。

如果错过了一次重传,samedec将自动回退到仅使用两个突发进行解码。解码器对所有接收到的头部施加了大约1.311秒的延迟。这种延迟通常不会引起问题,因为大多数SAME消息都带有不是信息性的警告警报音。

消息尾部不遵循与头部相同的错误纠正过程和延迟。消息结束指示符(NNNN)将在接收和解码后立即打印。

调制解调器包含重复抑制逻辑。在约10.86秒的窗口内到达的相同消息将被抑制并不会发射。

子进程

 | samedec -r 22050 -- play -q -t raw -r 22.05k -e signed -b 16 -c 1 -

samedec可以生成子进程来处理消息音频。

samedec的参数,在--之后,将被解释为为每个接收到的SAME消息启动的子进程。上面的第一个参数("play")被解释为可执行文件名。有关$PATH的查找和可执行位必须设置的常规规则适用于您的平台。其余参数将被原样传递给可执行文件,而samedec不会进一步解释。

每个接收到的SAME消息都会启动一个子进程。

子进程通过标准输入接收“透传”语音消息音频。提供给samedec的输入样本将以输入--rate的速度原样流式传输到子进程。语音消息结束时,子进程的标准输入将被关闭。进一步的进展将被阻塞,直到子进程终止。

上面的例子将在您的系统扬声器上播放通过sox的play命令接收到的任何SAME消息。

这有什么好处?

您可以使用子进程有选择地播放或存储SAME消息音频。您甚至可以压缩音频并发送电子邮件,但请注意:SAME消息可以长达两分钟。对于一些需要快速响应的紧急情况,两分钟的时间太长了。

子进程环境

子进程会收到以下额外的环境变量

  • SAMEDEC_RATE:解码器运行的采样率,以Hz为单位的整数:22050。对于传递到音频输出或编码程序非常有用。

  • SAMEDEC_MSG:完整的SAME头:"ZCZC-EAS-RWT-012057-012081+0030-2780415-WTSP/TV-"

  • SAMEDEC_ORG:三个字符的SAME发起者代码,如"EAS。"。

  • SAMEDEC_ORIGINATOR:人类可读的发起者字符串,如"EAS Participant"。

  • SAMEDEC_EVT:三个字符的SAME事件代码,如"RWT"。

  • SAMEDEC_EVENT:人类可读的事件描述,包括其重要性级别:"Required Weekly Test"。如果事件代码未知,并且其重要性级别也未知,则此字符串将为"Unrecognized Warning"。

  • SAMEDEC_SIGNIFICANCE:一个字符的重要性级别。如果无法确定重要性级别(即,因为事件代码未知),则此变量将为空。

       
    "T" 测试
    "S" 声明
    "E" 紧急情况
    "A" 留意
    "W" 警告
    "" 未知
  • SAMEDEC_SIG_NUM:重要性级别,以严重程度递增的整数表示。

       
    "0" 测试
    "1" 声明
    "2" 紧急情况
    "3" 留意
    "4" 警告
    "5" 未知
  • SAMEDEC_LOCATIONS:以空格分隔的FIPS位置代码列表,长度为六个字符。例如:"012057 012081"。

  • SAMEDEC_ISSUETIME:消息发布时间,作为UTC UNIX时间戳,如果可以计算的话。例如:“1424301369”,可以解释为“Wed, 18 Feb 2015 23:16:09 GMT”。

    • 如果无法计算发布时间,则此变量将为空!
    • 由于消息中没有完整的发布时间,samedec程序假设消息大约是“现在”收到的,其中“现在”由您的系统的实时时钟确定。
    • 历史消息的重放不保证产生相同的价值。
  • SAMEDEC_PURGETIME:消息清除时间,作为UTC UNIX时间戳,如果可以计算的话。与上面的SAMEDEC_ISSUETIME相同。记住:清除时间是消息的过期时间,而不是危害的预期持续时间。

  • SAMEDEC_IS_NATIONAL:如果消息包含公认的国家级事件和位置代码,则设置为“Y”。消息可以是测试或实际紧急情况。强烈建议客户端始终播放国家级消息,并且永远不要提供禁用它们的选项。对于非国家级消息,此变量设置为空字符串。

子进程的设计要求

samedec通过阻塞调用,同步地向子进程提供输入样本。由samedec生成的子进程必须具有以下行为

  1. 子进程必须读取关闭它们的标准输入。未能这样做将暂时阻止samedec前进,直到子进程退出。

  2. 从标准输入读取的子进程必须在达到文件末尾时及时退出。未能这样做将暂时阻止samedec前进,直到子进程退出。

子进程应避免启动长时间运行的前台作业,这些作业可能会长时间阻塞。以下部分提供了使用bash脚本的示例。您可以为子进程使用任何语言。

发送到子进程的音频可能包含一个或多个跟在语音消息后面的SAME尾迹(NNNN)。为了最小化延迟,samedec不会尝试移除这些。

示例:忽略输入

#!/bin/bash

# close standard input to ignore it
exec 0>/dev/null

echo "I got a ${SAMEDEC_EVENT}!"

在这里,我们关闭标准输入以避免阻塞samedec。您的脚本文件必须设置执行位(chmod +x …)。

示例:条件播放

#!/bin/bash

[[ -n "${SAMEDEC_IS_NATIONAL}" || "${SAMEDEC_SIG_NUM}" -ge 4 ]] || exit 0

exec play -q -t raw --rate "${SAMEDEC_RATE}" -e signed -b 16 -c 1 - "$@"

上面的脚本将使用sox播放以下任何消息

  1. 是国家级激活;或者
  2. 具有至少警告级别的意义

我们使用execplay替换正在运行的shell。 --rate "${SAMEDEC_RATE}"告诉sox采样率是多少。"$@"是bash的一个特性,它将脚本的其他输入参数传递给sox作为参数。

如果您将此脚本命名为./play_on_warn.sh,则samedec的一个示例调用是

sox 'Same.wav' -t raw -r 22.05k -e signed -b 16 -c 1 - | \
  samedec -r 22050 -- ./play_on_warn.sh

示例:压缩并保存

#!/bin/bash

outfile="$(date +%s)_${SAMEDEC_ORG}_${SAMEDEC_EVT}_${SAMEDEC_SIGNIFICANCE}_${SAMEDEC_ISSUETIME}.ogg"

exec sox -q -t raw -r "${SAMEDEC_RATE}" -e signed -b 16 -c 1 - \
  -t ogg -C-1 "$outfile"

示例调用,假设脚本命名为./save.sh

sox 'Same.wav' -t raw -r 22.05k -e signed -b 16 -c 1 - | \
  samedec -r 22050 -- ./save.sh

演示模式

使用samedec--demo选项来模拟接收事件代码为"DMO"的SAME标题。信息将被打印到控制台,并且(如果有)将启动子进程。子进程将在运行八秒后被终止,并显示SAME的"消息结束"。在演示结束时,samedec将退出。这种模式适用于测试子进程和其他事件处理程序。

在演示期间,输入到samedec的音频将通过子进程。运行演示模式仍需要一个音频源,但如果你愿意,可以从/dev/zero进行管道输入。

sameold库认为"DMO"事件代码的严重级别为警告(SAMEDEC_SIGNIFICANCE=W)。

调试和故障排除

此crate包括pretty_env_logger。您可以使用-v请求更详细的输出。使用最多三次-vvv来增加详细程度。日志消息将被打印到stderr。

如果您有一段您认为应该解调但未解调的信号的录音,请在github上创建一个新问题。您可以将录音附加或链接到问题中。

在提交任何问题或PR之前,请阅读我们的贡献指南

依赖项

~10–21MB
~305K SLoC