当前位置: 首页 > news >正文

绵竹深夜连震,iPhone 用户只能刷朋友圈?我写了一个开源地震预警系统

7 月 5 日晚,四川绵竹半小时内连发 3 次 4 级以上地震。当国产手机自动弹出预警时,iPhone 用户的第一反应往往是——一脸懵逼感受到地震后打开朋友圈刷刷看看“朋友圈预警”。


一、那个晚上,朋友圈比地震局还快

2026 年 7 月 5 日,深夜 23 点。

四川绵竹,第一次地震来了——4.5 级,震源深度 20 公里。

17 分钟后,第二次——4.0 级。

又过 10 分钟,第三次——还是 4.5 级。

半小时内连震三次,成都、乐山、内江、宜宾等多地震感明显。

有意思的是,地震发生后最先"播报"的不是电视,不是广播,而是朋友圈

“刚才摇了没?”
“我杯子里的水在晃!”
“又来了一次!”

而 iPhone 用户——手机安安静静,什么都没发生。直到打开朋友圈,才知道刚刚地震了。

这不是 iPhone 用户第一次感到无奈。事实上,华为、小米、OPPO、vivo 等国产手机早已内置地震预警功能,接入的是成都高新减灾研究所的地震预警网络。但 iPhone 因为系统封闭和一些已知原因、未接入中国地震预警网络,至今无法像国产手机那样自动弹出预警通知。

作为一个写了多年代码的人,我在想:能不能自己动手,做一个能跑的预警系统?

答案是:可以。


二、系统能做什么

一句话概括:实时监听中国地震台网数据,计算你所在城市的预计到达时间和影响程度,在破坏性地震波到达前通过手机推送通知你。

具体来说:

  • 📡数据源:通过 WebSocket 实时接收 wolfx.jp 转发的中国地震台网(CENC)数据,WebSocket 断线自动切换 HTTP 轮询兜底。

    关于 Wolfx.jp:这是一个基于 P2P 网络的全球地震监测数据聚合平台(可以理解为地震界的"广播站"),它从各国地震台网采集原始数据并以 WebSocket 实时转发,个人开发者无需自建台站即可获取高质量的地震波形和事件数据。

  • 🧮计算引擎:基于 IASPEI-91 全球一维地球速度模型,计算 P 波(纵波)和 S 波(横波/破坏性波)到你所在城市的精确到达时间
  • 📊烈度预估:基于 GB 18306-2015《中国地震动参数区划图》东部衰减模型 + 场地放大系数修正,估算你所在位置的本地烈度
  • 📱推送通知:通过 Bark 将预警推送到你的 iPhone/Android,通知包含震级、地点、距你多远、还有多少秒 S 波到达、建议行动
  • 🔊语音倒计时:打开详情页,系统会用中文语音播报倒计时,根据地震强度自动匹配三种模式

三种语音模式

地震强度影响等级播报方式示例
几乎无感0-1纯数字报数“10……9……8……7……”
有感地震2-3数字 + 一声"滴"“1098……”
破坏性地震4-5数字 + 两声"滴滴"“10滴滴9滴滴8滴滴……”

这个设计的逻辑是:强度越大,警报声越急促,大脑对"滴滴"次数的感知比看数字更快。

关于误报和深夜骚扰的考量:为了避免普通的无感地震频繁触发语音吵醒用户,系统对本地烈度 1-2 级(几乎无感)的地震仅在通知栏静默提示,不会触发语音倒计时。只有本地烈度达到 4 级以上(破坏性地震)时,才会激活最高优先级的"滴滴"急促警报。这个阈值可以通过RuntimeConfigService中的voiceWarningThreshold自由调整——身处地震带上、对震动敏感的用户可以设得更低一些。


三、技术架构

Wolfx CENC WebSocket → 实时地震数据 ↓ [走时计算] IASPEI-91 射线追踪 → P波/S波到达时间 [烈度计算] GB 18306-2015 衰减模型 → 基岩烈度 [场地修正] 场地放大系数 → 本地影响烈度 ↓ [影响分级] 0 无感 → 5 毁灭性 ↓ [推送决策] 震级≥阈值 && 影响等级≥阈值 ↓ [Bark 推送] → 📱 iOS/Android 实时通知 [Web 详情页] → 语音倒计时 + 波到达可视化

技术栈

技术版本用途
Java17运行时
Spring Boot3.3.5后端框架
Java-WebSocket1.5.7实时数据接收
OkHttp4.12.0HTTP 代理客户端
SpringDoc OpenAPI2.6.0API 文档
HTML/CSS/JS-原生前端,零框架依赖

前端没有用任何框架(Vue/React),纯原生 HTML + CSS + JavaScript。原因很简单——地震预警页面的第一要务是速度,任何 JS 框架的加载时间都可能是致命的。


