硬件部分
模块 | 功能 | 典型部件/建议 |
---|---|---|
机柜结构 | 支撑和保护无人机 | 金属机柜或高强度塑料,带防雨防尘设计 |
存放仓位 | 无人机存放、锁定 | 可控电子锁或电磁锁;仓位托盘设计,适配不同型号无人机 |
充电系统 | 对无人机电池充电 | 充电模块(智能锂电池充电器),电源管理板 |
控制板/主控 | 管理柜子各模块 | MCU 或嵌入式Linux主控(如Raspberry Pi, STM32, RK芯片) |
通信模块 | 与服务器和用户APP交互 | 4G/5G模块、Wi-Fi、蓝牙,或NB-IoT |
传感器 | 安全和状态监控 | 门磁传感器、红外/光电检测、重量传感器(判断无人机是否在位) |
显示与交互 | 用户操作界面 | LCD/触摸屏、LED指示灯、按钮或扫码器 |
安全防护 | 防盗、防火 | 防撬传感器、防火材料、报警器 |
电源 | 系统供电 | 交流电输入、UPS/备用电池,必要时支持太阳能板 |
环境监控 | 温湿度控制 | 温湿度传感器、风扇或小型空调 |
断路器
特性 / 属性 | CHINT NXB-63 C20 | CHINT NXU-II G 40/275 |
---|---|---|
核心功能 | 过载与短路保护、断电隔离 | 防雷击和瞬态过电压保护 |
典型用途 | 配电系统及电气设备电流保护 | 电涌保护,保护系统设备免受过电压损害 |
额定参数 | 20A 电流、约 400V 额定电压 | 40 kA 冲击电流、275 V 持续电压 |
符合标准 | GB/T 10963.1, IEC 60898-1 | IEC/EN 61643-11, GB/T 18802.11 |
保护机制 | 断电切断保护 | 吸收或旁路电涌,保护设备 |
结构特点 | 传统断路器结构 | 模块化设计,可在线更换模块 |
使用建议
- 若你的需求是针对电路中的过载或短路事件进行保护——比如当电流过大或发生短路时希望自动断开电路——则应选择 NXB-63 C20 小型断路器。
- 若你需要防护来自电网的瞬态高压冲击(如雷击或电压浪涌)——保护后级设备不被高电压损坏——则应选择 NXU-II G 40/275 电涌保护器。
- 实际应用中,这两种产品常常可以配套使用:断路器负责常规保护,电涌保护器负责突发高压冲击保护,形成前后协同机制,提高整体电气安全性。
单相电子式导轨智能电能表
用于测量和记录电力消耗。该电能表符合国家标准GB/T 17215.321-2008,并且带有二维码,可能用于远程读取数据或设备信息
微电脑时控开关
它是一种用于自动控制电器设备在特定时间开启或关闭的电子设备。通过设定时间参数,它可以按照预设的时间表自动控制电路的通断,适用于需要定时控制的场合,如路灯、水泵、空调等
无人机供电和锁控板
主控芯片STM32F103C8T6
这是 STMicroelectronics(意法半导体) 的一颗 STM32F1 系列 ARM Cortex-M3 内核 MCU,常见于工业控制、物联网和智能设备
- 通过 RS-485 或 UART 与上位机通讯
- 控制 MOSFET 驱动锁(LK1~LK5)
- 读取锁的反馈信号(FB1~FB5)
- 控制 DC-DC 输出状态
- 监测电压、电流状态
- 管理 USB 口的供电控制
电池充电板
这块电路板是一个多通道的电源管理板,很可能用于电池充电或平衡应用。它通过六个独立的降压/升压模块,由一个中央控制器进行管理。
主控芯片STM32F103C8T6
USB-A口可能的作用: CDC (Communication Device Class): 模拟一个串口(Serial Port)。这是最简单也最常用的方法。电路板向安卓屏幕“报告”自己是一个虚拟串口,然后就可以像传统的串口通信一样,通过收发字符串或二进制数据来交换信息
读卡器控制板
这块小板子是一个RFID读卡器模块。它的作用是:
- 射频收发: 通过板子内部的PCB天线(图片中没有明显的天线线圈,但天线可能集成在板子内层,或通过旁边的电感L1/L2进行匹配),它能产生13.56 MHz的射频场。
- 卡片感应: 当兼容的RFID标签(如MIFARE卡)靠近时,它会感应到卡片的信号。
- 数据读写: 通过感应到的信号,它能读取或写入卡片中的数据。
- 通信接口: 通过底部的4针连接器,它与主控板(例如你之前上传的电池板或控制板)进行通信,通常采用SPI或I2C协议,将读到的数据发送给主控芯片,或者接收主控芯片的指令去写入数据。
主控芯片Geehy APM32 F072RBT6
- 用户将RFID卡靠近读卡器模块(ANT522-M2)。
- 读卡器模块读取卡片上的唯一ID或数据。
- 读卡器模块通过SPI或I2C接口将数据发送给24路板子上的主控芯片。
- 主控芯片(APM32)根据卡片ID,在程序中进行身份验证。
- 如果验证通过,主控芯片会控制相应的输出通道(例如,开启第5路和第12路),并点亮相应的LED指示灯。
软件逻辑
- android_serialport_api: 用于通过串口与外部硬件设备进行通信。
- com.alibaba.android.arouter: 一个Android路由框架。
- com.bumptech.glide: 一个流行的图片加载和缓存库。
- com.google.zxing: 用于处理条形码和二维码的库。
- com.tendcloud.tenddata: 移动应用数据分析平台。
- com.youth.banner: 一个用于创建横幅视图的库。
- com.zhy.view.flowlayout: 一个用于实现流式布局的库。
- io.reactivex: 用于实现响应式编程的库。
软件需求-1
android app 产品需求:
- app启动后先全屏播放一个本地准备好的mp4视频(循环播放)
- 视频界面的底部显示当前设备的无线信号和设备序列号,内容悬浮在视频上方显示
- app启动的同时请求接口,如果接口返回有新的视频文件需要下载,则下载新的视频文件
- 新的视频文件下载到本地后替换掉初始的视频文件播放显示
- app启动后连接到后台的MQTT服务
- app启动后打开RS485串口ttyS3, 读取串口设备信息并通过mqtt上报
- app启动后打开TTL串口ttyS7, 读取串口信息并通过mqtt上报
- 服务器下发指令,然后通过串口发送指令到串口设备,串口设备反馈结果更新到UI
- 串口设备主动上报信息也需要更新UI
帮我设计个实现上述需求的架构
架构设计
+----------------------------------------------------------------------------------------------+
| Android App |
+----------------------+----------------------+----------------------+-----------------------+
| UI 层 | 视频播放层 | 后台服务层 | 串口 & MQTT层 |
+----------------------+----------------------+----------------------+-----------------------+
| SplashVideoActivity | VideoManager | ApiService | MqttManager |
| - 全屏播放视频 | - 播放本地视频 | - 请求视频更新接口 | - 连接 MQTT Broker |
| - 底部悬浮UI显示 | - 循环播放 | DownloadService | - 上报串口数据 |
| WiFi & 设备序列号 | - 切换新视频源 | - 校验文件完整性 | - 接收服务器指令 |
| - 更新UI显示串口数据 | | - 替换本地视频 | - 将指令下发到串口 |
| | | | - 串口反馈更新UI |
+----------------------+----------------------+----------------------+-----------------------+
| 数据存储层 |
+----------------------+
| FileStorage |
| - /files/video.mp4 |
| - /cache/new_video.mp4|
+----------------------+
时序图
┌─────────────────┐ ┌───────────────┐ ┌──────────────────┐ ┌──────────────────────┐
│ SplashVideoActivity │ │ ExoPlayer 播放器 │ │ ApiService 接口层 │ │ DownloadService 下载器 │
└─────────┬─────────┘ └──────┬────────┘ └─────────┬────────┘ └──────────┬─────────┘
│ │ │ │
│ 1. 启动 Activity │ │ │
│────────────────────────>│ │ │
│ │ │ │
│ 2. 加载本地 video.mp4 │ │ │
│────────────────────────>│ │ │
│ │ │ │
│ │ 3. 循环播放(REPEAT_ALL) │ │
│ │────────────────────────>│ │
│ │ │ │
│ 4. 并发发起接口请求 │ │ │
│──────────────────────────────────────────────────>│ │
│ │ │ │
│ │ │ 5. 返回新视频下载地址 │
│ │ │─────────────────────────>│
│ │ │ │
│ │ │ │ 6. 下载新视频到缓存
│ │ │ │──────────────────▶
│ │ │ │
│ │ │ │ 7. 校验 MD5 通过
│ │ │ │
│ │ │ │ 8. 替换本地 video.mp4
│ │ │ │
│ │ 9. 切换播放源 setMediaItem(new.mp4) │
│<────────────────────────│ │ │
│ │ │ │
│ 10. 循环播放新视频 │ │ │
│────────────────────────>│ │ │
泳道图
用到的库
功能模块 | 库/组件 | 说明 |
---|---|---|
视频播放 | ExoPlayer | 循环播放本地视频,可动态切换视频源 |
网络请求 | Retrofit + OkHttp | 请求视频更新接口 |
后台下载 | WorkManager / ForegroundService | 下载新视频到缓存并替换 |
JSON解析 | Gson / Moshi | 解析接口返回信息 |
UI布局 | ConstraintLayout / FrameLayout | 视频上方悬浮显示 WiFi & 序列号和串口数据 |
WiFi/设备信息 | Android 原生 API | 获取信号强度和设备序列号 |
MQTT通信 | Eclipse Paho / HiveMQ MQTT Client | 上报串口数据,接收服务器指令 |
串口操作 | jSerialComm / Android NDK | 打开 ttyS3 / ttyS7,读写数据 |
UI数据绑定 | LiveData / StateFlow / Flow | 实时更新 UI 显示串口数据和反馈结果 |
时序图
A133 视频编解码
A133支持的硬件编解码能力:
- 视频编码能力: H.264 的最大编码性能为 1080p@60fps。
- 视频解码能力: HEVC (H.265) 和 H.264 的最大解码性能为 4K@30fps。
查看视频源信息
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'test.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf58.76.100
Duration: 00:00:36.27, start: 0.000000, bitrate: 3202 kb/s <-- 总码率约 3.2Mbps(比较高,对低端 SoC 有压力)
Stream #0:0(und):
Video: h264 (High) (avc1 / 0x31637661) <-- H.264 High Profile,Allwinner 硬解常见不兼容点
yuv420p(tv, bt709), 1080x1920 [SAR 1:1 DAR 9:16] <-- 分辨率 1080x1920(竖屏 Full HD,部分硬件更习惯 1920x1080)
2999 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default) <-- 30fps,参考时钟 15360,说明码流比较规范
Metadata:
handler_name : VideoHandler
vendor_id : [0][0][0][0]
Stream #0:1(und):
Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 193 kb/s (default) <-- AAC LC,没问题
Metadata:
handler_name : SoundHandler
vendor_id : [0][0][0][0]
报错-1
修改视频帧率命令
ffmpeg -i test_60fps.mp4 -vf “fps=30” -c:a copy test_30fps.mp4
报错-2
ACodec E signalError(omxError 0x80001001, internalError -62)
MediaCodec E Codec reported err 0xffffffc2, actionCode 0, while in state 6
ACodec W not dequeuing from native window due to fatal error
ACodec W not dequeuing from native window due to fatal error
SurfaceUtils D disconnecting from surface 0xc5137808, reason disconnectFromSurface
ACodec W not dequeuing from native window due to fatal error
MediaCodecVideoRenderer E Video codec error (Ask Gemini)
java.lang.IllegalStateException
at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:2789)
at androidx.media3.exoplayer.mediacodec.SynchronousMediaCodecAdapter.dequeueOutputBufferIndex(SynchronousMediaCodecAdapter.java:112)
at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.drainOutputBuffer(MediaCodecRenderer.java:2104)
at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:896)
at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.render(MediaCodecVideoRenderer.java:1314)
at androidx.media3.exoplayer.RendererHolder.render(RendererHolder.java:391)
at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1367)
at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:697)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:214)
at android.os.HandlerThread.run(HandlerThread.java:67)
ExoPlayerImplInternal E Playback error (Ask Gemini)
androidx.media3.exoplayer.ExoPlaybackException: MediaCodecVideoRenderer error, index=0, format=Format(1, null, video/mp4, video/avc, avc1.640028, 2999664, und, [1080, 1920, 30.000004, ColorInfo(BT709, Limited range, SDR SMPTE 170M, false, 8bit Luma, 8bit Chroma)], [-1, -1]), format_supported=YES
at androidx.media3.exoplayer.BaseRenderer.createRendererException(BaseRenderer.java:545)
at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:926)
at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.render(MediaCodecVideoRenderer.java:1314)
at androidx.media3.exoplayer.RendererHolder.render(RendererHolder.java:391)
at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1367)
at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:697)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:214)
at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: androidx.media3.exoplayer.video.MediaCodecVideoDecoderException: Decoder failed: OMX.allwinner.video.decoder.avc
at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.createDecoderException(MediaCodecVideoRenderer.java:2468)
at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:920)
at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.render(MediaCodecVideoRenderer.java:1314)
at androidx.media3.exoplayer.RendererHolder.render(RendererHolder.java:391)
at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1367)
at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:697)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:214)
at android.os.HandlerThread.run(HandlerThread.java:67)
Caused by: java.lang.IllegalStateException
at android.media.MediaCodec.native_dequeueOutputBuffer(Native Method)
at android.media.MediaCodec.dequeueOutputBuffer(MediaCodec.java:2789)
at androidx.media3.exoplayer.mediacodec.SynchronousMediaCodecAdapter.dequeueOutputBufferIndex(SynchronousMediaCodecAdapter.java:112)
at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.drainOutputBuffer(MediaCodecRenderer.java:2104)
at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:896)
at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.render(MediaCodecVideoRenderer.java:1314)
at androidx.media3.exoplayer.RendererHolder.render(RendererHolder.java:391)
at androidx.media3.exoplayer.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:1367)
at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:697)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:214)
at android.os.HandlerThread.run(HandlerThread.java:67)
ExoPlayerImplInternal E Disable failed. (Ask Gemini)
java.lang.IllegalStateException
at android.media.MediaCodec.native_flush(Native Method)
at android.media.MediaCodec.flush(MediaCodec.java:2194)
at androidx.media3.exoplayer.mediacodec.SynchronousMediaCodecAdapter.flush(SynchronousMediaCodecAdapter.java:160)
at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.flushCodec(MediaCodecRenderer.java:1033)
at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.flushOrReleaseCodec(MediaCodecRenderer.java:964)
at androidx.media3.exoplayer.mediacodec.MediaCodecRenderer.onDisabled(MediaCodecRenderer.java:797)
at androidx.media3.exoplayer.video.MediaCodecVideoRenderer.onDisabled(MediaCodecVideoRenderer.java:1081)
at androidx.media3.exoplayer.BaseRenderer.disable(BaseRenderer.java:247)
at androidx.media3.exoplayer.RendererHolder.disableRenderer(RendererHolder.java:673)
at androidx.media3.exoplayer.RendererHolder.disable(RendererHolder.java:567)
at androidx.media3.exoplayer.ExoPlayerImplInternal.disableRenderer(ExoPlayerImplInternal.java:2164)
at androidx.media3.exoplayer.ExoPlayerImplInternal.disableRenderers(ExoPlayerImplInternal.java:2157)
at androidx.media3.exoplayer.ExoPlayerImplInternal.resetInternal(ExoPlayerImplInternal.java:1890)
at androidx.media3.exoplayer.ExoPlayerImplInternal.stopInternal(ExoPlayerImplInternal.java:1847)
at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:876)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:214)
at android.os.HandlerThread.run(HandlerThread.java:67)
Surface E getSlotFromBufferLocked: unknown buffer: 0xc4ea98c0
ACodec W [OMX.allwinner.video.decoder.avc] can not return buffer 22 to native window
Surface E getSlotFromBufferLocked: unknown buffer: 0xc4ea91c0
ACodec W [OMX.allwinner.video.decoder.avc] can not return buffer 17 to native window
Surface E getSlotFromBufferLocked: unknown buffer: 0xeefe9900
ACodec W [OMX.allwinner.video.decoder.avc] can not return buffer 16 to native window
当前修改方案
定时重建exoplayer