# COM_SkydroidDemo
**Repository Path**: skydroid/SkydroidDemo
## Basic Information
- **Project Name**: COM_SkydroidDemo
- **Description**: H16及H30安卓开发示例
- **Primary Language**: Android
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 4
- **Forks**: 13
- **Created**: 2023-06-05
- **Last Updated**: 2026-03-10
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 云卓 Demo 简介:
- 1.RCSDKDemo: [遥控器SDK及Demo(推荐)](https://gitee.com/skydroid/rcsdk-demo)
- 2.SkydroidFpvTest: [适用于T10,T12,H12,H30串口连接方式 ](https://gitee.com/skydroid/SkydroidFpvTest)
- 3.SkydroidH12Demo: [H12数传图传SDKDemo(旧版,不推荐,后续不再维护)](https://gitee.com/skydroid/SkydroidH12Demo)
- 4.SkydroidDemo: [H16及H30安卓开发示例](https://gitee.com/skydroid/SkydroidDemo)
- 5.FPVPlayerDemo: [云卓图传播放器Demo](https://gitee.com/skydroid/fpv-player-demo)
| Demo | RCSDK | SkydroidFpvTest | SkydroidH12Demo
旧版 | SkydroidDemo | FPV-Player
网口 图传 |
| :----: | :----: | :----: | :----: | :----: | :----: |
| 适用于 |H12、H12Pro、H16
后续会新增H30| T10、T12、H12、H30 | T10、T12、H12 | H16、H30 | H12Pro、H16、H30 |
| T10,T12图传 | ✘ | ✔
USB 图传 | ✔
USB 图传 | ✘ | ✘ |
| H12数传 | ✔ | ✔ | ✔ | ✘ | ✘ |
| H12图传 | ✘ | ✔
串口 图传 | ✔
串口 图传 | ✘ | ✘ |
| H12Pro数传 | ✔ | ✘ | ✘ | ✘ | ✘ |
| H12Pro图传 | ✘ | ✘ | ✘ | ✘ | ✔ |
| H16数传 | ✔ | ✘ | ✘ | ✔
舵量、手型 | ✘ |
| H16图传 | ✘ | ✘ | ✘ | ✔
网口 图传 | ✔ |
| H30数传 | ✔ | ✔ | ✘ | ✔
舵量、手型、信号 | ✘ |
| H30图传 | ✘ | ✘ | ✘ | ✔
网口 图传 | ✔ |
| 遥控调参 | ✔
支持助手功能 | ✘ | ✘ | ✘ | ✘ |
| 云台控制 | ✘ | ✔ | ✘ | ✘ | ✔ |
---
# H16及H30安卓开发示例

## H16通讯方式
### 天空端数传接口
##### 天空端有2路串口,均具备透传功能

* uart0地址:通过本地 UDP 14551 端口接收数据,通过本地 UDP 14552 端口发送数据。
默认波特率 57600
* uart1 地址:通过本地 UDP 13551 端口接收数据,通过本地 UDP 13552 端口发送数据。
默认波特率 115200
##### 串口调用示例代码
1. 创建连接
```
try {
var datagramSocket = DatagramSocket(14551)
datagramSocket.connect(InetAddress.getByName("127.0.0.1"), 14552)
} catch (e: IOException) {
e.printStackTrace()
}
```
2. 读取数据
```
var buffer = ByteArray(256)
var receivePacket = DatagramPacket(buffer , buffer.size)
datagramSocket.receive(receivePacket)
```
3. 发送数据
```
var data = "hello uart0".toByteArray()
var packet = DatagramPacket( data, data.size)
packet.data = data
datagramSocket?.send(packet)
```
4. 关闭连接
```
datagramSocket.close()
```
----
### 遥控器通讯串口
##### 获取遥控器相关数据
与遥控器通讯采用LocalSocket交互方式。数据传输私有协议,详情请见协议文档
* uart0:用于获取遥控器舵量值,bindCode为"uart0app";uart0为单向通讯,只用来读取摇杆舵量值,不支持数据的写入。
* uart3:用于 读取设置手型, 获取遥控器SN;bindCode为"uart3app",connectCode为"uart3endpoint";双向通讯可收发
##### LocalSocket调用示例代码
1. 创建连接
```
try {
var localSocket = LocalSocket(LocalSocket.SOCKET_DGRAM)
localSocket.bind(LocalSocketAddress("uart3app"))
//uart0 单向通讯 所以不需要 调用connect
localSocket.connect(LocalSocketAddress("uart3endpoint"))
} catch (e: IOException) {
e.printStackTrace()
}
```
2. 读取数据
```
try {
var buffer = ByteArray(1024)
localSocket.inputStream.read(buffer)
} catch (e: IOException) {
e.printStackTrace()
}
```
3. 发送数据
```
try {
var buffer = ByteArray(1024)
localSocket.outputStream.write(buffer)
} catch (e: IOException) {
e.printStackTrace()
}
```
4. 关闭连接
```
try {
localSocket?.shutdownInput()
} catch (e: IOException) {
e.printStackTrace()
}
try {
localSocket?.shutdownOutput()
} catch (e: IOException) {
e.printStackTrace()
}
try {
localSocket?.close()
} catch (e: IOException) {
e.printStackTrace()
}
try {
localSocket?.inputStream?.close()
} catch (e: IOException) {
e.printStackTrace()
}
try {
localSocket?.outputStream?.close()
} catch (e: IOException) {
e.printStackTrace()
}
```
----
### 遥控器通讯协议
遥控器通讯协议分为2种
1. 用于解析遥控器舵量,帧头为"SKYDROID:" (目前只用在舵量上)
```
遥控器回复: "SKYDROID:" + 0xB1 + 数据len + 数据 + SUM(BCC异或校验)
```
2. 用于获取设置手型等,帧头为"fengyingdianzi:"
```
帧格式:“fengyingdianzi:” + FUN + LEN + DATA + SUM
“fengyingdianzi:” 帧头,字符串
FUN 功能字,可以是 0x00到0xFF,代表帧的含义;
LEN DATA的长度(不包括帧头、FUN、LEN、SUM)。
DATA 数据,1~255字节
SUM 包括帧头一直到DATA最后一字节的BCC校验和,uint8格式
例:
APP发送: “fengyingdianzi:” + 0xA9 +2 + Option1 + Option2 +SUM
遥控器回复: “fengyingdianzi:” + 0xA9 + 2 + ‘O’ + ‘K’ + SUM
```
---
## H30通讯方式

### 天空端数传接口
##### 天空端有2路串口,均具备透传功能

如上图:1号接口 表示uart0,1号接口表示 uart1
* uart0地址:通过TCP 访问192.168.144.101:14550端口进行数据收发
默认波特率 57600
* uart1 地址:通过TCP 访问192.168.144.101:14551端口进行数据收发
默认波特率 115200
##### 串口调用示例代码
1. 创建连接
```
val CONNECTION_TIMEOUT = 20 * 1000 //20s
try {
var socket = Socket()
socket.connect(new InetSocketAddress("192.168.144.101", 14550), CONNECTION_TIMEOUT);
var outputStream:BufferedOutputStream = BufferedOutputStream((socket.getOutputStream()))
var inputStream:BufferedInputStream = BufferedInputStream((socket.getInputStream()))
} catch (e: IOException) {
e.printStackTrace()
}
```
2. 读取数据
```
var buffer = ByteArray(256)//数组长度自定义
inputStream.read(buffer)
```
3. 发送数据
```
var data = "hello uart0".toByteArray()
outputStream.write(buffer);
outputStream.flush();
```
4. 关闭连接
```
inputStream.close()
outputStream.close()
socket.close()
```
### 遥控器通讯串口
##### 获取遥控器相关数据
与遥控器通讯采用硬件串口交互方式。数据传输私有协议,详情请见协议文档
* uart path "/dev/ttyMSM1",uart baudrate "57600"
##### 串口调用示例代码
1. 创建连接
```
var mSerialPortConnection = SerialPortConnection.newBuilder("/dev/ttyMSM1", 57600).build()
mSerialPortConnection?.setDelegate(object : SerialPortConnection.Delegate {
override fun received(bytes: ByteArray, size: Int) {
//数据回调
}
override fun connect() {
//连接成功回调
}
})
//打开串口
mSerialPortConnection?.openConnection()
```
2. 发送数据
```
var data = "hello uart0".toByteArray()
mSerialPortConnection?.sendData()
```
3. 关闭连接
```
mSerialPortConnection?.closeConnection()
```
### 遥控器通讯协议
遥控器通讯协议
1. 用于获取设置手型等,帧头为"fengyingdianzi:"
```
帧格式:“fengyingdianzi:” + FUN + LEN + DATA + SUM
“fengyingdianzi:” 帧头,字符串
FUN 功能字,可以是 0x00到0xFF,代表帧的含义;
LEN DATA的长度(不包括帧头、FUN、LEN、SUM)。
DATA 数据,1~255字节
SUM 包括帧头一直到DATA最后一字节的BCC校验和,uint8格式
例:
APP发送: “fengyingdianzi:” + 0xA9 +2 + Option1 + Option2 +SUM
遥控器回复: “fengyingdianzi:” + 0xA9 + 2 + ‘O’ + ‘K’ + SUM
```
### H30信号强度
1. 创建连接
```
mSocketATGCS = SocketAT("192.168.144.66",5051)
mSocketATGCS?.openConnect()
```
2. 读取数据(目前数据主要来源于dapr,其中signalStrength为信号强度百分比)
```
mSocketATGCS?.setRadioParameterListener(object:SocketAT.RadioParameterListener{
override fun onDrprListener(datas1: DRPR, datas2: DRPR, signalStrength: Int) {
//解析后 的drpr数据
Log.e("onDrprListener","index:${datas1.index},rssi:${datas1.rssi},rsrp:${datas1.rsrp},rsrq:${datas1.rsrq},snr:${datas1.snr}")
Log.e("onDrprListener","index:${datas2.index},rssi:${datas2.rssi},rsrp:${datas2.rsrp},rsrq:${datas2.rsrq},snr:${datas2.snr}")
}
override fun onDaprListener(datas1: DAPR, datas2: DAPR, signalStrength: Int) {
//解析后 的dapr数据
Log.e("onDrprListener","index:${datas1.index},rssi:${datas1.rssi},rsrp:${datas1.rsrp},rsrq:${datas1.rsrq},snr:${datas1.snr}")
Log.e("onDrprListener","index:${datas2.index},rssi:${datas2.rssi},rsrp:${datas2.rsrp},rsrq:${datas2.rsrq},snr:${datas2.snr}")
}
})
```
3. 发送数据
```
mSocketATGCS?.queryVersion()// 查询版本
mSocketATGCS?.startReportGCS()// 开启上报 信号强度
mSocketATGCS?.stopReportGCS()// 停止上报 信号强度
```
4. 关闭连接
```
mSocketATGCS?.stopReportGCS()
```
----