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

基于树莓派与OpenSky API的飞机预警灯:从地理计算到物联网实践

1. 项目概述与核心思路

作为一个常年在家办公、偶尔录点视频的创作者,最头疼的事情之一就是录到一半,窗外突然传来飞机引擎的轰鸣声,一段精心准备的内容可能就废了。相信很多住在航路附近或者对航空感兴趣的朋友都有类似的困扰——你听到声音时,飞机往往已经飞过去了。于是我就想,能不能做一个“预警”装置,在飞机真正飞临头顶前就给我提个醒?这个想法催生了这个基于树莓派和OpenSky API的飞机预警灯项目。

本质上,这是一个典型的物联网(IoT)应用,它巧妙地连接了虚拟的实时数据世界和真实的物理设备。核心逻辑并不复杂:获取你当前位置上空的飞机实时数据 -> 通过地理计算判断是否有飞机会经过你附近 -> 如果有,则点亮一个灯作为预警信号。听起来简单,但其中涉及了网络API调用、球面几何计算、数据库管理、硬件控制等多个环节,是一个综合性很强的练手项目。我选择用树莓派Zero作为主控,一是因为它足够小巧,可以轻松塞进一个精致的模型外壳里;二是其完整的Linux系统和GPIO引脚,既能跑复杂的后台脚本,又能直接驱动LED,是这类项目的绝佳平台。

整个项目可以拆解为三个主要部分:硬件制作软件开发数据逻辑处理。硬件部分,我设计并3D打印了一个仿真的跑道灯外壳,并尝试了树脂铸造来制作更逼真的透镜。软件部分,核心是一个运行在树莓派上的后台脚本,它周期性地从OpenSky Network获取数据,进行计算,并控制GPIO。数据逻辑则是整个项目的“大脑”,负责判断哪架飞机值得预警。下面,我就把这几个月折腾下来的经验、踩过的坑和最终可行的方案,毫无保留地分享出来。

2. 硬件设计与制作:从3D建模到实体灯

硬件部分的目标是制作一个既美观又能完整容纳所有电子元件的“跑道灯”外壳。我选择仿真跑道灯,一是觉得造型酷,二来它本身就是一个现成的“灯”,与项目功能完美契合。

2.1 3D建模与结构设计

我使用Fusion 360进行建模。设计时主要考虑了以下几点:

  1. 分体式结构:将模型分为底座、中部灯体和顶部透镜盖三部分。这样设计最大的好处是便于喷涂上色,无需进行复杂的遮盖。底座和中部灯体通过卡扣或螺丝固定,顶部透镜盖则用于固定树脂透镜。
  2. 内部布局:中部灯体内部需要预留树莓派Zero、LED灯珠(我用了高亮度的5mm蓝色LED)、限流电阻以及一个微型轻触开关(用于关机/开机)的空间。我在Fusion 360里重新利用了之前项目中画好的树莓派Zero固定架模型,节省了大量时间。强烈建议建立自己的常用元件模型库,比如各种型号的树莓派、Arduino、标准螺丝孔位等,这能极大提升后续项目的效率。
  3. 比例与细节:真实的跑道灯很大,所以我按比例缩小到适合放在书架或桌面的尺寸(最终成品高度约15cm)。添加了一些螺栓、散热鳍片等细节,让模型看起来更“工业风”,更接近真实设备。

注意:设计打印件时,务必考虑公差。尤其是需要互相配合的卡扣或插槽部分,我通常会在Fusion 360中给配合面留出0.2mm-0.3mm的间隙,这样既能保证组合牢固,又不会因为打印误差导致无法安装。模型文件我上传到了Thingiverse,你可以在文末的链接中找到。

2.2 3D打印与后期处理