四、核心计算模型

这是这个系统最有技术含量的部分。

4.1 P 波 / S 波走时计算

地震发生时产生两种体波:

  • P 波(纵波):速度快、破坏力小,先到达
  • S 波(横波):速度慢、破坏力大,后到达

两者的到达时间差,就是我们能用来预警的黄金时间窗口

系统引入IASPEI-91 国际标准地球模型进行射线追踪。该模型将地球内部分层,每层有不同的 P 波速度(Vp)和 S 波速度(Vs),通过 Snell 定律计算射线路径和走时:

走时 = Σ ( 层厚 / 层速度 × cos(入射角) )

对于地壳范围内的地震(深度通常 10-30 km),系统简化处理为水平分层模型,根据震源深度和震中距查 IASPEI-91 走时表进行插值计算。

4.2 烈度衰减模型

系统基于GB 18306-2015 中国东部烈度衰减公式

I = a + b×M - c×log(R+R0) - d×R

其中:

  • I:基岩场地地震烈度
  • M:面波震级
  • R:震中距(km)
  • a, b, c, d, R0:经验常数(中国东部参数)

4.3 场地放大修正

同一震中距下,软土场地的震感会比基岩场地强烈得多。系统根据《建筑抗震设计规范》GB 50011-2010 的场地类别对基岩烈度进行修正:

  • I 类场地(基岩):放大系数 1.0(不放大)
  • II 类场地(中硬土):放大系数 1.1
  • III 类场地(中软土):放大系数 1.25
  • IV 类场地(软弱土):放大系数 1.4

五、WebSocket 双通道容灾设计

系统最棘手的问题不是计算,而是数据链路的可靠性

数据源 wolfx.jp 的 WebSocket 在境外服务器,国内直连不稳定。系统做了三层容灾:

优先级 1: WebSocket 直连(低延迟,实时推送) ↓ 断线 优先级 2: WebSocket + SOCKS5 代理(墙内可达) ↓ 断线 优先级 3: HTTP 轮询(最可靠,每 5 秒请求一次)

每层自动降级、自动恢复,确保数据不丢失。控制面板实时显示当前连接方式和状态。

HTTP 轮询时的"数据去重"问题

HTTP 轮询拿到的数据是时间窗口列表,可能和上一轮有重叠。系统通过ConcurrentHashMap<String, EarthquakeRecord>配合事件 ID 去重,保证同一次地震不会重复触发预警。


六、移动端语音倒计时的踩坑之路

语音倒计时是整个项目中踩坑最多的功能,这里分享几个典型问题。

坑 1:浏览器自动播放策略

Chrome、Safari、Edge 都严禁在没有用户手势的情况下播放音频。AudioContext默认状态是suspendedspeechSynthesis.speak()会被直接拦截。

解决方案:添加全屏透明遮罩,用户轻触屏幕任意位置即可解锁音频。移动端用户打开页面的自然行为(点击查看)恰好触发了解锁。这是目前 Web 标准下能做到的最接近"自动播放"的方案。

坑 2:事件双重触发

按钮的 HTML 模板中同时写了onclick内联属性和addEventListener,点击一次触发两个回调。结果:第一个回调解锁音频 → 第二个回调立刻把音频重新静音。

教训永远不要在同一个元素上同时使用 onclick 和 addEventListener。

坑 3:setInterval 的首次延迟

// ❌ 错误写法:第一次执行在 1 秒后setInterval(countdownTick,1000);// ✅ 正确写法:先立即执行,再启动定时器countdownTick();setInterval(countdownTick,1000);

setInterval的第一个回调在delay毫秒后才触发。如果倒计时从 10 开始,用户看到的第一个数字是 10,但要等 1 秒才变 9,造成"停顿感"且整体延迟 1 秒。


七、Web 控制台展示

系统自带一个完整的 Web 管理控制台(原生 HTML,零依赖):

  • 📡 实时连接状态(绿色 WebSocket / 蓝色 HTTP 轮询)
  • ⚙️ 全量运行时配置(无需重启,即时生效)
  • 📍 监测城市管理(添加/删除/编辑,支持场地类别配置)
  • 📱 Bark 设备管理(多设备同时推送)
  • 🧪 模拟测试(输入虚拟震中,预览所有城市的预警结果)
  • 📊 Swagger UI(完整 REST API 文档)

八、开源 & 部署

项目已开源在 GitHub,采用 MIT 协议:

🔗GitHub 仓库:跳转链接

快速启动

# 1. 克隆仓库gitclone<your-repo-url>cdearthquake-warning# 2. 配置监测城市和 Bark Device Key# 编辑 application.yml 和 RuntimeConfigService.java# 详见 README → 部署前必读# 3. 构建 & 运行java-jartarget/earthquake-warning-5.6.0.jar# 4. 打开控制台# http://localhost:5050

