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日 |
#96 in 硬件支持
每月 121 次下载
在 samedec 中使用
305KB
4.5K SLoC
sameold: SAME/EAS 解调
为您的桌面或 RPi 提供空中的天气警报。
此包为 特定区域消息编码 (SAME) 提供数字解调器和解码器。它可以检测音频信号中是否存在 SAME 消息,并将它们报告给调用者。
免责声明
此包同时受 MIT 和 Apache 2.0 许可。请仔细阅读这些许可证,因为它们可能会影响您的权利。
此包未经过作为天气收音机接收器或任何其他用途的认证。作者 强烈反对 在任何安全关键应用中使用。始终至少有两种接收天气警报的方法。
示例
完整的示例可以在我们的 samedec
包中找到,该包提供通过管道解码 SAME 的命令行程序。
解调和解码
您首先需要从广播 SAME 信号电台恢复 基带音频。获取您通常会听到的音频信号。您可以使用以下任一方法:
- 收音机、扫描仪或其他接收器的音频“线路输出”插孔;或者
- 软件定义的无线电
在任一情况下,获取音频超出了此包的范围。为了采样您的声卡,请尝试 cpal。如果您有立体声信号,首先将其混合为单声道。如果您正在解调宽带 FM,并且您的解调器提供了选择,请选择仅单声道解调。
use sameold::{Message, SameReceiverBuilder};
// Create a SameReceiver with your audio sampling rate
// Sound cards typically run at 44100 Hz or 48000 Hz. Use
// an input rate of at least 8000 Hz.
let mut rx = SameReceiverBuilder::new(48000)
.with_agc_bandwidth(0.05) // AGC bandwidth at symbol rate, < 1.0
.with_agc_gain_limits(1.0/(i16::MAX as f32), 1.0/200.0) // for i16
.with_squelch_power(0.10, 0.05) // squelch open/close power, 0.0 < power < 1.0
.with_preamble_max_errors(2) // bit error limit when detecting sync sequence
.build();
// let audiosrc be an iterator which outputs audio samples,
// such as a BufReader bound to stdin or a file, in f32
// format at the sampling rate (here 48000 Hz)
let audiosrc = some_audio_source_iterator();
for msg in rx.iter_messages(audiosrc) {
match msg {
Message::StartOfMessage(hdr) => {
println!("begin SAME voice message: {}", hdr);
}
Message::EndOfMessage => {
println!("end SAME voice message");
}
}
}
通过 构建器 创建数字接收器。
SameReceiver
通过迭代器绑定到任何 f32
PCM 单声道(1通道)音频样本的来源。如果您使用的是 i16
样本(如大多数声卡所做的那样),则需要将它们转换为 f32
。只要您正确配置AGC,就不需要缩放,如上所述。
iter_messages()
迭代器消耗尽可能多的样本,直到解码下一个 Message
。
调制解调器行为
脉冲数 | 解码策略 |
---|---|
1 | 快速EOM / NNNN 仅 |
2 | 错误检测(相等检查) |
3 | 错误校正(比特投票) |
SAME消息始终以单独的“脉冲”形式传输三次,以提高冗余。在解码消息 标题(ZCZC
)时,samedec
将使用所有三个脉冲,以改进解码——如果可能的话。
如果错过一次重传,samedec
将自动回退到只使用两个脉冲进行解码。解码器对所有接收到的标题施加约 1.311秒 的延迟。这种延迟通常不会造成问题,因为大多数SAME消息都带有非信息性的警报音,作为前缀。
消息 尾部 不受标题相同的错误校正过程和延迟的影响。消息结束指示符(NNNN
)将在接收到并解码后立即打印。
调制解调器包含重复抑制逻辑。在彼此之间大约 10.86秒 的窗口内到达的相同消息将被抑制并不会发出。
调制解调器分为两部分
-
“链路层”,将模拟波形转换为帧化的
Burst
; -
以及“传输层”,将单个
Bursts
组装成Messages
。
可以使用 iter_events()
方法捕获来自这两层的所有事件,而不是 iter_messages()
。事件迭代器可以用来获取原始的帧化 脉冲,而不会延迟或进行错误校正。事件还可以在消息解码之前和期间报告检测到SAME载波信号。
解释消息
Message
类型标志着SAME消息的开始或结束。SAME消息的“实际消息”部分是音频本身,它应该包含描述事件并给出听众指示的语音消息。
- 描述事件;
- 并为听众提供指示。
这个crate解码数字标题和尾部,它们总结了消息。一个示例标题,以ASCII格式接收“off the wire”,如下所示
ZCZC-WXR-RWT-012345-567890-888990+0015-0321115-KLOX/NWS-
如果这是接收到的标题字符串,那么您可以像以下示例那样解码前面的 hdr
use sameold::{Phenomenon, Originator, SignificanceLevel};
// what organization originated the message?
assert_eq!(Originator::NationalWeatherService, hdr.originator());
// parse SAME event code `RWT`
let evt = hdr.event();
// the Phenomenon describes what is occurring
assert_eq!(Phenomenon::RequiredWeeklyTest, evt.phenomenon());
// the SignificanceLevel indicates the overall severity and/or
// how intrusive or noisy the alert should be
assert_eq!(SignificanceLevel::Test, evt.significance());
assert!(SignificanceLevel::Test < SignificanceLevel::Warning);
// Display to the user
assert_eq!("Required Weekly Test", &format!("{}", evt));
// location codes are accessed by iterator
let first_location = hdr.location_str_iter().next();
assert_eq!(Some("012345"), first_location);
相同的消息总是传输三次以提高冗余。在解码消息头时,sameold
将使用所有三次传输来提高解码。对于所有三个头部传输,只输出一个 Message::StartOfMessage
。标记消息结束的尾迹 不 受此错误纠正过程的影响。对于每个接收到的尾迹,输出一个 Message::EndOfMessage
。对于每个完整的 SAME 消息,可能有最多三个 EndOfMessage
输出。
背景
SAME 通常用于在美国和加拿大分发天气警报。最初是为与携带模拟音频信号的广播电台一起使用而开发的,例如
- NOAA 天气电台
- 商业 FM 广播电台
- 商业电视广播和有线电视网络
这些电台参与一个称为紧急警报系统的紧急警报网络,该系统向公众传播警报。
SAME 消息作为纯音频消息替换电台的正常节目传输。SAME 消息包括一个数字头,将其与电台的正常节目区分开来。数字头也以带内方式发送——使用模拟调制来保留它。SAME 头部使用双极性频率键控 (FSK) 调制,并以 520.83 Hz 的波特率发送。
箱子功能
chrono
:使用 chrono 计算消息 发行时间 和其他字段作为真正的 UTC 时间戳。如果启用,chrono
成为此箱子的公共 API 的一部分。
MSRV 政策
最小支持的 Rust 版本 (MSRV) 的增加将被视为小版本升级。
贡献
如果您有一份您认为应该解调但未解调的信号的 录音,请在新 github 问题上打开。要么附加或链接到您的录音。
在打开任何问题或 PR 之前,请阅读我们的 贡献指南。
许可:MIT OR Apache-2.0
依赖项
~7–14MB
~169K SLoC