我使用的是Hatchbox的ABS线材。ABS强度好,耐温性也比PLA强,后期打磨处理也相对容易。

  • 打印设置:层高0.2mm,填充率20%。对于这种展示模型,不需要太高的填充,节省时间和材料。记得开启支撑,特别是灯体内部那些悬空的结构。
  • 打磨流程:这是让打印件脱胎换骨的关键一步。我的流程是:
    1. 粗打磨:使用60-80目的砂纸,去除明显的层纹和支撑残留。这一步要大胆,但注意别磨过头,破坏了形体。
    2. 中细打磨:换用120目、240目砂纸,进一步平滑表面。
    3. 精细打磨:使用400目、800目甚至1000目砂纸进行水磨(沾水打磨),这样可以获得非常光滑的表面,为喷漆打下完美基础。
  • 喷涂上色
    1. 补土:先喷一层水补土(模型用灰色补土)。这能统一底色,更重要的是能检查表面是否有瑕疵。喷完后如果发现还有小坑或层纹,可以用牙膏补土(膏状)填补,干透后再用细砂纸打磨平整。
    2. 底漆:再喷一层灰色底漆,增加面漆的附着力。
    3. 面漆:我参考了真实跑道灯的配色,主体用了福特信号黄,底座用了布鲁克兰兹绿。这些都是模型漆,发色和质感更好。螺栓等细节部分用田宫银色手涂点缀。
    4. 保护漆:全部完成后,喷一层消光或半光保护漆,保护漆面,同时统一光泽。

2.3 树脂透镜铸造的“踩坑”与成功

最初我想用透明PLA打印透镜,但透光性和质感都不理想,于是决定挑战树脂铸造。这个过程可谓一波三折。

第一次尝试(失败):我异想天开,想直接用3D打印的PETG材料作为模具来浇注树脂。心想多涂点脱模剂应该没问题。结果树脂像胶水一样死死粘在PETG模具上,完全分不开,宣告失败。教训:除非使用专用的模具树脂或对打印件进行特殊的模具处理(如喷涂模具胶衣),否则不要直接用FDM打印件做树脂模具,成功率极低。

第二次尝试(成功)

  1. 制作母模:首先,我在Fusion 360里精确设计了透镜的模型,然后用光固化(SLA)3D打印机打印出来(ABS打印也行,但SLA表面更光滑)。这个打印件就是我们的“母模”。
  2. 制作硅胶模具:找一个比母模大一圈的容器(我用的是打印的围挡,用硬纸板做也行),将母模用热熔胶固定在容器底部。在母模表面均匀涂抹凡士林或专用的蜡基脱模剂,这步至关重要。然后按照比例混合硅胶(我用的是GP-3481, Shore硬度27左右,比较柔软易脱模),缓慢倒入容器,直至完全淹没母模并高出至少1厘米。静置24小时固化。
  3. 浇注树脂透镜:脱模后,我们就得到了一个负型的硅胶模具。我这次选择了2:1混合比例的透明环氧树脂。在混合树脂和固化剂时,必须充分搅拌至少3-5分钟,确保杯壁和杯底都搅拌到,否则会出现局部不固化的情况。搅拌后静置几分钟让气泡浮上来。为了给LED留出安装空间,我在倒入树脂后,在中心位置压入了一个小号shot glass(或任何圆柱形物体),创造出中空的灯杯。再次静置24-48小时固化。
  4. 脱模与后处理:从硅胶模具中取出树脂透镜非常轻松,硅胶的弹性让脱模变得简单。成品透镜通透度很好,但内部有些许微小气泡。这是因为我没有真空机进行消泡。对于要求不高的装饰件可以接受,如果追求完美,可以考虑购买一个真空泵和真空罐,在树脂混合后倒入模具前进行抽真空处理。

3. 软件开发:数据获取与核心算法解析

硬件是躯壳,软件才是灵魂。这个项目的软件核心是一个运行在树莓派上的PHP脚本(当然用Python实现逻辑也完全一样),它每隔一段时间(如20秒)执行一次,完成“获取数据->分析数据->控制硬件”的循环。

