初始
This commit is contained in:
1
third/plane/dj/constant.go
Normal file
1
third/plane/dj/constant.go
Normal file
@ -0,0 +1 @@
|
||||
package dj
|
1217
third/plane/dj/dj.go
Normal file
1217
third/plane/dj/dj.go
Normal file
File diff suppressed because it is too large
Load Diff
203
third/plane/dj/errorcode.go
Normal file
203
third/plane/dj/errorcode.go
Normal file
@ -0,0 +1,203 @@
|
||||
package dj
|
||||
|
||||
var errorMap map[int]Error
|
||||
|
||||
type Error struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
func InitError() {
|
||||
errorMap = make(map[int]Error)
|
||||
errors := []Error{
|
||||
{0, "成功"},
|
||||
{314000, "设备当前无法支持该操作,建议检查设备当前工作状态"},
|
||||
{314001, "飞行任务下发失败,请稍后重试"},
|
||||
{314002, "飞行任务下发失败,请稍后重试"},
|
||||
{314003, "航线文件格式不兼容,请检查航线文件是否正确"},
|
||||
{314004, "飞行任务下发失败,请稍后重试或重启机场后重试"},
|
||||
{314005, "飞行任务下发失败,请稍后重试或重启机场后重试"},
|
||||
{314006, "飞行器初始化失败,请重启机场后重试"},
|
||||
{314007, "机场传输航线至飞行器失败,请重启机场后重试"},
|
||||
{314008, "飞行器起飞前准备超时,请重启机场后重试"},
|
||||
{314009, "飞行器初始化失败,请重启机场后重试"},
|
||||
{314010, "航线执行失败,请重启机场后重试"},
|
||||
{314011, "机场系统异常,无法获取飞行任务执行结果"},
|
||||
{314012, "飞行器起飞前准备失败,无法执行飞行任务,请重启机场后重试"},
|
||||
{314013, "飞行任务下发失败,机场无法获取到本次飞行任务的航线,无法执行飞行任务,请稍后重试"},
|
||||
{314014, "机场系统异常,飞行任务执行失败,请稍后重试"},
|
||||
{314015, "机场传输精准复拍航线至飞行器失败,无法执行飞行任务,请稍后重试或重启机场后重试"},
|
||||
{314016, "航线文件解析失败,无法执行飞行任务,请检查航线文件"},
|
||||
{314017, "机场系统异常,飞行任务执行失败,请稍后重试"},
|
||||
{314018, "飞行器 RTK 定位异常,无法执行飞行任务,请稍后重试或重启机场后重试"},
|
||||
{314019, "飞行器 RTK 收敛失败,无法执行飞行任务,请稍后重试或重启机场后重试"},
|
||||
{314020, "飞行器不在停机坪正中间或飞行器朝向不正确,无法执行飞行任务,请检查飞行器位置和朝向"},
|
||||
{314021, "飞行器 RTK 定位异常,无法执行飞行任务,请稍后重试或重启机场后重试"},
|
||||
{316001, "飞行器参数配置失败,请重启机场后重试"},
|
||||
{316002, "飞行器参数配置失败,请重启机场后重试"},
|
||||
{316003, "飞行器参数配置失败,请重启机场后重试"},
|
||||
{316004, "飞行器参数配置失败,请重启机场后重试"},
|
||||
{316005, "飞行器 RTK 收敛失败,无法执行飞行任务,请重启机场后重试"},
|
||||
{316006, "飞行器降落前机场未开启舱盖或展开推杆,飞行器无法降落至机场,请尽快至机场部署现场检查飞行器状况"},
|
||||
{316007, "飞行器初始化失败,请重启机场后重试"},
|
||||
{316008, "机场获取飞行器控制权失败,无法执行飞行任务,请确认遥控器未锁定控制权"},
|
||||
{316009, "飞行器电量低于30%,无法执行飞行任务,请充电后重试(建议电量≥50%)"},
|
||||
{316010, "机场未检测到飞行器,无法执行飞行任务,请检查舱内是否有飞行器,机场与飞行器是否已对频,或重启机场后重试"},
|
||||
{316011, "飞行器降落位置偏移过大,请检查飞行器是否需要现场摆正"},
|
||||
{316012, "飞行器起飞前准备失败,无法执行飞行任务,请重启机场后重试"},
|
||||
{316013, "飞行器起飞前准备失败,无法执行飞行任务,请重启机场后重试"},
|
||||
{316014, "飞行器起飞前准备失败,无法执行飞行任务,请重启机场后重试"},
|
||||
{316015, "飞行器 RTK 收敛位置距离机场过远,无法执行飞行任务,请重启机场后重试"},
|
||||
{316016, "飞行器降落至机场超时,可能是机场与飞行器断连导致,请通过直播查看飞行器是否降落至舱内"},
|
||||
{316017, "获取飞行器媒体数量超时,可能是机场与飞行器断连导致,请通过直播查看飞行器是否降落至舱内"},
|
||||
{316018, "飞行任务执行超时,可能是机场与飞行器断连导致,请通过直播查看飞行器是否降落至舱内"},
|
||||
{316019, "服务器内部错误,无法执行飞行任务,请稍后重试"},
|
||||
{316020, "飞行器使用的 RTK 信号源错误,请稍后重试"},
|
||||
{316021, "飞行器 RTK 信号源检查超时,请稍后重试"},
|
||||
{316022, "飞行器无法执行返航指令,请检查飞行器是否已开机,机场与飞行器是否已断连,请确认无以上问题后重试"},
|
||||
{316023, "飞行器无法执行返航指令,飞行器已被 B 控接管,请在 B 控操控飞行器,或关闭 B 控后重试"},
|
||||
{316024, "飞行器执行返航指令失败,请检查飞行器是否已起飞,确认飞行器已起飞后请重试"},
|
||||
{316025, "飞行器参数配置失败,请稍后重试或重启机场后重试"},
|
||||
{316026, "机场急停按钮被按下,无法执行飞行任务,请释放急停按钮后重试"},
|
||||
{316027, "飞行器参数配置超时,请稍后重试或重启机场后重试"},
|
||||
{316029, "机场急停按钮被按下,飞行器将飞往备降点降落,请立即检查飞行器是否已安全降落并将飞行器放回至机场"},
|
||||
{317001, "获取飞行器媒体文件数量失败,请重启机场后重试"},
|
||||
{317002, "飞行器存储格式化失败,飞行器未开机、未连接或未检测到相机,请确认无以上问题后重试,或重启飞行器后重试"},
|
||||
{317003, "飞行器存储格式化失败,请重启飞行器后重试"},
|
||||
{317004, "机场媒体文件格式化失败,请稍后重试或重启机场后重试"},
|
||||
{317005, "飞行器结束录像失败,本次飞行任务的媒体文件可能无法上传"},
|
||||
{319001, "机场作业中或(设备异常反馈)上传日志中,无法执行飞行任务,请等待当前飞行任务或操作执行完成后重试"},
|
||||
{319002, "机场系统运行异常,请重启机场后重试"},
|
||||
{319003, "机场系统运行异常,请重新下发任务"},
|
||||
{319004, "飞行任务执行超时,已自动终止本次飞行任务"},
|
||||
{319005, "云端与机场通信异常,无法执行飞行任务"},
|
||||
{319006, "取消飞行任务失败,飞行任务已经在执行中"},
|
||||
{319007, "修改飞行任务失败,飞行任务已经在执行中"},
|
||||
{319008, "机场时间与云端时间不同步,机场无法执行飞行任务"},
|
||||
{319009, "飞行任务下发失败,请稍后重试或重启机场后重试"},
|
||||
{319010, "机场固件版本过低,无法执行飞行任务,请升级机场固件为最新版本后重试"},
|
||||
{319015, "机场正在初始化中,无法执行飞行任务,请等待机场初始化完成后重试"},
|
||||
{319016, "机场正在执行其他飞行任务,无法执行本次飞行任务"},
|
||||
{319017, "机场正在处理上次飞行任务媒体文件,无法执行本次飞行任务,请稍后重试"},
|
||||
{319018, "机场正在自动导出日志中(设备异常反馈),无法执行飞行任务,请稍后重试"},
|
||||
{319019, "机场正在拉取日志中(设备异常反馈),无法执行飞行任务,请稍后重试"},
|
||||
{319025, "机场未准备完成,无法执行云端下发的飞行任务,请稍后重试"},
|
||||
{319026, "飞行器电池电量低于用户设置的任务开始执行的电量,请等待充电完成后再执行飞行任务"},
|
||||
{319027, "机场或飞行器剩余存储容量过低,无法执行飞行任务,请等待媒体文件上传,机场和飞行器存储容量释放后再执行飞行任务"},
|
||||
{319999, "机场系统运行异常,请重启机场后重试"},
|
||||
{321000, "航线执行异常,请稍后重试或重启机场后重试"},
|
||||
{321004, "航线文件解析失败,无法执行飞行任务,请检查航线文件"},
|
||||
{321005, "航线缺少断点信息,机场无法执行飞行任务"},
|
||||
{321257, "飞行任务已在执行中,请勿重复执行"},
|
||||
{321258, "飞行任务无法终止,请检查飞行器状态"},
|
||||
{321259, "飞行任务未开始执行,无法终止飞行任务"},
|
||||
{321260, "飞行任务未开始执行,无法中断飞行任务"},
|
||||
{321513, "航线规划高度已超过飞行器限高,机场无法执行飞行任务"},
|
||||
{321514, "任务失败,起点或终点位于限远区域的缓冲区内或超过了限远距离"},
|
||||
{321515, "航线穿过限飞区,机场无法执行飞行任务"},
|
||||
{321517, "飞行器触发避障,飞行任务执行被终止"},
|
||||
{321519, "飞行器接近限飞区或限远距离自动返航,无法完成航线飞行"},
|
||||
{321523, "飞行器起桨失败,请稍后重试,如果仍报错请联系大疆售后。"},
|
||||
{321524, "飞行器起飞前准备失败,可能是飞行器无发定位或档位错误导致,请检查飞行器状态"},
|
||||
{321769, "飞行器卫星定位信号差,无法执行飞行任务,请重启机场后重试"},
|
||||
{321770, "飞行器挡位错误,无法执行飞行任务,请重启机场后重试"},
|
||||
{321771, "飞行器返航点未设置,无法执行飞行任务,请重启机场后重试"},
|
||||
{321772, "飞行器电量低于30%,无法执行飞行任务,请充电后重试(建议电量≥50%)"},
|
||||
{321773, "飞行器执行飞行任务过程中低电量返航,无法完成航线飞行"},
|
||||
{321775, "飞行器航线飞行过程中失联,无法完成航线飞行"},
|
||||
{321776, "飞行器 RTK 收敛失败,无法执行飞行任务,请重启机场后重试"},
|
||||
{321777, "飞行器未悬停,无法开始执行飞行任务"},
|
||||
{321778, "用户使用 B 控操控飞行器起桨,机场无法执行飞行任务"},
|
||||
{322282, "机场执行飞行任务过程中被中断,飞行器被云端用户或B控接管"},
|
||||
{322283, "机场执行飞行任务过程中被用户触发返航,无法完成航线飞行"},
|
||||
{322539, "航线的断点信息错误,机场无法执行飞行任务"},
|
||||
{324012, "日志压缩过程超时,所选日志过多,请减少选择的日志后重试"},
|
||||
{324013, "设备日志列表获取失败,请稍后重试"},
|
||||
{324014, "设备日志列表为空,请刷新页面或重启机场后重试"},
|
||||
{324015, "飞行器已关机或未连接,无法获取日志列表,请确认飞行器在舱内,通过远程调试将飞行器开机后重试"},
|
||||
{324016, "机场存储空间不足,日志压缩失败,请清理机场存储空间或稍后重试"},
|
||||
{324017, "日志压缩失败,无法获取所选飞行器日志,请刷新页面或重启机场后重试"},
|
||||
{324018, "日志文件拉取失败,导致本次设备异常反馈上传失败,请稍后重试或重启机场后重试"},
|
||||
{324019, "因机场网络异常,日志上传失败,请稍后重试。如果连续多次出现该问题,请联系代理商或大疆售后进行网络排障"},
|
||||
{325001, "云端下发给机场的命令不符合格式要求,机场无法执行"},
|
||||
{327500, "飞行器镜头除雾失败,请稍后重试"},
|
||||
{386535, "航线执行异常,请稍后重试或重启机场后重试"},
|
||||
{513001, "直播失败,飞行器不存在或飞行器类型错误"},
|
||||
{513002, "直播失败,相机不存在或相机类型错误"},
|
||||
{513003, "相机已经在直播中,请勿重复开启直播"},
|
||||
{513005, "直播失败,直播参数清晰度设置错误"},
|
||||
{513005, "直播失败,直播参数清晰度设置错误"},
|
||||
{513006, "操作失败,相机未开启直播"},
|
||||
{513008, "直播失败,设备端图传数据异常"},
|
||||
{513010, "直播失败,设备无法联网"},
|
||||
{513011, "操作失败,设备未开启直播"},
|
||||
{513012, "操作失败,设备已在直播中,不支持切换镜头"},
|
||||
{513013, "直播失败,直播使用的视频传输协议不支持"},
|
||||
{513014, "直播失败,直播参数错误或者不完整"},
|
||||
{513015, "直播异常,网络卡顿"},
|
||||
{513016, "直播异常,视频解码失败"},
|
||||
{513099, "直播失败,请稍后重试"},
|
||||
{514100, "机场运行异常,请重启机场后重试"},
|
||||
{514101, "推杆闭合失败,请检查停机坪上是否存在异物,飞行器方向是否放反,或重启机场后重试"},
|
||||
{514102, "推杆展开失败,请检查停机坪上是否存在异物,或重启机场后重试"},
|
||||
{514103, "飞行器电量低于30%,无法执行飞行任务,请充电后重试(建议电量≥50%)"},
|
||||
{514104, "飞行器电池开始充电失败,请重启机场后重试"},
|
||||
{514105, "飞行器电池停止充电失败,请重启机场后重试"},
|
||||
{514106, "飞行器电源控制异常,请重启机场后重试"},
|
||||
{514107, "舱盖开启失败,请检查舱盖周围是否存在异物,或重启机场后重试"},
|
||||
{514108, "舱盖关闭失败,请检查舱盖周围是否存在异物,或重启机场后重试"},
|
||||
{514109, "飞行器开机失败,请重启机场后重试"},
|
||||
{514110, "飞行器关机失败,请重启机场后重试"},
|
||||
{514111, "飞行器慢转收桨控制异常,请重启机场后重试"},
|
||||
{514112, "飞行器慢转收桨控制异常,请重启机场后重试"},
|
||||
{514113, "机场推杆与飞行器无法连接,请检查飞行器是否在舱内,推杆闭合时是否被卡住,充电连接器是否脏污或损坏"},
|
||||
{514114, "获取飞行器电源状态失败,请重启机场后重试"},
|
||||
{514116, "无法执行当前操作,机场正在执行其他控制指令,请稍后重试"},
|
||||
{514117, "舱盖开启或关闭未到位,请重启机场后重试"},
|
||||
{514118, "推杆展开或闭合未到位,请重启机场后重试"},
|
||||
{514120, "机场与飞行器断连,请重启机场后重试或重新对频"},
|
||||
{514121, "机场急停按钮被按下,请释放急停按钮"},
|
||||
{514122, "获取飞行器充电状态失败,请重启机场后重试"},
|
||||
{514123, "飞行器电池电量过低无法开机"},
|
||||
{514124, "获取飞行器电池信息失败,无法执行飞行任务,请重启机场后重试"},
|
||||
{514125, "飞行器电池电量已接近满电状态,无法开始充电,请使用至95%以下再进行充电"},
|
||||
{514134, "雨量过大,机场无法执行飞行任务,请稍后重试"},
|
||||
{514135, "风速过大≥12m/s,机场无法执行飞行任务,请稍后重试"},
|
||||
{514136, "机场供电断开,机场无法执行飞行任务,请恢复机场供电后重试"},
|
||||
{514137, "环境温度过低<-20℃,机场无法执行飞行任务,请稍后重试"},
|
||||
{514138, "飞行器电池正在保养中,机场无法执行飞行任务,请等待保养结束后重试"},
|
||||
{514139, "飞行器电池无法执行保养指令,飞行器电池无需保养"},
|
||||
{514140, "飞行器电池无法执行保养指令,飞行器电池无需保养"},
|
||||
{514141, "机场系统运行异常,请重启机场后重试"},
|
||||
{514142, "飞行器起飞前,机场推杆与飞行器无法连接,请检查飞行器是否在舱内,推杆闭合时是否被卡住,充电连接器是否脏污或损坏"},
|
||||
{514143, "推杆未闭合或闭合不到位,请稍后重试或重启机场后重试"},
|
||||
{514144, "舱盖未关闭或关闭不到位,请稍后重试或重启机场后重试"},
|
||||
{514145, "机场处于现场调试中,无法执行当前操作或执行飞行任务,请断开遥控器和机场的数据线连接后重试"},
|
||||
{514146, "机场处于远程调试中,无法执行飞行任务,请退出远程调试后重试"},
|
||||
{514147, "设备升级中,无法执行飞行任务,请等待升级完成后重试"},
|
||||
{514148, "机场已经在作业中,无法进行远程调试或再次执行飞行任务,请等待当前任务执行完成后重试"},
|
||||
{514149, "机场系统运行异常,无法执行飞行任务,请重启机场后重试"},
|
||||
{514150, "设备重启中,无法执行飞行任务,请等待重启完成后重试"},
|
||||
{514151, "设备升级中,无法执行设备重启指令,请等待升级完成后重试"},
|
||||
{514153, "机场已退出远程调试模式,无法执行当前操作"},
|
||||
{514170, "机场系统初始化中,无法执行当前操作或指令,请等待机场系统初始化完成后重试"},
|
||||
{514171, "云端下发给机场的命令不符合格式要求,机场无法执行"},
|
||||
{514180, "停止空调制冷或停止空调制热失败,请稍后重试"},
|
||||
{514181, "开启空调制冷失败,请稍后重试"},
|
||||
{514182, "开启空调制热失败,请稍后重试"},
|
||||
{514183, "开启空调除湿失败,请稍后重试"},
|
||||
{514184, "当前温度低于 0 ℃,无法开启空调制冷"},
|
||||
{514185, "当前温度高于 45 ℃,无法开启空调制热"},
|
||||
{514300, "网关异常"},
|
||||
{514301, "请求超时,连接断开"},
|
||||
{514302, "网络证书异常,连接失败"},
|
||||
{514303, "网络异常,连接断开"},
|
||||
{514304, "机场请求被拒,连接失败"},
|
||||
}
|
||||
for _, e := range errors {
|
||||
errorMap[e.Code] = e
|
||||
}
|
||||
}
|
||||
func GetErrorMap() map[int]Error {
|
||||
return errorMap
|
||||
}
|
259
third/plane/dj/minio.go
Normal file
259
third/plane/dj/minio.go
Normal file
@ -0,0 +1,259 @@
|
||||
package dj
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
awscs "github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/sts"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/minio/minio-go/v7"
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
//// minio的配置信息
|
||||
//const (
|
||||
// Endpoint string = coryCommon.Global + ":9999"
|
||||
// AccessKeyID string = "admin"
|
||||
// SecretAccessKey string = "12345678"
|
||||
// BucketName string = "cory-create"
|
||||
// RoleARN string = "arn:aws:s3:::cory-create/*"
|
||||
// RoleSessionName string = "anysession"
|
||||
// Region string = "cn-chengdu"
|
||||
// UseSSL bool = true
|
||||
// DurationSeconds int64 = 3600
|
||||
//
|
||||
// // Endpoint string = "jl.yj-3d.com:8154"
|
||||
// // AccessKeyID string = "minioadmin"
|
||||
// // SecretAccessKey string = "minioadmin"
|
||||
// // BucketName string = "cory-create"
|
||||
// // RoleARN string = "arn:aws:s3:::cory-create/*"
|
||||
// // RoleSessionName string = "anysession"
|
||||
// // Region string = "cn-chengdu"
|
||||
// // UseSSL bool = true
|
||||
// // DurationSeconds int64 = 3600
|
||||
//)
|
||||
|
||||
var (
|
||||
Endpoint string
|
||||
AccessKeyID string
|
||||
SecretAccessKey string
|
||||
BucketName string
|
||||
RoleARN string
|
||||
RoleSessionName string
|
||||
Region string
|
||||
UseSSL bool
|
||||
DurationSeconds int64
|
||||
)
|
||||
|
||||
func init() {
|
||||
Endpoint = g.Cfg().MustGet(context.Background(), "minio.endpoint").String()
|
||||
AccessKeyID = g.Cfg().MustGet(context.Background(), "minio.accessKeyID").String()
|
||||
SecretAccessKey = g.Cfg().MustGet(context.Background(), "minio.secretAccessKey").String()
|
||||
BucketName = g.Cfg().MustGet(context.Background(), "minio.bucketName").String()
|
||||
RoleSessionName = g.Cfg().MustGet(context.Background(), "minio.roleSessionName").String()
|
||||
Region = g.Cfg().MustGet(context.Background(), "minio.region").String()
|
||||
UseSSL = g.Cfg().MustGet(context.Background(), "minio.useSSL").Bool()
|
||||
DurationSeconds = g.Cfg().MustGet(context.Background(), "minio.durationSeconds").Int64()
|
||||
RoleARN = g.Cfg().MustGet(context.Background(), "minio.roleARN").String()
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
IsEnablingSSL = false //是否开启SSL安全 (只针对初始化客户端)
|
||||
)
|
||||
|
||||
// PublicMinioClient 初始化MinIO客户端
|
||||
func PublicMinioClient() (minioClient *minio.Client, err error) {
|
||||
// 获取临时凭证
|
||||
token, accessKey, secretAccessKey := MinioVoucher()
|
||||
// 初始化MinIO客户端
|
||||
minioClient, err = minio.New(Endpoint, &minio.Options{
|
||||
Creds: credentials.NewStaticV4(accessKey, secretAccessKey, token),
|
||||
Secure: IsEnablingSSL,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// MinioVoucher 获取minio的临时凭证
|
||||
func MinioVoucher() (sessionToken, accessKey, secretKey string) {
|
||||
// 创建AWS会话
|
||||
sess, err := session.NewSession(&aws.Config{
|
||||
Endpoint: aws.String(Endpoint),
|
||||
DisableSSL: aws.Bool(UseSSL),
|
||||
Region: aws.String(Region),
|
||||
Credentials: awscs.NewStaticCredentials(AccessKeyID, SecretAccessKey, ""),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("创建AWS会话错误:%v", err)
|
||||
return
|
||||
}
|
||||
// 创建STS服务客户端
|
||||
stsSvc := sts.New(sess)
|
||||
|
||||
// 获取STS凭证
|
||||
input := &sts.AssumeRoleInput{
|
||||
RoleArn: aws.String(RoleARN),
|
||||
RoleSessionName: aws.String(RoleSessionName),
|
||||
DurationSeconds: aws.Int64(DurationSeconds),
|
||||
}
|
||||
result, err := stsSvc.AssumeRole(input)
|
||||
if err != nil {
|
||||
fmt.Println("获取STS凭证错误:", err)
|
||||
return
|
||||
}
|
||||
// 获取STS凭证的Token、AccessKey和SecretKey
|
||||
sessionToken = *result.Credentials.SessionToken
|
||||
accessKey = *result.Credentials.AccessKeyId
|
||||
secretKey = *result.Credentials.SecretAccessKey
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
TheTemporaryAccessUrlIsObtainedBasedOnThePrefixOfTheSpecifiedBucket 根据指定桶的前缀获取到临时访问URL
|
||||
bucketName:桶名
|
||||
prefix:前缀
|
||||
expiry:URL能够访问的时间(最长7天或至少1秒) expiry := 3 * 24 * time.Hour 3天时间访问Url
|
||||
isRecursion:是否递归
|
||||
*/
|
||||
func TheTemporaryAccessUrlIsObtainedBasedOnThePrefixOfTheSpecifiedBucket(ctx context.Context, minioClient *minio.Client, bucketName string, prefix string, expiry time.Duration, isRecursion bool) (url []string) {
|
||||
//1、获取递归集
|
||||
objectSet := ListAndGenerateURLs(ctx, minioClient, bucketName, prefix, isRecursion)
|
||||
//2、根据集获取到临时可访问的URL
|
||||
for _, object := range objectSet {
|
||||
preSignature := GenerateAnOnlineScopedUrlBasedOnTheObject(ctx, minioClient, bucketName, object.Key, expiry)
|
||||
url = append(url, preSignature)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
DownloadTheFileWithTheSpecifiedPrefixBasedOnTheObjectSet 根据对象集下载指定前缀的文件
|
||||
bucketName:桶名
|
||||
prefix:前缀
|
||||
filePath:下载后保存路径
|
||||
isRecursion:是否递归获取对象集
|
||||
*/
|
||||
func DownloadTheFileWithTheSpecifiedPrefixBasedOnTheObjectSet(ctx context.Context, minioClient *minio.Client, bucketName string, prefix string, filePath string, isRecursion bool) (err error) {
|
||||
objectList := ListAndGenerateURLs(ctx, minioClient, bucketName, prefix, isRecursion)
|
||||
for _, object := range objectList {
|
||||
//split := strings.Split(object.Key, "/")
|
||||
//wz := split[len(split)-1]
|
||||
//fileName := strings.Split(wz, ".")[0]
|
||||
//if strings.Contains(fileName, "W") {
|
||||
// fmt.Println(wz)
|
||||
//}
|
||||
err = minioClient.FGetObject(ctx, bucketName, object.Key, filepath.ToSlash(filePath+"/"+object.Key), minio.GetObjectOptions{})
|
||||
if err != nil {
|
||||
fmt.Println("下载minio资源失败:", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
DeletesTheFileWithTheSpecifiedPrefixBasedOnTheObjectSet 根据对象集删除指定前缀的文件
|
||||
bucketName:桶名
|
||||
prefix:前缀
|
||||
isRecursion:是否递归获取对象集
|
||||
*/
|
||||
func DeletesTheFileWithTheSpecifiedPrefixBasedOnTheObjectSet(ctx context.Context, minioClient *minio.Client, bucketName string, prefix string, isRecursion bool) (err error) {
|
||||
objectList := ListAndGenerateURLs(ctx, minioClient, bucketName, prefix, isRecursion)
|
||||
for _, object := range objectList {
|
||||
err = minioClient.RemoveObject(ctx, bucketName, object.Key, minio.RemoveObjectOptions{})
|
||||
if err != nil {
|
||||
fmt.Println("删除minio资源失败:", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
/*
|
||||
UploadDataAccordingToTemporaryCredentials 根据临时凭证上传数据
|
||||
filePath:本地文件路径
|
||||
objectName:存储到minio的地址(桶+前缀) 示例:cory-create/uav/key.txt
|
||||
*/
|
||||
func UploadDataAccordingToTemporaryCredentials(filePath string, objectName string) (err error) {
|
||||
minioClient, err := PublicMinioClient()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// 打开文件
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
fmt.Println("Error opening file:", err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
// 使用minio-go的PutObject方法上传文件
|
||||
n, err := minioClient.PutObject(context.Background(), BucketName, objectName, file, -1, minio.PutObjectOptions{})
|
||||
if err != nil {
|
||||
fmt.Println("Error uploading file:", err)
|
||||
return
|
||||
}
|
||||
fmt.Printf("Successfully uploaded %s of size %d\n", objectName, n)
|
||||
return err
|
||||
}
|
||||
|
||||
//=========================================================================================================================
|
||||
//=========================================================================================================================
|
||||
//=========================================================================================================================
|
||||
//=========================================================================================================================
|
||||
//=========================================================================================================================
|
||||
//=========================================================================================================================
|
||||
//=========================================================================================================================
|
||||
//=========================================================================================================================
|
||||
|
||||
/*
|
||||
ListAndGenerateURLs 获取指定前缀下的对象集
|
||||
bucketName:桶名
|
||||
prefix:前缀(获取哪个下面的对象集) 示例:"uav/9b0af64e1c274105b157a9781961ed99/DJI_202405170903_001_9b0af64e1c274105b157a9781961ed99"
|
||||
isRecursion:是否递归
|
||||
*/
|
||||
func ListAndGenerateURLs(ctx context.Context, minioClient *minio.Client, bucketName string, prefix string, isRecursion bool) (objectInfo []minio.ObjectInfo) {
|
||||
// 设置递归为 true,以获取所有对象,包括子目录中的对象
|
||||
objectCh := minioClient.ListObjects(ctx, bucketName, minio.ListObjectsOptions{
|
||||
Prefix: prefix,
|
||||
Recursive: isRecursion,
|
||||
})
|
||||
// 等待通道中的对象被填充
|
||||
for object := range objectCh {
|
||||
if object.Err != nil {
|
||||
fmt.Println("获取对象列表失败:", object.Err)
|
||||
continue
|
||||
}
|
||||
objectInfo = append(objectInfo, object)
|
||||
//fmt.Println("对象名称:", object.Key)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GenerateAnOnlineScopedUrlBasedOnTheObject 根据对象集生成可在线访问的URL
|
||||
func GenerateAnOnlineScopedUrlBasedOnTheObject(ctx context.Context, minioClient *minio.Client, bucketName string, objectName string, expiry time.Duration) string {
|
||||
// 生成预签名的 GET URL
|
||||
presignedURL, err := minioClient.PresignedGetObject(ctx, bucketName, objectName, expiry, nil)
|
||||
if err != nil {
|
||||
log.Fatalf("生成预签名 URL 失败:%v", err)
|
||||
}
|
||||
//// 使用预签名 URL 访问对象
|
||||
//resp, err := minioClie.
|
||||
//nt.GetObject(ctx, bucketName, objectName, minio.GetObjectOptions{})
|
||||
//if err != nil {
|
||||
// log.Fatalf("获取对象失败:%v", err)
|
||||
//}
|
||||
//defer resp.Close()
|
||||
return presignedURL.String()
|
||||
}
|
||||
|
||||
// StatObjectFunc 获取对象的元数据
|
||||
func StatObjectFunc(ctx context.Context, minioClient *minio.Client, bucketName string, objectName string) (objInfo minio.ObjectInfo, err error) {
|
||||
objInfo, err = minioClient.StatObject(ctx, bucketName, objectName, minio.GetObjectOptions{})
|
||||
return
|
||||
}
|
88
third/plane/event/event.go
Normal file
88
third/plane/event/event.go
Normal file
@ -0,0 +1,88 @@
|
||||
package event
|
||||
|
||||
// eventHandlerInfo定义了事件处理器的信息
|
||||
type eventHandlerInfo struct {
|
||||
handler EventHandler // 事件处理函数
|
||||
once bool // 是否只执行一次
|
||||
}
|
||||
|
||||
// EventHandler定义了事件处理函数的类型
|
||||
type EventHandler func(params ...any)
|
||||
|
||||
// Event表示一个事件对象
|
||||
type Event struct {
|
||||
handlers []eventHandlerInfo // 事件处理器列表
|
||||
}
|
||||
|
||||
// Attach将事件处理器附加到事件对象中,并返回处理器在列表中的索引
|
||||
func (e *Event) Attach(handler EventHandler) int {
|
||||
handlerInfo := eventHandlerInfo{handler, true} //默认只执行一次
|
||||
for i, h := range e.handlers {
|
||||
if h.handler == nil {
|
||||
e.handlers[i] = handlerInfo
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
||||
e.handlers = append(e.handlers, handlerInfo)
|
||||
|
||||
return len(e.handlers) - 1
|
||||
}
|
||||
|
||||
// Detach从事件对象中移除指定索引处的处理器
|
||||
func (e *Event) Detach(handle int) {
|
||||
e.handlers[handle].handler = nil
|
||||
}
|
||||
|
||||
// Once将事件处理器附加到事件对象中,并将处理器标记为只执行一次
|
||||
func (e *Event) Once(handler EventHandler) {
|
||||
i := e.Attach(handler)
|
||||
e.handlers[i].once = true
|
||||
}
|
||||
|
||||
// EventPublisher表示事件发布者
|
||||
type EventPublisher struct {
|
||||
event Event // 事件对象
|
||||
}
|
||||
|
||||
// Event返回事件对象的指针
|
||||
func (p *EventPublisher) Event() *Event {
|
||||
return &p.event
|
||||
}
|
||||
|
||||
// Publish触发事件,依次执行事件对象中的处理器,并在处理器标记为只执行一次时将其从事件对象中移除
|
||||
func (p *EventPublisher) Publish(params ...any) {
|
||||
for i, h := range p.event.handlers {
|
||||
if h.handler != nil {
|
||||
h.handler(params...)
|
||||
if h.once {
|
||||
p.event.Detach(i)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func GetEvent(fn func(params ...any)) *EventPublisher {
|
||||
publisher := &EventPublisher{}
|
||||
|
||||
// 定义一个事件处理器函数
|
||||
handler := fn
|
||||
// 将事件处理器附加到事件列表中
|
||||
publisher.Event().Attach(handler)
|
||||
return publisher
|
||||
}
|
||||
|
||||
/*func main() {
|
||||
// 在这里编写您的代码逻辑
|
||||
// 创建一个事件发布者
|
||||
publisher := &EventPublisher{}
|
||||
|
||||
// 定义一个事件处理器函数
|
||||
handler := func() {
|
||||
fmt.Println("Event handled!")
|
||||
}
|
||||
// 将事件处理器附加到事件列表中
|
||||
publisher.Event().Attach(handler)
|
||||
// 发布事件
|
||||
publisher.Publish()
|
||||
}*/
|
125
third/plane/globe/globe.go
Normal file
125
third/plane/globe/globe.go
Normal file
@ -0,0 +1,125 @@
|
||||
package globe
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
ALL = -1 //所有
|
||||
ENABLE = 1
|
||||
DISABLE = 0
|
||||
DESC = "desc"
|
||||
ASC = "asc"
|
||||
PAGE = 1
|
||||
PAGESIZE = 10
|
||||
ONLINE = 1
|
||||
OFFLINE = 0
|
||||
DEFAULTPWD = "123456"
|
||||
DEFAULTUSR = "admin"
|
||||
)
|
||||
|
||||
var DepartName = "一级部门" //默认的一级部门名称
|
||||
var IS_OFFLINE_VERSION = true //是否为单机版本
|
||||
const SOURCE = "static/source/"
|
||||
|
||||
type WS_MAP map[string]*ghttp.WebSocket
|
||||
|
||||
var WS_Status_map WS_MAP //状态数据ws
|
||||
var WS_Progress_drone_open_map WS_MAP //飞行器开机进度ws
|
||||
var WS_Progress_drone_close_map WS_MAP //飞行器关机进度ws
|
||||
var WS_Progress_cover_open_map WS_MAP //机库打开舱盖进度ws
|
||||
var WS_Progress_cover_close_map WS_MAP //机库关闭舱盖进度ws
|
||||
var WS_Progress_device_reboot_map WS_MAP //机库重启进度ws
|
||||
var WS_Progress_putter_open_map WS_MAP //推杆展开进度ws
|
||||
var WS_Progress_putter_close_map WS_MAP //推杆闭合进度ws
|
||||
var WS_Reply WS_MAP //状态恢复
|
||||
|
||||
var MutexRw sync.RWMutex //map的读写锁
|
||||
|
||||
const (
|
||||
TILESET = "tileset"
|
||||
BIM = "bim"
|
||||
LAYER = "layer"
|
||||
TERRAIN = "terrain"
|
||||
POINT = "point"
|
||||
LINE = "line"
|
||||
AREA = "area"
|
||||
MODEL = "model"
|
||||
KML = "kml"
|
||||
GEOJSON = "geojson"
|
||||
)
|
||||
|
||||
const (
|
||||
PAK = ".pak"
|
||||
MBTILES = ".mbtiles"
|
||||
CLT = ".clt"
|
||||
JCT = ".jct"
|
||||
)
|
||||
|
||||
var (
|
||||
PORT = "80"
|
||||
HOST = ""
|
||||
PROTOCOL = ""
|
||||
KEY = ""
|
||||
CRT = ""
|
||||
)
|
||||
|
||||
const (
|
||||
HTTP = "http"
|
||||
HTTPS = "https"
|
||||
)
|
||||
|
||||
func GetErrors(msg string) error {
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
func GetAddr() string {
|
||||
//单机版本时 无代理,需要补全地址
|
||||
if IS_OFFLINE_VERSION {
|
||||
return PROTOCOL + "://" + HOST + ":" + PORT + "/"
|
||||
}
|
||||
//网络版时 有代理 不需要补全地址
|
||||
return ""
|
||||
}
|
||||
|
||||
/*clt数据包*/
|
||||
type Tile struct {
|
||||
MD5 string `json:"md5"`
|
||||
PATH string `json:"path"`
|
||||
Tile []byte `json:"tile"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
func RenderData(request *ghttp.Request, data []byte) {
|
||||
request.Response.Header().Set("Cache-Control", "private,max-age="+strconv.Itoa(60*60))
|
||||
request.Response.WriteHeader(http.StatusOK)
|
||||
request.Response.Writer.Write(data)
|
||||
}
|
||||
func CloseDB(db *gorm.DB) {
|
||||
s, err := db.DB()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
s.Close()
|
||||
}
|
||||
|
||||
var IS_AUTH_SUCCESS = false //是否授权通过
|
||||
|
||||
func CheckAuth() bool {
|
||||
return IS_AUTH_SUCCESS
|
||||
}
|
||||
func SetAuth(auth bool) {
|
||||
IS_AUTH_SUCCESS = auth
|
||||
}
|
||||
|
||||
/*坐标点*/
|
||||
type Point struct {
|
||||
Lng float64 `json:"lng" v:"required"`
|
||||
Lat float64 `json:"lat" v:"required"`
|
||||
Alt float64 `json:"alt" v:"required"`
|
||||
}
|
197
third/plane/mqtt/emqx.go
Normal file
197
third/plane/mqtt/emqx.go
Normal file
@ -0,0 +1,197 @@
|
||||
package mqtt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gtimer"
|
||||
"github.com/tiger1103/gfast/v3/third/plane/dj"
|
||||
"github.com/tiger1103/gfast/v3/third/plane/event"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var timer *gtimer.Timer
|
||||
var client mqtt.Client
|
||||
var eventMap map[string]*event.EventPublisher
|
||||
|
||||
const (
|
||||
osd = "osd" //设备端定频向云平台推送的设备属性(properties), 具体内容范围参见物模型内容
|
||||
state = "state" //设备端按需上报向云平台推送的设备属性(properties), 具体内容范围参见物模型内容
|
||||
services_reply = "services_reply" //设备对 service 的回复、处理结果
|
||||
events = "events" //设备端向云平台发送的,需要关注和处理的事件。 比如SD满了,飞机解禁禁飞区等信息(事件范围参见物模型内容)
|
||||
status = "status" //设备上下线、更新拓扑
|
||||
set_reply = "set_reply" //设备属性设置的响应
|
||||
requests = "requests" //设备端向云平台发送请求,为了获取一些信息,比如上传的临时凭证
|
||||
services = "services" //云平台向设备发送的服务(具体service identifier 见物模型内容)。
|
||||
)
|
||||
|
||||
var MsgCallBackMap map[string]CB
|
||||
|
||||
func InitMQTT() {
|
||||
eventMap = make(map[string]*event.EventPublisher)
|
||||
timer = gtimer.New()
|
||||
initMsgs()
|
||||
dj.InitError()
|
||||
connect()
|
||||
}
|
||||
|
||||
func initMsgs() {
|
||||
MsgCallBackMap = make(map[string]CB)
|
||||
msgs := []CB{
|
||||
{osd, dealOsd, nil},
|
||||
{state, deal_state, nil},
|
||||
{requests, deal_requests, nil},
|
||||
{services_reply, deal_services_reply, nil},
|
||||
{status, deal_status, nil},
|
||||
{events, deal_events, nil},
|
||||
{services, deal_services, nil},
|
||||
}
|
||||
for _, msg := range msgs {
|
||||
MsgCallBackMap[msg.Flag] = msg
|
||||
}
|
||||
}
|
||||
|
||||
type CB struct {
|
||||
Flag string
|
||||
Recv func(mqtt.Client, mqtt.Message) //接收消息
|
||||
Reply func(mqtt.Client, mqtt.Message) //回复消息
|
||||
}
|
||||
|
||||
func connect() {
|
||||
host := g.Cfg().MustGet(gctx.New(), "mqtt.host").String()
|
||||
port := g.Cfg().MustGet(gctx.New(), "mqtt.port").String()
|
||||
username := g.Cfg().MustGet(gctx.New(), "mqtt.username").String()
|
||||
password := g.Cfg().MustGet(gctx.New(), "mqtt.password").String()
|
||||
clientid := g.Cfg().MustGet(gctx.New(), "mqtt.clientid").String()
|
||||
topics := g.Cfg().MustGet(gctx.New(), "mqtt.topics").String()
|
||||
fmt.Println(host, port, username, password, clientid, topics, "tcp://"+host+":"+port)
|
||||
opts := mqtt.NewClientOptions()
|
||||
opts.AddBroker("tcp://" + host + ":" + port) // 设置MQTT代理服务器地址
|
||||
opts.SetClientID(clientid) // 设置客户端ID
|
||||
opts.SetPassword(password) // 设置客户端ID
|
||||
opts.SetUsername(username) // 设置客户端ID
|
||||
// 处理消息接收
|
||||
opts.SetDefaultPublishHandler(receiveHandler)
|
||||
opts.SetConnectionLostHandler(disconnected)
|
||||
opts.SetOnConnectHandler(connected)
|
||||
opts.SetKeepAlive(1000 * time.Second) //超时等待,防止客户端掉线
|
||||
opts.SetAutoReconnect(true)
|
||||
client = mqtt.NewClient(opts)
|
||||
// 连接MQTT代理服务器
|
||||
if token := client.Connect(); token.Wait() && token.Error() != nil {
|
||||
panic(token.Error())
|
||||
}
|
||||
arr := strings.Split(topics, ",")
|
||||
for _, topic := range arr {
|
||||
// 订阅主题
|
||||
fmt.Println("订阅主题", topic)
|
||||
if token := client.Subscribe(topic, 0, nil); token.Wait() && token.Error() != nil {
|
||||
fmt.Println(token.Error())
|
||||
}
|
||||
//fmt.Println(topic)
|
||||
}
|
||||
|
||||
//ctx := gctx.New()
|
||||
////格式化
|
||||
//DeviceFormat(ctx, "4SEDL9C001X8GE")
|
||||
//DroneFormat(ctx, "4SEDL9C001X8GE")
|
||||
//DeviceFormat(ctx, "7CTDM4100BG7HV")
|
||||
//DroneFormat(ctx, "7CTDM4100BG7HV")
|
||||
|
||||
//飞机升级
|
||||
//OtaCreateFunc(ctx, "8UUXN4P00A06NK")
|
||||
|
||||
//gtimer.SetTimeout(gctx.New(), 2*time.Second, func(ctx context.Context) {
|
||||
//sn := "4SEDL9C001X8GE"
|
||||
//err, d := speaker_audio_play_start(sn)
|
||||
//if err != nil {
|
||||
// fmt.Println(err)
|
||||
// return
|
||||
//}
|
||||
//整一个pcm的音频文件
|
||||
// point := dj.Point{}
|
||||
// point.Longitude = 106.541923087
|
||||
// point.Latitude = 23.458531397
|
||||
// point.Height = 823.8873291015625 + 10
|
||||
// //err, d := Flight_authority_grab(sn)
|
||||
// //if err != nil {
|
||||
// // return
|
||||
// //}
|
||||
// err, d := Fly_to_point(sn, point)
|
||||
//fmt.Println(d)
|
||||
// fmt.Println(err)
|
||||
//
|
||||
// sn = "4TADL210010014" //中煤广西机库的sn
|
||||
// //// //sn = "4TADL2E001002D" //机库的sn
|
||||
// //// //sn = "1581F5BMD2323001S928" //飞机的sn
|
||||
// ////dev_sn := "1581F5BMD23280014131" //吉林飞机的sn
|
||||
// //dev_sn := "1581F5BMD238V00172JR" //吉林飞机的sn
|
||||
// //camera_index := "165-0-7" //机库的摄像头id
|
||||
// ////camera_index = "53-0-0" //飞机摄像头1的id
|
||||
// //camera_index = "39-0-7" //飞机摄像头2的id
|
||||
// //Debug_mode_open(sn) //调试模式,先调试模式才能飞行器开机,推流不需要調試
|
||||
// //Debug_mode_close(sn)
|
||||
// //err, d := Cover_open(sn) //打开舱盖
|
||||
// //err, d := Cover_close(sn)
|
||||
// //err, d := Drone_open(sn) //飞行器开机
|
||||
// //err, d := Drone_close(sn) //飞行器关机
|
||||
// //err, d := Device_reboot(sn)
|
||||
// //
|
||||
// //fmt.Println(d)
|
||||
// //if err != nil {
|
||||
// // fmt.Println(err)
|
||||
// //} //打开舱盖
|
||||
// ////fmt.Println("打开舱盖")
|
||||
// //err, d := Live_start_push(sn, sn, camera_index)
|
||||
// //err, d := Live_stop_push(sn, sn, camera_index)
|
||||
//
|
||||
// //fmt.Println(d)
|
||||
// //if err != nil {
|
||||
// // fmt.Println(err)
|
||||
// // return
|
||||
// //} //关闭舱盖
|
||||
// ////fmt.Println(d.Data.Result)
|
||||
// //// //device_reboot()
|
||||
// //// //if err != nil {
|
||||
// //// // return
|
||||
// //// //}
|
||||
// //// //fmt.Println(d)
|
||||
// //// //live_stop_push(sn, sn, camera_index)
|
||||
// ////
|
||||
//})
|
||||
}
|
||||
|
||||
func receiveHandler(client mqtt.Client, msg mqtt.Message) {
|
||||
topic := msg.Topic()
|
||||
arrs := strings.Split(topic, "/")
|
||||
|
||||
tp := arrs[len(arrs)-1]
|
||||
if v, ok := MsgCallBackMap[tp]; ok {
|
||||
v.Recv(client, msg)
|
||||
if v.Reply != nil {
|
||||
v.Reply(client, msg)
|
||||
}
|
||||
} else {
|
||||
fmt.Println("非法topic", topic)
|
||||
}
|
||||
}
|
||||
func disconnected(client mqtt.Client, err error) {
|
||||
fmt.Println("断开了,准备重连")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
g.Log("uav").Error(gctx.New(), err)
|
||||
}
|
||||
|
||||
timer.Start()
|
||||
timer.Add(gctx.New(), time.Second*5, func(ctx context.Context) {
|
||||
connect()
|
||||
})
|
||||
}
|
||||
|
||||
func connected(client mqtt.Client) {
|
||||
fmt.Println("链接成功")
|
||||
timer.Stop()
|
||||
}
|
31
third/plane/mqtt/entity.go
Normal file
31
third/plane/mqtt/entity.go
Normal file
@ -0,0 +1,31 @@
|
||||
package mqtt
|
||||
|
||||
// LiveStreamingCapabilityUpdateEntity 直播能力更新 UP
|
||||
type LiveStreamingCapabilityUpdateEntity struct {
|
||||
Tid string `json:"tid"`
|
||||
Bid string `json:"bid"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Gateway string `json:"gateway"`
|
||||
Method string `json:"method"`
|
||||
Data struct {
|
||||
LiveCapacity struct {
|
||||
AvailableVideoNumber int `json:"available_video_number"`
|
||||
CoexistVideoNumberMax int `json:"coexist_video_number_max"`
|
||||
DeviceList []struct {
|
||||
Sn string `json:"sn"`
|
||||
AvailableVideoNumber int `json:"available_video_number"`
|
||||
CoexistVideoNumberMax int `json:"coexist_video_number_max"`
|
||||
CameraList []struct {
|
||||
CameraIndex string `json:"camera_index"`
|
||||
AvailableVideoNumber int `json:"available_video_number"`
|
||||
CoexistVideoNumberMax int `json:"coexist_video_number_max"`
|
||||
VideoList []struct {
|
||||
VideoIndex string `json:"video_index"`
|
||||
VideoType string `json:"video_type"`
|
||||
SwitchableVideoTypes []string `json:"switchable_video_types"`
|
||||
} `json:"video_list"`
|
||||
} `json:"camera_list"`
|
||||
} `json:"device_list"`
|
||||
} `json:"live_capacity"`
|
||||
} `json:"data"`
|
||||
}
|
1282
third/plane/mqtt/msg_deal.go
Normal file
1282
third/plane/mqtt/msg_deal.go
Normal file
File diff suppressed because it is too large
Load Diff
334
third/plane/plane.go
Normal file
334
third/plane/plane.go
Normal file
@ -0,0 +1,334 @@
|
||||
package plane
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/tiger1103/gfast/v3/internal/app/system/service"
|
||||
"github.com/tiger1103/gfast/v3/third/plane/dj"
|
||||
"github.com/tiger1103/gfast/v3/third/plane/globe"
|
||||
"github.com/tiger1103/gfast/v3/third/plane/mqtt"
|
||||
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type PLANE struct {
|
||||
}
|
||||
|
||||
func InitPlaneApi(group *ghttp.RouterGroup) {
|
||||
init_map()
|
||||
group.Group("/plane", func(group *ghttp.RouterGroup) {
|
||||
group.Bind(new(PLANE))
|
||||
group.Middleware(service.Middleware().Ctx, service.Middleware().Auth)
|
||||
})
|
||||
}
|
||||
|
||||
func init_map() {
|
||||
globe.WS_Status_map = make(globe.WS_MAP)
|
||||
globe.WS_Progress_drone_open_map = make(globe.WS_MAP)
|
||||
globe.WS_Progress_drone_close_map = make(globe.WS_MAP)
|
||||
globe.WS_Progress_cover_open_map = make(globe.WS_MAP)
|
||||
globe.WS_Progress_cover_close_map = make(globe.WS_MAP)
|
||||
globe.WS_Progress_device_reboot_map = make(globe.WS_MAP)
|
||||
globe.WS_Progress_putter_close_map = make(globe.WS_MAP)
|
||||
globe.WS_Progress_putter_open_map = make(globe.WS_MAP)
|
||||
globe.WS_Reply = make(globe.WS_MAP)
|
||||
}
|
||||
|
||||
type UsualRes struct {
|
||||
}
|
||||
|
||||
type DeviceGoHomeReq struct {
|
||||
g.Meta `path:"gohome" summary:"一键返航" method:"post" tags:"无人机相关"`
|
||||
GatewaySn string `json:"gateway_sn" v:"required" dc:"机库sn"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) DeviceGoHome(ctx context.Context, req *DeviceGoHomeReq) (res *UsualRes, err error) {
|
||||
err, d := mqtt.Return_home(ctx, req.GatewaySn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Data.Result > 0 {
|
||||
err = geterror(d.Data.Result)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type DeviceListReq struct {
|
||||
g.Meta `path:"list" summary:"获取飞机列表" method:"get" tags:"无人机相关"`
|
||||
}
|
||||
type DeviceListRes struct {
|
||||
}
|
||||
|
||||
func (receiver PLANE) DeviceList(ctx context.Context, req *DeviceListReq) (res *DeviceListRes, err error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
type DeviceRebootReq struct {
|
||||
g.Meta `path:"device_reboot" summary:"机库重启" method:"post" tags:"无人机相关"`
|
||||
GatewaySn string `json:"gateway_sn" v:"required" dc:"机库sn"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) DeviceReboot(ctx context.Context, req *DeviceRebootReq) (res *UsualRes, err error) {
|
||||
err, d := mqtt.Device_reboot(req.GatewaySn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Data.Result > 0 {
|
||||
err = geterror(d.Data.Result)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type ClosePutterReq struct {
|
||||
g.Meta `path:"close_putter" summary:"关闭推杆" method:"post" tags:"无人机相关"`
|
||||
GatewaySn string `json:"gateway_sn" v:"required" dc:"机库sn"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) ClosePutterReq(ctx context.Context, req *ClosePutterReq) (res *UsualRes, err error) {
|
||||
err, d := mqtt.Putter_close(ctx, req.GatewaySn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Data.Result > 0 {
|
||||
err = geterror(d.Data.Result)
|
||||
return
|
||||
}
|
||||
g.DB().Model("manage_button_state").
|
||||
Where("mq_client_id", req.GatewaySn).
|
||||
Update(g.Map{"push_rod": 2})
|
||||
return
|
||||
}
|
||||
|
||||
type OpenPutterReq struct {
|
||||
g.Meta `path:"open_putter" summary:"打开推杆" method:"post" tags:"无人机相关"`
|
||||
GatewaySn string `json:"gateway_sn" v:"required" dc:"机库sn"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) OpenPutterReq(ctx context.Context, req *OpenPutterReq) (res *UsualRes, err error) {
|
||||
err, d := mqtt.Putter_open(ctx, req.GatewaySn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Data.Result > 0 {
|
||||
err = geterror(d.Data.Result)
|
||||
return
|
||||
}
|
||||
g.DB().Model("manage_button_state").
|
||||
Where("mq_client_id", req.GatewaySn).
|
||||
Update(g.Map{"push_rod": 1})
|
||||
return
|
||||
}
|
||||
|
||||
type OpenChargeReq struct {
|
||||
g.Meta `path:"open_charge" summary:"打开充电" method:"post" tags:"无人机相关"`
|
||||
GatewaySn string `json:"gateway_sn" v:"required" dc:"机库sn"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) OpenChargeReq(ctx context.Context, req *OpenChargeReq) (res *UsualRes, err error) {
|
||||
err, d := mqtt.Charge_open(ctx, req.GatewaySn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Data.Result > 0 {
|
||||
err = geterror(d.Data.Result)
|
||||
return
|
||||
}
|
||||
g.DB().Model("manage_button_state").
|
||||
Where("mq_client_id", req.GatewaySn).
|
||||
Update(g.Map{"recharge": 1})
|
||||
return
|
||||
}
|
||||
|
||||
type CloseChargeReq struct {
|
||||
g.Meta `path:"close_charge" summary:"关闭充电" method:"post" tags:"无人机相关"`
|
||||
GatewaySn string `json:"gateway_sn" v:"required" dc:"机库sn"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) CloseCharge(ctx context.Context, req *CloseChargeReq) (res *UsualRes, err error) {
|
||||
err, d := mqtt.Charge_close(ctx, req.GatewaySn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Data.Result > 0 {
|
||||
err = geterror(d.Data.Result)
|
||||
return
|
||||
}
|
||||
g.DB().Model("manage_button_state").
|
||||
Where("mq_client_id", req.GatewaySn).
|
||||
Update(g.Map{"recharge": 2})
|
||||
return
|
||||
}
|
||||
|
||||
type CloseDroneReq struct {
|
||||
g.Meta `path:"close_drone" summary:"飞行器关机(调试模式下)" method:"post" tags:"无人机相关"`
|
||||
GatewaySn string `json:"gateway_sn" v:"required" dc:"机库sn"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) CloseDrone(ctx context.Context, req *CloseDroneReq) (res *UsualRes, err error) {
|
||||
err, d := mqtt.Drone_close(ctx, req.GatewaySn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Data.Result > 0 {
|
||||
err = geterror(d.Data.Result)
|
||||
return
|
||||
}
|
||||
g.DB().Model("manage_button_state").
|
||||
Where("mq_client_id", req.GatewaySn).
|
||||
Update(g.Map{"power": 2})
|
||||
return
|
||||
}
|
||||
|
||||
type OpenDroneReq struct {
|
||||
g.Meta `path:"open_drone" summary:"飞行器开机(调试模式下)" method:"post" tags:"无人机相关"`
|
||||
GatewaySn string `json:"gateway_sn" v:"required" dc:"机库sn"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) OpenDrone(ctx context.Context, req *OpenDroneReq) (res *UsualRes, err error) {
|
||||
err, d := mqtt.Drone_open(ctx, req.GatewaySn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Data.Result > 0 {
|
||||
err = geterror(d.Data.Result)
|
||||
return
|
||||
}
|
||||
g.DB().Model("manage_button_state").
|
||||
Where("mq_client_id", req.GatewaySn).
|
||||
Update(g.Map{"power": 1})
|
||||
return
|
||||
}
|
||||
|
||||
type CloseCoverReq struct {
|
||||
g.Meta `path:"close_cover" summary:"关闭舱盖(调试模式下)" method:"post" tags:"无人机相关"`
|
||||
GatewaySn string `json:"gateway_sn" v:"required" dc:"机库sn"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) CloseCover(ctx context.Context, req *CloseCoverReq) (res *UsualRes, err error) {
|
||||
err, d := mqtt.Cover_close(ctx, req.GatewaySn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Data.Result > 0 {
|
||||
err = geterror(d.Data.Result)
|
||||
return
|
||||
}
|
||||
g.DB().Model("manage_button_state").
|
||||
Where("mq_client_id", req.GatewaySn).
|
||||
Update(g.Map{"hatch_cover": 2})
|
||||
return
|
||||
}
|
||||
|
||||
type OpenCoverReq struct {
|
||||
g.Meta `path:"open_cover" summary:"打开舱盖(调试模式下)" method:"post" tags:"无人机相关"`
|
||||
GatewaySn string `json:"gateway_sn" v:"required" dc:"机库sn"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) OpenCover(ctx context.Context, req *OpenCoverReq) (res *UsualRes, err error) {
|
||||
err, d := mqtt.Cover_open(ctx, req.GatewaySn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Data.Result > 0 {
|
||||
err = geterror(d.Data.Result)
|
||||
return
|
||||
}
|
||||
g.DB().Model("manage_button_state").
|
||||
Where("mq_client_id", req.GatewaySn).
|
||||
Update(g.Map{"hatch_cover": 1})
|
||||
return
|
||||
}
|
||||
|
||||
type CloseDebugReq struct {
|
||||
g.Meta `path:"close_debug" summary:"关闭调试模式" method:"post" tags:"无人机相关"`
|
||||
GatewaySn string `json:"gateway_sn" v:"required" dc:"机库sn"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) CloseDebug(ctx context.Context, req *CloseDebugReq) (res *UsualRes, err error) {
|
||||
err, d := mqtt.Debug_mode_close(ctx, req.GatewaySn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Data.Result > 0 {
|
||||
err = geterror(d.Data.Result)
|
||||
return
|
||||
}
|
||||
g.DB().Model("manage_button_state").
|
||||
Where("mq_client_id", req.GatewaySn).
|
||||
Update(g.Map{"debug": 2})
|
||||
return
|
||||
}
|
||||
|
||||
type OpenDebugReq struct {
|
||||
g.Meta `path:"open_debug" summary:"打开调试模式" method:"post" tags:"无人机相关"`
|
||||
GatewaySn string `json:"gateway_sn" v:"required" dc:"机库sn"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) OpenDebug(ctx context.Context, req *OpenDebugReq) (res *UsualRes, err error) {
|
||||
err, d := mqtt.Debug_mode_open(ctx, req.GatewaySn)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Data.Result > 0 {
|
||||
err = geterror(d.Data.Result)
|
||||
return
|
||||
}
|
||||
g.DB().Model("manage_button_state").
|
||||
Where("mq_client_id", req.GatewaySn).
|
||||
Update(g.Map{"debug": 1})
|
||||
return
|
||||
}
|
||||
|
||||
type StopLiveReq struct {
|
||||
g.Meta `path:"stop_live" summary:"停止直播" method:"post" tags:"无人机相关"`
|
||||
GatewaySn string `json:"gateway_sn" v:"required" dc:"机库sn"`
|
||||
Devsn string `json:"devsn" v:"required" dc:"设备sn"`
|
||||
Camera_index string `json:"camera_index" v:"required" dc:"摄像头"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) StopLive(ctx context.Context, req *StopLiveReq) (res *UsualRes, err error) {
|
||||
err, d := mqtt.Live_stop_push(req.GatewaySn, req.Devsn, req.Camera_index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Data.Result > 0 {
|
||||
err = geterror(d.Data.Result)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type StartLiveReq struct {
|
||||
g.Meta `path:"start_live" summary:"开始直播" method:"post" tags:"无人机相关"`
|
||||
GatewaySn string `json:"gateway_sn" v:"required" dc:"机库sn"`
|
||||
Devsn string `json:"devsn" v:"required" dc:"设备sn"`
|
||||
Camera_index string `json:"camera_index" v:"required" dc:"摄像头"`
|
||||
}
|
||||
type StartLiveRes struct {
|
||||
Url string `json:"url"`
|
||||
}
|
||||
|
||||
func geterror(code int) error {
|
||||
if v, ok := dj.GetErrorMap()[code]; ok {
|
||||
return globe.GetErrors(v.Msg)
|
||||
} else {
|
||||
return globe.GetErrors("未知错误:" + strconv.Itoa(code))
|
||||
}
|
||||
}
|
||||
|
||||
func (receiver PLANE) StartLive(ctx context.Context, req *StartLiveReq) (res *StartLiveRes, err error) {
|
||||
err, d := mqtt.Live_start_push(req.GatewaySn, req.Devsn, req.Camera_index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if d.Data.Result > 0 && d.Data.Result != 513003 /*正在直播中 ,可直接返回地址*/ {
|
||||
err = geterror(d.Data.Result)
|
||||
return
|
||||
}
|
||||
res = &StartLiveRes{}
|
||||
res.Url = d.Data.Url
|
||||
return
|
||||
}
|
107
third/plane/progress.go
Normal file
107
third/plane/progress.go
Normal file
@ -0,0 +1,107 @@
|
||||
package plane
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/tiger1103/gfast/v3/third/plane/globe"
|
||||
)
|
||||
|
||||
type Progerss_putter_close_Req struct {
|
||||
g.Meta `path:"progress/putter_close" summary:"推杆闭合进度" method:"get" tags:"无人机进度数据相关(ws)"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) Progerss_putter_close(ctx context.Context, req *Progerss_putter_close_Req) (res *UsualRes, err error) {
|
||||
return save_ws(ctx, &globe.WS_Progress_putter_close_map)
|
||||
}
|
||||
|
||||
type Progerss_putter_open_Req struct {
|
||||
g.Meta `path:"progress/putter_open" summary:"推杆展开进度" method:"get" tags:"无人机进度数据相关(ws)"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) Progerss_putter_open(ctx context.Context, req *Progerss_putter_open_Req) (res *UsualRes, err error) {
|
||||
return save_ws(ctx, &globe.WS_Progress_putter_open_map)
|
||||
}
|
||||
|
||||
type Progerss_Reply_Req struct {
|
||||
g.Meta `path:"progress/err_reply" summary:"up回复错误状态" method:"get" tags:"无人机进度数据相关(ws)"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) Progerss_Reply(ctx context.Context, req *Progerss_Reply_Req) (res *UsualRes, err error) {
|
||||
return save_ws(ctx, &globe.WS_Reply)
|
||||
}
|
||||
|
||||
type Progerss_device_reboot_Req struct {
|
||||
g.Meta `path:"progress/device_reboot" summary:"机库重启进度推送" method:"get" tags:"无人机进度数据相关(ws)"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) Progerss_device_reboot(ctx context.Context, req *Progerss_device_reboot_Req) (res *UsualRes, err error) {
|
||||
return save_ws(ctx, &globe.WS_Progress_device_reboot_map)
|
||||
}
|
||||
|
||||
type Progerss_cover_close_Req struct {
|
||||
g.Meta `path:"progress/cover_close" summary:"机库关闭舱盖进度推送" method:"get" tags:"无人机进度数据相关(ws)"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) Progerss_cover_close(ctx context.Context, req *Progerss_cover_close_Req) (res *UsualRes, err error) {
|
||||
return save_ws(ctx, &globe.WS_Progress_cover_close_map)
|
||||
}
|
||||
|
||||
type Progerss_cover_open_Req struct {
|
||||
g.Meta `path:"progress/cover_open" summary:"机库打开舱盖进度推送" method:"get" tags:"无人机进度数据相关(ws)"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) Progerss_cover_open(ctx context.Context, req *Progerss_cover_open_Req) (res *UsualRes, err error) {
|
||||
return save_ws(ctx, &globe.WS_Progress_cover_open_map)
|
||||
}
|
||||
|
||||
type Progerss_drone_close_Req struct {
|
||||
g.Meta `path:"progress/drone_close" summary:"飞行器关机进度推送" method:"get" tags:"无人机进度数据相关(ws)"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) Progerss_drone_close(ctx context.Context, req *Progerss_drone_close_Req) (res *UsualRes, err error) {
|
||||
return save_ws(ctx, &globe.WS_Progress_drone_close_map)
|
||||
}
|
||||
|
||||
type Progerss_drone_open_Req struct {
|
||||
g.Meta `path:"progress/drone_open" summary:"飞行器开机进度推送" method:"get" tags:"无人机进度数据相关(ws)"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) Progerss_drone_open(ctx context.Context, req *Progerss_drone_open_Req) (res *UsualRes, err error) {
|
||||
return save_ws(ctx, &globe.WS_Progress_drone_open_map)
|
||||
}
|
||||
|
||||
type DeviceStatusReq struct {
|
||||
g.Meta `path:"device_status" summary:"ws推送飞机状态" method:"get" tags:"无人机进度数据相关(ws)"`
|
||||
}
|
||||
type DeviceStatusRes struct {
|
||||
Code int `json:"code"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
func (receiver PLANE) DeviceStatus(ctx context.Context, req *DeviceStatusReq) (res *UsualRes, err error) {
|
||||
return save_ws(ctx, &globe.WS_Status_map)
|
||||
}
|
||||
|
||||
func save_ws(ctx context.Context, _map *globe.WS_MAP) (res *UsualRes, err error) {
|
||||
r := ghttp.RequestFromCtx(ctx)
|
||||
ws, err := r.WebSocket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ip := r.Get("token").String()
|
||||
|
||||
globe.MutexRw.Lock()
|
||||
(*_map)[ip] = ws
|
||||
globe.MutexRw.Unlock()
|
||||
fmt.Println("ws连接了", ip)
|
||||
for {
|
||||
_, _, err = ws.ReadMessage()
|
||||
if err != nil {
|
||||
fmt.Println("ws断开了", ip)
|
||||
delete(*_map, ip)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
157
third/plane/wayline/struct/struct.go
Normal file
157
third/plane/wayline/struct/struct.go
Normal file
@ -0,0 +1,157 @@
|
||||
package _struct
|
||||
|
||||
import "encoding/xml"
|
||||
|
||||
// 飞向首航点模式
|
||||
const (
|
||||
Safely = "safely"
|
||||
PointToPoint = "pointToPoint"
|
||||
)
|
||||
|
||||
// 航线结束动作
|
||||
const (
|
||||
GoHome = "goHome"
|
||||
AutoLand = "autoLand"
|
||||
GotoFirstWaypoint = "gotoFirstWaypoint"
|
||||
)
|
||||
|
||||
//失控是否继续执行航线
|
||||
|
||||
const (
|
||||
GoContinue = "goContinue" //继续执行航线
|
||||
ExecuteLostAction = "executeLostAction" //退出航线,执行失控动作
|
||||
)
|
||||
|
||||
// 失控动作类型
|
||||
const (
|
||||
GoBack = "goBack" //返航。飞行器从失控位置飞向起飞点
|
||||
Landing = "landing" //降落。飞行器从失控位置原地降落
|
||||
Hover = "hover" //悬停。飞行器从失控位置悬停
|
||||
)
|
||||
|
||||
// 预定义模板类型
|
||||
const (
|
||||
Waypoint = "waypoint" //航点飞行
|
||||
Mapping2d = "mapping2d" //建图航拍
|
||||
Mapping3d = "mapping3d" //倾斜摄影
|
||||
MappingStrip = "mappingStrip" //航带飞行
|
||||
)
|
||||
|
||||
// Placemark 结构表示 KML 的地点标记
|
||||
type Placemark struct {
|
||||
Point Point `xml:"Point"`
|
||||
Index int `xml:"wpml:index"`
|
||||
EllipsoidHeight float64 `xml:"wpml:ellipsoidHeight"`
|
||||
Height float64 `xml:"wpml:height"`
|
||||
UseGlobalSpeed int `xml:"wpml:useGlobalSpeed"`
|
||||
UseGlobalHeadingParam int `xml:"wpml:useGlobalHeadingParam"`
|
||||
UseGlobalTurnParam int `xml:"wpml:useGlobalTurnParam"`
|
||||
UseStraightLine int `xml:"wpml:useStraightLine"`
|
||||
//ActionGroup ActionGroup `xml:"wpml:actionGroup"`
|
||||
}
|
||||
|
||||
// Point 结构表示地点坐标
|
||||
type Point struct {
|
||||
Coordinates string `xml:"coordinates"`
|
||||
}
|
||||
|
||||
type PayloadParam struct {
|
||||
PayloadPositionIndex int `xml:"wpml:payloadPositionIndex"`
|
||||
ImageFormat string `xml:"wpml:imageFormat"`
|
||||
}
|
||||
|
||||
type Doc struct {
|
||||
Author string `xml:"wpml:author"`
|
||||
UpdateTime int64 `xml:"wpml:updateTime"`
|
||||
CreateTime int64 `xml:"wpml:createTime"`
|
||||
MissionConfig MissionConfig `xml:"wpml:missionConfig"`
|
||||
Folder interface{} `xml:"Folder"`
|
||||
}
|
||||
|
||||
type PublicTemplate struct {
|
||||
TemplateType string `xml:"wpml:templateType"`
|
||||
TemplateId int `xml:"wpml:templateId"`
|
||||
AutoFlightSpeed float64 `xml:"wpml:autoFlightSpeed"`
|
||||
WaylineCoordinateSysParam struct {
|
||||
CoordinateMode string `xml:"wpml:coordinateMode"`
|
||||
HeightMode string `xml:"wpml:heightMode"`
|
||||
GlobalShootHeight float64 `xml:"wpml:globalShootHeight"`
|
||||
PositioningType string `xml:"wpml:positioningType"`
|
||||
SurfaceFollowModeEnable int `xml:"wpml:surfaceFollowModeEnable"`
|
||||
SurfaceRelativeHeight string `xml:"wpml:surfaceRelativeHeight"`
|
||||
} `xml:"wpml:waylineCoordinateSysParam"`
|
||||
}
|
||||
|
||||
type ActionGroup struct {
|
||||
ActionGroupId int `xml:"wpml:actionGroupId"`
|
||||
ActionGroupStartIndex int `xml:"wpml:actionGroupStartIndex"`
|
||||
ActionGroupEndIndex int `xml:"wpml:actionGroupEndIndex"`
|
||||
ActionGroupMode string `xml:"wpml:actionGroupMode"`
|
||||
ActionTrigger struct {
|
||||
ActionTriggerType string `xml:"actionTriggerType"`
|
||||
} `xml:"actionTrigger"`
|
||||
Action Action `xml:"action"`
|
||||
}
|
||||
|
||||
type Action struct {
|
||||
ActionId int `xml:"actionId"`
|
||||
ActionActuatorFunc string `xml:"actionActuatorFunc"`
|
||||
ActionActuatorFuncParam ActionActuatorFuncParam `xml:"actionActuatorFuncParam"`
|
||||
}
|
||||
|
||||
type ActionActuatorFuncParam struct {
|
||||
FileSuffix string `xml:"fileSuffix"`
|
||||
PayloadPositionIndex string `xml:"payloadPositionIndex"`
|
||||
}
|
||||
|
||||
type MissionConfig struct {
|
||||
FlyToWaylineMode string `xml:"wpml:flyToWaylineMode"`
|
||||
FinishAction string `xml:"wpml:finishAction"`
|
||||
ExitOnRCLost string `xml:"wpml:exitOnRCLost"`
|
||||
ExecuteRCLostAction string `xml:"wpml:executeRCLostAction"`
|
||||
TakeOffSecurityHeight float64 `xml:"wpml:takeOffSecurityHeight"`
|
||||
GlobalTransitionalSpeed float64 `xml:"wpml:globalTransitionalSpeed"`
|
||||
GlobalRTHHeight float64 `xml:"wpml:globalRTHHeight"`
|
||||
|
||||
//TakeOffRefPoint xml.Name `xml:"wpml:takeOffRefPoint"`
|
||||
//
|
||||
//TakeOffRefPointAGLHeight xml.Name `xml:"wpml:takeOffRefPointAGLHeight"`
|
||||
|
||||
//DroneInfo struct {
|
||||
// DroneEnumValue xml.Name `xml:"wpml:droneEnumValue"`
|
||||
// DroneSubEnumValue xml.Name `xml:"wpml:droneSubEnumValue"`
|
||||
//} `xml:"wpml:droneInfo"`
|
||||
//PayloadInfo struct {
|
||||
// PayloadEnumValue xml.Name `xml:"wpml:payloadEnumValue"`
|
||||
// PayloadSubEnumValue xml.Name `xml:"wpml:payloadSubEnumValue"`
|
||||
// PayloadPositionIndex xml.Name `xml:"wpml:payloadPositionIndex"`
|
||||
//} `xml:"wpml:payloadInfo"`
|
||||
}
|
||||
|
||||
type WayPointTemplate struct {
|
||||
PublicTemplate
|
||||
GlobalWaypointTurnMode string `xml:"wpml:globalWaypointTurnMode"` //全局航点类型(全局航点转弯模式)coordinateTurn:协调转弯,不过点,提前转弯 toPointAndStopWithDiscontinuityCurvature:直线飞行,飞行器到点停 toPointAndStopWithContinuityCurvature:曲线飞行,飞行器到点停 toPointAndPassWithContinuityCurvature:曲线飞行,飞行器过点不停
|
||||
GlobalUseStraightLine int `xml:"wpml:globalUseStraightLine"` //全局航段轨迹是否尽量贴合直线
|
||||
GimbalPitchMode string `xml:"wpml:gimbalPitchMode"` //云台俯仰角控制模式 manual:手动控制。飞行器从一个航点飞向下一个航点的过程中,
|
||||
// 支持用户手动控制云台的俯仰角度。若无用户控制,则保持飞离航点时的云台俯仰角度。
|
||||
//usePointSetting:依照每个航点设置。飞行器从一个航点飞向下一个航点的过程中,云台俯仰角均匀过渡至下一个航点的俯仰角。
|
||||
GlobalHeight float64 `xml:"wpml:globalHeight"` //全局航线高度(相对起飞点高度
|
||||
Placemark []Placemark `xml:"Placemark"`
|
||||
//UseGlobalTransitionalSpeed string `xml:"wpml:useGlobalTransitionalSpeed"`
|
||||
//TransitionalSpeed string `xml:"wpml:transitionalSpeed"`
|
||||
//GlobalWaypointHeadingParam struct {
|
||||
// WaypointHeadingMode string `xml:"wpml:waypointHeadingMode"`
|
||||
// WaypointHeadingAngle string `xml:"wpml:waypointHeadingAngle"`
|
||||
// WaypointPoiPoint string `xml:"wpml:waypointPoiPoint"`
|
||||
// WaypointHeadingPathMode string `xml:"wpml:waypointHeadingPathMode"`
|
||||
//} `xml:"wpml:globalWaypointHeadingParam"` //全局偏航角模式参数
|
||||
}
|
||||
|
||||
// KML 结构表示完整的 KML 文件
|
||||
type KML struct {
|
||||
//XMLName xml.Attr `xml:"kml"`
|
||||
XMLName xml.Name `xml:"http://www.opengis.net/kml/2.2 kml"`
|
||||
XmlnsStream string `xml:"xmlns:wpml,attr"`
|
||||
//Test []Test `xml:"test"`
|
||||
Document Doc `xml:"Document"`
|
||||
}
|
78
third/plane/wayline/template/template.go
Normal file
78
third/plane/wayline/template/template.go
Normal file
@ -0,0 +1,78 @@
|
||||
package template
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/tiger1103/gfast/v3/third/plane/wayline/struct"
|
||||
"os"
|
||||
)
|
||||
|
||||
func CreateWayPointTempalteWpml() {
|
||||
|
||||
}
|
||||
|
||||
func CreateWayPointTempalteKml() {
|
||||
kml := _struct.KML{
|
||||
//XmlnsStream: "http://www.dji.com/wpmz/1.0.3",
|
||||
Document: _struct.Doc{
|
||||
Author: "重庆远界大数据研究院有限公司",
|
||||
CreateTime: gtime.Now().TimestampMilli(),
|
||||
UpdateTime: gtime.Now().TimestampMilli(),
|
||||
},
|
||||
}
|
||||
msconfig := _struct.MissionConfig{
|
||||
FlyToWaylineMode: _struct.Safely,
|
||||
FinishAction: _struct.GoHome,
|
||||
ExitOnRCLost: _struct.ExecuteLostAction,
|
||||
ExecuteRCLostAction: _struct.Hover,
|
||||
TakeOffSecurityHeight: 5,
|
||||
GlobalTransitionalSpeed: 5,
|
||||
GlobalRTHHeight: 5,
|
||||
}
|
||||
//设置公共配置
|
||||
kml.Document.MissionConfig = msconfig
|
||||
tp := _struct.WayPointTemplate{}
|
||||
|
||||
tp.TemplateType = _struct.Waypoint //航点飞行
|
||||
tp.TemplateId = 0 //模板ID * 注:在一个kmz文件内该ID唯一。建议从0开始单调连续递增。在template.kml和waylines.wpml文件中,将使用该id将模板与所生成的可执行航线进行关联。
|
||||
tp.AutoFlightSpeed = 5 //全局航线飞行速度
|
||||
|
||||
tp.WaylineCoordinateSysParam.CoordinateMode = "WGS84"
|
||||
tp.WaylineCoordinateSysParam.HeightMode = "EGM96"
|
||||
tp.WaylineCoordinateSysParam.PositioningType = "GPS"
|
||||
tp.WaylineCoordinateSysParam.SurfaceFollowModeEnable = 0
|
||||
|
||||
tp.GlobalHeight = 100
|
||||
|
||||
kml.Document.Folder = tp
|
||||
createXML(kml, "template.xml")
|
||||
}
|
||||
|
||||
func createXML(v interface{}, file string) {
|
||||
// 生成 XML
|
||||
xmlBytes, err := xml.MarshalIndent(v, "", " ")
|
||||
if err != nil {
|
||||
fmt.Println("生成XML失败:", err)
|
||||
return
|
||||
}
|
||||
// 将 XML 写入文件
|
||||
xmlFile, err := os.Create(file)
|
||||
if err != nil {
|
||||
fmt.Println("创建文件失败:", err)
|
||||
return
|
||||
}
|
||||
defer xmlFile.Close()
|
||||
xmlWithVersion := []byte(xml.Header + string(xmlBytes))
|
||||
_, err = xmlFile.Write(xmlWithVersion)
|
||||
if err != nil {
|
||||
fmt.Println("写入文件失败:", err)
|
||||
return
|
||||
}
|
||||
|
||||
fmt.Println("生成的KML文件:output.kml")
|
||||
}
|
||||
|
||||
//func CreateWayPointTempalte(points []globe.Point) {
|
||||
//
|
||||
//}
|
1
third/plane/wayline/wayline.go
Normal file
1
third/plane/wayline/wayline.go
Normal file
@ -0,0 +1 @@
|
||||
package wayline
|
Reference in New Issue
Block a user