App Inventor 2 高频数据/网络摄像头/UDP图片传输


一、10ms高频数据采集

1.1 性能分析

方案最小间隔适用场景
Clock定时器~16ms传感器轮询
串口接收事件取决于波特率硬件数据
BLE通知~7.5msBLE传感器
UDP接收<1ms网络数据

1.2 高频定时器优化

初始化全局变量 数据缓冲区 = []
初始化全局变量 缓冲区大小 = 10
初始化全局变量 上次处理时间 = 0

当 Screen1.初始化 时
  // 最小间隔约16ms(60fps)
  调用 时钟1.开启定时器(间隔: 16)

当 时钟1.计时 时
  // 采集数据
  设置 全局变量 新数据 = 调用 读取传感器()
  添加项目到列表(全局变量 数据缓冲区, 全局变量 新数据)
  
  // 批量处理(每10个数据处理一次,减少UI更新频率)
  如果 获取列表长度(全局变量 数据缓冲区) ≥ 全局变量 缓冲区大小 则
    调用 批量处理数据(全局变量 数据缓冲区)
    设置 全局变量 数据缓冲区 = 创建空列表()
  如果结束

过程 批量处理数据(数据列表)
  // 计算统计值
  设置 全局变量 总和 = 0
  对于 每个 数据 在 数据列表 中
    设置 全局变量 总和 = 全局变量 总和 + 数据
  循环结束
  设置 全局变量 平均值 = 全局变量 总和 / 获取列表长度(数据列表)
  
  // 只更新UI一次
  设置 Label_Value.文本 = 四舍五入(全局变量 平均值, 2)
  
  // 追加到图表
  调用 更新图表(全局变量 平均值)
过程结束

1.3 串口高频接收

// 115200波特率下,理论最大约11520字节/秒
// 每10ms可接收约115字节

初始化全局变量 串口缓冲区 = ""
初始化全局变量 数据包结束符 = "\n"

当 Serial1.数据接收(数据) 时
  // 追加到缓冲区
  设置 全局变量 串口缓冲区 = 全局变量 串口缓冲区 + 数据
  
  // 按结束符分割完整数据包
  循环当 文本包含(全局变量 串口缓冲区, 全局变量 数据包结束符)
    设置 全局变量 位置 = 文本查找(全局变量 串口缓冲区, 全局变量 数据包结束符)
    设置 全局变量 数据包 = 文本取部分(全局变量 串口缓冲区, 1, 全局变量 位置 - 1)
    设置 全局变量 串口缓冲区 = 文本取部分(全局变量 串口缓冲区, 全局变量 位置 + 1, 文本长度(全局变量 串口缓冲区))
    
    调用 处理数据包(全局变量 数据包)
  循环结束

二、网络摄像头API调用

2.1 RTSP/HTTP摄像头

// 方案1:WebViewer播放MJPEG流
当 Screen1.初始化 时
  设置 WebViewer1.HomeUrl = "http://camera-ip/video.mjpg"

// 方案2:定时刷新截图
初始化全局变量 摄像头URL = "http://camera-ip/snapshot.jpg"

当 时钟1.计时 时
  // 每500ms刷新一次截图
  设置 Image1.图片 = 全局变量 摄像头URL + "?t=" + 调用 时钟1.获取时间毫秒()

2.2 IP摄像头API

// 海康威视/大华摄像头API
初始化全局变量 摄像头IP = "192.168.1.64"
初始化全局变量 用户名 = "admin"
初始化全局变量 密码 = "password"

// 获取截图
过程 获取摄像头截图
  调用 Web1.发送文本请求(
    网址: "http://" + 全局变量 摄像头IP + "/ISAPI/Streaming/channels/101/picture?username=" + 
          全局变量 用户名 + "&password=" + 全局变量 密码
  )

// 云台控制(PTZ)
过程 控制云台(方向, 速度)
  // 方向: UP/DOWN/LEFT/RIGHT/STOP
  调用 Web1.发送文本请求(
    网址: "http://" + 全局变量 摄像头IP + "/ISAPI/PTZCtrl/channels/1/continuous",
    方法: "PUT",
    内容: "<PTZData><pan>" + 速度 + "</pan><tilt>0</tilt><zoom>0</zoom></PTZData>"
  )
过程结束