⚠️ 部署前必读

代码中的以下内容已脱敏,需要替换为你自己的值:

  1. Bark Device KeyRuntimeConfigService.java第 161 行)— 在 iOS/Android 安装 Bark App 即可获取
  2. 详情页跳转地址application.yml)— 填你的服务器 IP 或域名
  3. SOCKS5 代理(按需)— 如果 wolfx.jp 被你的服务器屏蔽
  4. 推送图标 URL(可选)

详细配置说明见 README 中的「⚠️ 部署前必读:脱敏内容配置」章节。

💡 不想折腾服务器?

坦白说,这个项目需要一台能跑 Java 的服务器,对非技术用户有一定门槛。如果你只是想体验预警功能——可以关注评论区或 GitHub Issues,后续整一个公益服务器供大家使用。


九、写在最后

这个项目从想法到 v5.6.0 大约是七天的工作量,其中写代码大概占 40%,剩下 60% 全在踩坑——Maven 构建兼容性、SSH 部署、浏览器自动播放策略、事件双重触发、setInterval 时序问题……

但最终它跑起来了,而且真的能在地震发生后几秒内计算出你所在城市的预警信息

当然,这只是一个个人项目,它无法替代专业的应急广播,但希望能成为你手机里最后一道防线。精度无法和成都高新减灾研究所的专业系统相比。但它的意义在于:

  1. 证明了个人开发者也可以搭建一套可用的地震预警系统
  2. 所有计算过程和代码完全透明,没有任何黑箱
  3. 开源免费,任何人都可以部署、修改、改进

如果你也受够了 iPhone 在地震时的沉默,或者只是在技术上有兴趣,欢迎来 GitHub 看看源码,提 Issue。


📝 欢迎在评论区和 GitHub 交流。

🔗 GitHub 仓库:跳转链接

📖 完整踩坑记录:TROUBLESHOOTING.md

📋 更新日志:CHANGELOG.md

http://www.cnnetsun.cn/news/3213363.html

相关文章:

  • 采购智慧养老设备总踩坑?星梦云康轻量化方案提供参考
  • A股实时行情 API 接入教程:TickDB REST ticker、K线与 WebSocket 实测
  • 2026OpenClaw企业版品牌下载推荐 八款商用智能体分行业量化选型测评指南
  • PyTorch 2.0 线性回归实战:3步从数据加载到模型保存(附完整代码)
  • ZIP密码破解工具对比:ARCHPR vs fcrackzip vs ZipCracker 3款实战评测
  • TraceID 跨越异步任务:不要让消息队列切断调用链
  • 孩子书桌用什么灯好?盘点护眼效果好的护眼台灯,品质过硬!
  • 半导体超纯水系统 2026:3种主流配置方案与18.2 MΩ·cm水质保障
  • 2026工程物资管理软件哪个好?5款轻付费和免费的管理软件对比!
  • 智算中心冷板批量焊接的产能瓶颈:柔性换型怎么破?
  • 多版本Python共存以及环境变量配置
  • 翠湖逛累了别瞎跑!翠怡酒店旁藏着机关食堂开的便民小吃点
  • 报社登报多少钱?报社登报如何办理?办理须注意什么?
  • 全终端接入:OKCC呼叫中心五大接入方式的技术实现解析
  • 深化实验室数智化管理:广凌实验室一体化管理系统的创新实践
  • 太原装修最容易后悔的10个设计|花钱添堵!入住90%想拆掉
  • 银行流水识别工具怎么选?企业批量处理要看字段、结构和复核路径
  • MEMS倾角振动一体机 vs 独立传感器:工业监测系统集成度与边缘计算能力对比分析
  • Outlook、GMX、华为花瓣邮箱3款安全邮箱深度解析:隐私保护与反垃圾实战配置
  • 翻译够准 沟通够稳
  • 德国宣誓翻译件怎么弄?很简单!只需要这三步!
  • 2026儿童口腔健康:专业运营学习伙伴助您一臂之力
  • 力扣560. 和为 K 的子数组中,哈希表mp为什么要mp[0] = 1 ?
  • APK Editor Studio:当传统逆向工具无法满足时,如何构建跨平台的Android应用分析工作流
  • 2026日志分析工具选型参考:卓豪Log360产品能力介绍
  • 运营策划哪家好
  • 电池供电设备零功耗一键开关机方案:ECJ5056-50A8DE 应用笔记
  • 2026年度10款降AI率平台红黑榜!优缺点全透明,达标率硬核对标行业天花板
  • 市面上靠谱的AI伴学教育一对一企业哪家专业
  • HC32L136=HC32L126 硬件兼容