3.1 环境准备与依赖安装

首先,确保你的树莓派系统是最新的(我用的是Raspberry Pi OS Lite),并安装必要的软件包:

sudo apt update sudo apt upgrade -y sudo apt install php php-curl mariadb-server mariadb-client -y sudo mysql_secure_installation # 运行安全安装脚本,设置root密码等

我们使用PHP的file_get_contents或cURL来调用API,用MariaDB(MySQL的一个分支)来存储飞机信息数据库。

3.2 获取OpenSky Network API密钥与数据理解

OpenSky Network是一个由志愿者运行的全球航班跟踪网络,它提供了一个免费的、非商业用途的API。你需要先去其官网注册一个账户,然后可以在个人页面找到你的API凭证(用户名和密码)。不过,我们项目使用的/api/states/all接口在匿名访问(不提供凭证)时,有调用频率限制(类似每秒一次),对于我们的预警灯项目来说,匿名访问通常就足够了。

这个接口的核心是“边界框”查询。你需要提供你感兴趣区域西南角和东北角的经纬度,它会返回这个方框内所有飞机的状态信息。返回的数据是一个JSON数组,每个飞机状态包含多达17个字段,我们主要关心其中几个:

  • icao24: 飞机的唯一24位ICAO地址(十六进制)。
  • callsign: 航班呼号(如“BAW123”),可能为空。
  • latitude,longitude: 飞机的经纬度。
  • baro_altitude: 气压高度(米)。
  • velocity: 地速(米/秒)。
  • true_track: 飞机真实的航向角(度,从正北顺时针计算)。
  • on_ground: 是否在地面。

3.3 核心地理计算逻辑详解

这是项目的算法核心,目的是从一堆飞机中筛选出“即将从我头顶附近飞过”的那一架。逻辑分三步走:

第一步:划定监控区域(计算边界框)我们以自家坐标为中心,画一个正方形区域。这里不能直接用经纬度加减公里数,因为地球是球体,经度线在赤道最宽,向两极收敛。我们需要一个将公里距离转换为经纬度偏移的函数:

