Compare commits

...

18 Commits

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,64 @@
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
const char* ssid = "xiu"; // 请替换成您的WiFi热点名称SSID
const char* password = "12345678"; // 请替换成您的WiFi热点密码
const char* host = "192.168.39.219"; // 请替换成您的服务端IP地址
const uint16_t port = 9975; // 请替换成您的服务端监听端口号
int pirPin = 13; //out引脚接到GPIO_13
bool motionDetected = false; // 初始状态设定为没有检测到人
unsigned long motionDetectedTimestamp = 0; // 记录最近一次检测到人的时间戳
unsigned long motionThreshold = 3000; // 设置人体运动持续时间阈值为3秒
WiFiUDP udp;
void setup() {
pinMode(pirPin, INPUT);
Serial.begin(115200);
WiFi.mode(WIFI_STA);
//连接wifi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi...");
}
Serial.println("Connected to WiFi");
Serial.println(WiFi.localIP());
udp.begin(8888);
}
void loop() {
bool currentMotionState = digitalRead(pirPin); // 读取HCSR-501输出引脚的状态
if (currentMotionState == HIGH) { // 如果检测到人
//motionDetected = true;
//motionDetectedTimestamp = millis(); // 记录最近一次检测到人的时间戳
// 发送消息到服务端
udp.beginPacket(host, port);
udp.write("Motion detected!");
udp.endPacket();
Serial.println("Motion detected!"); // 在串口打印检测到信息
} else if (motionDetected && (millis() - motionDetectedTimestamp > motionThreshold)) {
// 如果当前没有检测到人,并且已经超过了阈值时间,重置状态
motionDetected = false;
motionDetectedTimestamp = 0;
Serial.println("Motion disapper");
}
// 接收服务端的回复
/*
int packetSize = udp.parsePacket();
if (packetSize) {
String response = "";
while (udp.available()) {
response += (char) udp.read();
}
Serial.println("Response received: " + response);
}*/
// 每隔1秒钟执行一次循环
delay(1000);
}

@ -1,3 +1,8 @@
{
<<<<<<< HEAD
"ip": "rtsp://admin:admin888@192.168.1.67:555"
}
=======
"ip": "udp://@192.168.39.58:11111"
}
}
>>>>>>> develop

@ -1,6 +1,11 @@
{
<<<<<<< HEAD
"iou": 0.42,
"conf": 0.43,
=======
"iou": 0.3,
"conf": 0.45,
>>>>>>> develop
"rate": 20,
"check": 0,
"savecheck": 0

@ -2,7 +2,11 @@
# Form implementation generated from reading ui file 'rtsp_dialog.ui'
#
<<<<<<< HEAD
# Created by: PyQt5 UI code generator 5.15.2
=======
# Created by: PyQt5 UI code generator 5.15.9
>>>>>>> develop
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
@ -84,7 +88,13 @@ class Ui_Form(object):
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
<<<<<<< HEAD
Form.setWindowTitle(_translate("Form", "Form"))
self.label.setText(_translate("Form", "rtsp address:"))
self.rtspButton.setText(_translate("Form", "confirm"))
=======
Form.setWindowTitle(_translate("Form", "表单"))
self.label.setText(_translate("Form", "rtsp地址:"))
self.rtspButton.setText(_translate("Form", "确认"))
>>>>>>> develop
import apprcc_rc

@ -23,7 +23,11 @@
</size>
</property>
<property name="windowTitle">
<<<<<<< HEAD
<string>Form</string>
=======
<string>表单</string>
>>>>>>> develop
</property>
<property name="windowIcon">
<iconset resource="../apprcc.qrc">
@ -60,7 +64,11 @@ font-weight: bold;
color:white;}</string>
</property>
<property name="text">
<<<<<<< HEAD
<string>rtsp address:</string>
=======
<string>rtsp地址:</string>
>>>>>>> develop
</property>
</widget>
</item>
@ -119,7 +127,11 @@ border-radius: 0px;
background-color: rgba(255,255,255,50);}</string>
</property>
<property name="text">
<<<<<<< HEAD
<string>confirm</string>
=======
<string>确认</string>
>>>>>>> develop
</property>
</widget>
</item>

Binary file not shown.

After

Width:  |  Height:  |  Size: 366 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 986 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

@ -16,10 +16,13 @@ import time
import cv2
import socket
<<<<<<< HEAD
=======
import select
import tello_control
import datetime
import threading
>>>>>>> develop
from models.experimental import attempt_load
from utils.datasets import LoadImages, LoadWebcam
@ -34,7 +37,10 @@ from utils.capnums import Camera
from dialog.rtsp_win import Window
<<<<<<< HEAD
=======
>>>>>>> develop
class DetThread(QThread):
send_img = pyqtSignal(np.ndarray)
send_raw = pyqtSignal(np.ndarray)
@ -58,6 +64,10 @@ class DetThread(QThread):
self.rate = 100
self.save_fold = './result'
<<<<<<< HEAD
self.socket_host = '192.168.39.219'
self.socket_port = 9999
=======
self.socket_host = '192.168.39.145'
self.socket_port = 9999
@ -66,6 +76,7 @@ class DetThread(QThread):
# 多线程运行recive
self.drone = tello_control.TelloControl()
>>>>>>> develop
@torch.no_grad()
def run(self,
imgsz=640, # inference size (pixels)
@ -110,14 +121,22 @@ class DetThread(QThread):
model.half() # to FP16
# Dataloader
<<<<<<< HEAD
if self.source.isnumeric() or self.source.lower().startswith(('rtsp://', 'rtmp://', 'http://', 'https://')):
=======
if self.source.isnumeric() or self.source.lower().startswith(('rtsp://', 'rtmp://', 'http://', 'https://', 'udp://')):
>>>>>>> develop
view_img = check_imshow()
cudnn.benchmark = True # set True to speed up constant image size inference
dataset = LoadWebcam(self.source, img_size=imgsz, stride=stride)
# bs = len(dataset) # batch_size
else:
dataset = LoadImages(self.source, img_size=imgsz, stride=stride)
<<<<<<< HEAD
=======
print('device.type', device.type)
>>>>>>> develop
# Run inference
if device.type != 'cpu':
model(torch.zeros(1, 3, imgsz, imgsz).to(device).type_as(next(model.parameters()))) # run once
@ -126,9 +145,13 @@ class DetThread(QThread):
start_time = time.time()
dataset = iter(dataset)
<<<<<<< HEAD
while True:
=======
while True:
>>>>>>> develop
if self.jump_out:
self.vid_cap.release()
self.send_percent.emit(0)
@ -154,9 +177,15 @@ class DetThread(QThread):
self.current_weight = self.weights
if self.is_continue:
path, img, im0s, self.vid_cap = next(dataset)
<<<<<<< HEAD
# jump_count += 1
# if jump_count % 5 != 0:
# continue
=======
jump_count += 1
if jump_count % 10 != 0:
continue
>>>>>>> develop
count += 1
if count % 30 == 0 and count >= 30:
fps = int(30/(time.time()-start_time))
@ -221,8 +250,12 @@ class DetThread(QThread):
self.out.write(im0)
# Send frame via UDP socket
<<<<<<< HEAD
_, frame_encoded = cv2.imencode('.jpg', im0, [cv2.IMWRITE_JPEG_QUALITY, 50])
=======
# if self.source in ['udp', 'rtp', 'rtsp', 'http', 'https']:
_, frame_encoded = cv2.imencode('.jpg', im0, [cv2.IMWRITE_JPEG_QUALITY, self.drone.photo_quality])
>>>>>>> develop
# frame_bytes = frame_encoded.tobytes()
# print(len(frame_encoded))
sock.sendto(frame_encoded, (self.socket_host, self.socket_port))
@ -306,9 +339,12 @@ class MainWindow(QMainWindow, Ui_mainWindow):
self.saveCheckBox.clicked.connect(self.is_save)
self.load_setting()
<<<<<<< HEAD
=======
# self.chose_rtsp()
self.load_rtsp("udp://@192.168.39.58:11111")
>>>>>>> develop
def search_pt(self):
pt_list = os.listdir('./pt')
pt_list = [file for file in pt_list if file.endswith('.pt')]
@ -335,8 +371,12 @@ class MainWindow(QMainWindow, Ui_mainWindow):
self.rtsp_window = Window()
config_file = 'config/ip.json'
if not os.path.exists(config_file):
<<<<<<< HEAD
ip = "rtsp://admin:admin888@192.168.1.67:555"
=======
# ip = "rtsp://admin:admin888@192.168.1.67:555"
ip = "udp://@192.168.39.58:11111"
>>>>>>> develop
new_config = {"ip": ip}
new_json = json.dumps(new_config, ensure_ascii=False, indent=2)
with open(config_file, 'w', encoding='utf-8') as f:
@ -352,7 +392,11 @@ class MainWindow(QMainWindow, Ui_mainWindow):
try:
self.stop()
MessageBox(
<<<<<<< HEAD
self.closeButton, title='Tips', text='Loading rtsp stream', time=1000, auto=True).exec_()
=======
self.closeButton, title='提示', text='加载rtsp流', time=1000, auto=True).exec_()
>>>>>>> develop
self.det_thread.source = ip
new_config = {"ip": ip}
new_json = json.dumps(new_config, ensure_ascii=False, indent=2)
@ -367,7 +411,11 @@ class MainWindow(QMainWindow, Ui_mainWindow):
try:
self.stop()
MessageBox(
<<<<<<< HEAD
self.closeButton, title='Tips', text='Loading camera', time=2000, auto=True).exec_()
=======
self.closeButton, title='提示', text='加载摄像头', time=2000, auto=True).exec_()
>>>>>>> develop
# get the number of local cameras
_, cams = Camera().get_cam_num()
popMenu = QMenu()
@ -587,6 +635,15 @@ class MainWindow(QMainWindow, Ui_mainWindow):
with open(config_file, 'w', encoding='utf-8') as f:
f.write(config_json)
MessageBox(
<<<<<<< HEAD
self.closeButton, title='Tips', text='正在关闭', time=2000, auto=True).exec_()
sys.exit(0)
class TestWindow(QMainWindow, TEST):
def __init__(self):
super(TestWindow, self).__init__()
self.setupUi(self)
=======
self.closeButton, title='提示', text='正在关闭', time=2000, auto=True).exec_()
sys.exit(0)
@ -594,13 +651,19 @@ class MainWindow(QMainWindow, Ui_mainWindow):
# def __init__(self):
# super(TestWindow, self).__init__()
# self.setupUi(self)
>>>>>>> develop
if __name__ == "__main__":
app = QApplication(sys.argv)
myWin = MainWindow()
myWin.show()
<<<<<<< HEAD
myTest = TestWindow()
myTest.show()
=======
# myTest = TestWindow()
# myTest.show()
>>>>>>> develop
# myWin.showMaximized()
sys.exit(app.exec_())