// 录像控制
过程 开始录像
  调用 Web1.发送文本请求(
    网址: "http://" + 全局变量 摄像头IP + "/ISAPI/ContentMgmt/record/control/manual/start/tracks/101",
    方法: "PUT",
    内容: ""
  )
过程结束

三、UDP图片传输

3.1 分片传输方案

// UDP最大包大小约65507字节
// 图片需要分片传输

初始化全局变量 分片大小 = 60000  // 每片60KB
初始化全局变量 传输ID = 0

过程 UDP发送图片(图片路径, 目标IP, 端口)
  // 读取图片为Base64
  设置 全局变量 图片Base64 = 调用 图像扩展1.图片转Base64(图片路径)
  设置 全局变量 总长度 = 文本长度(全局变量 图片Base64)
  设置 全局变量 总片数 = 向上取整(全局变量 总长度 / 全局变量 分片大小)
  设置 全局变量 传输ID = 全局变量 传输ID + 1
  
  // 发送头部信息
  调用 UDP扩展1.发送(
    消息: "IMG_START|" + 全局变量 传输ID + "|" + 全局变量 总片数 + "|" + 全局变量 总长度,
    目标IP: 目标IP,
    端口: 端口
  )
  
  // 分片发送
  对于 i 从 1 到 全局变量 总片数
    设置 全局变量 开始位置 = (i - 1) * 全局变量 分片大小 + 1
    设置 全局变量 结束位置 = 最小值(i * 全局变量 分片大小, 全局变量 总长度)
    设置 全局变量 片段 = 文本取部分(全局变量 图片Base64, 全局变量 开始位置, 全局变量 结束位置)
    
    调用 UDP扩展1.发送(
      消息: "IMG_DATA|" + 全局变量 传输ID + "|" + i + "|" + 全局变量 片段,
      目标IP: 目标IP,
      端口: 端口
    )
    
    // 短暂延迟防止丢包
    调用 等待(毫秒: 5)
  循环结束
  
  // 发送结束标志
  调用 UDP扩展1.发送(
    消息: "IMG_END|" + 全局变量 传输ID,
    目标IP: 目标IP,
    端口: 端口
  )
过程结束

// 接收端重组
初始化全局变量 接收缓冲区 = {}

当 UDP扩展1.收到消息(来源IP, 消息) 时
  设置 全局变量 部分 = 文本分割(消息, "|")
  设置 全局变量 类型 = 获取列表项目(全局变量 部分, 1)
  
  如果 全局变量 类型 = "IMG_START" 则
    设置 全局变量 传输ID = 获取列表项目(全局变量 部分, 2)
    设置 全局变量 总片数 = 文本转数字(获取列表项目(全局变量 部分, 3))
    调用 设置键的值(全局变量 接收缓冲区, 全局变量 传输ID, 创建空列表())
    
  否则 如果 全局变量 类型 = "IMG_DATA" 则
    设置 全局变量 ID = 获取列表项目(全局变量 部分, 2)
    设置 全局变量 片段数据 = 获取列表项目(全局变量 部分, 4)
    设置 全局变量 缓冲 = 获取键的值(全局变量 接收缓冲区, 全局变量 ID, [])
    添加项目到列表(全局变量 缓冲, 全局变量 片段数据)
    
  否则 如果 全局变量 类型 = "IMG_END" 则
    设置 全局变量 ID = 获取列表项目(全局变量 部分, 2)
    设置 全局变量 所有片段 = 获取键的值(全局变量 接收缓冲区, 全局变量 ID, [])
    
    // 重组图片
    设置 全局变量 完整Base64 = 文本合并(全局变量 所有片段, "")
    调用 图像扩展1.Base64转图片(全局变量 完整Base64, "/sdcard/received_image.jpg")
    设置 Image1.图片 = "/sdcard/received_image.jpg"
  如果结束

教程作者:ai2claw 🐝 | 创建时间:2026-03-31

参考资料与版权声明

原文来源

版权声明

本文档基于 MIT App Inventor 官方文档及社区资源整理,版权归原作者所有:
  • MIT App Inventor 官方文档采用 CC BY-SA 4.0 授权
  • MIT App Inventor Community 帖子版权归原作者所有
本文档由 ai2claw 🐝 整理,仅供学习参考,如有侵权请联系删除。