function get_bounding_box($lat_deg, $lon_deg, $half_side_km) { $earth_radius = 6371; // 地球平均半径,公里 $lat_rad = deg2rad($lat_deg); $lon_rad = deg2rad($lon_deg); // 计算给定纬度处的平行圈半径 $parallel_radius = $earth_radius * cos($lat_rad); // 计算纬度的最大最小值(南北方向) $lat_min_rad = $lat_rad - ($half_side_km / $earth_radius); $lat_max_rad = $lat_rad + ($half_side_km / $earth_radius); // 计算经度的最大最小值(东西方向) $lon_min_rad = $lon_rad - ($half_side_km / $parallel_radius); $lon_max_rad = $lon_rad + ($half_side_km / $parallel_radius); // 转换回角度 return array( rad2deg($lat_min_rad), // 最小纬度 rad2deg($lon_min_rad), // 最小经度 rad2deg($lat_max_rad), // 最大纬度 rad2deg($lon_max_rad) // 最大经度 ); } // 示例:获取我家(假设坐标51.5074° N, 0.1278° W)周边15公里范围的边界 $my_lat = 51.5074; $my_lon = -0.1278; $range_km = 15; $bbox = get_bounding_box($my_lat, $my_lon, $range_km); // $bbox 数组即可用于API调用

第二步:计算飞机相对于我的方位角拿到飞机坐标后,我们需要知道飞机相对于我的方位,即“飞机在我的哪个方向”。这用到球面三角学中的方位角计算公式:

function get_bearing($home_lat, $home_lon, $plane_lat, $plane_lon) { $lat1 = deg2rad($home_lat); $lat2 = deg2rad($plane_lat); $dLon = deg2rad($plane_lon - $home_lon); $y = sin($dLon) * cos($lat2); $x = cos($lat1) * sin($lat2) - sin($lat1) * cos($lat2) * cos($dLon); $bearing_rad = atan2($y, $x); // 将弧度转换为度,并调整到0-360范围 $bearing_deg = rad2deg($bearing_rad); return fmod(($bearing_deg + 360), 360); }

这个函数返回一个0到360度的值,0度代表正北,90度代表正东,以此类推。这样我就知道飞机在我的东边还是西边。

第三步:判断是否会“擦肩而过”(侧向距离计算)知道飞机在哪和它朝哪飞后,最关键的一步是预测它的航线是否会接近我。想象一下:飞机有一个航向,我(家)是一个点。即使飞机航向大致对着我,它也可能从我左边或右边几公里外飞过,我们只关心那些会非常接近的。

这里我引入一个“侧向偏移距离”的概念。我把我的房子想象成一个半径为R(比如3公里)的圆。飞机当前的连线和我与飞机的连线有一个夹角(α)。通过三角函数,我们可以计算飞机按当前航向飞下去,其航线距离我家的最短距离(即侧向偏移)。

function get_intercept_distance($bearing_to_plane, $plane_true_track, $distance_to_plane) { // 计算飞机航向与指向我家方向之间的夹角差 $angle_diff = abs($bearing_to_plane - $plane_true_track); // 将夹角差规范到0-180度之间,因为航线从左或右接近,在几何上是对称的 $enclosed_angle = abs($angle_diff - 180); // 如果这个夹角大于90度,说明飞机航向基本是背离或横向,不可能接近,直接返回一个大数 if ($enclosed_angle > 90) { return 9999; // 表示不会接近 } // 使用正切函数计算侧向偏移距离:侧偏 = 距离 * tan(夹角) $angle_rad = deg2rad($enclosed_angle); $lateral_distance = $distance_to_plane * tan($angle_rad); return $lateral_distance; }

如果计算出的$lateral_distance小于我们设定的阈值(比如3公里),并且飞机距离我还在一定范围内(比如12公里内),且飞机在空中(高度>0),速度不为0,那么我们就认为这架飞机有可能会在很近的地方飞过,触发预警条件。

第四步:计算预计到达时间(ETA)最后,为了让预警更有意义,我们计算一下如果飞机直飞,到达离我最近点还需要多久。这很简单:时间 = 直线距离 / 地速。将速度从米/秒转换为公里/小时,就能得到一个以小时为单位的时间,再转换为秒或分钟。

$distance_km = ... // 用haversine公式计算出的距离 $speed_kmh = ($velocity_ms * 3600) / 1000; if ($speed_kmh > 0) { $eta_hours = $distance_km / $speed_kmh; $eta_seconds = $eta_hours * 3600; // 如果ETA小于45秒,且满足侧偏条件,则立即点亮预警灯 if ($eta_seconds < 45 && $lateral_distance < 3) { trigger_alert(); } }

3.4 飞机数据库的建立与查询优化

OpenSky返回的数据只包含ICAO地址和呼号等基本信息。如果你想知道飞过头顶的是一架波音787还是一架空客A380,就需要一个本地数据库。OpenSky提供了飞机注册信息的数据库下载(CSV文件,包含制造商、型号、注册号等信息)。

  1. 下载与导入:从OpenSky网站下载aircraftDatabase.csv文件。在MariaDB中创建一个新数据库和表,表结构至少包含icao24(主键)、registration(注册号)、manufacturernamemodel等字段。然后使用LOAD DATA INFILE命令或通过编程方式(如PHP的fgetcsv)将CSV数据导入表中。这个过程可能比较慢,因为数据量很大(几十万条)。
  2. 查询与计数:每次检测到可能飞过的飞机,脚本会查询本地数据库。如果找到记录,就显示详细信息(如“这是一架波音737-800,隶属于XX航空”),并将该飞机的“看到次数”计数器加1。如果没找到(可能是新飞机或数据库未收录),就插入一条新记录。这样久而久之,你就有了一个专属的本地飞机观测日志。
  3. 特别关注列表:我额外在数据库里加了一个special字段。我可以手动将一些我特别感兴趣的飞机(比如老式军机、罕见机型、特定航空公司的飞机)的这个字段标记为1。在预警逻辑里,如果发现special=1的飞机正在接近,我可以让LED灯以不同的模式闪烁(比如快速闪烁),实现分级预警。

4. 系统集成与硬件控制

软件算出了结果,最终要落到硬件动作上——点亮那盏蓝色的跑道灯。

4.1 树莓派GPIO控制与接线

我选择使用树莓派的GPIO 17(物理引脚11)来控制LED。接线非常简单:

  • LED阳极(长脚)-> 串联一个270Ω的限流电阻-> 连接到GPIO 17
  • LED阴极(短脚)-> 连接到树莓派的GND(任意接地引脚,如引脚6、9等)。

为什么是270Ω?树莓派GPIO输出高电平时约为3.3V,典型LED正向压降约为2.0-3.0V(蓝/白光LED通常更高,约3.0-3.4V)。我们以3.0V估算,那么电阻需要分担的电压是3.3V - 3.0V = 0.3V。对于普通LED,工作电流一般在10-20mA比较安全且明亮。根据欧姆定律 R = V / I,如果期望电流为15mA (0.015A),则 R = 0.3V / 0.015A = 20Ω。但这里有个问题:我们用的是高亮度LED,且树莓派GPIO引脚最大推荐输出电流为16mA。为了绝对安全并延长LED寿命,我选择将电流限制在10mA左右。那么 R = 0.3V / 0.01A = 30Ω。我手头有270Ω的电阻,虽然电流会更小(约1mA),但作为指示灯亮度也足够了,而且更省电、更安全。如果你希望更亮,可以换用更小阻值的电阻,但务必确保计算后的电流不超过16mA。

在PHP中控制GPIO,我使用了pigs命令(通过shell_execexec函数调用),它是pigpio守护进程的客户端。首先需要安装并启动pigpio

sudo apt install pigpio sudo systemctl enable pigpiod sudo systemctl start pigpiod

然后在PHP脚本中:

function set_led($state) { // $state: 1 开, 0 关 $command = "pigs w 17 " . $state; exec($command . " > /dev/null 2>&1 &"); // 后台执行,不阻塞脚本 }

4.2 增加物理按钮与状态指示灯

一个放在桌上的设备,总不能每次开关机都去拔插头或者SSH进去输命令。我增加了两个实用的硬件功能:

  1. 关机/开机按钮:利用树莓派的一个GPIO(如GPIO 3)连接一个轻触开关到GND。然后使用 Howchoo的Pi Power Button脚本 。这个脚本监听按钮按下事件,短按执行安全关机,在关机状态下短按则开机(需要配合一些硬件改动,具体见其教程)。这大大提升了设备的独立性和用户体验。
  2. 电源状态指示灯:利用树莓派串口TXD引脚(GPIO 14)在启动过程中的电平变化,连接一个绿色LED(串联一个合适电阻,如330Ω)到GND。系统启动时,TXD引脚会有数据波动,LED会快速闪烁;系统完全启动后,LED常亮;关机时,LED熄灭。这是一个非常直观的系统状态指示。

4.3 后台服务与自启动

我们需要让这个PHP脚本在树莓派启动后就在后台一直运行。最好的方式是将其配置为一个systemd服务

  1. 创建一个服务文件:sudo nano /etc/systemd/system/plane_alert.service
  2. 写入以下内容:
    [Unit] Description=Plane Alert Light Service After=network.target pigpiod.service [Service] Type=simple User=pi WorkingDirectory=/home/pi/plane_alert # 你的脚本所在目录 ExecStart=/usr/bin/php /home/pi/plane_alert/alert.php Restart=on-failure RestartSec=10 [Install] WantedBy=multi-user.target
  3. 保存退出,然后启用并启动服务:
    sudo systemctl daemon-reload sudo systemctl enable plane_alert.service sudo systemctl start plane_alert.service
  4. 检查服务状态:sudo systemctl status plane_alert.service

这样,树莓派一开机,预警程序就会自动运行。你可以通过sudo journalctl -u plane_alert.service -f来实时查看脚本的日志输出,非常方便调试。

5. 调试、优化与经验心得

项目做完了,但让它稳定可靠地运行,才是真正的挑战。下面分享一些调试过程中的关键点和优化建议。

5.1 数据源的局限性与应对

OpenSky Network的数据依赖于志愿者的ADS-B接收器。这意味着:

  • 覆盖不均:在城市和主要航路附近,数据丰富且更新快;在偏远地区或海洋上空,数据可能稀疏或延迟。
  • MLAT依赖:没有装备ADS-B(Mode S)应答器的老式飞机,其位置需要通过多基站三角定位(MLAT)计算。OpenSky的MLAT覆盖不如Flightradar24等商业平台广泛。所以,你的预警灯可能会“漏报”一些飞机,尤其是通用航空的小飞机或某些军机。这是免费数据源的固有局限。
  • 更新频率:免费API有调用频率限制。我的脚本设置为20秒查询一次,这对于预警几十秒后飞临的飞机是足够的。更频繁的调用可能导致IP被暂时限制。

应对策略

  • 调整预警阈值:将预警的侧向距离和ETA时间阈值适当放宽。例如,侧偏距离从3公里调到5公里,ETA从45秒调到90秒。这样能捕捉到更多飞机,但误报(飞机其实不会从正上方飞过)的几率也会增加,需要根据你的位置和需求权衡。
  • 数据融合(进阶):可以考虑同时查询多个免费的航空数据源(如果存在),进行数据比对和融合,提高覆盖率。但这会显著增加代码复杂度。

5.2 误报过滤与逻辑优化

最初的逻辑可能会被机场地面滑行的飞机触发(航向对着你,但速度慢、高度0)。我的脚本通过检查geo_altitude_m > 0air_speed_kmh > 一个最小值(如50)来过滤。但还有更复杂的情况:

  • 盘旋的飞机:训练飞机或等待降落的飞机可能在你的监控区域内绕圈,导致预警灯反复亮灭。可以在代码中加入简单的状态记忆,如果同一架飞机(通过icao24判断)在短时间内重复触发,则延长预警灯的熄灭延迟,或改为缓慢闪烁,而不是频繁开关。
  • 爬升/下降阶段的飞机:其航向和地速可能不稳定,计算出的ETA和侧偏距离跳动大。可以对连续几次查询的结果做平滑处理(取平均值),以减少抖动。

5.3 性能与稳定性考量

  • 数据库优化:飞机数据库表很大,务必在icao24字段上建立索引,否则每次查询都会全表扫描,速度极慢。在MariaDB中执行:CREATE INDEX idx_icao24 ON aircraftdatabase (icao24);
  • 脚本容错:网络请求可能失败,API可能暂时不可用。你的脚本必须有良好的错误处理(try-catch),并在网络请求失败时等待一段时间后重试,而不是直接崩溃。
  • 日志记录:将重要的事件(如发现飞机、触发预警、API错误)记录到文件或系统日志(syslog)中。这对于后期排查问题至关重要。我使用PHP的error_log函数将信息写入指定文件。
  • 资源监控:长时间运行后,检查树莓派的内存和CPU使用情况。PHP脚本本身不耗资源,但如果你未来增加更多功能,需要注意。

5.4 功能扩展想法

这个项目的基础框架很灵活,你可以在此基础上玩出很多花样:

  1. 多级预警与灯光模式:除了常亮,可以让LED实现呼吸灯、快闪、慢闪等不同模式,对应不同距离、高度或机型(利用数据库中的special字段)。
  2. 声音提示:通过连接一个小喇叭或蜂鸣器,发出不同的提示音。
  3. 网络仪表盘:用Python的Flask或PHP内置的Web服务器,做一个简单的本地网页,实时显示当前监控状态、最近看到的飞机列表、历史统计等。
  4. 推送通知:集成Telegram Bot或Server酱,当特别关注的飞机出现时,给你的手机发送一条消息。
  5. 数据记录与分析:将每次预警的飞机数据(时间、机型、高度、速度等)记录到数据库的另一张表中,用于分析你家上空的航班 patterns。

6. 完整代码结构与部署清单

为了让项目更容易复现,这里给出一个清晰的部署步骤和代码结构概览。

项目目录结构建议

/home/pi/plane_alert/ ├── alert.php # 主预警脚本 ├── config.php # 配置文件(存放API密钥、数据库密码、坐标等敏感信息) ├── logs/ # 日志目录 │ └── alert.log ├── lib/ # 函数库目录(可选) │ ├── geo_calculations.php │ └── database.php └── README.md # 项目说明

config.php示例(务必保护好此文件)

<?php // config.php - 配置文件 define('HOME_LAT', 51.5074); // 你的纬度 define('HOME_LON', -0.1278); // 你的经度 define('MONITOR_RADIUS_KM', 15); // 监控半径(公里) define('ALERT_LATERAL_KM', 3); // 触发预警的侧向距离(公里) define('ALERT_ETA_SECONDS', 45); // 触发预警的ETA时间(秒) // 数据库配置 define('DB_HOST', 'localhost'); define('DB_USER', 'plane_user'); // 建议创建专用用户,不要用root define('DB_PASS', 'your_secure_password'); define('DB_NAME', 'plane_alert_db'); // GPIO引脚配置 define('LED_PIN', 17); ?>

主循环逻辑伪代码

// alert.php 主循环 include('config.php'); // 包含各种计算函数... while (true) { try { // 1. 计算边界框 $bbox = get_bounding_box(HOME_LAT, HOME_LON, MONITOR_RADIUS_KM); // 2. 调用OpenSky API $planes_data = fetch_opensky_data($bbox); $alert_triggered = false; // 3. 遍历每架飞机 foreach ($planes_data as $plane) { // 3.1 基础过滤(高度>0,速度>阈值) if (!is_valid_plane($plane)) continue; // 3.2 计算距离、方位角、侧偏、ETA $distance = haversine(HOME_LAT, HOME_LON, $plane['lat'], $plane['lon']); $bearing = get_bearing(HOME_LAT, HOME_LON, $plane['lat'], $plane['lon']); $lateral_dist = get_intercept_distance($bearing, $plane['track'], $distance); $eta = $distance / ($plane['velocity'] * 3.6); // 转换为小时 // 3.3 判断是否触发预警 if ($lateral_dist < ALERT_LATERAL_KM && $eta < (ALERT_ETA_SECONDS/3600) && $distance < 20) { $alert_triggered = true; log_plane_details($plane); // 记录日志 update_plane_database($plane['icao24']); // 更新数据库 break; // 找到一架就触发,跳出循环 } } // 4. 控制LED set_led($alert_triggered ? 1 : 0); // 5. 等待下一个周期 sleep(20); // 20秒查询一次 } catch (Exception $e) { error_log("Error in main loop: " . $e->getMessage()); sleep(60); // 出错时等待更久 } }

部署检查清单

  1. [ ] 树莓派安装好Raspberry Pi OS,并更新到最新。
  2. [ ] 安装PHP、MariaDB、pigpio:sudo apt install php php-curl mariadb-server mariadb-client pigpio
  3. [ ] 启动并启用pigpiod守护进程:sudo systemctl enable --now pigpiod
  4. [ ] 设置MariaDB root密码,创建专用数据库和用户,导入飞机数据库CSV。
  5. [ ] 将项目代码(包括alert.php,config.php等)上传到树莓派(如/home/pi/plane_alert)。
  6. [ ] 修改config.php中的坐标、数据库密码等配置。
  7. [ ] 按接线图连接LED和按钮。
  8. [ ] 测试脚本:cd /home/pi/plane_alert && php alert.php,观察输出和LED反应。
  9. [ ] 配置systemd服务文件,并启用自启动。
  10. [ ] 重启树莓派,验证服务是否自动运行,预警灯是否正常工作。

这个项目从构思到实现,花了大概一个月的业余时间,其中大部分精力都花在了调试地理计算逻辑和优化误报上。当第一次看到预警灯因为一架即将飞过的飞机而自动点亮时,那种感觉非常奇妙——你通过代码和硬件,赋予了一个静态物体感知周围世界的能力。它不仅仅是一个提醒你关窗户的工具,更是一个连接广阔天空与个人空间的小小桥梁。希望这份详细的指南能帮你绕过我踩过的那些坑,顺利做出属于你自己的天空守望者。

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

相关文章:

  • 5分钟掌握ExplorerPatcher:高效恢复Windows 11经典任务栏与开始菜单
  • 语音转文字太麻烦?AsrTools三步搞定音频转录难题
  • 村长团队教你GTA5线下SP端与FiveM私服端脚本插件开发完整流程教程。
  • AntiDupl.NET:智能图片去重终极解决方案,3步告别重复照片困扰
  • IDM激活脚本完整指南:如何安全免费使用高速下载工具
  • STM32F103+PSD二维定位采集板:含完整AD调理、nRF24L01无线传输与可投产PCB工程
  • C++手写路径追踪渲染器源码包:含蒙特卡罗采样实现、酒杯焦散/景深效果与课程论文
  • 完全掌握网易云音乐无损解析工具:专业级音乐资源获取实战指南
  • Gemini 2.5 Pro视频理解首超人类:Video-MME 82.3%背后的三大架构突破,附完整API调用
  • 2026年视频提取文字保姆级教程:手把手教你快速转换成文档
  • Rainmeter插件性能调优实战:从卡顿到丝滑的蜕变之旅
  • 别再只盯着ERP了!手把手教你用免费开源的Odoo搭建产品数据管理核心(PLM实战)
  • 智能采购系统集成失败率高达68%?(2024 Gartner审计报告独家拆解)
  • 【独家首发】Gartner未公开的AI采购效能白皮书核心结论:仅12%企业真正实现“AI+谈判力”双闭环
  • 国产大模型 API 基础 —— 课程笔记
  • 当一个AI编程助手在TCL深度上岗,工程师的活儿变了
  • 终极指南:如何用Attu轻松管理你的Milvus向量数据库
  • 从0到1搭建企业内训平台:教育培训系统源码开发实践
  • 璞华易研PLM-食品研发ROI持续走低:数字化如何破解“低投入、低产出”困局?
  • ICASSP 2018微软语音技术前沿:从鲁棒识别到神经合成的全链条解析
  • Rhino Compute技术架构解析:构建云端几何计算引擎的完整指南
  • Topit:如何彻底告别Mac多窗口切换烦恼?终极窗口置顶解决方案
  • NCMDump终极指南:三步轻松解密网易云音乐NCM格式文件
  • 三步搞定顽固窗口:WindowResizer 终极窗口尺寸强制调整指南
  • IO流知识点笔记
  • 16通道PXIe高速串口卡RS422总线/RS485总线
  • 一文解读:多模态大语言模型综述,建议收藏!
  • OpenCV实战:基于SIFT特征匹配的实时物体检测与定位
  • GitHub爆火装机工具Ventoy,一个U盘搞定所有系统安装
  • 海外直播拍卖订单履约难点:跨境链路协同与流程优化