@ -0,0 +1,436 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'Mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
import os
import sys
import cv2
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap, QPalette, QBrush
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import *
from PyQt5 import QtCore, QtGui, QtWidgets
class TEST(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(450,705)
icon = QtGui.QIcon()
icon.addPixmap(QtGui.QPixmap("window_png/main-icon.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
MainWindow.setWindowIcon(icon)
# 创建QLabel对象
self.background_label = QLabel(self)
self.background_label.setGeometry(0, 0, self.width(), self.height())
self.background_label.setAutoFillBackground(True) # 允许填充背景
# 设置窗口透明
self.setWindowFlags(Qt.FramelessWindowHint) # 去掉窗口边框
self.setAttribute(Qt.WA_TranslucentBackground) # 设置窗口背景透明
# 设置背景图像
image = QPixmap("icon/back.jpg").scaled(self.size(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
self.background_label.setPixmap(image)
# palette = QPalette()
# background_image = QPixmap("icon/back.jpg")
# palette.setBrush(QPalette.Background, QBrush(background_image))
# self.setPalette(palette)
MainWindow.setAnimated(True)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.frame = QtWidgets.QFrame(self.centralwidget)
self.frame.setGeometry(QtCore.QRect(50, 25, 391, 161))
self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame.setObjectName("frame")
#设置无人机状态
self.tellostate = QtWidgets.QLabel(self.frame)
self.tellostate.setGeometry(QtCore.QRect(0, 0, 111, 25))
font = QtGui.QFont()
font.setFamily("微软雅黑")
font.setPointSize(14)
font.setBold(True)
font.setWeight(80)
self.tellostate.setFont(font)
self.tellostate.setStyleSheet("QLabel\n"
"{\n"
" color:white\n"
"}")
self.tellostate.setObjectName("tellostate")
#设置充电状态
self.charge = QtWidgets.QLabel(self.frame)
self.charge.setGeometry(QtCore.QRect(20, 30, 341, 41))
font = QtGui.QFont()
font.setFamily("微软雅黑")
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.charge.setFont(font)
self.charge.setStyleSheet("QLabel\n"
"{\n"
" color:blue\n"
"}\n"
"")
self.charge.setObjectName("charge")
self.chargetxt = QtWidgets.QLabel(self.frame)
self.chargetxt.setGeometry(QtCore.QRect(100, 30, 341, 41))
font = QtGui.QFont()
font.setFamily("微软雅黑")
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.chargetxt.setFont(font)
self.chargetxt.setStyleSheet("QLabel\n"
"{\n"
" color:green\n"
"}\n"
"")
self.chargetxt.setObjectName("chargetxt")
#设置WIFI状态
self.Wifi = QtWidgets.QLabel(self.frame)
self.Wifi.setGeometry(QtCore.QRect(20, 100, 341, 41))
font = QtGui.QFont()
font.setFamily("微软雅黑")
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.Wifi.setFont(font)
self.Wifi.setObjectName("Wifi")
self.Wifitxt = QtWidgets.QLabel(self.frame)
self.Wifitxt.setGeometry(QtCore.QRect(100, 100, 341, 41))
font = QtGui.QFont()
font.setFamily("微软雅黑")
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.Wifitxt.setFont(font)
self.Wifitxt.setObjectName("Wifitxt")
self.frame_2 = QtWidgets.QFrame(self.centralwidget)
self.frame_2.setGeometry(QtCore.QRect(50, 175, 391, 421))
self.frame_2.setStyleSheet("QPushButton\n"
"{\n"
" color:white\n"
"}")
self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_2.setObjectName("frame_2")
#设置无人机控制部分
self.tellocontrol = QtWidgets.QLabel(self.frame_2)
self.tellocontrol.setGeometry(QtCore.QRect(0, 0, 101, 31))
font = QtGui.QFont()
font.setFamily("微软雅黑")
font.setPointSize(14)
font.setBold(True)
font.setWeight(75)
self.tellocontrol.setFont(font)
self.tellocontrol.setStyleSheet("QLabel\n"
"{\n"
" color:white\n"
"}\n"
"")
self.tellocontrol.setObjectName("tellocontrol")
self.btn_tello_up = QtWidgets.QPushButton(self.frame_2)
self.btn_tello_up.setGeometry(QtCore.QRect(60, 30, 231, 91))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.btn_tello_up.setFont(font)
icon1 = QtGui.QIcon()
icon1.addPixmap(QtGui.QPixmap("tello_png/qifei.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_tello_up.setIcon(icon1)
self.btn_tello_up.setIconSize(QtCore.QSize(150, 150))
self.btn_tello_up.setObjectName("btn_tello_up")
self.upload = QtWidgets.QPushButton(self.frame_2)
self.upload.setGeometry(QtCore.QRect(300, 30, 50, 180))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.upload.setFont(font)
self.upload.setObjectName("upload")
self.download = QtWidgets.QPushButton(self.frame_2)
self.download.setGeometry(QtCore.QRect(300, 220, 50, 180))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.download.setFont(font)
self.download.setObjectName("download")
self.btn_tello_down = QtWidgets.QPushButton(self.frame_2)
self.btn_tello_down.setGeometry(QtCore.QRect(60, 310, 231, 91))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(10)
font.setBold(True)
font.setItalic(False)
font.setWeight(75)
self.btn_tello_down.setFont(font)
icon2 = QtGui.QIcon()
icon2.addPixmap(QtGui.QPixmap("tello_png/jiangluo.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_tello_down.setIcon(icon2)
self.btn_tello_down.setIconSize(QtCore.QSize(150, 150))
self.btn_tello_down.setObjectName("btn_tello_down")
self.btn_tello_right = QtWidgets.QPushButton(self.frame_2)
self.btn_tello_right.setGeometry(QtCore.QRect(220, 220, 71, 71))
self.btn_tello_right.setText("")
icon3 = QtGui.QIcon()
icon3.addPixmap(QtGui.QPixmap("tello_png/right.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_tello_right.setIcon(icon3)
self.btn_tello_right.setIconSize(QtCore.QSize(70, 100))
self.btn_tello_right.setObjectName("btn_tello_right")
self.btn_tello_left = QtWidgets.QPushButton(self.frame_2)
self.btn_tello_left.setGeometry(QtCore.QRect(60, 220, 71, 71))
self.btn_tello_left.setText("")
icon4 = QtGui.QIcon()
icon4.addPixmap(QtGui.QPixmap("tello_png/left.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_tello_left.setIcon(icon4)
self.btn_tello_left.setIconSize(QtCore.QSize(70, 100))
self.btn_tello_left.setObjectName("btn_tello_left")
self.btn_tello_hold = QtWidgets.QPushButton(self.frame_2)
self.btn_tello_hold.setGeometry(QtCore.QRect(140, 220, 71, 71))
self.btn_tello_hold.setText("")
icon5 = QtGui.QIcon()
icon5.addPixmap(QtGui.QPixmap("tello_png/hold.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_tello_hold.setIcon(icon5)
self.btn_tello_hold.setIconSize(QtCore.QSize(70, 100))
self.btn_tello_hold.setObjectName("btn_tello_hold")
self.btn_tello_forward = QtWidgets.QPushButton(self.frame_2)
self.btn_tello_forward.setGeometry(QtCore.QRect(140, 140, 71, 71))
self.btn_tello_forward.setText("")
icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap("tello_png/up.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_tello_forward.setIcon(icon6)
self.btn_tello_forward.setIconSize(QtCore.QSize(70, 100))
self.btn_tello_forward.setObjectName("btn_tello_forward")
self.btn_tello_turnright = QtWidgets.QPushButton(self.frame_2)
self.btn_tello_turnright.setGeometry(QtCore.QRect(220, 140, 71, 71))
self.btn_tello_turnright.setText("")
icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap("tello_png/return.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_tello_turnright.setIcon(icon6)
self.btn_tello_turnright.setIconSize(QtCore.QSize(70, 100))
self.btn_tello_turnright.setObjectName("btn_tello_turnright")
self.btn_tello_turnleft = QtWidgets.QPushButton(self.frame_2)
self.btn_tello_turnleft.setGeometry(QtCore.QRect(60, 140, 71, 71))
self.btn_tello_turnleft.setText("")
icon6 = QtGui.QIcon()
icon6.addPixmap(QtGui.QPixmap("tello_png/return_2.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_tello_turnleft.setIcon(icon6)
self.btn_tello_turnleft.setIconSize(QtCore.QSize(70, 100))
self.btn_tello_turnleft.setObjectName("btn_tello_turnleft")
#设置无人机连接部分
self.frame_3 = QtWidgets.QFrame(self.centralwidget)
self.frame_3.setGeometry(QtCore.QRect(50, 605, 391, 80))
self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)
self.frame_3.setObjectName("frame_3")
self.btn_tello_connect = QtWidgets.QPushButton(self.frame_3)
self.btn_tello_connect.setGeometry(QtCore.QRect(20, 10, 75, 61))
self.btn_tello_connect.setText("")
icon7 = QtGui.QIcon()
icon7.addPixmap(QtGui.QPixmap("window_png/连接.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.btn_tello_connect.setIcon(icon7)
self.btn_tello_connect.setIconSize(QtCore.QSize(60, 60))
self.btn_tello_connect.setObjectName("btn_tello_connect")
self.connectstate = QtWidgets.QLabel(self.frame_3)
self.connectstate.setGeometry(QtCore.QRect(120, 15, 231, 51))
font = QtGui.QFont()
font.setFamily("微软雅黑")
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.connectstate.setFont(font)
self.connectstate.setObjectName("connectstate")
self.connecttxt = QtWidgets.QLabel(self.frame_3)
self.connecttxt.setGeometry(QtCore.QRect(200, 15, 231, 51))
font = QtGui.QFont()
font.setFamily("微软雅黑")
font.setPointSize(10)
font.setBold(True)
font.setWeight(75)
self.connecttxt.setFont(font)
self.connecttxt.setStyleSheet("QLabel\n"
"{\n"
" color:red\n"
"}\n"
"")
self.connecttxt.setObjectName("connecttxt")
MainWindow.setCentralWidget(self.centralwidget)
#上方工具栏
# self.menubar = QtWidgets.QMenuBar(MainWindow)
# self.menubar.setGeometry(QtCore.QRect(0, 0, 1260, 23))
# self.menubar.setObjectName("menubar")
# self.menu = QtWidgets.QMenu(self.menubar)
# self.menu.setObjectName("menu")
# self.menu_2 = QtWidgets.QMenu(self.menubar)
# self.menu_2.setObjectName("menu_2")
# MainWindow.setMenuBar(self.menubar)
# self.statusbar = QtWidgets.QStatusBar(MainWindow)
# self.statusbar.setObjectName("statusbar")
# MainWindow.setStatusBar(self.statusbar)
# self.toolBar = QtWidgets.QToolBar(MainWindow)
# self.toolBar.setMinimumSize(QtCore.QSize(0, 0))
# self.toolBar.setIconSize(QtCore.QSize(50, 24))
# self.toolBar.setObjectName("toolBar")
# MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar)
# self.tello = QtWidgets.QAction(MainWindow)
# icon8 = QtGui.QIcon()
# icon8.addPixmap(QtGui.QPixmap("window_png/实时画面-1.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
# self.tello.setIcon(icon8)
# self.tello.setObjectName("tello")
# self.pathfind = QtWidgets.QAction(MainWindow)
# icon9 = QtGui.QIcon()
# icon9.addPixmap(QtGui.QPixmap("window_png/路径分析-1.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
# self.pathfind.setIcon(icon9)
# self.pathfind.setObjectName("pathfind")
# self.screenshot = QtWidgets.QAction(MainWindow)
# icon10 = QtGui.QIcon()
# icon10.addPixmap(QtGui.QPixmap("window_png/录像.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
# self.screenshot.setIcon(icon10)
# self.screenshot.setObjectName("screenshot")
# self.menubar.addAction(self.menu.menuAction())
# self.menubar.addAction(self.menu_2.menuAction())
# self.toolBar.addAction(self.tello)
# self.toolBar.addAction(self.pathfind)
# self.toolBar.addAction(self.screenshot)
self.img_label = QtWidgets.QLabel()
self.connect_flag = False
#槽函数部分
# self.pathfind.triggered.connect(lambda: self.path())
# self.screenshot.triggered.connect(lambda: self.video())
self.btn_tello_connect.clicked.connect(lambda: self.connect())
self.btn_tello_up.clicked.connect(lambda: self.up())
self.btn_tello_down.clicked.connect(lambda: self.down())
self.btn_tello_forward.clicked.connect(lambda: self.forward())
self.btn_tello_right.clicked.connect(lambda: self.right())
self.btn_tello_left.clicked.connect(lambda: self.left())
self.btn_tello_hold.clicked.connect(lambda: self.Return())
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
#点击路径分析事件
def path(self):
pass
# self.MainWindow1 = QMainWindow()
# ui = Ui_MainWindow1()
# ui.setupUi(self.MainWindow1)
# self.MainWindow1.show()
#点击屏幕录制事件
def video(self):
pass
# bar.show()
#点击连接无人机事件
def connect(self):
pass
# self.connect_flag = True
# self.connecttxt.setStyleSheet("QLabel\n"
# "{\n"
# " color:green\n"
# "}\n"
# "")
# self.connecttxt.setText("已连接")
# self.chargetxt.setStyleSheet("QLabel\n"
# "{\n"
# " color:green\n"
# "}\n"
# "")
# self.chargetxt.setText("100%")
# self.Wifitxt.setStyleSheet("QLabel\n"
# "{\n"
# " color:green\n"
# "}\n"
# "")
# self.Wifitxt.setText("强")
# KeyControl.connect()
#点击无人机起飞事件
def up(self):
pass
# if self.connect_flag:
# KeyControl.getKeyboardInput("UP")
# else:
# return
#点击无人机降落事件
def down(self):
pass
# if self.connect_flag:
# KeyControl.getKeyboardInput("DOWN")
# else:
# return
#点击无人机前进事件
def forward(self):
pass
# if self.connect_flag:
# KeyControl.getKeyboardInput("i")
# else:
# return
#点击无人机右偏事件
def right(self):
pass
# if self.connect_flag:
# KeyControl.getKeyboardInput("l")
# else:
# return
#点击无人机左偏事件
def left(self):
pass
# if self.connect_flag:
# KeyControl.getKeyboardInput("j")
# else:
# return
#点击无人机停止事件
def Return(self):
pass
# if self.connect_flag:
# KeyControl.getKeyboardInput("a")
# KeyControl.getKeyboardInput("dffsfdsa")
# else:
# return
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "无人机路径生成系统"))
self.tellostate.setText(_translate("MainWindow", "无人机状态"))
self.charge.setText(_translate("MainWindow", "剩余电量:"))
self.chargetxt.setText(_translate("MainWindow", "--"))
self.Wifi.setText(_translate("MainWindow", "WIFI强度"))
self.Wifitxt.setText(_translate("MainWindow", "--"))
self.tellocontrol.setText(_translate("MainWindow", "控制面板"))
self.btn_tello_up.setText(_translate("MainWindow", "起飞"))
self.btn_tello_down.setText(_translate("MainWindow", "降落"))
self.upload.setText(_translate("MainWindow", "上升"))
self.download.setText(_translate("MainWindow", "下降"))
self.connectstate.setText(_translate("MainWindow", "连接状态:"))
self.connecttxt.setText(_translate("MainWindow", "未连接"))
# self.menu.setTitle(_translate("MainWindow", "实时画面"))
# self.menu_2.setTitle(_translate("MainWindow", "路径分析"))
# self.toolBar.setWindowTitle(_translate("MainWindow", "toolBar"))
# self.tello.setText(_translate("MainWindow", "实时画面"))
# self.pathfind.setText(_translate("MainWindow", "路径分析"))
# if __name__ == '__main__':
# app = QApplication(sys.argv)
# MainWindow = QMainWindow()
# ui = Ui_MainWindow()
# ui.setupUi(MainWindow)
# app.setStyleSheet(qdarkstyle.load_stylesheet_pyqt5())
# MainWindow.show()
# bar = ScreenBar()
# bar.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
# sys.exit(app.exec_())

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QTableView" name="tableView">
<property name="geometry">
<rect>
<x>200</x>
<y>130</y>
<width>256</width>
<height>192</height>
</rect>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>26</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

@ -1066,10 +1066,17 @@ class Ui_mainWindow(object):
self.fileButton.setToolTip(_translate("mainWindow", "file"))
self.cameraButton.setToolTip(_translate("mainWindow", "camera"))
self.rtspButton.setToolTip(_translate("mainWindow", "rtsp"))
<<<<<<< HEAD
self.label_2.setText(_translate("mainWindow", "IoU"))
self.label.setText(_translate("mainWindow", "conf"))
self.label_8.setText(_translate("mainWindow", "latency"))
self.checkBox.setText(_translate("mainWindow", "enable"))
=======
self.label_2.setText(_translate("mainWindow", "交并比"))
self.label.setText(_translate("mainWindow", "置信度"))
self.label_8.setText(_translate("mainWindow", "延迟"))
self.checkBox.setText(_translate("mainWindow", "启用"))
>>>>>>> develop
self.saveCheckBox.setText(_translate("mainWindow", "自动保存"))
self.label_11.setText(_translate("mainWindow", "结果统计\n"
"\n"

@ -837,7 +837,11 @@ color: rgb(218, 218, 218);
</string>
</property>
<property name="text">
<<<<<<< HEAD
<string>IoU</string>
=======
<string>交并比</string>
>>>>>>> develop
</property>
</widget>
</item>
@ -965,7 +969,11 @@ color: rgb(218, 218, 218);
</string>
</property>
<property name="text">
<<<<<<< HEAD
<string>conf</string>
=======
<string>置信度</string>
>>>>>>> develop
</property>
</widget>
</item>
@ -1107,7 +1115,11 @@ color: rgb(218, 218, 218);
</string>
</property>
<property name="text">
<<<<<<< HEAD
<string>latency</string>
=======
<string>延迟</string>
>>>>>>> develop
</property>
</widget>
</item>
@ -1138,7 +1150,11 @@ QCheckBox::indicator:checked {
</string>
</property>
<property name="text">
<<<<<<< HEAD
<string>enable</string>
=======
<string>启用</string>
>>>>>>> develop
</property>
<property name="checked">
<bool>true</bool>

@ -0,0 +1,325 @@
from djitellopy import tello
import datetime
import time
import threading
import socket
import json
class TelloControl:
'''
tello控制类
'''
def __init__(self):
self.drone = tello.Tello(host="192.168.39.58")
self.speed = 50
self.timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
log_filename = f"log/log_{self.timestamp}.txt"
self.log_file = open(file=log_filename, mode="a+", encoding="utf-8",buffering=1)
self.log_file.write(f"{self.timestamp}\n")
self.socket_recv_host = ''
self.socket_recv_port = 8888
self.recv_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.recv_sock.bind((self.socket_recv_host, self.socket_recv_port))
self.recv_thread = threading.Thread(target=self.recive)
self.recv_thread.setDaemon(True)
self.recv_thread.start()
self.auto_fly_flag = False
self.auto_home_flag = False
self.photo_quality = 50
self.send_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.send_address = ('192.168.39.145', 6666)
self.start_time = None
self.distance=100
self.angle=20
self.send_info_thread = threading.Thread(target=self.send_info)
self.send_info_thread.setDaemon(True)
self.send_info_thread.start()
def recive(self):
while True:
data, addr = self.recv_sock.recvfrom(1024)
print('Received: ', data.decode('utf-8'))
if data:
self.control(data.decode('utf-8'))
def control(self, data):
"""
tello控制
:param data:
:return:
"""
try:
if data == "TAKEOFF":
self.drone.takeoff()
self.drone.set_speed(self.speed)
self.log_file.write(str(datetime.datetime.now()) + "\tTAKEOFF" + "\n")
elif data == "LAND":
self.drone.land()
self.log_file.write(str(datetime.datetime.now()) + "\tLAND" + "\n")
elif data == "FORWARD":
self.drone.move_forward(self.distance)
# time.sleep(self.distance / self.speed)
self.log_file.write(str(datetime.datetime.now()) + f"\tFORWARD {self.distance}" + "\n")
elif data == "BACKWORD":
self.drone.move_back(self.distance)
# time.sleep(self.distance / self.speed)
self.log_file.write(str(datetime.datetime.now()) + f"\tBACK {self.distance}" + "\n")
elif data == "LEFT":
self.drone.move_left(self.distance)
# time.sleep(self.distance / self.speed)
self.log_file.write(str(datetime.datetime.now()) + f"\tLEFT {self.distance}" + "\n")
elif data == "RIGHT":
self.drone.move_right(self.distance)
# time.sleep(self.distance / self.speed)
self.log_file.write(str(datetime.datetime.now()) + f"\tRIGHT {self.distance}" + "\n")
elif data == "UP":
self.drone.move_up(self.distance)
# time.sleep(self.distance / self.speed)
self.log_file.write(str(datetime.datetime.now()) + f"\tUP {self.distance}" + "\n")
elif data == "DOWN":
self.drone.move_down(self.distance)
# time.sleep(self.distance / self.speed)
self.log_file.write(str(datetime.datetime.now()) + f"\tDOWN {self.distance}" + "\n")
elif data == "TURN_LEFT":
self.drone.rotate_counter_clockwise(self.angle)
self.log_file.write(str(datetime.datetime.now()) + f"\tTURN_LEFT {self.angle}" + "\n")
elif data == "TURN_RIGHT":
self.drone.rotate_clockwise(self.angle)
self.log_file.write(str(datetime.datetime.now()) + f"\tTURN_RIGHT {self.angle}" + "\n")
elif "SPEED" in data:
speed = int(data.split(" ")[1])
self.drone.set_speed(speed)
self.speed = speed
self.log_file.write(str(datetime.datetime.now()) +"\t"+ data + "\n")
# elif "AUTOF" in data:
# distance = int(data.split(" ")[1])
# angle = int(data.split(" ")[2])
# self.autofly(distance, angle)
# self.log_file.write(str(datetime.datetime.now()) + data + "\n")
elif data == "STOP":
self.log_file.write(str(datetime.datetime.now()) + "\tSTOP" + "\n")
self.auto_fly_flag = True
self.auto_home_flag = True
self.drone.stopmove()
elif data == "PHOTO_LOW":
self.photo_quality = 50
elif data == "PHOTO_HIGH":
self.photo_quality = 100
elif "WARNING" in data:
self.auto_fly_flag = False
self.drone.connect()
self.drone.streamon()
self.drone.takeoff()
self.log_file.write( str(datetime.datetime.now()) +"\t"+ data + "\n")
distance = int(data.split(" ")[1])
angle = int(data.split(" ")[2])
self.log_file.write(f"TURN_RIGHT {angle}\n")
self.log_file.write(f"FORWARD {distance}\n")
self.autofly(distance, angle)
# elif data == "INFO":
# data_thread = threading.Thread(target=self.send_info)
# data_thread.setDaemon(True)
# data_thread.start()
elif data == "DIRECTHOME":
self.auto_home_flag = False
self.return_home_line()
self.log_file.write(str(datetime.datetime.now()) + "\tDIRECTHOME" + "\n")
except Exception as e:
print(e)
self.log_file.write(str(datetime.datetime.now()) + "\t" + str(e) + "\n")
if "Command" not in str(e):
self.drone.land()
self.drone.streamoff()
self.drone.end()
self.log_file.close()
def autofly(self, distance, angle):
'''
自动飞行
:param distance:
:param angle:
:return:
'''
self.start_time = datetime.datetime.now()
self.drone.rotate_clockwise(angle)
while distance > 500:
if self.auto_fly_flag:
self.auto_fly_flag = False
return
self.drone.move_forward(500)
distance -= 500
# time.sleep(100 / self.speed)
self.drone.move_forward(distance)
time.sleep(distance / self.speed)
def return_home(self):
# 实现将无人机返回到出发点的逻辑
# 根据日志中的操作,执行相反的操作即可
# 例如,如果日志中有"FORWARD self.distance"的操作,则执行"BACK self.distance"来反向操作
# 注意控制时间间隔可以使用time.sleep()方法
self.log_file.seek(0) # 将文件指针移动到文件开头
for line in self.log_file:
if self.auto_home_flag:
self.drone.emergency()
return
if "FORWARD" in line:
distance = int(line.split(" ")[-1])
self.drone.move_back(distance)
time.sleep(distance / self.speed)
elif "BACK" in line:
distance = int(line.split(" ")[-1])
self.drone.move_forward(distance)
time.sleep(distance / self.speed)
elif "LEFT" in line:
distance = int(line.split(" ")[-1])
self.drone.move_right(distance)
time.sleep(distance / self.speed)
elif "RIGHT" in line:
distance = int(line.split(" ")[-1])
self.drone.move_left(distance)
time.sleep(distance / self.speed)
elif "UP" in line:
distance = int(line.split(" ")[-1])
self.drone.move_down(distance)
time.sleep(distance / self.speed)
elif "DOWN" in line:
distance = int(line.split(" ")[-1])
self.drone.move_up(distance)
time.sleep(distance / self.speed)
elif "TURN_LEFT" in line:
angle = int(line.split(" ")[-1])
self.drone.rotate_clockwise(angle)
time.sleep(angle / self.speed)
elif "TURN_RIGHT" in line:
angle = int(line.split(" ")[-1])
self.drone.rotate_counter_clockwise(angle)
time.sleep(angle / self.speed)
self.drone.land()
# 文件指针移动到文件末尾
self.log_file.seek(0, 2)
def return_home_line(self):
'''
通过直线距离返回
:return:
'''
self.log_file.seek(0) # 将文件指针移动到文件开头
total_distance_forward = 0
total_distance_right = 0
total_distance_up = 0
for line in self.log_file:
if self.auto_home_flag: # 如果标志变量为True中断自动返回
self.auto_home_flag = False
break
if "FORWARD" in line:
distance = int(line.split(" ")[-1])
total_distance_forward += distance
elif "BACK" in line:
distance = int(line.split(" ")[-1])
total_distance_forward -= distance
elif "LEFT" in line:
distance = int(line.split(" ")[-1])
total_distance_right -= distance
elif "RIGHT" in line:
distance = int(line.split(" ")[-1])
total_distance_right += distance
elif "UP" in line:
distance = int(line.split(" ")[-1])
total_distance_up += distance
elif "DOWN" in line:
distance = int(line.split(" ")[-1])
total_distance_up -= distance
print(total_distance_forward, total_distance_right, total_distance_up)
self.log_file.seek(0, 2)
while total_distance_forward != 0:
distance = min(500, abs(total_distance_forward))
if self.auto_home_flag: # 如果标志变量为True中断自动返回
self.auto_home_flag = False
return
if total_distance_forward > 0:
self.drone.move_back(distance)
total_distance_forward -= distance
else:
self.drone.move_forward(distance)
total_distance_forward += distance
time.sleep(distance / self.speed)
while total_distance_right != 0:
distance = min(500, abs(total_distance_right))
if self.auto_home_flag: # 如果标志变量为True中断自动返回
self.auto_home_flag = False
return
if total_distance_right > 0:
self.drone.move_left(distance)
total_distance_right -= distance
else:
self.drone.move_right(distance)
total_distance_right += distance
time.sleep(distance / self.speed)
while total_distance_up != 0:
distance = min(500, abs(total_distance_up))
if self.auto_home_flag: # 如果标志变量为True中断自动返回
self.auto_home_flag = False
return
if total_distance_up > 0:
self.drone.move_down(distance)
total_distance_up -= distance
else:
self.drone.move_up(distance)
total_distance_up += distance
time.sleep(distance / self.speed)
def send_info(self):
'''
发送无人机的信息
:return:
'''
while True:
battery = self.drone.query_battery()
data = {
"battery": battery,
"speed": self.speed,
"distance": self.calculate_distance(self.start_time)}
self.send_sock.send(json.dumps(data).encode())
time.sleep(2)
def calculate_distance(self, start_time ):
'''
计算无人机飞行的距离
:param start_time:
:return distance_diff:
'''
current_time = datetime.datetime.now()
time_diff = current_time - start_time
distance_diff = time_diff.total_seconds() * self.speed
return distance_diff

@ -0,0 +1 @@
srouce code

@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
</component>
</project>

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<runningDeviceTargetSelectedWithDropDown>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="W3VBB21918206146" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-06-28T03:24:01.996639400Z" />
</component>
</project>

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DesignSurface">
<option name="filePathToZoomLevelMap">
<map>
<entry key="..\:/MiNote_maintain/new_MiCode/src/sixaunyi/app/src/main/res/drawable/icon_favorite_red.xml" value="0.12" />
<entry key="..\:/MiNote_maintain/new_MiCode/src/sixaunyi/app/src/main/res/layout/activity_detect.xml" value="0.1" />
<entry key="..\:/MiNote_maintain/new_MiCode/src/sixaunyi/app/src/main/res/layout/activity_main.xml" value="0.1" />
<entry key="..\:/MiNote_maintain/new_MiCode/src/sixaunyi/app/src/main/res/layout/activity_map.xml" value="0.1125" />
<entry key="..\:/MiNote_maintain/new_MiCode/src/sixaunyi/app/src/main/res/layout/activity_video.xml" value="0.1" />
<entry key="..\:/MiNote_maintain/new_MiCode/src/sixaunyi/app/src/main/res/layout/content_detect.xml" value="0.1358695652173913" />
<entry key="..\:/MiNote_maintain/new_MiCode/src/sixaunyi/app/src/main/res/layout/fragment_first.xml" value="0.1358695652173913" />
<entry key="..\:/MiNote_maintain/new_MiCode/src/sixaunyi/app/src/main/res/layout/fragment_second.xml" value="0.1358695652173913" />
</map>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

@ -0,0 +1,15 @@
z
Japp/src/androidTest/java/com/example/sixaunyi/ExampleInstrumentedTest.java,7\e\7e2dc811cc280952b5bbbfb02aa0e4fa16a75d7c
F
app/proguard-rules.pro,9\e\9e08934d811afe28fbc77aaa3c0d747b94348db9
X
(gradle/wrapper/gradle-wrapper.properties,f\b\fbe448ebfc3eb2d4e308f6b8b043666f5b57235e
A
gradle.properties,2\a\2afbb999f001938c88fa43fc2ef52abf0f8213e4
k
;app/src/test/java/com/example/sixaunyi/ExampleUnitTest.java,8\9\892f839083a73d776402535dde27e522288853c9
?
settings.gradle,0\5\05efc8b1657769a27696d478ded1e95f38737233
@
app/build.gradle,f\4\f4a01d6a4fcb971362ec00a83903fd3902f52164

@ -0,0 +1 @@
/build

@ -0,0 +1,58 @@
plugins {
id 'com.android.application'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.sixaunyi"
minSdk 22
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation 'androidx.navigation:navigation-fragment:2.3.5'
implementation 'androidx.navigation:navigation-ui:2.3.5'
implementation 'com.google.android.gms:play-services-maps:17.0.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation fileTree(dir: 'libs', include: ['*.jar'])
//GoogleEasyPermission
implementation 'pub.devrel:easypermissions:3.0.0'
//Material
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.media:media:1.3.0'
//
/*implementation 'com.amap.api:location:latest.integration'
//
implementation 'com.amap.api:search:latest.integration'*/
}

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

@ -0,0 +1,20 @@
{
"version": 3,
"artifactType": {
"type": "APK",
"kind": "Directory"
},
"applicationId": "com.example.sixaunyi",
"variantName": "release",
"elements": [
{
"type": "SINGLE",
"filters": [],
"attributes": [],
"versionCode": 1,
"versionName": "1.0",
"outputFile": "app-release.apk"
}
],
"elementType": "File"
}

@ -0,0 +1,26 @@
package com.example.sixaunyi;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.example.sixaunyi", appContext.getPackageName());
}
}

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.sixaunyi">
<!-- 用于访问网络,网络定位需要上网 -->
<uses-permission android:name="android.permission.INTERNET" /> <!-- 用于读取手机当前的状态 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 用于写入缓存数据到扩展存储卡 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 用于申请调用A-GPS模块 -->
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> <!-- 用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- 用于访问GPS定位 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- 用于获取运营商信息,用于支持提供运营商信息相关的接口 -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 用于访问wifi网络信息wifi信息会用于进行网络定位 -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- 用于获取wifi的获取权限wifi信息会用来进行网络定位 -->
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<application
android:name=".MapApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@drawable/app"
android:label="哨兵"
android:roundIcon="@drawable/app"
android:supportsRtl="true"
android:theme="@style/Theme.Sixaunyi.NoActionBar"
tools:targetApi="31">
<activity
android:name=".SettingActivity"
android:exported="false"
android:screenOrientation="landscape"
android:theme="@style/TransparentTheme"/>
<!-- 定位service -->
<service android:name="com.amap.api.location.APSService" /> <!-- 设置高德Key -->
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="530a964ff05e45d9efb905abc9480690" />
<activity
android:name=".VideoActivity"
android:exported="false"
android:screenOrientation="landscape"
/>
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat.NoActionBar">
</activity>
<activity
android:name=".LoginActivity"
android:exported="true"
android:screenOrientation="portrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

@ -0,0 +1,46 @@
package com.example.sixaunyi;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;
import com.example.sixaunyi.databinding.FragmentFirstBinding;
public class FirstFragment extends Fragment {
private FragmentFirstBinding binding;
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
binding = FragmentFirstBinding.inflate(inflater, container, false);
return binding.getRoot();
}
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.buttonFirst.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NavHostFragment.findNavController(FirstFragment.this)
.navigate(R.id.action_FirstFragment_to_SecondFragment);
}
});
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}

@ -0,0 +1,79 @@
package com.example.sixaunyi;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.util.HashMap;
import java.util.Map;
public class LoginActivity extends AppCompatActivity {
private EditText mUsername;
private EditText mPassword;
private Button mLoginButton;
private CheckBox Account_remember;
private SharedPreferences sharedPreferences;
private Map<String, String> mUsers = new HashMap<>();
{
mUsers.put("admin", "123456");
mUsers.put("tiequan", "8731");
mUsers.put("zhenghaoyuan", "6666");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
// 获取输入框和按钮的实例
mUsername = findViewById(R.id.username);
mPassword = findViewById(R.id.password);
mLoginButton = findViewById(R.id.login);
Account_remember = findViewById(R.id.remember_check);
sharedPreferences = getSharedPreferences("account", Context.MODE_PRIVATE);
String username = sharedPreferences.getString("username", "");
String password =sharedPreferences.getString("password", "");
boolean isChecked = sharedPreferences.getBoolean("checkbox_state", false);
mUsername.setText(username);
mPassword.setText(password);
Account_remember.setChecked(isChecked);
// 设置登录按钮的点击事件
mLoginButton.setOnClickListener(v -> {
attemptLogin();
});
}
private void attemptLogin() {
String username = mUsername.getText().toString();
String password = mPassword.getText().toString();
boolean if_correct = verifyUser(username,password);
if (if_correct) {
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("username", username);
editor.putBoolean("checkbox_state", Account_remember.isChecked());
editor.apply();
if (Account_remember.isChecked()){
editor.putString("password", password);
}else{
editor.putString("password", "");
}
editor.apply();
Toast.makeText(this, "登录成功", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
} else {
Toast.makeText(this, "用户名或密码错误", Toast.LENGTH_SHORT).show();
}
}
private boolean verifyUser(String username, String password){
if (mUsers.containsKey(username) && mUsers.get(username).equals(password)) {
return true;
} else {
return false;
}
}
}

@ -0,0 +1,816 @@
package com.example.sixaunyi;
import static androidx.constraintlayout.motion.utils.Oscillator.TAG;
import static java.lang.Math.PI;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.app.AlertDialog;
import android.content.Context;
import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.location.Location;
import android.nfc.Tag;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import android.animation.Animator;
import android.animation.ValueAnimator;
import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapUtils;
import com.amap.api.maps.LocationSource;
import com.amap.api.maps.MapView;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.animation.Animation;
import com.amap.api.maps.model.animation.TranslateAnimation;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.geocoder.GeocodeResult;
import com.amap.api.services.geocoder.GeocodeSearch;
import com.amap.api.services.geocoder.RegeocodeAddress;
import com.amap.api.services.geocoder.RegeocodeQuery;
import com.amap.api.services.geocoder.RegeocodeResult;
import com.amap.api.services.poisearch.PoiResult;
import com.amap.api.services.poisearch.PoiSearch;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import android.view.animation.LinearInterpolator;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import pub.devrel.easypermissions.AfterPermissionGranted;
import pub.devrel.easypermissions.EasyPermissions;
public class MainActivity extends AppCompatActivity implements AMapLocationListener, LocationSource,
AMap.OnMapLongClickListener, GeocodeSearch.OnGeocodeSearchListener, AMap.OnMarkerDragListener,
AMap.OnMarkerClickListener{
//请求权限码
private static final int REQUEST_PERMISSIONS = 9527;
//声明AMapLocationClient类对象
public AMapLocationClient mLocationClient = null;
//声明AMapLocationClientOption对象
public AMapLocationClientOption mLocationOption = null;
private MapView mapView = null;
private String city;
private LatLng Current_latlng;
//地图控制器*********非常重要!!!!!!
private AMap aMap = null;
//位置更改监听
private LocationSource.OnLocationChangedListener mListener;
//地理编码搜索
private GeocodeSearch geocodeSearch;
//解析成功标识码
private static final int PARSE_SUCCESS_CODE = 1000;
//城市码
private String cityCode = null;
//浮动按钮
private FloatingActionButton fabPOI;
//浮动按钮 清空地图标点
private FloatingActionButton ClearMarker_btn;
//浮动按钮 更换活动
private ImageButton ChangeAct_btn;
//标点列表
private List<Marker> markerList = new ArrayList<>();
//标识参数类
private MarkerOptions markerOption = new MarkerOptions();
//
private DatagramSocket reveSocket;
private String value;
private ExecutorService mThreadPool = Executors.newCachedThreadPool();
//private ActivityResultLauncher<Intent> launcher;
////////////////////////////可修改部分/////////////////////////////
private final LatLng Monitorlatlng = new LatLng(28.257553,113.0417);
private final static String Recieve_IP = "192.168.39.46";
private final static int RECEIVE_PORT = 9975;
private final static String SEND_to_IP = "192.168.39.195";
private final static int SEND_PORT = 8888;
/////////////////////////////////////////////////////////////////
private InetAddress serverAddr;
private String Angle;
private String MonitorAngle;
private float distance;
private float MonitorDistance;
private UdpReceiveThread udpReceiveThread;
@SuppressLint("MissingInflatedId")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
// 从保存的状态数据中恢复状态
value = savedInstanceState.getString("key");
}
ClearMarker_btn = findViewById(R.id.clearMarker_btn);
ChangeAct_btn = findViewById(R.id.change_btn);
ChangeAct_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeAct();
}
});
initLocation();
//初始化地图
initMap(savedInstanceState);
//检查安卓版本
checkingAndroidVersion();
addSensorMarker(Monitorlatlng);
}
/**
* Android
*/
private void checkingAndroidVersion() {
//Android6.0及以上先获取权限再定位
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
requestPermission();
}
//Android6.0以下直接定位
else {
//直接定位
mLocationClient.startLocation();
}
}
/**
*
*/
@AfterPermissionGranted(REQUEST_PERMISSIONS)
private void requestPermission() {
String[] permissions = {
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
if (EasyPermissions.hasPermissions(this, permissions)) {
//有权限
//******
Log.d(TAG, "已获得权限,可以定位啦!");
showMsg("已获得权限,可以定位啦!");
//开始定位
mLocationClient.startLocation();
} else {
//false 无权限
EasyPermissions.requestPermissions(this, "需要权限", REQUEST_PERMISSIONS, permissions);
}
}
//提示框显示文本
private void showMsg(String msg) {
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
}
/**
*
* @param requestCode
* @param permissions
* @param grantResults
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
//设置请求到的权限结果
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
/******** 初始化定位 *******/
private void initLocation() {
//初始化定位
try {
mLocationClient = new AMapLocationClient(getApplicationContext());
} catch (Exception e) {
e.printStackTrace();
}
if (mLocationClient != null) {
//设置定位回调监听
mLocationClient.setLocationListener(this);
//初始化AMapLocationClientOption对象
mLocationOption = new AMapLocationClientOption();
//设置定位模式为AMapLocationMode.Hight_Accuracy高精度模式。
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
//获取最近3s内精度最高的一次定位结果
//设置setOnceLocationLatest(boolean b)接口为true启动定位时SDK会返回最近3s内精度最高的一次定位结果。如果设置其为truesetOnceLocation(boolean b)接口也会被设置为true反之不会默认为false。
mLocationOption.setOnceLocationLatest(true);
//设置是否返回地址信息(默认返回地址信息)
mLocationOption.setNeedAddress(true);
//设置定位请求超时时间单位是毫秒默认30000毫秒建议超时时间不要低于8000毫秒。
mLocationOption.setHttpTimeOut(20000);
//关闭缓存机制,高精度定位会产生缓存。
mLocationOption.setLocationCacheEnable(false);
//给定位客户端对象设置定位参数
mLocationClient.setLocationOption(mLocationOption);
}
}
/**
*
* @param savedInstanceState
*/
private void initMap(Bundle savedInstanceState) {
//因为mapView为null所以要加上这个括号不可常规的mapView.findViewById
mapView = (MapView) findViewById(R.id.map_view);
//在activity执行onCreate时执行mMapView.onCreate(savedInstanceState),创建地图
mapView.onCreate(savedInstanceState);
//初始化地图控制器对象
aMap = mapView.getMap();
// 设置定位监听
aMap.setLocationSource(this);
// 设置为true表示显示定位层并可触发定位false表示隐藏定位层并不可触发定位默认是false
aMap.setMyLocationEnabled(true);
//设置最小缩放等级为16 ,缩放级别范围为[3, 20]
aMap.setMinZoomLevel(14);
//设置地图标志点击事件
aMap.setOnMarkerClickListener(this);
//设置地图标志拖拽事件
aMap.setOnMarkerDragListener(this);
//开启室内地图
//aMap.showIndoorMap(true);
//设置地图长按事件
aMap.setOnMapLongClickListener(this);
//构造 GeocodeSearch 对象
try {
geocodeSearch = new GeocodeSearch(this);
} catch (AMapException e) {
e.printStackTrace();
}
//设置监听
geocodeSearch.setOnGeocodeSearchListener(this);
}
/**
*
*/
@Override
public void activate(OnLocationChangedListener onLocationChangedListener) {
mListener = onLocationChangedListener;
if (mLocationClient == null) {
mLocationClient.startLocation();//启动定位
}
}
/**
*
*/
@Override
public void deactivate() {
mListener = null;
if (mLocationClient != null) {
mLocationClient.stopLocation();
mLocationClient.onDestroy();
}
mLocationClient = null;
}
@Override
public void onLocationChanged(AMapLocation aMapLocation) {
if (aMapLocation != null) {
//定位成功
if (aMapLocation.getErrorCode() == 0) {
//地址
String address = aMapLocation.getAddress();
//城市赋值
city = aMapLocation.getCity();
//当前位置经纬度坐标
Current_latlng = new LatLng(aMapLocation.getLatitude(), aMapLocation.getLongitude());
MonitorDistance = AMapUtils.calculateLineDistance(Current_latlng,Monitorlatlng);
Log.i(TAG, String.valueOf(Current_latlng.longitude));
Log.i(TAG, String.valueOf(Current_latlng.latitude));
//
//获取纬度
double latitude = aMapLocation.getLatitude();
//获取经度
double longitude = aMapLocation.getLongitude();
Log.d("MainActivity", aMapLocation.getCity());
showMsg(address);
udpReceiveThread = new UdpReceiveThread();
udpReceiveThread.startListening();
//停止定位后,本地定位服务并不会被销毁
mLocationClient.stopLocation();
if (mListener != null) {
// 显示系统图标
mListener.onLocationChanged(aMapLocation);
}
//显示浮动按钮
fabPOI.show();
//赋值
cityCode = aMapLocation.getCityCode();
}
else {
//定位失败时可通过ErrCode错误码信息来确定失败的原因errInfo是错误信息详见错误码表。
Log.e("AmapError", "location Error, ErrCode:"
+ aMapLocation.getErrorCode() + ", errInfo:"
+ aMapLocation.getErrorInfo());
}
}
}
/***********************Activity相关函数其中添加了保证mapView与activity同步相关函数******************/
@Override
protected void onResume() {
super.onResume();
//在activity执行onResume时执行mMapView.onResume (),重新绘制加载地图
mapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
//在activity执行onPause时执行mMapView.onPause (),暂停地图的绘制
mapView.onPause();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("key", value);
//在activity执行onSaveInstanceState时执行mMapView.onSaveInstanceState (outState),保存地图当前的状态
mapView.onSaveInstanceState(outState);
}
@Override
protected void onDestroy() {
super.onDestroy();
//销毁定位客户端,同时销毁本地定位服务。
if (mLocationClient != null) {
mLocationClient.onDestroy();
}
//在activity执行onDestroy时执行mMapView.onDestroy(),销毁地图
mapView.onDestroy();
}
/******************************************************************/
/* * * 长按地图响应函数 * * */
//LatLng 为高德地图包自带的存储坐标对象
@Override
public void onMapLongClick(LatLng latLng) {
distance = AMapUtils.calculateLineDistance(Current_latlng,latLng);
Angle = calcAngle(Current_latlng.latitude, Current_latlng.longitude, latLng.latitude,latLng.longitude);
MonitorAngle = calcAngle(Current_latlng.latitude, Current_latlng.longitude, 113.05370390725032,28.256794281117525);
//showMsg("长按了地图,经度:"+latLng.longitude+",纬度:"+latLng.latitude);
Log.i(TAG, String.valueOf(latLng.longitude));
Log.i(TAG, String.valueOf(latLng.latitude));
showMsg("直线距离:"+distance+"米"+"角度"+Angle);
//坐标转地址113.05370390725032 28.256794281117525
latlonToAddress(latLng);
//添加标点
addMarker(latLng);
}
/**
*
* @param latLng
*/
private void addMarker(LatLng latLng) {
//显示浮动按钮
ClearMarker_btn.show();
//添加标点
Marker marker = aMap.addMarker(markerOption
.position(latLng)
.draggable(true)
//标点图标
.icon(BitmapDescriptorFactory.
fromBitmap(BitmapFactory.decodeResource(getResources(),R.drawable.weizhi)))
//备注
.title("路径点")
.snippet("距离:")
);
marker.showInfoWindow();
markerList.add(marker);
}
// 添加传感器标点
private Marker sensorMarker = null;
private void addSensorMarker(LatLng latLng) {
// 显示浮动按钮
// 添加传感器标点
MarkerOptions sensorMarkerOption = new MarkerOptions();
sensorMarker = aMap.addMarker(sensorMarkerOption
.position(latLng)
.draggable(false)
// 标点图标
.icon(BitmapDescriptorFactory.
fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.sensor)))
// 备注
.title("传感器")
);
sensorMarker.showInfoWindow();
}
// 添加无人机标点
private Marker droneMarker = null;
private void addDroneMarker() {
// 添加无人机标点
MarkerOptions droneMarkerOption = new MarkerOptions();
droneMarker = aMap.addMarker(droneMarkerOption
.position(Current_latlng)
.draggable(false)
// 标点图标
.icon(BitmapDescriptorFactory.
fromBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.drone)))
// 备注
.title("无人机")
);
droneMarker.showInfoWindow();
}
// 移动无人机标点到传感器标点并显示平移动画
public static class SmoothMoveUtil {
private Marker droneMarker;
private LatLng startLatLng;
private LatLng endLatLng;
private long duration;
public SmoothMoveUtil(Marker marker) {
this.droneMarker = marker;
}
public void moveDroneMarker(LatLng sensorLatLng, long duration) {
if (droneMarker != null) {
startLatLng = droneMarker.getPosition();
endLatLng = sensorLatLng;
this.duration = duration;
// 开始动画
startSmoothMove();
}
}
private void startSmoothMove() {
LatLngInterpolator latLngInterpolator = new LatLngInterpolator.LinearFixed();
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(duration);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float fraction = animation.getAnimatedFraction();
LatLng newPosition = latLngInterpolator.interpolate(fraction, startLatLng, endLatLng);
droneMarker.setPosition(newPosition);
}
});
valueAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
// 动画结束
droneMarker.setPosition(endLatLng);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
valueAnimator.start();
}
// LatLng 插值器接口——算经纬度过渡用的
public interface LatLngInterpolator {
LatLng interpolate(float fraction, LatLng a, LatLng b);
class LinearFixed implements LatLngInterpolator {
@Override
public LatLng interpolate(float fraction, LatLng a, LatLng b) {
double lat = (b.latitude - a.latitude) * fraction + a.latitude;
double lngDelta = b.longitude - a.longitude;
// 如果跨越了 180 度经度,则进行调整
if (Math.abs(lngDelta) > 180) {
lngDelta -= Math.signum(lngDelta) * 360;
}
double lng = lngDelta * fraction + a.longitude;
return new LatLng(lat, lng);
}
}
}
}
/**
* Marker
* @param view
*/
public void clearAllMarker(View view) {
if (markerList != null && markerList.size()>0){
for (Marker markerItem : markerList) {
markerItem.remove();
}
}
ClearMarker_btn.hide();
}
public void moveDrone(){
SmoothMoveUtil moveUtil = new SmoothMoveUtil(droneMarker);
long time = (long) MonitorDistance/2*1000;
moveUtil.moveDroneMarker(Monitorlatlng,time);
}
public void changeAct() {
udpReceiveThread.stopListening();
Intent intent = new Intent(MainActivity.this, VideoActivity.class);
Bundle b = new Bundle();
b.putString("Angle", MonitorAngle);
b.putFloat("Distance", MonitorDistance);
intent.putExtras(b);
int requestCode = 1; // 可以是任何非负整数
startActivity(intent);
}
/**
* Marker
*
* @param marker
* @return
*/
@Override
public boolean onMarkerClick(Marker marker) {
Log.d(TAG,"点击了标点");
//显示InfoWindow
/*
if (!marker.isInfoWindowShown()) {
//显示
marker.showInfoWindow();
} else {
//隐藏
marker.hideInfoWindow();
}
*/
return true;
}
/**
*
* @param marker
*/
@Override
public void onMarkerDragStart(Marker marker) {
Log.d(TAG,"开始拖动");
}
/**
*
* @param marker
*/
@Override
public void onMarkerDrag(Marker marker) {
Log.d(TAG,"拖动中");
}
/**
*
* @param marker
*/
@Override
public void onMarkerDragEnd(Marker marker) {
Log.d(TAG,"拖动完成");
}
/* * * * * *
*
* @param latLng
*/
private void latlonToAddress(LatLng latLng) {
//位置点 通过经纬度进行构建
LatLonPoint latLonPoint = new LatLonPoint(latLng.latitude, latLng.longitude);
//逆编码查询 第一个参数表示一个Latlng第二参数表示范围多少米第三个参数表示是火系坐标系还是GPS原生坐标系
RegeocodeQuery query = new RegeocodeQuery(latLonPoint, 20, GeocodeSearch.AMAP);
//异步获取地址信息
geocodeSearch.getFromLocationAsyn(query);
}
/*********************************************************
* @param regeocodeResult
* @param rCode
*/
@Override
public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int rCode) {
if(rCode == PARSE_SUCCESS_CODE){
RegeocodeAddress regeocodeAddress = regeocodeResult.getRegeocodeAddress();
//显示解析后的地址
showMsg("地址:"+regeocodeAddress.getFormatAddress());
} else {
showMsg("获取地址失败");
}
}
@Override
public void onGeocodeSearched(GeocodeResult geocodeResult, int i) {
}
class ReceiveHandler extends Handler{
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Context context = MainActivity.this;
showAlert(context,"传感器报警");
addDroneMarker();
moveDrone();
}
});
}
}
}
public class UdpReceiveThread extends Thread {
private static final String TAG = "UdpReceiveThread";
private static final int mRECEIVE_PORT = RECEIVE_PORT;
private boolean mRunning = true;
private String mReceiveIp = Recieve_IP;
private String mExpectedData = "Motion detected!";
private float udpMonitorDistance = MonitorDistance;
private String udpMonitorAngle = MonitorAngle;
private Handler receiveHandler = new ReceiveHandler();
@Override
public void run() {
try {
DatagramSocket socket = new DatagramSocket(mRECEIVE_PORT);
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
while (mRunning) {
Log.i(TAG, "run: 111111111111111111");
socket.receive(packet);
byte[] data = packet.getData();
String receivedString = new String(data, 0, packet.getLength());
Log.d(TAG, "Received data: " + receivedString);
if (receivedString.equals(mExpectedData)) {
Log.i(TAG, "run: 222222222222222222222222222");
receiveHandler.sendEmptyMessage(1);
sendCommand("WARNING "+String.valueOf(udpMonitorDistance)+" "+udpMonitorAngle);
mRunning = false;
}
}
socket.close();
} catch (SocketException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
public void startListening() {
mRunning = true;
start();
}
public void stopListening() {
mRunning = false;
}
}
public void showAlert(Context context, String message) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("警告");
builder.setMessage(message);
builder.setIcon(R.drawable.warning);
builder.setPositiveButton("确定", null);
AlertDialog dialog = builder.create();
dialog.show();
}
//以北为0度
public static String calcAngle(Double centerLat, Double centerLon, Double anotherLat, Double anotherLon) {
//差值
double subLat = anotherLat - centerLat;
double subLon = anotherLon - centerLon;
double angle = 0;
if (subLat == 0) {
//纬度差值为0 表示两点在同一高度 此时点必然在x轴右侧 或者 x轴左侧
if (subLon > 0) {
//x轴右侧
angle = 90;
} else if (subLon < 0) {
//x轴左侧
angle = 270;
}
} else if (subLon == 0) {
//经度差值为0 说明点在y轴上方或者y轴下方
if (subLat > 0) {
//y轴上方
angle = 0;
} else if (subLat < 0) {
//y轴下方
angle = 180;
}
} else {
//根据tan的值求角度 subLon不能为0 纬度差值 除以 经度差值 = tan的值
double v = subLat / subLon;
angle = Math.atan(v) * 180 / PI;
//angle的值在-180到180之间
System.out.println("未处理的角度值:" + (angle));
//第二种求角度的方法
//angle = Math.atan2(subLat,subLon) * 180 / PI ;
//判断数据在第几象限
//1、正切小于0 在二四象限
if (angle < 0) {
if (subLon > 0) {
//此时的点在中心点的右下角
angle = Math.abs(angle)+ 90;
} else if (subLon < 0) {
//此时的点在中心点的左上角
angle = Math.abs(angle) + 270;
}
}
//2、正切大于0 在一三象限
else if (angle > 0) {
if (subLon > 0) {
//此时的点在中心点的右上角 360-angle
angle = 90-angle;
} else if (subLat < 0) {
// 此时的点在中心点的左下角
angle = 270-angle;
}
}
}
return String.valueOf(angle);
}
/*
*UDP线
*/
class SendRunnable implements Runnable {
byte[] mData;
InetAddress mAddress;
int mPort;
public SendRunnable(byte[] data, InetAddress address, int port) {
mData = data;
mAddress = address;
mPort = port;
}
@Override
public void run() {
try {
// 创建发送数据报文
DatagramPacket packet = new DatagramPacket(mData, mData.length, mAddress, mPort);
// 创建 DatagramSocket 对象并发送数据报文
DatagramSocket socket = new DatagramSocket();
socket.send(packet);
// 关闭 DatagramSocket 对象
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//封装好的接口函数
private void sendCommand(String str) throws UnknownHostException {
byte[] sendData = str.getBytes();
InetAddress address = InetAddress.getByName(SEND_to_IP);
SendRunnable sendRunnable1 = new SendRunnable(sendData, address, SEND_PORT);
mThreadPool.execute(sendRunnable1);
}
}

@ -0,0 +1,27 @@
package com.example.sixaunyi;
import android.app.Application;
import android.content.Context;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.maps.MapsInitializer;
import com.amap.api.services.core.ServiceSettings;
public class MapApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Context context = this;
//定位隐私政策同意
AMapLocationClient.updatePrivacyShow(context,true,true);
AMapLocationClient.updatePrivacyAgree(context,true);
//地图隐私政策同意
MapsInitializer.updatePrivacyShow(context,true,true);
MapsInitializer.updatePrivacyAgree(context,true);
//搜索隐私政策同意
ServiceSettings.updatePrivacyShow(context,true,true);
ServiceSettings.updatePrivacyAgree(context,true);
}
}

@ -0,0 +1,46 @@
package com.example.sixaunyi;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.navigation.fragment.NavHostFragment;
import com.example.sixaunyi.databinding.FragmentSecondBinding;
public class SecondFragment extends Fragment {
private FragmentSecondBinding binding;
@Override
public View onCreateView(
LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState
) {
binding = FragmentSecondBinding.inflate(inflater, container, false);
return binding.getRoot();
}
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding.buttonSecond.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NavHostFragment.findNavController(SecondFragment.this)
.navigate(R.id.action_SecondFragment_to_FirstFragment);
}
});
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
}

@ -0,0 +1,194 @@
package com.example.sixaunyi;
import static androidx.constraintlayout.motion.utils.Oscillator.TAG;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class SettingActivity extends AppCompatActivity {
private final static String SEND_to_IP = "192.168.39.47";
private SeekBar Speed_btn;
private SeekBar Battery_btn;
private ImageButton return_btn;
private final static int SEND_PORT = 8888;
private ExecutorService mThreadPool = Executors.newCachedThreadPool();
private Switch photo_btn;
private Context context;
private SharedPreferences sharedPreferences;
private TextView tvProgress;
private TextView Battery_warning;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setting);
Speed_btn= findViewById(R.id.speed);
return_btn=findViewById(R.id.returns);
photo_btn = findViewById(R.id.photo);
Battery_btn = findViewById(R.id.warning_num);
tvProgress = findViewById(R.id.tvProgress);
Battery_warning=findViewById(R.id.Battery_warning);
sharedPreferences = getSharedPreferences("control_state", MODE_PRIVATE);
boolean photo_btn_state= sharedPreferences.getBoolean("photo_btn_state", false);
photo_btn.setChecked(photo_btn_state);
// 恢复SeekBar状态
int speedProgress = sharedPreferences.getInt("speed_progress", 0);
Speed_btn.setProgress(speedProgress);
tvProgress.setText(String.valueOf(speedProgress+10));
int warning_num= sharedPreferences.getInt("battery_num", 0);
Battery_btn.setProgress(warning_num);
Battery_warning.setText(String.valueOf(warning_num));
photo_btn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
// 保存Switch状态
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putBoolean("photo_btn_state", isChecked);
editor.apply();
}
});
Speed_btn.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
tvProgress.setText(String.valueOf(progress+10));
int speed=progress+10;
String s = "SPEED " + Integer.toString(speed);
try {
sendCommand(s);
} catch (UnknownHostException e) {
e.printStackTrace();
}
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("speed_progress", progress);
editor.apply();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
});
Battery_btn.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
Battery_warning.setText(String.valueOf(progress));
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putInt("battery_num", progress);
editor.apply();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
});
return_btn.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
// 启动目标 Activity
passingParameters();
}
});
photo_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (photo_btn.isChecked()) {
try {
sendCommand("PHOTO_HIGH");
} catch (UnknownHostException e) {
e.printStackTrace();
}
}else
{
try {
sendCommand("PHOTO_LOW");
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
});
}
/*
* UDP线
* */
class SendRunnable implements Runnable {
byte[] mData;
InetAddress mAddress;
int mPort;
public SendRunnable(byte[] data, InetAddress address, int port) {
mData = data;
mAddress = address;
mPort = port;
}
@Override
public void run() {
try {
// 创建发送数据报文
DatagramPacket packet = new DatagramPacket(mData, mData.length, mAddress, mPort);
// 创建 DatagramSocket 对象并发送数据报文
DatagramSocket socket = new DatagramSocket();
socket.send(packet);
// 关闭 DatagramSocket 对象
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*封装函数*/
private void sendCommand(String str) throws UnknownHostException {
byte[] sendData = str.getBytes();
InetAddress address = InetAddress.getByName(SEND_to_IP);
SendRunnable sendRunnable1 = new SendRunnable(sendData, address, SEND_PORT);
mThreadPool.execute(sendRunnable1);
}
@Override
public void onBackPressed() {
// 在这里处理返回事件的逻辑
super.onBackPressed(); // 调用父类的方法,执行默认的返回操作
passingParameters();
}
private void passingParameters(){
int warning_num= sharedPreferences.getInt("battery_num", 0);
Log.i(TAG, "111111111111111111111"+String.valueOf(warning_num));
Intent intent = new Intent(SettingActivity.this,VideoActivity.class);
intent.putExtra("BATTERY_NUM", warning_num); // 设置要传递的参数
setResult(RESULT_OK, intent);
finish();
}
}

@ -0,0 +1,813 @@
package com.example.sixaunyi;
import static androidx.constraintlayout.motion.utils.Oscillator.TAG;
import androidx.appcompat.app.AppCompatActivity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaCodecList;
import android.media.MediaFormat;
import android.media.MediaScannerConnection;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.provider.ContactsContract;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.*;
import java.nio.ByteBuffer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import android.os.Bundle;
import android.widget.ToggleButton;
public class VideoActivity extends AppCompatActivity {
private final static String SEND_to_IP = "192.168.39.195"; //填写接收方IP
private final static String Recieve_IP = "192.168.39.195";//填服务器IP与send_to_IP为同一个
private final static int SEND_PORT = 8888; //发送端口号
private final static int RECEIVE_PORT = 9999; //接收端口号
private static boolean listenStatus = true; //接收线程的循环标识
private byte[] buf;
static Bitmap bp;
private DatagramSocket reveSocket;
private DatagramSocket sendSocket;
private static InetAddress serverAddr;
private SendHandler sendHandler = new SendHandler();
private ReceiveHandler receiveHandler = new ReceiveHandler();
private Button Trans_to_Detect;
private ImageView imgShow;
private Button btn;
private ImageButton Forward_btn;
private ImageButton Back_btn;
private ImageButton Left_btn;
private ImageButton Right_btn;
private ImageButton Down_btn;
private ImageButton Up_btn;
private ImageButton TurnLeft_btn;
private ImageButton TurnRight_btn;
private ImageButton Setting_btn;
private ImageButton TakeOff_btn;
private ImageButton Landing_btn;
private ImageButton Record_btn;
private ToggleButton Mode_btn;
private ImageButton selfHome_btn;
private String mangle;
private float mdistance;
// 创建一个可缓存的线程池
private ExecutorService mThreadPool = Executors.newCachedThreadPool();
private UdpDataThread warning_thread;
private TextView battery_warning;
private ImageButton show_status;
private String batteryStatus="未获取";
private String speedStatus="未获取";
private String distanceStatus="未获取";
//ReceiveData()显示到imageView
//manager部分打开线程接收
//model部分发送视频流
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_control);
imgShow = findViewById(R.id.imageView);
Forward_btn = findViewById(R.id.forward_button);
Back_btn = findViewById(R.id.backward_button);
Left_btn = findViewById(R.id.left_button);
Right_btn = findViewById(R.id.right_button);
Down_btn = findViewById(R.id.down_button);
Up_btn = findViewById(R.id.up_button);
TurnLeft_btn = findViewById(R.id.rotate_left_button);
Landing_btn = findViewById(R.id.landing_button);
TurnRight_btn = findViewById(R.id.rotate_right_button);
TakeOff_btn = findViewById(R.id.takeoff_button);
Mode_btn = findViewById(R.id.toggleButton2);
Record_btn = findViewById(R.id.start_record_button);
Setting_btn = findViewById(R.id.setting_button);
Setting_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(VideoActivity.this, SettingActivity.class);
startActivity(intent);
}
});
selfHome_btn = findViewById(R.id.self_home);
selfHome_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
try {
sendCommand("DIRECTHOME");
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
}
});
battery_warning =findViewById(R.id.warning);
show_status=findViewById(R.id.show_status_button);
battery_warning.setTextColor(Color.RED);
Animation anim = new AlphaAnimation(0.0f, 1.0f);
anim.setDuration(500); // 闪烁时间间隔
anim.setStartOffset(20);
anim.setRepeatMode(Animation.REVERSE);
anim.setRepeatCount(Animation.INFINITE);
battery_warning.startAnimation(anim);
Intent i = getIntent();
mdistance = i.getFloatExtra("Distance",0);
mangle = i.getStringExtra("Angle");
warning_thread = new UdpDataThread();
warning_thread.start();
try {
Condition_Init();
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
show_status.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 在这里编写 ImageButton 的点击事件处理逻辑
showPopup(speedStatus,batteryStatus,distanceStatus);
}
});
}
private void Control_Button_Init(){
TakeOff_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
sendCommand("TAKEOFF");
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
Log.i(TAG, "onClick: TTTTTTTTTTTTTTakeoff");
}
});
Landing_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
sendCommand("LAND");
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
Log.i(TAG, "onClick: LLLLLLLLLLLLLLLLLLand");
}
});
Forward_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
sendCommand("FORWARD");
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
Log.i(TAG, "onClick: FFFFFFFForward");
}
});
Back_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
sendCommand("BACKWORD");
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
Log.i(TAG, "onClick: BBBBBBBBackward");
}
});
Left_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
sendCommand("LEFT");
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
Log.i(TAG, "onClick: LLLLLLLLLLLLeft");
}
});
Right_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
sendCommand("RIGHT");
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
Log.i(TAG, "onClick: RRRRRRRRRRight");
}
});
Down_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
sendCommand("DOWN");
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
Log.i(TAG, "onClick: DDDDDDDDDown");
}
});
Up_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
sendCommand("UP");
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
Log.i(TAG, "onClick: UUUUUUUUUUUUUUp");
}
});
TurnLeft_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
sendCommand("TURN_LEFT");
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
Log.i(TAG, "onClick: TTTTTTTTTurnLLLLLLLLLLeft");
}
});
TurnRight_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
sendCommand("TURN_RIGHT");
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
Log.i(TAG, "onClick: TTTTTTTTTTTTurnRRRRRRRRRRight");
}
});
}
private void Condition_Init() throws UnknownHostException {
ReceiveHandler receiveHandler = new ReceiveHandler();
UdpReceiveThread StreamThread = new UdpReceiveThread(Recieve_IP,RECEIVE_PORT,receiveHandler);
try {
StreamThread.startListen();
StreamThread.start();
} catch (SocketException | UnknownHostException e) {
e.printStackTrace();
}
Mode_btn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
// 执行功能2
try {
changetoManual();
Control_Button_Init();
} catch (UnknownHostException e) {
throw new RuntimeException(e);
}
} else {
// 执行功能1
// try {
// changetoAuto();
// } catch (UnknownHostException e) {
// throw new RuntimeException(e);
// }
}
}
});
Record_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
saveVideo(bp);
}
});
}
private void changetoManual() throws UnknownHostException {
sendCommand("STOP");
}
class ReceiveHandler extends Handler{
@Override
public void handleMessage(Message msg) {
if (msg.what == 1) {
runOnUiThread(new Runnable() {
@Override
public void run() {
int targetWidth = imgShow.getWidth();
int targetHeight = imgShow.getHeight();
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bp, targetWidth, targetHeight, true);
imgShow.setImageBitmap(scaledBitmap);
}
});
}
}
}
class SendHandler extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
}
/*
* UDP线
* */
public class UdpReceiveThread extends Thread {
private DatagramSocket reveSocket;
private String Recieve_IP;
private int RECEIVE_PORT;
private Handler receiveHandler;
public UdpReceiveThread(String ip, int port, Handler handler) {
this.Recieve_IP = ip;
this.RECEIVE_PORT = port;
this.receiveHandler = handler;
}
public void startListen() throws SocketException, UnknownHostException {
reveSocket = new DatagramSocket(RECEIVE_PORT);
}
public void stopListen() {
if (reveSocket != null && !reveSocket.isClosed()) {
listenStatus = false;
//reveSocket.close();
}
}
@Override
public void run() {
try {
InetAddress serverAddr = InetAddress.getByName(Recieve_IP);
while (listenStatus) {
byte[] inBuf = new byte[1024 * 1024];
DatagramPacket inPacket = new DatagramPacket(inBuf, inBuf.length);
reveSocket.receive(inPacket);
if (!inPacket.getAddress().equals(serverAddr)) {
throw new IOException("未知名的报文");
}
ByteArrayInputStream in = new ByteArrayInputStream(inPacket.getData());
receiveHandler.sendEmptyMessage(1);
bp = BitmapFactory.decodeStream(in);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
* UDP线Runnable
* */
class SendRunnable implements Runnable {
byte[] mData;
InetAddress mAddress;
int mPort;
public SendRunnable(byte[] data, InetAddress address, int port) {
mData = data;
mAddress = address;
mPort = port;
}
@Override
public void run() {
try {
// 创建发送数据报文
DatagramPacket packet = new DatagramPacket(mData, mData.length, mAddress, mPort);
// 创建 DatagramSocket 对象并发送数据报文
DatagramSocket socket = new DatagramSocket();
socket.send(packet);
// 关闭 DatagramSocket 对象
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*封装函数*/
private void sendCommand(String str) throws UnknownHostException {
byte[] sendData = str.getBytes();
InetAddress address = InetAddress.getByName(SEND_to_IP);
SendRunnable sendRunnable1 = new SendRunnable(sendData, address, SEND_PORT);
mThreadPool.execute(sendRunnable1);
}
/*
*UDP线
*/
public class UdpDataThread extends Thread {
private DatagramSocket socket;
private boolean running;
private byte[] buffer;
private static final int BUFFER_SIZE = 1024; // 设置接收缓冲区大小
private JSONObject jsonObject;
public UdpDataThread() {
buffer = new byte[BUFFER_SIZE];
}
@Override
public void run() {
running = true;
try {
socket = new DatagramSocket(6666); // 设置接收端口号
while (running) {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String receivedData = new String(packet.getData(), 0, packet.getLength(), "UTF-8");
jsonObject = new JSONObject(receivedData);
batteryStatus = jsonObject.getString("battery");
speedStatus = jsonObject.getString("speed");
distanceStatus = jsonObject.getString("distance");
if (batteryStatus.equals("10")) {
battery_warning.setText("电量仅剩"+batteryStatus);}else{
battery_warning.setText("");
}
System.out.println("接收到数据:" + batteryStatus);
System.out.println("接收到数据:" + speedStatus);
System.out.println("接收到数据:" + distanceStatus);
// 在这里处理收到的数据,可以根据实际需求进行解析或其他操作
}
} catch (IOException | JSONException e) {
e.printStackTrace();
} finally {
if (socket != null) {
socket.close();
}
}
}
public void stopThread() {
running = false;
}
}
private String findEncoderCodecName(String mimeType) {
MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
int numCodecs = codecList.getCodecInfos().length;
for (int i = 0; i < numCodecs; i++) {
MediaCodecInfo codecInfo = MediaCodecList.getCodecInfoAt(i);
if (!codecInfo.isEncoder()) {
continue;
}
String[] types = codecInfo.getSupportedTypes();
for (String type : types) {
if (type.equalsIgnoreCase(mimeType)) {
return codecInfo.getName();
}
}
}
return null;
}
MediaCodec codec;
private void saveVideo(Bitmap videoBitmap) {
try {
String codecName = findEncoderCodecName(MediaFormat.MIMETYPE_VIDEO_AVC);
if (codecName != null) {
codec = MediaCodec.createByCodecName(codecName);
// 根据视频尺寸设置编码器参数
MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, videoBitmap.getWidth(), videoBitmap.getHeight());
format.setInteger(MediaFormat.KEY_BIT_RATE, 2000000);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 1);
// 配置编码器并启动
codec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
Surface inputSurface = codec.createInputSurface();
codec.start();
// 创建保存视频的路径和文件名
String fileName = "video_" + System.currentTimeMillis() + ".mp4";
String filePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES) + "/" + fileName;
File videoFile = new File(filePath);
FileOutputStream fileOutputStream = new FileOutputStream(videoFile);
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
// 循环编码每一帧
boolean isInputDone = false;
boolean isOutputDone = false;
while (!isOutputDone) {
if (!isInputDone) {
int index = codec.dequeueInputBuffer(10000);
if (index >= 0) {
ByteBuffer inputBuffer = codec.getInputBuffer(index);
inputBuffer.clear();
Canvas canvas = inputSurface.lockCanvas(null);
canvas.drawBitmap(videoBitmap, 0, 0, null);
inputSurface.unlockCanvasAndPost(canvas);
codec.queueInputBuffer(index, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
isInputDone = true;
}
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outputIndex = codec.dequeueOutputBuffer(bufferInfo, 10000);
if (outputIndex >= 0) {
ByteBuffer outputBuffer = codec.getOutputBuffer(outputIndex);
byte[] outData = new byte[bufferInfo.size];
outputBuffer.get(outData);
bufferedOutputStream.write(outData);
codec.releaseOutputBuffer(outputIndex, false);
}
if ((bufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
isOutputDone = true;
}
}
// 关闭文件流
bufferedOutputStream.flush();
bufferedOutputStream.close();
fileOutputStream.close();
// 通知媒体库更新文件
MediaScannerConnection.scanFile(this, new String[]{videoFile.getAbsolutePath()}, null, null);
Toast.makeText(this, "视频保存成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "无法找到支持的视频编码器", Toast.LENGTH_SHORT).show();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (codec != null) {
codec.stop();
codec.release();
}
}
}
public void showPopup(String speedStatus,String batteryStatus,String distanceStatus) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater inflater = getLayoutInflater();
View dialogView = inflater.inflate(R.layout.custom_dialog, null);
TextView speedstatus = dialogView.findViewById(R.id.speed);
speedstatus.setText("当前速度为:"+speedStatus);
TextView batterystatus = dialogView.findViewById(R.id.battery);
batterystatus.setText("当前电量为:"+batteryStatus);
TextView distancestatus = dialogView.findViewById(R.id.distance);
distancestatus.setText("当前距离为:"+distanceStatus);
builder.setView(dialogView);
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// 点击确定按钮后的操作
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
//////////////////////////////滑动开关//////////////////////////////
public static class SlideUnlockView extends View{
private final int BG_COLOR = Color.parseColor("#2D2E32"); // 背景颜色
private static final int GUIDE_TEXT_COLOR = Color.WHITE; // 引导文本颜色
private static final int GUIDE_TEXT_SIZE = 100; // 引导文本大小
private static final int INDICATOR_COLOR = Color.WHITE; // 指示器颜色
private static final int INDICATOR_RADIUS = 40; // 指示器半径
private static final int INDICATOR_GAP = 300; // 指示器间距
private static final int ARROW_COLOR = Color.WHITE; // 箭头颜色
private static final int ARROW_SIZE = 20; // 箭头大小
private static final int STATE_LOCKED = 0; // 锁屏状态
private static final int STATE_DRAGGING = 1; // 拖动状态
private static final int STATE_UNLOCKED = 2; // 解锁状态
private Paint mPaint;
private Path mPath;
private int mViewWidth;
private int mViewHeight;
private int mIndicatorCount;
private int mCurrentIndex;
private float mLastX;
private boolean mIsUnlocked;
private int mState;
private OnUnlockListener mOnUnlockListener;
public abstract static class OnUnlockListener {
public class SimpleOnUnlockListener extends OnUnlockListener {
@Override
public void onUnlock() {
// 默认空实现
}
}
public abstract void onUnlock();
}
public void setOnUnlockListener(OnUnlockListener listener) {
this.mOnUnlockListener = listener;
}
public SlideUnlockView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true); // 抗锯齿
mPaint.setStyle(Paint.Style.FILL);
mPath = new Path();
mIsUnlocked = false;
mState = STATE_LOCKED;
// 指示器个数为 3
mIndicatorCount = 3;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mViewWidth = w;
mViewHeight = h;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
switch (mState) {
case STATE_LOCKED:
drawGuideText(canvas);
drawIndicatorCircles(canvas);
break;
case STATE_DRAGGING:
drawUnlockPath(canvas);
drawUnlockArrow(canvas);
break;
case STATE_UNLOCKED:
if (mOnUnlockListener != null) {
mOnUnlockListener.onUnlock();
}
break;
}
}
private void drawGuideText(Canvas canvas) {
mPaint.setColor(BG_COLOR);
canvas.drawRect(0, 0, mViewWidth, mViewHeight, mPaint);
mPaint.setColor(GUIDE_TEXT_COLOR);
mPaint.setTextSize(GUIDE_TEXT_SIZE);
String guideText = "即将起飞";
float textWidth = mPaint.measureText(guideText);
float textX = mViewWidth / 2 - textWidth / 2;
float textY = mViewHeight * 2 / 3;
canvas.drawText(guideText, textX, textY, mPaint);
}
private void drawIndicatorCircles(Canvas canvas) {
mPaint.setColor(INDICATOR_COLOR);
float cy = mViewHeight / 2;
float startX = mViewWidth / 2 - INDICATOR_GAP * (mIndicatorCount - 1) / 2;
float radius = INDICATOR_RADIUS;
Path path = new Path();
for (int i = 0; i < mIndicatorCount; i++) {
float cx = startX + INDICATOR_GAP * i;
path.addCircle(cx, cy, radius, Path.Direction.CCW);
}
canvas.drawPath(path, mPaint);
}
private void drawUnlockPath(Canvas canvas) {
mPaint.setColor(INDICATOR_COLOR);
float cy = mViewHeight / 2;
float startX = mViewWidth / 2 - INDICATOR_GAP * (mIndicatorCount - 1) / 2;
float currentX = Math.max(Math.min(mLastX, mViewWidth - INDICATOR_RADIUS), startX + INDICATOR_GAP * mCurrentIndex);
Path path = new Path();
path.moveTo(startX + INDICATOR_RADIUS, cy);
path.lineTo(currentX - INDICATOR_RADIUS, cy);
path.arcTo(new RectF(currentX - INDICATOR_RADIUS, cy - INDICATOR_RADIUS,
currentX + INDICATOR_RADIUS, cy + INDICATOR_RADIUS), -90, 180);
path.lineTo(startX + INDICATOR_GAP * (mIndicatorCount - 1), cy);
canvas.drawPath(path, mPaint);
}
private void drawUnlockArrow(Canvas canvas) {
mPaint.setColor(ARROW_COLOR);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
Path arrowPath = new Path();
float x = Math.max(Math.min(mLastX, mViewWidth - INDICATOR_RADIUS - ARROW_SIZE), mViewWidth / 2 + INDICATOR_GAP * (mCurrentIndex - 1));
float y = mViewHeight / 2;
arrowPath.moveTo(x - ARROW_SIZE, y - ARROW_SIZE);
arrowPath.lineTo(x, y);
arrowPath.lineTo(x - ARROW_SIZE, y + ARROW_SIZE);
canvas.drawPath(arrowPath, mPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (mState == STATE_LOCKED) {
mState = STATE_DRAGGING;
mCurrentIndex = 0;
invalidate();
return true;
}
break;
case MotionEvent.ACTION_MOVE:
if (mState == STATE_DRAGGING) {
mLastX = x;
int index = (int) ((x - mViewWidth / 2) / INDICATOR_GAP);
index = Math.max(Math.min(index, mIndicatorCount - 1), 0);
if (index != mCurrentIndex) {
mCurrentIndex = index;
invalidate();
}
if (mCurrentIndex == mIndicatorCount - 1) {
mState = STATE_UNLOCKED;
mIsUnlocked = true;
}
return true;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (mState == STATE_DRAGGING) {
mState = STATE_LOCKED;
mCurrentIndex = 0;
invalidate();
return true;
}
break;
}
return super.onTouchEvent(event);
}
}
private void shutdown(){
warning_thread.stopThread();
mThreadPool.shutdownNow();
}
@Override
public void onBackPressed() {
// 返回到 MainActivity
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(intent);
finish(); // 结束 VideoActivity
}
@Override
protected void onDestroy() {
super.onDestroy();
// 关闭线程
shutdown();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save