diff --git a/app/build.gradle b/app/build.gradle index 6ce823b..9589003 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -71,6 +71,8 @@ dependencies { implementation 'com.squareup.okhttp3:okhttp:4.10.0' implementation 'com.squareup.okio:okio:3.2.0' + implementation 'com.google.code.gson:gson:2.10.1' + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a366c75..f5c1a85 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -8,7 +8,8 @@ - + @@ -57,6 +58,7 @@ diff --git a/app/src/main/java/com/example/longyi_groundstation/Login/Activity/LoginActivity.java b/app/src/main/java/com/example/longyi_groundstation/Login/Activity/LoginActivity.java index 1b2ae02..5b72078 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Login/Activity/LoginActivity.java +++ b/app/src/main/java/com/example/longyi_groundstation/Login/Activity/LoginActivity.java @@ -98,12 +98,7 @@ public class LoginActivity extends AppCompatActivity { } }); -// allView.rb_bt1.setOnClickListener(v -> { -// type = 0; -// }); -// allView.rb_bt2.setOnClickListener(v -> { -// type = 1; -// }); + } @@ -114,4 +109,6 @@ public class LoginActivity extends AppCompatActivity { } + + } \ No newline at end of file diff --git a/app/src/main/java/com/example/longyi_groundstation/Login/Void/UrlVoid.java b/app/src/main/java/com/example/longyi_groundstation/Login/Void/UrlVoid.java new file mode 100644 index 0000000..fa34b65 --- /dev/null +++ b/app/src/main/java/com/example/longyi_groundstation/Login/Void/UrlVoid.java @@ -0,0 +1,63 @@ +package com.example.longyi_groundstation.Login.Void; + +import static androidx.core.content.ContextCompat.startActivity; +import static com.example.longyi_groundstation.Util.Http.HttpUrl.LOGIN; + +import android.app.Activity; +import android.content.Intent; +import android.widget.EditText; +import android.widget.Toast; + +import androidx.annotation.NonNull; + +import com.example.longyi_groundstation.Funcation.Activity.FuncationActivity; +import com.example.longyi_groundstation.Util.Http.HttpUtil; +import com.example.longyi_groundstation.Util.SharedPreferencesTool; + +import org.json.JSONObject; + +import java.io.IOException; + +import okhttp3.Call; +import okhttp3.Response; + +public class UrlVoid { + + public static HttpUtil httpUtil = new HttpUtil(); + + private void Login(Activity activity, EditText et_username, EditText et_password) { + httpUtil.postForm( + LOGIN, + "mobile=" + et_username.getText().toString() + + "&password=" + et_password.getText().toString(), + null, new okhttp3.Callback() { + @Override + public void onFailure(@NonNull Call call, @NonNull IOException e) { + + } + + @Override + public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException { + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + try { + String json = response.body().string(); + JSONObject jsonObject = new JSONObject(json); + if (jsonObject.getInt("code") == 1) { + SharedPreferencesTool.saveLogin(activity, jsonObject.getJSONObject("data")); + activity.startActivity(new Intent(activity, FuncationActivity.class)); + activity.finish(); + } else { + Toast.makeText(activity, "账号密码错误", Toast.LENGTH_SHORT).show(); + } + } catch (Exception e) { + Toast.makeText(activity, "网络解析错误", Toast.LENGTH_SHORT).show(); + } + } + }); + } + }); + } + +} diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Activity/MainActivity.java b/app/src/main/java/com/example/longyi_groundstation/Main/Activity/MainActivity.java index 26b8022..987e0f8 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Activity/MainActivity.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Activity/MainActivity.java @@ -69,6 +69,7 @@ import com.example.longyi_groundstation.Main.Adapter.TypeAdapter; import com.example.longyi_groundstation.Main.Base.CreateLink; import com.example.longyi_groundstation.Main.Base.LogItem; import com.example.longyi_groundstation.Main.Base.Msg; +import com.example.longyi_groundstation.Main.Click.MainClick; import com.example.longyi_groundstation.Main.Service.MyBoundService; import com.example.longyi_groundstation.Main.Setting.Activity.SettingActivity; import com.example.longyi_groundstation.Main.View.BombingDialog; @@ -89,6 +90,7 @@ import com.example.longyi_groundstation.Main.Void.CoordinateConverter; import com.example.longyi_groundstation.Main.Void.FlyVoid; import com.example.longyi_groundstation.Main.Void.FpvGestureHandler; import com.example.longyi_groundstation.Main.Void.KeDaTTS; +import com.example.longyi_groundstation.Main.Void.LidarDataParser; import com.example.longyi_groundstation.Main.Void.MapVoid; import com.example.longyi_groundstation.Main.Void.MyReceiver; import com.example.longyi_groundstation.Main.Void.MyTool; @@ -131,21 +133,18 @@ public class MainActivity extends AppCompatActivity { //地图方法 private MapVoid mapVoid; //广播接收器 - private MyReceiver myReceiver_ATTITUDE, myReceiver_GPS_RAW_INT, myReceiver_GLOBAL_POSITION_INT, - myReceiver_POWER_STATUS, myReceiver_SYS_STATUS, myReceiver_STATUSTEXT, - myReceiver_HEARTBEAT, myReceiver_VFR_HUD, myReceiver_MISSION_REQUEST, myReceiver_MISSION_ACK, - myReceiver_MISSION_CURRENT; + private MyReceiver myReceiver_ATTITUDE, myReceiver_GPS_RAW_INT, myReceiver_GLOBAL_POSITION_INT, myReceiver_POWER_STATUS, myReceiver_SYS_STATUS, myReceiver_STATUSTEXT, myReceiver_HEARTBEAT, myReceiver_VFR_HUD, myReceiver_MISSION_REQUEST, myReceiver_MISSION_ACK, myReceiver_MISSION_CURRENT; //所有组件 private AllView allView; private ArrayList typeList = new ArrayList<>(); private TypeAdapter typeAdapter; - private TakeOffDialog takeOffDialog;//起飞弹窗 - private TurnBackDialog turnBackDialog;//返航弹窗 - private LandDialog landDialog;//降落弹窗 - private BombingDialog bombingDialog;//投弹弹窗 - private PointFlyDialog pointFlyDialog;//指点飞行弹窗 + public TakeOffDialog takeOffDialog;//起飞弹窗 + public TurnBackDialog turnBackDialog;//返航弹窗 + public LandDialog landDialog;//降落弹窗 + public BombingDialog bombingDialog;//投弹弹窗 + public PointFlyDialog pointFlyDialog;//指点飞行弹窗 public static StartExecuteDialog startExecuteDialog;//开始执行弹窗 - private SaveLinkNameDialog saveLinkNameDialog;//二次确认路线名称弹窗 + public SaveLinkNameDialog saveLinkNameDialog;//二次确认路线名称弹窗 private ArrayList LogItemList = new ArrayList<>(); private LogAdapter adapter; private FPV_Void fpvVoid = new FPV_Void(); @@ -154,7 +153,7 @@ public class MainActivity extends AppCompatActivity { private Marker mainMarker; private FlyVoid flyVoid = new FlyVoid(); private boolean islocation = true;//是否第一次定位 - private LatLng homeLatLng = null; + public static LatLng homeLatLng = null; private FpvGestureHandler fpvGestureHandler; // 云台手势类 private TcpClientUtil tcpClient;//云台连接类 @@ -174,6 +173,10 @@ public class MainActivity extends AppCompatActivity { private AllLinkAdapter allLinkAdapter; private SQLClass sqlClass; private List linkListInfoList; + public static double[] doubles; + private Marker orangeMarker = null;//指点飞行图标 + private int isAddOrEdit = 0;//0:添加 1:编辑 + private Marker selectMarker;//当前选中的航点marker @Override @@ -187,11 +190,19 @@ public class MainActivity extends AppCompatActivity { return insets; }); + // 关键初始化保留在主线程 initData(); initView(); initReceiver(); + + // 异步初始化非关键组件 + new Thread(() -> { + LidarDataParser.startHeightUpdate(allView.tv_height); + mapVoid.startFlightTracking(); + }).start(); + + // 用户交互相关的初始化保留在主线程 initOnClick(); - mapVoid.startFlightTracking(); } @@ -364,8 +375,10 @@ public class MainActivity extends AppCompatActivity { typeAdapter = new TypeAdapter(typeList); allView.rv_type_list.setAdapter(typeAdapter); - // 设置视频路径 - fpvVoid.setupFpvWidget(allView.fpvWidget, "rtsp://192.168.144.119/live"); + // 延迟初始化FPV视频流 + allView.fpvWidget.post(() -> { + fpvVoid.setupFpvWidget(allView.fpvWidget, "rtsp://192.168.144.119/live"); + }); // 初始化FPV手势处理 //起飞弹窗 @@ -425,15 +438,15 @@ public class MainActivity extends AppCompatActivity { //广播接收-ATTITUDE myReceiver_ATTITUDE.setATTITUDEListener(data -> { // 这里可以更新 UI 或刷新数据 - Log.d(TAG, "收到新数据ATTITUDE:" +MyReceiver.ATTITUDE_json.optDouble("yaw")); +// Log.d(TAG, "收到新数据ATTITUDE:" +MyReceiver.ATTITUDE_json.optDouble("yaw")); // allView.tv_connect.setText("已连接"); // 示例:更新 typeList 数据并刷新 RecyclerView if (data != null) { - flyVoid.setAttitude(getApplicationContext(), allView, MyReceiver.ATTITUDE_json.optDouble("roll"), MyReceiver.ATTITUDE_json.optDouble("pitch"),(int) Math.round(MyReceiver.ATTITUDE_json.optDouble("yaw") * 57.3)); + flyVoid.setAttitude(getApplicationContext(), allView, MyReceiver.ATTITUDE_json.optDouble("roll"), MyReceiver.ATTITUDE_json.optDouble("pitch"), (int) Math.round(MyReceiver.ATTITUDE_json.optDouble("yaw") * 57.3)); } //地图上飞机的朝向 - mainMarker.setRotateAngle( (int) Math.round(MyReceiver.ATTITUDE_json.optDouble("yaw")* 57.3) * -1); + mainMarker.setRotateAngle((int) Math.round(MyReceiver.ATTITUDE_json.optDouble("yaw") * 57.3) * -1); allView.tv_yaw.setText((int) Math.round(MyReceiver.ATTITUDE_json.optDouble("yaw") * 57.3) + "°"); mainMarker.setVisible(true); @@ -455,20 +468,14 @@ public class MainActivity extends AppCompatActivity { // Log.d(TAG, "收到新数据GLOBAL:" + data.toString()); //要把经纬度转换成高德经纬度 - double[] doubles = CoordinateConverter.wgs84ToGcj02( - (MyReceiver.GLOBAL_POSITION_INT_json.optDouble("lon", 0) / 10000000), - (MyReceiver.GLOBAL_POSITION_INT_json.optDouble("lat", 0) / 10000000)); + doubles = CoordinateConverter.wgs84ToGcj02((MyReceiver.GLOBAL_POSITION_INT_json.optDouble("lon", 0) / 10000000), (MyReceiver.GLOBAL_POSITION_INT_json.optDouble("lat", 0) / 10000000)); if (doubles[1] != 0) { //获取到位置后移动视角到当前位置 if (islocation) { // 移动视图到Marker点 - mapVoid.aMap.moveCamera(CameraUpdateFactory.newLatLngZoom( - new LatLng( - MyReceiver.GLOBAL_POSITION_INT_json.optDouble("lat", 0) / 10000000, - MyReceiver.GLOBAL_POSITION_INT_json.optDouble("lon", 0) / 10000000), - 15)); // 15是缩放级别 + mapVoid.aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(MyReceiver.GLOBAL_POSITION_INT_json.optDouble("lat", 0) / 10000000, MyReceiver.GLOBAL_POSITION_INT_json.optDouble("lon", 0) / 10000000), 15)); // 15是缩放级别 islocation = false; homeLatLng = new LatLng(doubles[1], doubles[0]); } @@ -488,11 +495,6 @@ public class MainActivity extends AppCompatActivity { // 添加更多字段... typeAdapter.notifyDataSetChanged(); - if (FlyVoid.parseSerialData != null) { -// allView.tv_height.setText(Math.round((MyReceiver.GLOBAL_POSITION_INT_json.optDouble("relative_alt") / 100) / 10.0) + "m"); -// Toast.makeText(this, flyVoid.parseSerialData[0]+"", Toast.LENGTH_SHORT).show(); - allView.tv_height.setText(flyVoid.parseSerialData[0] + "m"); - } } //如果有相同的点位就不添加到列表里面去 @@ -513,14 +515,14 @@ public class MainActivity extends AppCompatActivity { }); - //广播接收-setPowrStatuslistener - myReceiver_POWER_STATUS.setPowrStatuslistener(data -> { - // 这里可以更新 UI 或刷新数据 -// Log.d(TAG, "收到新数据POWER_STATUS:" + data.toString()); -// allView.tv_power.setText( -// MyReceiver.POWER_STATUS_json.optDouble("Vcc") / 100 -// + " V"); - }); +// //广播接收-setPowrStatuslistener +// myReceiver_POWER_STATUS.setPowrStatuslistener(data -> { +// // 这里可以更新 UI 或刷新数据 +//// Log.d(TAG, "收到新数据POWER_STATUS:" + data.toString()); +//// allView.tv_power.setText( +//// MyReceiver.POWER_STATUS_json.optDouble("Vcc") / 100 +//// + " V"); +// }); //广播接收-setSysStatuslistener myReceiver_SYS_STATUS.setSysStatuslistener(data -> { @@ -533,11 +535,7 @@ public class MainActivity extends AppCompatActivity { myReceiver_STATUSTEXT.setStatustextlistener(data -> { // 这里可以更新 UI 或刷新数据 if (MyReceiver.STATUSTEXT_json.optInt("severity") <= 5) { - LogItemList.add(0, new LogItem( - MyReceiver.STATUSTEXT_json.optString("text"), - ContrastTool.findMostSimilarMatch(MyReceiver.STATUSTEXT_json.optString("text")), - new Date(), - MyReceiver.STATUSTEXT_json.optInt("severity"))); + LogItemList.add(0, new LogItem(MyReceiver.STATUSTEXT_json.optString("text"), ContrastTool.findMostSimilarMatch(MyReceiver.STATUSTEXT_json.optString("text")), new Date(), MyReceiver.STATUSTEXT_json.optInt("severity"))); adapter.setList(LogItemList); allView.iv_error.setVisibility(VISIBLE); } @@ -551,7 +549,7 @@ public class MainActivity extends AppCompatActivity { isUnlock = Tool.getDecToFirstBin(MyReceiver.HEARTBEAT_json.optString("base_mode")).equals("1"); if (allView.ll_link_start.getVisibility() == VISIBLE) { - Log.d(TAG, "myReceiver_HEARTBEAT: " + data.toString()); +// Log.d(TAG, "myReceiver_HEARTBEAT: " + data.toString()); //判断飞控是否解锁 if (Tool.getDecToFirstBin(MyReceiver.HEARTBEAT_json.optString("base_mode")).equals("1")) { //已解锁 @@ -589,7 +587,7 @@ public class MainActivity extends AppCompatActivity { allView.tv_connect.setText("定点模式"); break; case 6: - allView.tv_connect.setText("返航模式"); + allView.tv_connect.setText("返航"); break; case 7: allView.tv_connect.setText("环绕模式"); @@ -624,33 +622,27 @@ public class MainActivity extends AppCompatActivity { // 1 // ))); if (data.optDouble("throttle") > 0) { - typeList.set(2, new Msg("throttle", String.format("%.1f", MyTool.getThrottle( - Double.parseDouble(FlyVoid.paramList.get("MOT_SPIN_MIN").getParam_value()), - Double.parseDouble(FlyVoid.paramList.get("MOT_SPIN_MAX").getParam_value()), - Double.parseDouble(FlyVoid.paramList.get("MOT_THST_EXPO").getParam_value()), - data.optDouble("throttle") / 100, - 1 - ) * 100) + "%", true)); + typeList.set(2, new Msg("throttle", String.format("%.1f", MyTool.getThrottle(Double.parseDouble(FlyVoid.paramList.get("MOT_SPIN_MIN").getParam_value()), Double.parseDouble(FlyVoid.paramList.get("MOT_SPIN_MAX").getParam_value()), Double.parseDouble(FlyVoid.paramList.get("MOT_THST_EXPO").getParam_value()), data.optDouble("throttle") / 100, 1) * 100) + "%", true)); } else { typeList.set(2, new Msg("throttle", "0%", true)); } }); - //广播接收-setMissionAcklistener - myReceiver_MISSION_REQUEST.setMissionRequestlistener(data -> { -// Log.d(TAG, "myReceiver_MISSION_REQUEST: "+data.toString()); - }); - +// //广播接收-setMissionAcklistener +// myReceiver_MISSION_REQUEST.setMissionRequestlistener(data -> { +//// Log.d(TAG, "myReceiver_MISSION_REQUEST: "+data.toString()); +// }); +// //广播接收-setMissionAcklistener myReceiver_MISSION_ACK.setMissionAcklistener(data -> { Log.d(TAG, "myReceiver_MISSION_ACK: " + data.toString()); }); - - //广播接收-setMissionAcklistener - myReceiver_MISSION_CURRENT.setMissionCurrentlistener(data -> { - Log.d(TAG, "myReceiver_MISSION_CURRENT: " + data.toString()); - allView.tv_test1.setText(data.optInt("seq") + ""); - }); +// +// //广播接收-setMissionAcklistener +// myReceiver_MISSION_CURRENT.setMissionCurrentlistener(data -> { +//// Log.d(TAG, "myReceiver_MISSION_CURRENT: " + data.toString()); +// allView.tv_test1.setText(data.optInt("seq") + ""); +// }); } @@ -662,799 +654,197 @@ public class MainActivity extends AppCompatActivity { */ @SuppressLint({"NotifyDataSetChanged", "SetTextI18n", "DefaultLocale", "ClickableViewAccessibility"}) private void initOnClick() { + // 创建MainClick实例 + MainClick mainClick = new MainClick(this, allView, mapVoid, flyVoid, tcpClient, + waypointMarkers, waypointPositions, createLinkList, selectedLinkList, + uploadLinkList, createLinkAdapter, allLinkAdapter, sqlClass, mainMarker); - //点击切换窗口显示 - allView.v_mainDisplay.setOnClickListener(v -> { - if (mainDisplay == 1) { - mainDisplay = 2; - MyTool.setViewWH(this, allView.map, 150, 95, 3); - MyTool.setViewWH(this, allView.fpvWidget, 1920, 1200, 0); - mapVoid.allView.map.setElevation(5f); - mapVoid.allView.fpvWidget.setElevation(1f); - allView.map.setBackgroundResource(R.drawable.x80202020_4round_3stroke_bg); - allView.fpvWidget.setBackgroundColor(Color.parseColor("#ffffff")); - allView.map.setPadding(6, 6, 6, 6); - allView.fpvWidget.setPadding(0, 0, 0, 0); -// allView.map.setVisibility(GONE); -// allView.map_s.setVisibility(VISIBLE); -// allView.fpvWidget.setVisibility(VISIBLE); -// allView.fpvWidget_s.setVisibility(GONE); - allView.ll_left_error_layout.setVisibility(GONE); - allView.ll_ptz_ctrl.setVisibility(VISIBLE); - allView.ll_ptz_fun.setVisibility(VISIBLE); - } else { - mainDisplay = 1; - MyTool.setViewWH(this, allView.fpvWidget, 150, 95, 3); - MyTool.setViewWH(this, allView.map, 1920, 1200, 0); - mapVoid.allView.fpvWidget.setElevation(5f); - mapVoid.allView.map.setElevation(1f); - allView.fpvWidget.setBackgroundResource(R.drawable.x80202020_4round_3stroke_bg); - allView.map.setBackgroundColor(Color.parseColor("#ffffff")); - allView.fpvWidget.setPadding(6, 6, 6, 6); - allView.map.setPadding(0, 0, 0, 0); -// allView.map.setVisibility(GONE); -// allView.map_s.setVisibility(VISIBLE); -// allView.fpvWidget.setVisibility(VISIBLE); -// allView.fpvWidget_s.setVisibility(GONE); - allView.ll_left_error_layout.setVisibility(GONE); - allView.ll_ptz_ctrl.setVisibility(GONE); - allView.ll_ptz_fun.setVisibility(GONE); + // 设置MainClick的各种状态 + mainClick.setIsUnlock(isUnlock); + mainClick.setIsAdviseFly(isAdviseFly); + mainClick.setIsSetLink(isSetLink); + mainClick.setMainDisplay(mainDisplay); + mainClick.setIsAddOrEdit(isAddOrEdit); - } - }); + // 为所有普通点击事件设置监听器 + allView.ll_create_link_layout.setOnClickListener(mainClick); + allView.ll_all_link_layout.setOnClickListener(mainClick); + allView.v_mainDisplay.setOnClickListener(mainClick); + allView.iv_error.setOnClickListener(mainClick); + allView.ll_location_me.setOnClickListener(mainClick); + allView.ll_turn_back.setOnClickListener(mainClick); + allView.ll_lift_off.setOnClickListener(mainClick); + allView.ll_icon_land.setOnClickListener(mainClick); + allView.ll_setting.setOnClickListener(mainClick); + allView.ll_link_start_fun1.setOnClickListener(mainClick); + allView.ll_link_start_fun2.setOnClickListener(mainClick); + allView.ll_link_start_back.setOnClickListener(mainClick); + allView.ll_left_open.setOnClickListener(mainClick); + allView.ll_link.setOnClickListener(mainClick); + allView.ll_title.setOnClickListener(mainClick); + allView.ll_clear.setOnClickListener(mainClick); + allView.tv_add_link.setOnClickListener(mainClick); + allView.ll_map.setOnClickListener(mainClick); + allView.ll_link_save.setOnClickListener(mainClick); + allView.tv_link_fun1.setOnClickListener(mainClick); + allView.tv_link_fun2.setOnClickListener(mainClick); + allView.ll_link_back.setOnClickListener(mainClick); + allView.ll_execute_line.setOnClickListener(mainClick); + allView.ll_bombing.setOnClickListener(mainClick); + allView.ll_shout.setOnClickListener(mainClick); + allView.ll_hook.setOnClickListener(mainClick); + allView.ll_searchlight.setOnClickListener(mainClick); + allView.ll_PTZ_one_center.setOnClickListener(mainClick); + allView.ll_PTZ_one_bottom.setOnClickListener(mainClick); + allView.iv_open_link_list.setOnClickListener(mainClick); + allView.ll_clear_fly_line.setOnClickListener(mainClick); - //点击异常窗口 - allView.iv_error.setOnClickListener(v -> { + // 为四个方向按钮设置统一的点击监听器 + View.OnClickListener markerMoveClickListener = mainClick.getMarkerMoveClickListener(); + allView.iv_marker_top.setOnClickListener(markerMoveClickListener); + allView.iv_marker_bottom.setOnClickListener(markerMoveClickListener); + allView.iv_marker_left.setOnClickListener(markerMoveClickListener); + allView.iv_marker_right.setOnClickListener(markerMoveClickListener); - if (allView.ll_left_error_layout.getVisibility() == VISIBLE) { - allView.ll_left_error_layout.setVisibility(GONE); - } else { - allView.ll_left_error_layout.setVisibility(VISIBLE); - } - }); - - //点击定位到当前位置按钮 - allView.ll_location_me.setOnClickListener(v -> { - if (MyReceiver.GLOBAL_POSITION_INT_json.optDouble("lat", 0) / 10000000 != 0) { - // 移动视图到Marker点 - mapVoid.aMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(MyReceiver.GLOBAL_POSITION_INT_json.optDouble("lat", 0) / 10000000, MyReceiver.GLOBAL_POSITION_INT_json.optDouble("lon", 0) / 10000000), 15)); // 15是缩放级别 - mainMarker.setVisible(true); - } - }); - - //返航按钮 - allView.ll_turn_back.setOnClickListener(v -> { - turnBackDialog.show(); - }); - - // 起飞按钮 - allView.ll_lift_off.setOnClickListener(v -> { - takeOffDialog.show(); - }); - - // 降落按钮 - allView.ll_icon_land.setOnClickListener(v -> { - landDialog.show(); - }); - - //进设置页面 - allView.ll_setting.setOnClickListener(v -> { -// Toast.makeText(this, "维护中..", Toast.LENGTH_SHORT).show(); - Intent intent = new Intent(this, SettingActivity.class); - startActivity(intent); - }); - - //航线执行-上传航线 - allView.ll_link_start_fun1.setOnClickListener(v -> { - // 添加航线发送功能 - if (selectedLinkList.size() > 0) { - // 调用FlyVoid中的方法发送航线到飞控 - flyVoid.sendMissionToFlightController(this, - selectedLinkList, - allView.et_start_execute_height.getText().toString()); - // 清除当前地图上的所有航点和航线 -// clearWaypoints(); - allView.v_mainDisplay.setVisibility(VISIBLE); - allView.ll_open_layout.setVisibility(VISIBLE); - allView.ll_text.setVisibility(VISIBLE); - allView.ll_link_start.setVisibility(GONE); - allView.ll_all_link_layout.setVisibility(GONE); - allView.fpvWidget.setVisibility(VISIBLE); - uploadLinkList.addAll(selectedLinkList); - allView.ll_assistance_layout.setVisibility(VISIBLE); - } else { - Toast.makeText(this, "请选择航线", Toast.LENGTH_SHORT).show(); - } - }); - //开始执行 - allView.ll_link_start_fun2.setOnClickListener(v -> { - // 开始执行 - if (selectedLinkList != null) { - // 调用FlyVoid中的方法发送航线到飞控 - //flyVoid.requestMissionStart(0,0); - if (isUnlock) { - startExecuteDialog.show(); - } else { - Toast.makeText(this, "请先解锁", Toast.LENGTH_SHORT).show(); - } - - } else { - Toast.makeText(this, "请先选择航线", Toast.LENGTH_SHORT).show(); - } - - }); - - //航线执行-退出 - allView.ll_link_start_back.setOnClickListener(v -> { - //判断是否选择了航线 - if (uploadLinkList != null) { - // 清除当前地图上的所有航点和航线 - clearWaypoints(); - // 在地图上显示航线-之前上传的航线 - displayRouteOnMap(uploadLinkList); - } - allView.v_mainDisplay.setVisibility(VISIBLE); - allView.ll_open_layout.setVisibility(VISIBLE); - allView.ll_text.setVisibility(VISIBLE); - allView.ll_link_start.setVisibility(GONE); - allView.ll_all_link_layout.setVisibility(GONE); - allView.fpvWidget.setVisibility(VISIBLE); - allView.ll_assistance_layout.setVisibility(VISIBLE); - isAdviseFly = true; - }); - - allView.ll_left_open.setOnClickListener(v -> { - if (allView.ll_function_layout.getVisibility() == VISIBLE) { - allView.ll_function_layout.setVisibility(GONE); - } else { - allView.ll_function_layout.setVisibility(VISIBLE); - } - }); - - //清除所有航线的方法 - allView.ll_clear.setOnClickListener(v -> { - uploadLinkList.clear(); - // 清除所有航点和航线 - clearWaypoints(); - // 在地图上显示航线-清除选中点在更新地图 - displayRouteOnMap(uploadLinkList); - Toast.makeText(this, "已清除", Toast.LENGTH_SHORT).show(); - }); - - //添加航线跳转 - allView.tv_add_link.setOnClickListener(v -> { - // 清除所有航点和航线 - clearWaypoints(); - isSetLink = true; - allView.ll_all_link_layout.setVisibility(GONE); - allView.ll_link_start.setVisibility(GONE); - allView.v_mainDisplay.setVisibility(GONE); - allView.ll_open_layout.setVisibility(GONE); - allView.ll_text.setVisibility(GONE); - allView.ll_link.setVisibility(VISIBLE); - allView.ll_create_link_layout.setVisibility(VISIBLE); - allView.fpvWidget.setVisibility(GONE); - }); - - //航线规划 - allView.ll_map.setOnClickListener(v -> { - // 清除所有航点和航线 - clearWaypoints(); - isAdviseFly = false; - allView.ll_all_link_layout.setVisibility(VISIBLE); - allView.ll_link_start.setVisibility(VISIBLE); - allView.v_mainDisplay.setVisibility(GONE); - allView.ll_open_layout.setVisibility(GONE); - allView.ll_text.setVisibility(GONE); - allView.ll_link.setVisibility(GONE); - allView.ll_create_link_layout.setVisibility(GONE); - allView.fpvWidget.setVisibility(GONE); - allView.ll_assistance_layout.setVisibility(GONE); - }); - //航线规划功能-保存 - allView.ll_link_save.setOnClickListener(v -> { - if (allView.et_link_name.getText().toString().length() != 0){ - saveLink(null); - }else { - saveLinkNameDialog.show(); - } - - }); - // 航线规划功能-1:反转航点顺序 - allView.tv_link_fun1.setOnClickListener(v -> { - // 创建确认对话框 - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle("反转航点顺序"); - builder.setMessage("确定要反转当前航点的顺序吗?"); - - builder.setPositiveButton("确定", (dialog, which) -> { - // 反转航点位置列表 - java.util.Collections.reverse(waypointPositions); - - // 反转航点标记列表 - java.util.Collections.reverse(waypointMarkers); - - // 反转createLinkList列表 - java.util.Collections.reverse(createLinkList); - - // 重新编号航点标记 - renumberWaypoints(); - - // 更新航线显示 - updateFlightPath(); - - dialog.dismiss(); - }); - - builder.setNegativeButton("取消", (dialog, which) -> { - dialog.dismiss(); - }); - - AlertDialog dialog = builder.create(); - dialog.show(); - }); - // 航线规划功能-2:清除所有线航 - allView.tv_link_fun2.setOnClickListener(v -> { - // 创建确认对话框 - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle("清除所有航点"); - builder.setMessage("确定要清除所有航点和航线吗?"); - - builder.setPositiveButton("确定", (dialog, which) -> { - // 清除所有航点和航线 - clearWaypoints(); - dialog.dismiss(); - }); - - builder.setNegativeButton("取消", (dialog, which) -> { - dialog.dismiss(); - }); - - AlertDialog dialog = builder.create(); - dialog.show(); - }); - //航线规划功能-退出 - allView.ll_link_back.setOnClickListener(v -> { - if (createLinkList.size() > 0) { - // 创建确认对话框 - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle("退出"); - builder.setMessage("确定要退出嘛?退出前的航线不会保存"); - - builder.setPositiveButton("确定", (dialog, which) -> { - // 清除所有航点和航线 - clearWaypoints(); - isSetLink = false; - allView.ll_all_link_layout.setVisibility(VISIBLE); - allView.ll_link_start.setVisibility(VISIBLE); - allView.v_mainDisplay.setVisibility(GONE); - allView.ll_open_layout.setVisibility(GONE); - allView.ll_text.setVisibility(GONE); - allView.ll_link.setVisibility(GONE); - allView.ll_create_link_layout.setVisibility(GONE); - allView.fpvWidget.setVisibility(GONE); - displayRouteOnMap(selectedLinkList); - dialog.dismiss(); - // 在地图上显示航线-之前上传的航线 - displayRouteOnMap(selectedLinkList); - - }); - - builder.setNegativeButton("取消", (dialog, which) -> { - dialog.dismiss(); - }); - - AlertDialog dialog = builder.create(); - dialog.show(); - } else { - // 清除所有航点和航线 - clearWaypoints(); - isSetLink = false; - allView.ll_all_link_layout.setVisibility(VISIBLE); - allView.ll_link_start.setVisibility(VISIBLE); - allView.v_mainDisplay.setVisibility(GONE); - allView.ll_open_layout.setVisibility(GONE); - allView.ll_text.setVisibility(GONE); - allView.ll_link.setVisibility(GONE); - allView.ll_create_link_layout.setVisibility(GONE); - allView.fpvWidget.setVisibility(GONE); - } - }); - - allView.ll_execute_line.setOnClickListener(v -> { - startExecuteDialog.show(); - }); - allView.ll_bombing.setOnClickListener(v -> { - bombingDialog.show(); -// Toast.makeText(this, "正在研发..", Toast.LENGTH_SHORT).show(); - }); - allView.ll_shout.setOnClickListener(v -> { - Toast.makeText(this, "正在研发..", Toast.LENGTH_SHORT).show(); - }); - allView.ll_hook.setOnClickListener(v -> { - Toast.makeText(this, "正在研发..", Toast.LENGTH_SHORT).show(); - }); - allView.ll_searchlight.setOnClickListener(v -> { - Toast.makeText(this, "正在研发..", Toast.LENGTH_SHORT).show(); - }); - //初始化FPV手势处理 + // 初始化FPV手势处理 fpvGestureHandler = new FpvGestureHandler(allView.fpvWidget); - fpvGestureHandler.setOnFpvGestureListener(new FpvGestureHandler.OnFpvGestureListener() { - // 添加一个标志位来跟踪是否已经处理过滑动 - private boolean isSwiping = false; - private String lastDirection = ""; + fpvGestureHandler.setOnFpvGestureListener(mainClick.getFpvGestureListener()); - @Override - public void onTap(float x, float y) { - // 处理单击事件 - Log.d(TAG, "FPV单击: x=" + x + ", y=" + y); - // 获取FPV控件的宽度和高度 - int fpvWidth = allView.fpvWidget.getWidth(); - int fpvHeight = allView.fpvWidget.getHeight(); - - // 将坐标转换为0x00-0xff范围内的值 - // X方向: 从左(0x00)到右(0xff) - // Y方向: 从上(0x00)到下(0xff) - byte convertedX = (byte) Math.max(0x00, Math.min(0xFF, Math.round((x / fpvWidth) * 255))); - byte convertedY = (byte) Math.max(0x00, Math.min(0xFF, Math.round((y / fpvHeight) * 255))); - - if (!tcpClient.isConnected()) { - Toast.makeText(getApplicationContext(), "未连接到服务器", Toast.LENGTH_SHORT).show(); - } else { - // 发送指点 - byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x10, 0x00, convertedX, convertedY, - Protocol.calculateCheckCode((byte) 0x01, (byte) 0x10, (byte) 0x00, convertedX, convertedY)}; - tcpClient.sendBytes(testData); - } - } - - @Override - public void onDoubleTap(float x, float y) { - // 处理双击事件 - Log.d(TAG, "FPV双击: x=" + x + ", y=" + y); - // 在这里添加您的双击处理逻辑 - } - - @Override - public void onLongPress(float x, float y) { - // 处理长按事件 - Log.d(TAG, "FPV长按: x=" + x + ", y=" + y); - // 在这里添加您的长按处理逻辑 - } - - @Override - public void onSwipe(float startX, float startY, float endX, float endY, float distanceX, float distanceY) { - // 处理滑动事件 -// Log.d(TAG, "FPV滑动: startX=" + startX + ", startY=" + startY + -// ", endX=" + endX + ", endY=" + endY + -// ", distanceX=" + distanceX + ", distanceY=" + distanceY); - - // 判断滑动方向 - String currentDirection; - if (Math.abs(distanceX) > Math.abs(distanceY)) { - // 水平滑动 - if (distanceX > 0) { - // 向右滑动 - currentDirection = "right"; -// Log.d(TAG, "FPV向右滑动"); - } else { - // 向左滑动 - currentDirection = "left"; -// Log.d(TAG, "FPV向左滑动"); - } - } else { - // 垂直滑动 - if (distanceY > 0) { - // 向下滑动 - currentDirection = "down"; -// Log.d(TAG, "FPV向下滑动"); - } else { - // 向上滑动 - currentDirection = "up"; -// Log.d(TAG, "FPV向上滑动"); - } - } - - // 如果方向改变或者刚开始滑动,则更新方向并处理 - if (!isSwiping || !lastDirection.equals(currentDirection)) { - isSwiping = true; - lastDirection = currentDirection; - Log.d(TAG, "FPV向" + currentDirection + "滑动"); - // 在这里添加您的滑动处理逻辑 - switch (currentDirection) { - case "up": - if (!tcpClient.isConnected()) { - Toast.makeText(getApplicationContext(), "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送左转数据 - byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x08, 0x00, (byte) 0xFF, 0x08}; - tcpClient.sendBytes(testData); - } - break; - - case "down": - if (!tcpClient.isConnected()) { - Toast.makeText(getApplicationContext(), "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送左转数据 - byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x10, 0x00, (byte) 0xFF, 0x10}; - tcpClient.sendBytes(testData); - } - break; - - case "left": - if (!tcpClient.isConnected()) { - Toast.makeText(getApplicationContext(), "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送左转数据 - byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x04, (byte) 0xFF, 0x00, 0x04}; - tcpClient.sendBytes(testData); - } - break; - - case "right": - // 停止数据 - if (!tcpClient.isConnected()) { - Toast.makeText(getApplicationContext(), "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送左转数据 - byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x02, (byte) 0xFF, 0x00, 0x02}; - tcpClient.sendBytes(testData); - } - - } - } - } - - @Override - public void onSwipeUp() { - // 向上滑动的专门处理方法 -// Log.d(TAG, "FPV向上滑动事件"); - } - - @Override - public void onSwipeDown() { - // 向下滑动的专门处理方法 -// Log.d(TAG, "FPV向下滑动事件"); - } - - @Override - public void onSwipeLeft() { - // 向左滑动的专门处理方法 -// Log.d(TAG, "FPV向左滑动事件"); - - } - - @Override - public void onSwipeRight() { - // 向右滑动的专门处理方法 -// Log.d(TAG, "FPV向右滑动事件"); - } - - @Override - public void onZoom(float scaleFactor) { - // 处理缩放事件 - Log.d(TAG, "FPV缩放: scaleFactor=" + scaleFactor); - // 在这里添加您的缩放处理逻辑 - } - - @Override - public void onSwipeEnd() { - // 滑动结束(抬起)事件 - Log.d(TAG, "FPV滑动结束(手指抬起)"); - // 重置标志位,以便下一次滑动可以被处理 - isSwiping = false; - lastDirection = ""; - // 发送停止数据 - byte[] testData1 = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01}; - tcpClient.sendBytes(testData1); - } - }); - - // 为iv_ptz_top添加按下和抬起事件 - allView.iv_ptz_top.setOnTouchListener((v, event) -> { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - // 按下事件 - Log.d("PTZ", "iv_ptz_top被按下"); - if (!tcpClient.isConnected()) { - Toast.makeText(this, "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送左转数据 - byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x08, 0x00, (byte) 0xFF, 0x08}; - tcpClient.sendBytes(testData); - } - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - if (!tcpClient.isConnected()) { - Toast.makeText(this, "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送停止数据 - byte[] testData1 = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01}; - tcpClient.sendBytes(testData1); - } - break; - } - return true; // 返回true表示处理了触摸事件 - }); - - // 为iv_ptz_left添加按下和抬起事件 - allView.iv_ptz_left.setOnTouchListener((v, event) -> { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - // 按下事件 - Log.d("PTZ", "iv_ptz_left被按下"); - if (!tcpClient.isConnected()) { - Toast.makeText(this, "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送左转数据 - byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x04, (byte) 0xFF, 0x00, 0x04}; - tcpClient.sendBytes(testData); - } - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - // 抬起或取消事件 - Log.d("PTZ", "iv_ptz_left被释放"); - if (!tcpClient.isConnected()) { - Toast.makeText(this, "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送停止数据 - byte[] testData1 = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01}; - tcpClient.sendBytes(testData1); - } - - // 在这里添加抬起时需要执行的代码 - // 例如停止云台转动 - break; - } - return true; // 返回true表示处理了触摸事件 - }); - - // 为iv_ptz_right添加按下和抬起事件 - allView.iv_ptz_right.setOnTouchListener((v, event) -> { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - // 按下事件 - Log.d("PTZ", "iv_ptz_right被按下"); - if (!tcpClient.isConnected()) { - Toast.makeText(this, "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送左转数据 - byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x02, (byte) 0xFF, 0x00, 0x02}; - tcpClient.sendBytes(testData); - } - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - // 抬起或取消事件 - Log.d("PTZ", "iv_ptz_right被释放"); - if (!tcpClient.isConnected()) { - Toast.makeText(this, "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送停止数据 - byte[] testData1 = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01}; - tcpClient.sendBytes(testData1); - } - break; - } - return true; // 返回true表示处理了触摸事件 - }); - - // 为iv_ptz_bottom添加按下和抬起事件 - allView.iv_ptz_bottom.setOnTouchListener((v, event) -> { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - // 按下事件 - Log.d("PTZ", "iv_ptz_bottom被按下"); - if (!tcpClient.isConnected()) { - Toast.makeText(this, "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送左转数据 - byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x10, 0x00, (byte) 0xFF, 0x10}; - tcpClient.sendBytes(testData); - } - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - if (!tcpClient.isConnected()) { - Toast.makeText(this, "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送停止数据 - byte[] testData1 = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01}; - tcpClient.sendBytes(testData1); - } - break; - } - return true; // 返回true表示处理了触摸事件 - }); - - //一键回中 - allView.ll_PTZ_one_center.setOnClickListener(v -> { - // 发送左转数据 - byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x13, 0x03, 0x00, 0x00, 0x17}; - tcpClient.sendBytes(testData); - }); - - //一键向下 - allView.ll_PTZ_one_bottom.setOnClickListener(v -> { - // 发送左转数据 - byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x13, 0x02, 0x00, 0x00, 0x16}; - tcpClient.sendBytes(testData); - }); - - // 为ll_PTZ_amplify添加按下和抬起事件 - allView.ll_PTZ_amplify.setOnTouchListener((v, event) -> { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - // 按下事件 - Log.d("PTZ", "ll_PTZ_amplify被按下"); - if (!tcpClient.isConnected()) { - Toast.makeText(this, "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送变倍数据 - byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x40, 0x04, 0x00, 0x45}; - tcpClient.sendBytes(testData); - } - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - if (!tcpClient.isConnected()) { - Toast.makeText(this, "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送停止数据 - byte[] testData1 = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x60, 0x00, 0x00, 0x61}; - tcpClient.sendBytes(testData1); - } - break; - } - return true; // 返回true表示处理了触摸事件 - }); - - // 为ll_PTZ_reduce添加按下和抬起事件 - allView.ll_PTZ_reduce.setOnTouchListener((v, event) -> { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - // 按下事件 - Log.d("PTZ", "ll_PTZ_reduce被按下"); - if (!tcpClient.isConnected()) { - Toast.makeText(this, "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送变倍数据 - byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x20, 0x04, 0x00, 0x25}; - tcpClient.sendBytes(testData); - } - break; - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - if (!tcpClient.isConnected()) { - Toast.makeText(this, "未连接到服务器", Toast.LENGTH_SHORT).show(); - break; - } else { - // 发送停止数据 - byte[] testData1 = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x60, 0x00, 0x00, 0x61}; - tcpClient.sendBytes(testData1); - } - break; - } - return true; // 返回true表示处理了触摸事件 - }); + // 为PTZ控件添加触摸事件 + allView.iv_ptz_top.setOnTouchListener(mainClick.getPTZTouchListener()); + allView.iv_ptz_left.setOnTouchListener(mainClick.getPTZTouchListener()); + allView.iv_ptz_right.setOnTouchListener(mainClick.getPTZTouchListener()); + allView.iv_ptz_bottom.setOnTouchListener(mainClick.getPTZTouchListener()); + allView.ll_PTZ_amplify.setOnTouchListener(mainClick.getPTZTouchListener()); + allView.ll_PTZ_reduce.setOnTouchListener(mainClick.getPTZTouchListener()); // 设置地图点击监听器以添加航点 - allView.map.getMap().setOnMapClickListener(latLng -> { - if (isSetLink) { -// Log.d("setOnMapClickListener", latLng.toString()+"++"+isSetLink); - addWaypoint(latLng); - } - }); + allView.map.getMap().setOnMapClickListener(mainClick.getMapClickListener()); - //地图长按 - allView.map.getMap().setOnMapLongClickListener(latLng -> { - if (isAdviseFly) { - pointFlyDialog.setLatLng(latLng); - pointFlyDialog.show(); - } - }); + // 地图长按指点飞行 + allView.map.getMap().setOnMapLongClickListener(mainClick.getMapLongClickListener()); - // 设置标记点击监听器以删除航点 - allView.map.getMap().setOnMarkerClickListener(marker -> { - if (isSetLink) { - // 检查是否是航点标记 - int index = findWaypointMarkerIndex(marker); - if (index != -1) { - // 显示删除确认对话框 - showDeleteWaypointDialog(index, marker); - return true; // 消费点击事件 - } - } - - return false; // 不消费点击事件 - }); + // 设置标记点击监听器 -- 航点移动 + allView.map.getMap().setOnMarkerClickListener(mainClick.getMarkerClickListener()); // 设置标记的标题始终显示 - allView.map.getMap().setOnMapLoadedListener(() -> { - if (isSetLink) { - // 地图加载完成后,确保所有航点标题可见 - for (Marker marker : waypointMarkers) { - marker.showInfoWindow(); - } - } - - }); + allView.map.getMap().setOnMapLoadedListener(mainClick.getMapLoadedListener()); // 设置删除监听器 createLinkAdapter.setOnItemClickListener(new CreateLinkAdapter.OnItemClickListener() { @Override public void onDeleteClick(int position) { - // 删除对应的航点 removeWaypointByIndex(position); } }); - //根据输入的文字模糊查询(名字)搜索框 - allView.et_link_search.addTextChangedListener(new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - // 不需要实现 - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - // 实时查询 - filterLinkList(s.toString()); - } - - @Override - public void afterTextChanged(Editable s) { - // 不需要实现 - } - }); - - //清除飞行轨迹 - allView.ll_clear_fly_line.setOnClickListener(v -> { - if (mapVoid.isTracking){ - mapVoid.isTracking = false; - mapVoid.clearFlightTrack(); - mapVoid.stopFlightTracking(); - }else { - mapVoid.startFlightTracking(); - } - - }); - - //开启|关闭航线点位 - allView.iv_open_link_list.setOnClickListener(v -> { - if (allView.ll_create_link_item_layout.getVisibility() == View.GONE){ - allView.ll_create_link_item_layout.setVisibility(View.VISIBLE); - }else { - allView.ll_create_link_item_layout.setVisibility(View.GONE); - } - }); - + // 根据输入的文字模糊查询(名字)搜索框 + allView.et_link_search.addTextChangedListener(mainClick.getTextWatcher()); } + + + + // 在 MainActivity 中添加以下公共方法 + + public void updateFlightPath() { + if (flightPathPolyline != null) { + flightPathPolyline.remove(); + flightPathPolyline = null; + } + + if (waypointPositions.size() > 1) { + flightPathPolyline = allView.map.getMap().addPolyline(new PolylineOptions() + .addAll(waypointPositions).width(6).color(Color.parseColor("#FFEB3B"))); + } + } + + public void displayRouteOnMap(ArrayList createLinkList) { + for (int i = 0; i < createLinkList.size(); i++) { + CreateLink createLink = createLinkList.get(i); + LatLng latLng = createLink.getLatLng(); + if (latLng == null) continue; + + View markerView = getLayoutInflater().inflate(R.layout.custom_marker_layout, null); + TextView markerText = markerView.findViewById(R.id.marker_text); + markerText.setText(createLink.getName()); + + markerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + markerView.layout(0, 0, markerView.getMeasuredWidth(), markerView.getMeasuredHeight()); + markerView.buildDrawingCache(); + Bitmap markerBitmap = markerView.getDrawingCache(); + + MarkerOptions markerOptions = new MarkerOptions().position(latLng) + .icon(BitmapDescriptorFactory.fromBitmap(markerBitmap)).draggable(false); + + Marker marker = allView.map.getMap().addMarker(markerOptions); + + waypointMarkers.add(marker); + waypointPositions.add(latLng); + + CreateLink newCreateLink = new CreateLink(createLink.getName(), createLink.getHeight(), + createLink.getSpeed(), createLink.getWaypointIndex(), latLng, createLink.getStop_time(), + createLink.isBom1_show(), createLink.isBom2_show()); + this.createLinkList.add(newCreateLink); + } + + createLinkAdapter.setCreateLinkList(this.createLinkList); + updateFlightPath(); + + if (!waypointPositions.isEmpty()) { + LatLng firstWaypoint = waypointPositions.get(0); + allView.map.getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(firstWaypoint, 15)); + } + } + + public int findWaypointMarkerIndex(Marker marker) { + return waypointMarkers.indexOf(marker); + } + + public void renumberWaypoints() { + for (int i = 0; i < waypointMarkers.size(); i++) { + Bitmap markerBitmap = createCustomMarkerBitmap((i + 1) + ""); + waypointMarkers.get(i).setIcon(BitmapDescriptorFactory.fromBitmap(markerBitmap)); + + if (i < createLinkList.size()) { + createLinkList.get(i).setName((i + 1) + ""); + } + } + + createLinkAdapter.setCreateLinkList(createLinkList); + } + + public Bitmap createCustomMarkerBitmap(String text) { + View markerView = getLayoutInflater().inflate(R.layout.custom_marker_layout, null); + TextView markerText = markerView.findViewById(R.id.marker_text); + markerText.setText(text); + + markerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + markerView.layout(0, 0, markerView.getMeasuredWidth(), markerView.getMeasuredHeight()); + markerView.buildDrawingCache(); + return markerView.getDrawingCache(); + } + + public void removeWaypointByIndex(int position) { + if (position >= 0 && position < waypointMarkers.size()) { + waypointMarkers.get(position).remove(); + waypointMarkers.remove(position); + waypointPositions.remove(position); + createLinkList.remove(position); + + createLinkAdapter.setCreateLinkList(createLinkList); + renumberWaypoints(); + updateFlightPath(); + } + } + + /** * 方法:保存航线 * * @cuijingzhou */ - public void saveLink( String linkName) { + public void saveLink(String linkName) { // 初始化数据库 SQLClass sqlClass = new SQLClass(this); // 添加一个CreateLink列表 @@ -1462,15 +852,38 @@ public class MainActivity extends AppCompatActivity { if (createLinkList.size() > 0) { createLinkLists.addAll(createLinkList); boolean success; - if (linkName == null){ - // 添加CreateLink对象到列表中 - if (allView.et_link_name.getText().toString().length() != 0) { - success = sqlClass.addCreateLinkList(allView.et_link_name.getText().toString(), createLinkLists); + + if (isAddOrEdit == 0) { // 添加模式 + if (linkName == null) { + // 添加CreateLink对象到列表中 + if (allView.et_link_name.getText().toString().length() != 0) { + success = sqlClass.addCreateLinkList(allView.et_link_name.getText().toString(), createLinkLists); + } else { + success = sqlClass.addCreateLinkList("航线-" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), createLinkLists); + } } else { - success = sqlClass.addCreateLinkList("航线-" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), createLinkLists); + success = sqlClass.addCreateLinkList(linkName, createLinkLists); } - }else { - success = sqlClass.addCreateLinkList(linkName, createLinkLists); + } else { // 编辑模式 + if (allLinkAdapter.getSelectLinkListInfo() != -1){ + // 获取当前编辑的航线ID(需要您根据实际情况调整) + int currentLinkId = allLinkAdapter.getSelectLinkListInfo(); // 这个方法需要您实现 todo + if (linkName == null) { + if (allView.et_link_name.getText().toString().length() != 0) { + success = sqlClass.updateCreateLinkList(currentLinkId, allView.et_link_name.getText().toString(), createLinkLists); + } else { + success = sqlClass.updateCreateLinkList( + currentLinkId, + "航线-" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), createLinkLists); + } + } else { + success = sqlClass.updateCreateLinkList(currentLinkId, linkName, createLinkLists); + } + }else { + Toast.makeText(this, "获取列表错误", Toast.LENGTH_SHORT).show(); + success = false; + } + } if (success) { @@ -1489,161 +902,11 @@ public class MainActivity extends AppCompatActivity { // 在地图上显示航线-之前选中的航线 displayRouteOnMap(selectedLinkList); refreshLinkList();//刷新航线列表 - Toast.makeText(this, "航线保存成功", Toast.LENGTH_SHORT).show(); + Toast.makeText(this, isAddOrEdit == 0 ? "航线保存成功" : "航线更新成功", Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(this, "请先添加航点", Toast.LENGTH_SHORT).show(); } - - - - } - - // 添加过滤方法 - private void filterLinkList(String query) { - if (sqlClass != null && allLinkAdapter != null) { - if (query.isEmpty()) { - // 如果查询为空,显示所有数据 - List allList = sqlClass.getAllLinkListInfo(); - allLinkAdapter.updateDataList(allList); - } else { - // 根据输入文字模糊查询 - List filteredList = new ArrayList<>(); - List fullList = sqlClass.getAllLinkListInfo(); - - for (SQLClass.LinkListInfo item : fullList) { - // 模糊匹配航线名称 - if (item.getListName().toLowerCase().contains(query.toLowerCase())) { - filteredList.add(item); - } - } - - allLinkAdapter.updateDataList(filteredList); - } - } - } - - /** - * 显示删除航点确认对话框 - * - * @param index 航点索引 - * @param marker 航点标记 - */ - private void showDeleteWaypointDialog(int index, Marker marker) { - // 创建自定义对话框 - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle("删除航点"); - builder.setMessage("确定要删除航点" + (index + 1) + "吗?"); - - builder.setPositiveButton("确定", (dialog, which) -> { - // 删除航点时同时删除对应的列表项 - removeWaypointByIndex(index); - dialog.dismiss(); - }); - - builder.setNegativeButton("取消", (dialog, which) -> { - dialog.dismiss(); - }); - - AlertDialog dialog = builder.create(); - dialog.show(); - } - - - // 修改 addWaypoint 方法 - private void addWaypoint(LatLng latLng) { - // 创建自定义标记视图 - View markerView = getLayoutInflater().inflate(R.layout.custom_marker_layout, null); - @SuppressLint({"MissingInflatedId", "LocalSuppress"}) TextView markerText = markerView.findViewById(R.id.marker_text); - markerText.setText( "" + (waypointMarkers.size() + 1)); - - // 将视图转换为Bitmap - markerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); - markerView.layout(0, 0, markerView.getMeasuredWidth(), markerView.getMeasuredHeight()); - markerView.buildDrawingCache(); - Bitmap markerBitmap = markerView.getDrawingCache(); - - // 创建标记选项 - MarkerOptions markerOptions = new MarkerOptions() - .position(latLng) - .icon(BitmapDescriptorFactory.fromBitmap(markerBitmap)) - .draggable(false); - - // 添加标记到地图 - Marker marker = allView.map.getMap().addMarker(markerOptions); - - waypointMarkers.add(marker); - waypointPositions.add(latLng); - - // 添加到列表 - CreateLink createLink = new CreateLink( - waypointMarkers.size()+"", - 30, - 10, - waypointMarkers.size() - 1, - latLng, - true, - true - ); - createLinkList.add(createLink); - createLinkAdapter.setCreateLinkList(createLinkList); - - // 更新航线 - updateFlightPath(); - } - - // 添加新的方法 - private void removeWaypointByIndex(int position) { - if (position >= 0 && position < waypointMarkers.size()) { - // 移除标记 - waypointMarkers.get(position).remove(); - waypointMarkers.remove(position); - waypointPositions.remove(position); - createLinkList.remove(position); - - // 更新适配器 - createLinkAdapter.setCreateLinkList(createLinkList); - - // 重新编号剩余的航点 - renumberWaypoints(); - - // 更新航线 - updateFlightPath(); - } - } - - // 修改 renumberWaypoints 方法以同步更新列表项 - private void renumberWaypoints() { - for (int i = 0; i < waypointMarkers.size(); i++) { - // 创建新的自定义标记Bitmap - Bitmap markerBitmap = createCustomMarkerBitmap( (i + 1)+""); - // 更新标记图标 - waypointMarkers.get(i).setIcon(BitmapDescriptorFactory.fromBitmap(markerBitmap)); - - // 更新列表项名称 - if (i < createLinkList.size()) { - createLinkList.get(i).setName( (i + 1)+""); - } - } - - createLinkAdapter.setCreateLinkList(createLinkList); - } - - /** - * 创建自定义标记Bitmap - * - * @param text 标记文字 - * @return Bitmap - */ - private Bitmap createCustomMarkerBitmap(String text) { - View markerView = getLayoutInflater().inflate(R.layout.custom_marker_layout, null); - @SuppressLint({"MissingInflatedId", "LocalSuppress"}) TextView markerText = markerView.findViewById(R.id.marker_text); - markerText.setText(text); - - markerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); - markerView.layout(0, 0, markerView.getMeasuredWidth(), markerView.getMeasuredHeight()); - markerView.buildDrawingCache(); - return markerView.getDrawingCache(); } @@ -1668,77 +931,77 @@ public class MainActivity extends AppCompatActivity { } } - - /** - * 根据标记查找航点索引 - * - * @param marker 标记对象 - * @return 航点索引,未找到返回-1 - */ - private int findWaypointMarkerIndex(Marker marker) { - return waypointMarkers.indexOf(marker); - } - - - /** - * 更新航线显示 - */ - private void updateFlightPath() { - // 如果已有航线,先移除 - if (flightPathPolyline != null) { - flightPathPolyline.remove(); - flightPathPolyline = null; - } - - // 只有当航点数量大于1时才绘制航线 - if (waypointPositions.size() > 1) { - flightPathPolyline = allView.map.getMap().addPolyline(new PolylineOptions() - .addAll(waypointPositions) - .width(6) - .color(Color.parseColor("#FFEB3B"))); - } - } - - /** - * 获取所有航点的经纬度列表(按顺序) - * - * @return 航点经纬度列表 - */ - public List getWaypointPositions() { - return new ArrayList<>(waypointPositions); - } - - private void setupAllLinkList() { // 初始化数据库 sqlClass = new SQLClass(this); - // 获取所有航线列表信息 - linkListInfoList = sqlClass.getAllLinkListInfo(); + try { + // 获取所有航线列表信息 + linkListInfoList = sqlClass.getAllLinkListInfo(); - // 设置适配器 - allLinkAdapter = new AllLinkAdapter(this, linkListInfoList, sqlClass); - allView.rv_all_link_list.setLayoutManager(new LinearLayoutManager(this)); - allView.rv_all_link_list.setAdapter(allLinkAdapter); + // 设置适配器 + allLinkAdapter = new AllLinkAdapter(this, linkListInfoList, sqlClass); + allView.rv_all_link_list.setLayoutManager(new LinearLayoutManager(this)); + allView.rv_all_link_list.setAdapter(allLinkAdapter); - // 设置item点击监听器(可选) - allLinkAdapter.setOnItemClickListener(new AllLinkAdapter.OnItemClickListener() { - @Override - public void onItemClick(int listId, int position) { - // 清除所有航点和航线 - clearWaypoints(); - // 从数据库中获取选中的航线数据 - selectedLinkList = sqlClass.getCreateLinkList(listId); - if (selectedLinkList.size() > 0) { + // 设置item点击监听器(可选) + allLinkAdapter.setOnItemClickListener(new AllLinkAdapter.OnItemClickListener() { + @Override + public void onItemClick(int listId, int position) { + // 清除所有航点和航线 + clearWaypoints(); + // 从数据库中获取选中的航线数据 + selectedLinkList = sqlClass.getCreateLinkList(listId); + if (selectedLinkList.size() > 0) { // Toast.makeText(MainActivity.this, "已加载航线: " + linkListInfoList.get(position).getListName(), // Toast.LENGTH_SHORT).show(); - // 在地图上显示航线 - displayRouteOnMap(selectedLinkList); - } else { - Toast.makeText(MainActivity.this, "加载航线失败", Toast.LENGTH_SHORT).show(); + // 在地图上显示航线 + displayRouteOnMap(selectedLinkList); + } else { +// Toast.makeText(MainActivity.this, "加载航线失败", Toast.LENGTH_SHORT).show(); + } } - } - }); + }); + + // 设置item点击监听器(可选) + allLinkAdapter.setOnItemEditClickListener(new AllLinkAdapter.OnItemEditClickListener() { + @Override + public void onItemEditClick(int listId, int position) { + isAddOrEdit = 1; + + // 清除所有航点和航线 + clearWaypoints(); + + // 从数据库中获取选中的航线数据 + selectedLinkList.addAll(sqlClass.getCreateLinkList(listId)); + if (selectedLinkList.size() > 0) { +// Toast.makeText(MainActivity.this, "已加载航线: " + linkListInfoList.get(position).getListName(), +// Toast.LENGTH_SHORT).show(); + // 更新适配器 + createLinkAdapter.setCreateLinkList(selectedLinkList); + // 在地图上显示航线 + displayRouteOnMap(selectedLinkList); + isSetLink = true; + allView.ll_all_link_layout.setVisibility(GONE); + allView.ll_link_start.setVisibility(GONE); + allView.v_mainDisplay.setVisibility(GONE); + allView.ll_open_layout.setVisibility(GONE); + allView.ll_text.setVisibility(GONE); + allView.ll_link.setVisibility(VISIBLE); + allView.ll_create_link_layout.setVisibility(VISIBLE); + allView.fpvWidget.setVisibility(GONE); + allView.et_link_name.setText(sqlClass.getAllLinkListInfo().get( position).getListName()); + } else { +// Toast.makeText(MainActivity.this, "加载航线失败", Toast.LENGTH_SHORT).show(); + } + } + }); + + + } catch (Exception e) { + Log.d("cjz-数据库异常", "" + e); + } + } // 如果需要刷新数据,可以调用此方法 @@ -1747,72 +1010,7 @@ public class MainActivity extends AppCompatActivity { List updatedList = sqlClass.getAllLinkListInfo(); allLinkAdapter.updateDataList(updatedList); } - } - - - /** - * 在地图上显示航线 - * - * @param createLinkList 航线数据列表 - */ - private void displayRouteOnMap(ArrayList createLinkList) { - - // 遍历航线数据并在地图上显示 - for (int i = 0; i < createLinkList.size(); i++) { - CreateLink createLink = createLinkList.get(i); - - // 获取航点坐标 - LatLng latLng = createLink.getLatLng(); - if (latLng == null) continue; - - // 创建自定义标记视图 - View markerView = getLayoutInflater().inflate(R.layout.custom_marker_layout, null); - TextView markerText = markerView.findViewById(R.id.marker_text); - markerText.setText(createLink.getName()); - - // 将视图转换为Bitmap - markerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); - markerView.layout(0, 0, markerView.getMeasuredWidth(), markerView.getMeasuredHeight()); - markerView.buildDrawingCache(); - Bitmap markerBitmap = markerView.getDrawingCache(); - - // 创建标记选项 - MarkerOptions markerOptions = new MarkerOptions() - .position(latLng) - .icon(BitmapDescriptorFactory.fromBitmap(markerBitmap)) - .draggable(false); - - // 添加标记到地图 - Marker marker = allView.map.getMap().addMarker(markerOptions); - - // 添加到航点列表 - waypointMarkers.add(marker); - waypointPositions.add(latLng); - - // 更新CreateLink列表(用于适配器显示) - CreateLink newCreateLink = new CreateLink( - createLink.getName(), - createLink.getHeight(), - createLink.getSpeed(), - createLink.getWaypointIndex(), - latLng, - createLink.isBom1_show(), - createLink.isBom2_show() - ); - this.createLinkList.add(newCreateLink); - } - - // 更新适配器 - createLinkAdapter.setCreateLinkList(this.createLinkList); - - // 更新航线显示 - updateFlightPath(); - - // 如果有航点,将地图中心移动到第一个航点 - if (!waypointPositions.isEmpty()) { - LatLng firstWaypoint = waypointPositions.get(0); - allView.map.getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(firstWaypoint, 15)); - } + linkListInfoList = sqlClass.getAllLinkListInfo(); } @Override diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Adapter/AllLinkAdapter.java b/app/src/main/java/com/example/longyi_groundstation/Main/Adapter/AllLinkAdapter.java index dcb805d..6f0599b 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Adapter/AllLinkAdapter.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Adapter/AllLinkAdapter.java @@ -30,6 +30,7 @@ public class AllLinkAdapter extends RecyclerView.Adapter linkListInfoList; private SQLClass sqlClass; private OnItemClickListener onItemClickListener; + private OnItemEditClickListener onItemEditClickListener; public AllLinkAdapter(Context context, List linkListInfoList, SQLClass sqlClass) { this.context = context; @@ -73,6 +74,14 @@ public class AllLinkAdapter extends RecyclerView.Adapter updatedList = sqlClass.getAllLinkListInfo(); updateDataList(updatedList); }); + + // 点击编辑按钮 + holder.tv_edit.setOnClickListener(v -> { + if (onItemEditClickListener != null) { + setSelects(position); + onItemEditClickListener.onItemEditClick(linkListInfo.getListId(), position); + } + }); // 设置整个item的点击事件 holder.itemView.setOnClickListener(v -> { @@ -99,6 +108,16 @@ public class AllLinkAdapter extends RecyclerView.Adapter parent, View view, int positions, long id) { +// Log.d("onItemSelected", positions+""); +// holder.tv_turn.setText(parent.getItemAtPosition(positions).toString()); +// if (positions == 0) { +// holder.et_turn_time.setText("0"); +// createLinkList.get(position).setStop_time(0); +// notifyDataSetChanged(); +// } else { +// holder.et_turn_time.setText("1"); +// createLinkList.get(position).setStop_time(1); +// } +// } +// +// @Override +// public void onNothingSelected(AdapterView parent) { +// // 什么都不做 +// Log.d("onItemSelected", "11"); +// } +// }); + + holder.et_turn_time.setText(createLink.getStop_time() + ""); + holder.et_speed.setText(createLink.getSpeed() + ""); + + + //投弹是否显示 + if (createLink.isBom1_show()) { + holder.ll_bom_layout1.setVisibility(View.VISIBLE); + } else { + holder.ll_bom_layout1.setVisibility(View.GONE); + } + if (createLink.isBom2_show()) { + holder.ll_bom_layout2.setVisibility(View.VISIBLE); + } else { + holder.ll_bom_layout2.setVisibility(View.GONE); + } + + //投弹高度 + holder.et_bom1.setText(createLink.getBom1_height() + ""); + holder.et_bom2.setText(createLink.getBom2_height() + ""); + + if (!createLink.isBom1_show() && !createLink.isBom2_show()) { + holder.tv_null_data.setVisibility(View.VISIBLE); + } else { + holder.tv_null_data.setVisibility(View.GONE); + } + + + if (createLink.isBom1_select()) { + holder.tv_bom_text1.setBackgroundResource(R.drawable.ff029a45_4round_1stroke_bg); + holder.iv_bom1.setImageResource(R.mipmap.icon_select_link_yes); +// ll_bom_height_layout1.setVisibility(View.VISIBLE); + } else { + holder.tv_bom_text1.setBackgroundResource(R.drawable.b2101010_4round_1stroke_bg); + holder.iv_bom1.setImageResource(R.mipmap.icon_select_link_no); +// ll_bom_height_layout1.setVisibility(View.INVISIBLE); + } + + if (createLink.isBom2_select()) { + holder.tv_bom_text2.setBackgroundResource(R.drawable.ff029a45_4round_1stroke_bg); + holder.iv_bom2.setImageResource(R.mipmap.icon_select_link_yes); +// ll_bom_height_layout2.setVisibility(View.VISIBLE); + } else { + holder.tv_bom_text2.setBackgroundResource(R.drawable.b2101010_4round_1stroke_bg); + holder.iv_bom2.setImageResource(R.mipmap.icon_select_link_no); +// ll_bom_height_layout2.setVisibility(View.INVISIBLE); + } + + + holder.tvDel.setOnClickListener(v -> { + if (onItemClickListener != null) { + onItemClickListener.onDeleteClick(position); + } + }); + + // 为停留时间输入框添加实时监听事件 + holder.et_turn_time.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + try { + if (s.length() > 0){ + createLinkList.get(position).setStop_time(Integer.parseInt(s.toString())); + }else { + createLinkList.get(position).setStop_time(0); + } + }catch (Exception e){ + Log.d("不用理会", "afterTextChanged: "); + } + + } + }); + + + // 为停留时间输入框添加实时监听事件 + holder.etHeight.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + try { + if (s.length() > 0){ + createLinkList.get(position).setHeight(Integer.parseInt(s.toString())); + }else { + createLinkList.get(position).setHeight(0); + } + }catch (Exception e){ + Log.d("不用理会", "afterTextChanged: "); + } + + } + }); + + // 为停留时间输入框添加实时监听事件 + holder.et_lat.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + try { + if (s.length() > 0){ + Log.d("afterTextChanged", "afterTextChanged: "+s); + // 更新CreateLink中的LatLng对象 + double newLat = Double.parseDouble(s.toString()); + double newLng = createLinkList.get(position).getLatLng().longitude; + createLinkList.get(position).setLatLng(new com.amap.api.maps.model.LatLng(newLat, newLng)); + }else { + createLinkList.get(position).setLatLng(new com.amap.api.maps.model.LatLng(0, createLinkList.get(position).getLatLng().longitude)); + } + } catch (Exception e){ + Log.d("不用理会", "afterTextChanged: "); + } + + + } + }); + + // 为停留时间输入框添加实时监听事件 + holder.et_lon.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + try { + if (s.length() > 0){ + Log.d("afterTextChanged", "afterTextChanged: "+s); + // 更新CreateLink中的LatLng对象 + double newLng = Double.parseDouble(s.toString()); + double newLat = createLinkList.get(position).getLatLng().latitude; + createLinkList.get(position).setLatLng(new com.amap.api.maps.model.LatLng(newLat, newLng)); + }else { + createLinkList.get(position).setLatLng(new com.amap.api.maps.model.LatLng(createLinkList.get(position).getLatLng().latitude, 0)); + } + }catch (Exception e){ + Log.d("不用理会", "afterTextChanged: "); + } + + + } + }); + + + // 为停留时间输入框添加实时监听事件 + holder.et_speed.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + try{ + if (s.length() > 0){ + createLinkList.get(position).setSpeed(Double.parseDouble(s.toString())); + }else { + createLinkList.get(position).setSpeed(0); + } + }catch (Exception e){ + Log.d("不用理会", "afterTextChanged: "); + } + + } + }); + + //展开 + holder.tv_expand.setOnClickListener(v -> { + if (holder.ll_expand.getVisibility() == View.VISIBLE) { + holder.ll_expand.setVisibility(View.GONE); + holder.tv_expand.setText("展开"); + } else { + holder.ll_expand.setVisibility(View.VISIBLE); + holder.tv_expand.setText("收起"); + } + }); + + //投弹选中1 + holder.ll_bom_layout1.setOnClickListener(v -> { + if (createLinkList.get(position).isBom1_select()) { + // 取消选中状态 + holder.tv_bom_text1.setBackgroundResource(R.drawable.b2101010_4round_1stroke_bg); + holder.iv_bom1.setImageResource(R.mipmap.icon_select_link_no); + } else { + // 设置当前项为选中状态 + holder.tv_bom_text1.setBackgroundResource(R.drawable.ff029a45_4round_1stroke_bg); + holder.iv_bom1.setImageResource(R.mipmap.icon_select_link_yes); + } + // 选中状态 - 先取消其他所有项的选中状态 + clearAllSelectionsExcept(position, 1); // 1表示bom1 + }); + + //投弹选中2 + holder.ll_bom_layout2.setOnClickListener(v -> { + if (createLinkList.get(position).isBom2_select()) { + // 取消选中状态 + holder.tv_bom_text2.setBackgroundResource(R.drawable.b2101010_4round_1stroke_bg); + holder.iv_bom2.setImageResource(R.mipmap.icon_select_link_no); + + } else { + // 设置当前项为选中状态 + holder.tv_bom_text2.setBackgroundResource(R.drawable.ff029a45_4round_1stroke_bg); + holder.iv_bom2.setImageResource(R.mipmap.icon_select_link_yes); + } + // 选中状态 - 先取消其他所有项的选中状态 + clearAllSelectionsExcept(position, 2); // 2表示bom2 + }); + + + } + + /** + * 清除除指定位置和类型外的所有显示状态 + * + * @param currentPosition 当前项的位置 + * @param type 1表示bom1,2表示bom2 + */ + private void clearAllSelectionsExcept(int currentPosition, int type) { + // bom1 + if (type == 1) { + //如果当前项是选中状态,则取消所有bom1的选中状态并显示出来 + if (createLinkList.get(currentPosition).isBom1_select()) { + for (int i = 0; i < createLinkList.size(); i++) { + CreateLink link = createLinkList.get(i); + link.setBom1_show(true); + link.setBom1_select(false); + } + isExpand.set(0, true); + } + //如果当前项不是选中状态,则取消除了当前项其它所有bom1的选中状态并隐藏 + else { + for (int i = 0; i < createLinkList.size(); i++) { + CreateLink link = createLinkList.get(i); + if (i == currentPosition) { + link.setBom1_show(true); + link.setBom1_select(true); + } else { + link.setBom1_show(false); + link.setBom1_select(false); + } + } + isExpand.set(0, false); + } + + } + //bom2 + else { + if (createLinkList.get(currentPosition).isBom2_select()) { + for (int i = 0; i < createLinkList.size(); i++) { + CreateLink link = createLinkList.get(i); + link.setBom2_show(true); + link.setBom2_select(false); + } + isExpand.set(1, true); + } + //如果当前项不是选中状态,则取消除了当前项其它所有bom2的选中状态并隐藏 + else { + for (int i = 0; i < createLinkList.size(); i++) { + CreateLink link = createLinkList.get(i); + if (i == currentPosition) { + link.setBom2_show(true); + link.setBom2_select(true); + } else { + link.setBom2_show(false); + link.setBom2_select(false); + } + } + isExpand.set(1, false); + } + } + + notifyDataSetChanged(); } @Override @@ -73,14 +396,13 @@ public class CreateLinkAdapter extends RecyclerView.Adapter linkAdapter = new ArrayAdapter<>(content, - android.R.layout.simple_spinner_item, linkOptions); - linkAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - sp_turn.setAdapter(linkAdapter); - - - - //投弹是否显示 - if (createLink.isBom1_show()){ - ll_bom_layout1.setVisibility(View.VISIBLE); - }else { - ll_bom_layout1.setVisibility(View.GONE); - } - if (createLink.isBom2_show()){ - ll_bom_layout2.setVisibility(View.VISIBLE); - }else { - ll_bom_layout2.setVisibility(View.GONE); - } - - //投弹高度 - et_bom1.setText(createLink.getBom1_height() + ""); - et_bom2.setText(createLink.getBom2_height() + ""); - - if (!createLink.isBom1_show() && !createLink.isBom2_show()){ - tv_null_data.setVisibility(View.VISIBLE); - }else { - tv_null_data.setVisibility(View.GONE); - } - - - if (createLink.isBom1_select()) { - tv_bom_text1.setBackgroundResource(R.drawable.ff029a45_2round_1stroke_bg); - iv_bom1.setImageResource(R.mipmap.icon_select_link_yes); -// ll_bom_height_layout1.setVisibility(View.VISIBLE); - } else { - tv_bom_text1.setBackgroundResource(R.drawable.b2101010_4round_1stroke_bg); - iv_bom1.setImageResource(R.mipmap.icon_select_link_no); -// ll_bom_height_layout1.setVisibility(View.INVISIBLE); - } - - if (createLink.isBom2_select()) { - tv_bom_text2.setBackgroundResource(R.drawable.ff029a45_2round_1stroke_bg); - iv_bom2.setImageResource(R.mipmap.icon_select_link_yes); -// ll_bom_height_layout2.setVisibility(View.VISIBLE); - } else { - tv_bom_text2.setBackgroundResource(R.drawable.b2101010_4round_1stroke_bg); - iv_bom2.setImageResource(R.mipmap.icon_select_link_no); -// ll_bom_height_layout2.setVisibility(View.INVISIBLE); - } - - - tvDel.setOnClickListener(v -> { - if (onItemClickListener != null) { - onItemClickListener.onDeleteClick(position); - } - }); - - // 可以添加文本变化监听器来更新数据 - etHeight.setOnFocusChangeListener((v, hasFocus) -> { - if (!hasFocus) { - try { - createLink.setHeight(Double.parseDouble(etHeight.getText().toString())); - } catch (NumberFormatException e) { - etHeight.setText(String.valueOf((int) createLink.getHeight())); - } - } - }); - - // 为Spinner设置选择监听器 - sp_turn.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView parent, View view, int position, long id) { - tv_turn.setText(parent.getItemAtPosition(position).toString()); - - } - - @Override - public void onNothingSelected(AdapterView parent) { - // 什么都不做 - } - }); - - rl_turn.setOnClickListener(v -> { - showCustomDropdown(rl_turn, tv_turn,ll_turn); - }); - - //长按弹出窗口 - tv_expand.setOnClickListener(v -> { - if (ll_expand.getVisibility() == View.VISIBLE) { - ll_expand.setVisibility(View.GONE); - tv_expand.setText("展开"); - } else { - ll_expand.setVisibility(View.VISIBLE); - tv_expand.setText("收起"); - } - }); - - //投弹选中1 - ll_bom_layout1.setOnClickListener(v -> { - if (createLink.isBom1_select()) { - // 取消选中状态 - tv_bom_text1.setBackgroundResource(R.drawable.b2101010_4round_1stroke_bg); - iv_bom1.setImageResource(R.mipmap.icon_select_link_no); - } else { - // 设置当前项为选中状态 - tv_bom_text1.setBackgroundResource(R.drawable.ff029a45_2round_1stroke_bg); - iv_bom1.setImageResource(R.mipmap.icon_select_link_yes); - } - // 选中状态 - 先取消其他所有项的选中状态 - clearAllSelectionsExcept(position, 1); // 1表示bom1 - }); - - //投弹选中2 - ll_bom_layout2.setOnClickListener(v -> { - if (createLink.isBom2_select()) { - // 取消选中状态 - tv_bom_text2.setBackgroundResource(R.drawable.b2101010_4round_1stroke_bg); - iv_bom2.setImageResource(R.mipmap.icon_select_link_no); - - } else { - // 设置当前项为选中状态 - tv_bom_text2.setBackgroundResource(R.drawable.ff029a45_2round_1stroke_bg); - iv_bom2.setImageResource(R.mipmap.icon_select_link_yes); - } - // 选中状态 - 先取消其他所有项的选中状态 - clearAllSelectionsExcept(position, 2); // 2表示bom2 - }); - - } - - /** - * 清除除指定位置和类型外的所有显示状态 - * @param currentPosition 当前项的位置 - * @param type 1表示bom1,2表示bom2 - */ - private void clearAllSelectionsExcept(int currentPosition, int type) { - // bom1 - if (type == 1){ - //如果当前项是选中状态,则取消所有bom1的选中状态并显示出来 - if (createLinkList.get(currentPosition).isBom1_select()){ - for (int i = 0; i < createLinkList.size(); i++) { - CreateLink link = createLinkList.get(i); - link.setBom1_show(true); - link.setBom1_select(false); - } - isExpand.set(0,true); - } - //如果当前项不是选中状态,则取消除了当前项其它所有bom1的选中状态并隐藏 - else { - for (int i = 0; i < createLinkList.size(); i++) { - CreateLink link = createLinkList.get(i); - if (i == currentPosition){ - link.setBom1_show(true); - link.setBom1_select(true); - }else { - link.setBom1_show(false); - link.setBom1_select(false); - } - } - isExpand.set(0,false); - } - - } - //bom2 - else { - if (createLinkList.get(currentPosition).isBom2_select()){ - for (int i = 0; i < createLinkList.size(); i++) { - CreateLink link = createLinkList.get(i); - link.setBom2_show(true); - link.setBom2_select(false); - } - isExpand.set(1,true); - } - //如果当前项不是选中状态,则取消除了当前项其它所有bom2的选中状态并隐藏 - else { - for ( int i = 0; i < createLinkList.size(); i++) { - CreateLink link = createLinkList.get(i); - if (i == currentPosition){ - link.setBom2_show(true); - link.setBom2_select(true); - }else { - link.setBom2_show(false); - link.setBom2_select(false); - } - } - isExpand.set(1,false); - } - } - - notifyDataSetChanged(); - } } - //转弯方式选择弹窗 - private void showCustomDropdown(RelativeLayout anchor, TextView tv_turn,LinearLayout ll_turn) { - String[] options = {"协调转弯", "到点转弯"}; - AlertDialog.Builder builder = new AlertDialog.Builder(content); - builder.setItems(options, (dialog, which) -> { - tv_turn.setText(options[which]); - if (which == 1){ - ll_turn.setVisibility(View.VISIBLE); - }else { - ll_turn.setVisibility(View.GONE); - } - // 更新选中状态 - }); - builder.show(); - } - - } diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Base/CreateLink.java b/app/src/main/java/com/example/longyi_groundstation/Main/Base/CreateLink.java index bea35e4..7153fe9 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Base/CreateLink.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Base/CreateLink.java @@ -9,6 +9,7 @@ public class CreateLink { private double speed;//速度 private int waypointIndex;//航点索引 private LatLng latLng;//点经纬度 + private int stop_time;//停留时间 private boolean bom1_select;//弹道1选择 private boolean bom1_show;//弹道1是否显示 private int bom1_height;//弹道1投弹高度 @@ -18,14 +19,16 @@ public class CreateLink { public CreateLink(String name, double height, double speed, int waypointIndex, LatLng latLng - ,boolean bom1_show,boolean bom2_show) { + ,int stop_time,boolean bom1_show,boolean bom2_show) { this.name = name; this.height = height; this.speed = speed; this.waypointIndex = waypointIndex; this.latLng = latLng; + this.stop_time = stop_time; this.bom1_show = bom1_show; this.bom2_show = bom2_show; + } public CreateLink(String name, double height, double speed, int waypointIndex, LatLng latLng) { @@ -123,4 +126,12 @@ public class CreateLink { public void setBom2_show(boolean bom2_show) { this.bom2_show = bom2_show; } + + public int getStop_time() { + return stop_time; + } + + public void setStop_time(int stop_time) { + this.stop_time = stop_time; + } } diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Click/MainClick.java b/app/src/main/java/com/example/longyi_groundstation/Main/Click/MainClick.java new file mode 100644 index 0000000..1c3a883 --- /dev/null +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Click/MainClick.java @@ -0,0 +1,1022 @@ +package com.example.longyi_groundstation.Main.Click; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import com.amap.api.maps.CameraUpdateFactory; +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.PolylineOptions; +import com.example.longyi_groundstation.Main.Activity.MainActivity; +import com.example.longyi_groundstation.Main.Adapter.AllLinkAdapter; +import com.example.longyi_groundstation.Main.Adapter.CreateLinkAdapter; +import com.example.longyi_groundstation.Main.Base.CreateLink; +import com.example.longyi_groundstation.Main.Service.MyBoundService; +import com.example.longyi_groundstation.Main.Setting.Activity.SettingActivity; +import com.example.longyi_groundstation.Main.Void.AllView; +import com.example.longyi_groundstation.Main.Void.CoordinateConverter; +import com.example.longyi_groundstation.Main.Void.FlyVoid; +import com.example.longyi_groundstation.Main.Void.FpvGestureHandler; +import com.example.longyi_groundstation.Main.Void.KeDaTTS; +import com.example.longyi_groundstation.Main.Void.LidarDataParser; +import com.example.longyi_groundstation.Main.Void.MapVoid; +import com.example.longyi_groundstation.Main.Void.MyReceiver; +import com.example.longyi_groundstation.Main.Void.MyTool; +import com.example.longyi_groundstation.Main.Void.SQLClass; +import com.example.longyi_groundstation.Main.Void.XiangTuo.Protocol; +import com.example.longyi_groundstation.Main.Void.XiangTuo.TcpClientUtil; +import com.example.longyi_groundstation.R; +import com.example.longyi_groundstation.Util.Tool; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +import static android.view.View.GONE; +import static android.view.View.VISIBLE; +import static com.example.longyi_groundstation.MAVLink.enums.MAV_CMD.MAV_CMD_NAV_LAND; +import static com.example.longyi_groundstation.MAVLink.enums.MAV_CMD.MAV_CMD_NAV_RETURN_TO_LAUNCH; +import static com.example.longyi_groundstation.MAVLink.enums.MAV_CMD.MAV_CMD_NAV_TAKEOFF; + +public class MainClick implements View.OnClickListener { + private MainActivity mainActivity; + private AllView allView; + private MapVoid mapVoid; + private FlyVoid flyVoid; + private TcpClientUtil tcpClient; + private FpvGestureHandler fpvGestureHandler; + + // 航线相关 + private List waypointMarkers; + private List waypointPositions; + private List createLinkList; + private List selectedLinkList; + private List uploadLinkList; + private CreateLinkAdapter createLinkAdapter; + private AllLinkAdapter allLinkAdapter; + private SQLClass sqlClass; + private Marker selectMarker; + private Marker mainMarker; + private Marker orangeMarker; + + // 其他变量 + private int mainDisplay; + private boolean isSetLink; + private boolean isAdviseFly; + private boolean isUnlock; + private int isAddOrEdit; + + public MainClick(MainActivity mainActivity, AllView allView, MapVoid mapVoid, FlyVoid flyVoid, + TcpClientUtil tcpClient, List waypointMarkers, List waypointPositions, + List createLinkList, List selectedLinkList, + List uploadLinkList, CreateLinkAdapter createLinkAdapter, + AllLinkAdapter allLinkAdapter, SQLClass sqlClass, Marker mainMarker) { + this.mainActivity = mainActivity; + this.allView = allView; + this.mapVoid = mapVoid; + this.flyVoid = flyVoid; + this.tcpClient = tcpClient; + this.waypointMarkers = waypointMarkers; + this.waypointPositions = waypointPositions; + this.createLinkList = createLinkList; + this.selectedLinkList = selectedLinkList; + this.uploadLinkList = uploadLinkList; + this.createLinkAdapter = createLinkAdapter; + this.allLinkAdapter = allLinkAdapter; + this.sqlClass = sqlClass; + this.mainMarker = mainMarker; + this.mainDisplay = 1; + this.isSetLink = false; + this.isAdviseFly = true; + this.isUnlock = false; + this.isAddOrEdit = 0; + } + + // 设置器方法 + public void setSelectMarker(Marker selectMarker) { + this.selectMarker = selectMarker; + } + + public void setOrangeMarker(Marker orangeMarker) { + this.orangeMarker = orangeMarker; + } + + public void setMainDisplay(int mainDisplay) { + this.mainDisplay = mainDisplay; + } + + public void setIsSetLink(boolean isSetLink) { + this.isSetLink = isSetLink; + } + + public void setIsAdviseFly(boolean isAdviseFly) { + this.isAdviseFly = isAdviseFly; + } + + public void setIsUnlock(boolean isUnlock) { + this.isUnlock = isUnlock; + } + + public void setIsAddOrEdit(int isAddOrEdit) { + this.isAddOrEdit = isAddOrEdit; + } + + @Override + public void onClick(View v) { + int id = v.getId(); + + if (id == allView.ll_create_link_layout.getId()) { + Log.d("MainClick", "防止误触: "); + } else if (id == allView.ll_all_link_layout.getId()) { + Log.d("MainClick", "防止误触: "); + } else if (id == allView.v_mainDisplay.getId()) { + handleMainDisplayClick(); + } else if (id == allView.iv_error.getId()) { + handleErrorMessageClick(); + } else if (id == allView.ll_location_me.getId()) { + handleLocationMeClick(); + } else if (id == allView.ll_turn_back.getId()) { + mainActivity.turnBackDialog.show(); + } else if (id == allView.ll_lift_off.getId()) { + mainActivity.takeOffDialog.show(); + } else if (id == allView.ll_icon_land.getId()) { + mainActivity.landDialog.show(); + } else if (id == allView.ll_setting.getId()) { + handleSettingClick(); + } else if (id == allView.ll_link_start_fun1.getId()) { + handleUploadMissionClick(); + } else if (id == allView.ll_link_start_fun2.getId()) { + handleStartExecuteClick(); + } else if (id == allView.ll_link_start_back.getId()) { + handleMissionBackClick(); + } else if (id == allView.ll_left_open.getId()) { + handleLeftOpenClick(); + } else if (id == allView.ll_link.getId()) { + Log.d("MainClick", "防止下层误触"); + } else if (id == allView.ll_title.getId()) { + Log.d("MainClick", "防止下层误触"); + } else if (id == allView.ll_clear.getId()) { + handleClearClick(); + } else if (id == allView.tv_add_link.getId()) { + handleAddLinkClick(); + } else if (id == allView.ll_map.getId()) { + handleMapClick(); + } else if (id == allView.ll_link_save.getId()) { + handleSaveLinkClick(); + } else if (id == allView.tv_link_fun1.getId()) { + handleReverseWaypointsClick(); + } else if (id == allView.tv_link_fun2.getId()) { + handleClearAllWaypointsClick(); + } else if (id == allView.ll_link_back.getId()) { + handleLinkBackClick(); + } else if (id == allView.ll_execute_line.getId()) { + mainActivity.startExecuteDialog.show(); + } else if (id == allView.ll_bombing.getId()) { + mainActivity.bombingDialog.show(); + } else if (id == allView.ll_shout.getId()) { + Toast.makeText(mainActivity, "正在研发..", Toast.LENGTH_SHORT).show(); + } else if (id == allView.ll_hook.getId()) { + Toast.makeText(mainActivity, "正在研发..", Toast.LENGTH_SHORT).show(); + } else if (id == allView.ll_searchlight.getId()) { + Toast.makeText(mainActivity, "正在研发..", Toast.LENGTH_SHORT).show(); + } else if (id == allView.ll_PTZ_one_center.getId()) { + handlePTZCenterClick(); + } else if (id == allView.ll_PTZ_one_bottom.getId()) { + handlePTZBottomClick(); + } else if (id == allView.iv_open_link_list.getId()) { + handleOpenLinkListClick(); + } else if (id == allView.ll_clear_fly_line.getId()) { + handleClearFlyLineClick(); + } + } + + // 处理主显示切换点击 + private void handleMainDisplayClick() { + if (mainDisplay == 1) { + mainDisplay = 2; + MyTool.setViewWH(mainActivity, allView.map, 150, 95, 3); + MyTool.setViewWH(mainActivity, allView.fpvWidget, 1920, 1200, 0); + mapVoid.allView.map.setElevation(5f); + mapVoid.allView.fpvWidget.setElevation(1f); + allView.map.setBackgroundResource(R.drawable.x80202020_4round_3stroke_bg); + allView.fpvWidget.setBackgroundColor(Color.parseColor("#ffffff")); + allView.map.setPadding(6, 6, 6, 6); + allView.fpvWidget.setPadding(0, 0, 0, 0); + allView.ll_left_error_layout.setVisibility(GONE); + allView.ll_ptz_ctrl.setVisibility(VISIBLE); + allView.ll_ptz_fun.setVisibility(VISIBLE); + } else { + mainDisplay = 1; + MyTool.setViewWH(mainActivity, allView.fpvWidget, 150, 95, 3); + MyTool.setViewWH(mainActivity, allView.map, 1920, 1200, 0); + mapVoid.allView.fpvWidget.setElevation(5f); + mapVoid.allView.map.setElevation(1f); + allView.fpvWidget.setBackgroundResource(R.drawable.x80202020_4round_3stroke_bg); + allView.map.setBackgroundColor(Color.parseColor("#ffffff")); + allView.fpvWidget.setPadding(6, 6, 6, 6); + allView.map.setPadding(0, 0, 0, 0); + allView.ll_left_error_layout.setVisibility(GONE); + allView.ll_ptz_ctrl.setVisibility(GONE); + allView.ll_ptz_fun.setVisibility(GONE); + } + } + + // 处理错误信息点击 + private void handleErrorMessageClick() { + if (allView.ll_left_error_layout.getVisibility() == VISIBLE) { + allView.ll_left_error_layout.setVisibility(GONE); + } else { + allView.ll_left_error_layout.setVisibility(VISIBLE); + } + } + + // 处理定位到当前位置点击 + private void handleLocationMeClick() { + if (MyReceiver.GLOBAL_POSITION_INT_json.optDouble("lat", 0) / 10000000 != 0) { + mapVoid.aMap.moveCamera(CameraUpdateFactory.newLatLngZoom( + new LatLng(MyReceiver.GLOBAL_POSITION_INT_json.optDouble("lat", 0) / 10000000, + MyReceiver.GLOBAL_POSITION_INT_json.optDouble("lon", 0) / 10000000), 15)); + mainMarker.setVisible(true); + } + } + + // 处理设置点击 + private void handleSettingClick() { + if (MyBoundService.type == 0) { + if (MyBoundService.serialHelper != null) { + Intent intent = new Intent(mainActivity, SettingActivity.class); + mainActivity.startActivity(intent); + } else { + Toast.makeText(mainActivity, "串口连接失败", Toast.LENGTH_SHORT).show(); + } + } else if (MyBoundService.type == 1) { + if (MyBoundService.serverSocket != null) { + Intent intent = new Intent(mainActivity, SettingActivity.class); + mainActivity.startActivity(intent); + } else { + Toast.makeText(mainActivity, "UDP连接失败", Toast.LENGTH_SHORT).show(); + } + } + } + + // 处理上传航线点击 + private void handleUploadMissionClick() { + if (selectedLinkList.size() > 0) { + isAdviseFly = true; + flyVoid.creatDataList(mainActivity, (ArrayList) selectedLinkList, allView.et_start_execute_height.getText().toString()); + allView.v_mainDisplay.setVisibility(VISIBLE); + allView.ll_open_layout.setVisibility(VISIBLE); + allView.ll_text.setVisibility(VISIBLE); + allView.ll_link_start.setVisibility(GONE); + allView.ll_all_link_layout.setVisibility(GONE); + allView.fpvWidget.setVisibility(VISIBLE); + uploadLinkList.addAll(selectedLinkList); + allView.ll_assistance_layout.setVisibility(VISIBLE); + } else { + Toast.makeText(mainActivity, "请选择航线", Toast.LENGTH_SHORT).show(); + } + } + + // 处理开始执行点击 + private void handleStartExecuteClick() { + if (selectedLinkList != null) { + if (isUnlock) { + mainActivity.startExecuteDialog.show(); + } else { + Toast.makeText(mainActivity, "请先解锁", Toast.LENGTH_SHORT).show(); + } + } else { + Toast.makeText(mainActivity, "请先选择航线", Toast.LENGTH_SHORT).show(); + } + } + + // 处理航线退出点击 + private void handleMissionBackClick() { + if (uploadLinkList != null) { + clearWaypoints(); + displayRouteOnMap((ArrayList) uploadLinkList); + } + allView.v_mainDisplay.setVisibility(VISIBLE); + allView.ll_open_layout.setVisibility(VISIBLE); + allView.ll_text.setVisibility(VISIBLE); + allView.ll_link_start.setVisibility(GONE); + allView.ll_all_link_layout.setVisibility(GONE); + allView.fpvWidget.setVisibility(VISIBLE); + allView.ll_assistance_layout.setVisibility(VISIBLE); + isAdviseFly = true; + } + + // 处理左侧打开点击 + private void handleLeftOpenClick() { + if (allView.ll_function_layout.getVisibility() == VISIBLE) { + allView.ll_function_layout.setVisibility(GONE); + } else { + allView.ll_function_layout.setVisibility(VISIBLE); + } + } + + // 处理清除点击 + private void handleClearClick() { + try { + uploadLinkList.clear(); + clearWaypoints(); + displayRouteOnMap((ArrayList) uploadLinkList); + if (orangeMarker != null) { + orangeMarker.remove(); + } + } catch (Exception e) { + Log.d("MainClick", "handleClearClick: " + e); + } + Toast.makeText(mainActivity, "已清除", Toast.LENGTH_SHORT).show(); + } + + // 处理添加航线点击 + private void handleAddLinkClick() { + isAddOrEdit = 0; + clearWaypoints(); + isSetLink = true; + allView.ll_all_link_layout.setVisibility(GONE); + allView.ll_link_start.setVisibility(GONE); + allView.v_mainDisplay.setVisibility(GONE); + allView.ll_open_layout.setVisibility(GONE); + allView.ll_text.setVisibility(GONE); + allView.ll_link.setVisibility(VISIBLE); + allView.ll_create_link_layout.setVisibility(VISIBLE); + allView.fpvWidget.setVisibility(GONE); + } + + // 处理航线规划点击 + private void handleMapClick() { + clearWaypoints(); + isAdviseFly = false; + allView.ll_all_link_layout.setVisibility(VISIBLE); + allView.ll_link_start.setVisibility(VISIBLE); + allView.v_mainDisplay.setVisibility(GONE); + allView.ll_open_layout.setVisibility(GONE); + allView.ll_text.setVisibility(GONE); + allView.ll_link.setVisibility(GONE); + allView.ll_create_link_layout.setVisibility(GONE); + allView.fpvWidget.setVisibility(GONE); + allView.ll_assistance_layout.setVisibility(GONE); + } + + // 处理保存航线点击 + private void handleSaveLinkClick() { + if (allView.et_link_name.getText().toString().length() != 0) { + saveLink(null); + } else { + mainActivity.saveLinkNameDialog.show(); + } + } + + // 处理反转航点顺序点击 + private void handleReverseWaypointsClick() { + AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity); + builder.setTitle("反转航点顺序"); + builder.setMessage("确定要反转当前航点的顺序吗?"); + + builder.setPositiveButton("确定", (dialog, which) -> { + java.util.Collections.reverse(waypointPositions); + java.util.Collections.reverse(waypointMarkers); + java.util.Collections.reverse(createLinkList); + renumberWaypoints(); + updateFlightPath(); + dialog.dismiss(); + }); + + builder.setNegativeButton("取消", (dialog, which) -> { + dialog.dismiss(); + }); + + AlertDialog dialog = builder.create(); + dialog.show(); + } + + // 处理清除所有航点点击 + private void handleClearAllWaypointsClick() { + AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity); + builder.setTitle("清除所有航点"); + builder.setMessage("确定要清除所有航点和航线吗?"); + + builder.setPositiveButton("确定", (dialog, which) -> { + clearWaypoints(); + dialog.dismiss(); + }); + + builder.setNegativeButton("取消", (dialog, which) -> { + dialog.dismiss(); + }); + + AlertDialog dialog = builder.create(); + dialog.show(); + } + + // 处理航线规划退出点击 + private void handleLinkBackClick() { + if (createLinkList.size() > 0) { + AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity); + builder.setTitle("退出"); + builder.setMessage("确定要退出嘛?退出前的航线不会保存"); + + builder.setPositiveButton("确定", (dialog, which) -> { + clearWaypoints(); + isSetLink = false; + allView.ll_all_link_layout.setVisibility(VISIBLE); + allView.ll_link_start.setVisibility(VISIBLE); + allView.v_mainDisplay.setVisibility(GONE); + allView.ll_open_layout.setVisibility(GONE); + allView.ll_text.setVisibility(GONE); + allView.ll_link.setVisibility(GONE); + allView.ll_create_link_layout.setVisibility(GONE); + allView.fpvWidget.setVisibility(GONE); + displayRouteOnMap((ArrayList) selectedLinkList); + dialog.dismiss(); + displayRouteOnMap((ArrayList) selectedLinkList); + }); + + builder.setNegativeButton("取消", (dialog, which) -> { + dialog.dismiss(); + }); + + AlertDialog dialog = builder.create(); + dialog.show(); + } else { + clearWaypoints(); + isSetLink = false; + allView.ll_all_link_layout.setVisibility(VISIBLE); + allView.ll_link_start.setVisibility(VISIBLE); + allView.v_mainDisplay.setVisibility(GONE); + allView.ll_open_layout.setVisibility(GONE); + allView.ll_text.setVisibility(GONE); + allView.ll_link.setVisibility(GONE); + allView.ll_create_link_layout.setVisibility(GONE); + allView.fpvWidget.setVisibility(GONE); + } + } + + // 处理云台回中点击 + private void handlePTZCenterClick() { + byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x13, 0x03, 0x00, 0x00, 0x17}; + tcpClient.sendBytes(testData); + } + + // 处理云台向下点击 + private void handlePTZBottomClick() { + byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x13, 0x02, 0x00, 0x00, 0x16}; + tcpClient.sendBytes(testData); + } + + // 处理开启/关闭航线点位点击 + private void handleOpenLinkListClick() { + if (allView.ll_create_link_item_layout.getVisibility() == View.GONE) { + allView.ll_create_link_item_layout.setVisibility(View.VISIBLE); + } else { + allView.ll_create_link_item_layout.setVisibility(View.GONE); + } + } + + // 处理清除飞行轨迹点击 + private void handleClearFlyLineClick() { + if (mapVoid.isTracking) { + mapVoid.isTracking = false; + mapVoid.clearFlightTrack(); + mapVoid.stopFlightTracking(); + } else { + mapVoid.startFlightTracking(); + } + } + + // 保存航线方法 + private void saveLink(String linkName) { + ArrayList createLinkLists = new ArrayList<>(); + if (createLinkList.size() > 0) { + createLinkLists.addAll(createLinkList); + boolean success; + + if (isAddOrEdit == 0) { // 添加模式 + if (linkName == null) { + if (allView.et_link_name.getText().toString().length() != 0) { + success = sqlClass.addCreateLinkList(allView.et_link_name.getText().toString(), createLinkLists); + } else { + success = sqlClass.addCreateLinkList("航线-" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), createLinkLists); + } + } else { + success = sqlClass.addCreateLinkList(linkName, createLinkLists); + } + } else { // 编辑模式 + if (allLinkAdapter.getSelectLinkListInfo() != -1) { + int currentLinkId = allLinkAdapter.getSelectLinkListInfo(); + if (linkName == null) { + if (allView.et_link_name.getText().toString().length() != 0) { + success = sqlClass.updateCreateLinkList(currentLinkId, allView.et_link_name.getText().toString(), createLinkLists); + } else { + success = sqlClass.updateCreateLinkList( + currentLinkId, + "航线-" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), createLinkLists); + } + } else { + success = sqlClass.updateCreateLinkList(currentLinkId, linkName, createLinkLists); + } + } else { + Toast.makeText(mainActivity, "获取列表错误", Toast.LENGTH_SHORT).show(); + success = false; + } + } + + if (success) { + clearWaypoints(); + isSetLink = false; + allView.ll_all_link_layout.setVisibility(VISIBLE); + allView.ll_link_start.setVisibility(VISIBLE); + allView.v_mainDisplay.setVisibility(GONE); + allView.ll_open_layout.setVisibility(GONE); + allView.ll_text.setVisibility(GONE); + allView.ll_link.setVisibility(GONE); + allView.ll_create_link_layout.setVisibility(GONE); + allView.fpvWidget.setVisibility(GONE); + allView.et_link_name.setText(""); + displayRouteOnMap((ArrayList) selectedLinkList); + refreshLinkList(); + Toast.makeText(mainActivity, isAddOrEdit == 0 ? "航线保存成功" : "航线更新成功", Toast.LENGTH_SHORT).show(); + } + } else { + Toast.makeText(mainActivity, "请先添加航点", Toast.LENGTH_SHORT).show(); + } + } + + // 刷新航线列表 + private void refreshLinkList() { + if (sqlClass != null && allLinkAdapter != null) { + List updatedList = sqlClass.getAllLinkListInfo(); + allLinkAdapter.updateDataList(updatedList); + } + } + + // 清除航点 + private void clearWaypoints() { + for (Marker marker : waypointMarkers) { + if (marker != null) { + marker.remove(); + } + } + waypointMarkers.clear(); + waypointPositions.clear(); + createLinkList.clear(); + selectedLinkList.clear(); + createLinkAdapter.setCreateLinkList(createLinkList); + } + + // 重新编号航点 + private void renumberWaypoints() { + for (int i = 0; i < waypointMarkers.size(); i++) { + Bitmap markerBitmap = createCustomMarkerBitmap((i + 1) + ""); + waypointMarkers.get(i).setIcon(BitmapDescriptorFactory.fromBitmap(markerBitmap)); + if (i < createLinkList.size()) { + createLinkList.get(i).setName((i + 1) + ""); + } + } + createLinkAdapter.setCreateLinkList(createLinkList); + } + + // 创建自定义标记Bitmap + private Bitmap createCustomMarkerBitmap(String text) { + View markerView = mainActivity.getLayoutInflater().inflate(R.layout.custom_marker_layout, null); + TextView markerText = markerView.findViewById(R.id.marker_text); + markerText.setText(text); + + markerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + markerView.layout(0, 0, markerView.getMeasuredWidth(), markerView.getMeasuredHeight()); + markerView.buildDrawingCache(); + return markerView.getDrawingCache(); + } + + // 更新航线显示 + private void updateFlightPath() { + // 在MainActivity中实现,因为需要访问flightPathPolyline + } + + // 在地图上显示航线 + private void displayRouteOnMap(ArrayList createLinkList) { + // 在MainActivity中实现,因为需要访问this.createLinkList + } + + // 添加或更新橘黄色marker + public void addOrUpdateOrangeMarker(LatLng latLng) { + if (orangeMarker != null) { + orangeMarker.remove(); + } + orangeMarker = allView.map.getMap().addMarker(new MarkerOptions().position(latLng) + .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_ORANGE)) + .title("指点飞行目标点")); + } + + // 根据标记查找航点索引 + private int findWaypointMarkerIndex(Marker marker) { + return waypointMarkers.indexOf(marker); + } + + // 统一处理四个方向的航点移动点击事件 + public View.OnClickListener getMarkerMoveClickListener() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + int selectedIndex = findWaypointMarkerIndex(selectMarker); + if (selectedIndex == -1) { + Toast.makeText(mainActivity, "未选择有效的航点", Toast.LENGTH_SHORT).show(); + return; + } + + String distanceStr = allView.et_marker_distance.getText().toString(); + if (distanceStr.isEmpty()) { + Toast.makeText(mainActivity, "请输入移动距离", Toast.LENGTH_SHORT).show(); + return; + } + + double distanceInMeters; + try { + distanceInMeters = Double.parseDouble(distanceStr); + } catch (NumberFormatException e) { + Toast.makeText(mainActivity, "请输入有效的距离数值", Toast.LENGTH_SHORT).show(); + return; + } + + LatLng currentLatLng = selectMarker.getPosition(); + double latOffset = 0; + double lngOffset = 0; + + if (v == allView.iv_marker_top) { + latOffset = distanceInMeters / 111320.0; + } else if (v == allView.iv_marker_bottom) { + latOffset = -distanceInMeters / 111320.0; + } else if (v == allView.iv_marker_left) { + lngOffset = -distanceInMeters / (111320.0 * Math.cos(Math.toRadians(currentLatLng.latitude))); + } else if (v == allView.iv_marker_right) { + lngOffset = distanceInMeters / (111320.0 * Math.cos(Math.toRadians(currentLatLng.latitude))); + } + + LatLng newLatLng = new LatLng(currentLatLng.latitude + latOffset, currentLatLng.longitude + lngOffset); + selectMarker.setPosition(newLatLng); + waypointPositions.set(selectedIndex, newLatLng); + + if (selectedIndex < createLinkList.size()) { + CreateLink createLink = createLinkList.get(selectedIndex); + CreateLink updatedCreateLink = new CreateLink( + createLink.getName(), + createLink.getHeight(), + createLink.getSpeed(), + createLink.getWaypointIndex(), + newLatLng, + createLink.getStop_time(), + createLink.isBom1_show(), + createLink.isBom2_show() + ); + createLinkList.set(selectedIndex, updatedCreateLink); + createLinkAdapter.setCreateLinkList(createLinkList); + } + } + }; + } + + // 获取FPV手势监听器 + public FpvGestureHandler.OnFpvGestureListener getFpvGestureListener() { + return new FpvGestureHandler.OnFpvGestureListener() { + private boolean isSwiping = false; + private String lastDirection = ""; + + @Override + public void onTap(float x, float y) { + int fpvWidth = allView.fpvWidget.getWidth(); + int fpvHeight = allView.fpvWidget.getHeight(); + + byte convertedX = (byte) Math.max(0x00, Math.min(0xFF, Math.round((x / fpvWidth) * 255))); + byte convertedY = (byte) Math.max(0x00, Math.min(0xFF, Math.round((y / fpvHeight) * 255))); + + if (!tcpClient.isConnected()) { + Toast.makeText(mainActivity.getApplicationContext(), "未连接到服务器", Toast.LENGTH_SHORT).show(); + } else { + byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x10, 0x00, convertedX, convertedY, Protocol.calculateCheckCode((byte) 0x01, (byte) 0x10, (byte) 0x00, convertedX, convertedY)}; + tcpClient.sendBytes(testData); + } + } + + @Override + public void onDoubleTap(float x, float y) { + Log.d("MainClick", "FPV双击: x=" + x + ", y=" + y); + } + + @Override + public void onLongPress(float x, float y) { + Log.d("MainClick", "FPV长按: x=" + x + ", y=" + y); + } + + @Override + public void onSwipe(float startX, float startY, float endX, float endY, float distanceX, float distanceY) { + String currentDirection; + if (Math.abs(distanceX) > Math.abs(distanceY)) { + if (distanceX > 0) { + currentDirection = "right"; + } else { + currentDirection = "left"; + } + } else { + if (distanceY > 0) { + currentDirection = "down"; + } else { + currentDirection = "up"; + } + } + + if (!isSwiping || !lastDirection.equals(currentDirection)) { + isSwiping = true; + lastDirection = currentDirection; + Log.d("MainClick", "FPV向" + currentDirection + "滑动"); + switch (currentDirection) { + case "up": + if (!tcpClient.isConnected()) { + Toast.makeText(mainActivity.getApplicationContext(), "未连接到服务器", Toast.LENGTH_SHORT).show(); + break; + } else { + byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x08, 0x00, (byte) 0xFF, 0x08}; + tcpClient.sendBytes(testData); + } + break; + + case "down": + if (!tcpClient.isConnected()) { + Toast.makeText(mainActivity.getApplicationContext(), "未连接到服务器", Toast.LENGTH_SHORT).show(); + break; + } else { + byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x10, 0x00, (byte) 0xFF, 0x10}; + tcpClient.sendBytes(testData); + } + break; + + case "left": + if (!tcpClient.isConnected()) { + Toast.makeText(mainActivity.getApplicationContext(), "未连接到服务器", Toast.LENGTH_SHORT).show(); + break; + } else { + byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x04, (byte) 0xFF, 0x00, 0x04}; + tcpClient.sendBytes(testData); + } + break; + + case "right": + if (!tcpClient.isConnected()) { + Toast.makeText(mainActivity.getApplicationContext(), "未连接到服务器", Toast.LENGTH_SHORT).show(); + break; + } else { + byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x02, (byte) 0xFF, 0x00, 0x02}; + tcpClient.sendBytes(testData); + } + } + } + } + + @Override + public void onSwipeUp() {} + + @Override + public void onSwipeDown() {} + + @Override + public void onSwipeLeft() {} + + @Override + public void onSwipeRight() {} + + @Override + public void onZoom(float scaleFactor) { + Log.d("MainClick", "FPV缩放: scaleFactor=" + scaleFactor); + } + + @Override + public void onSwipeEnd() { + isSwiping = false; + lastDirection = ""; + byte[] testData1 = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01}; + tcpClient.sendBytes(testData1); + } + }; + } + + // 获取PTZ触摸监听器 + public View.OnTouchListener getPTZTouchListener() { + return new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + handlePTZTouchDown(v); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + handlePTZTouchUp(); + break; + } + return true; + } + }; + } + + // 处理PTZ触摸按下 + private void handlePTZTouchDown(View v) { + if (v == allView.iv_ptz_top) { + Log.d("MainClick", "iv_ptz_top被按下"); + if (!tcpClient.isConnected()) { + Toast.makeText(mainActivity, "未连接到服务器", Toast.LENGTH_SHORT).show(); + } else { + byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x08, 0x00, (byte) 0xFF, 0x08}; + tcpClient.sendBytes(testData); + } + } else if (v == allView.iv_ptz_left) { + Log.d("MainClick", "iv_ptz_left被按下"); + if (!tcpClient.isConnected()) { + Toast.makeText(mainActivity, "未连接到服务器", Toast.LENGTH_SHORT).show(); + } else { + byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x04, (byte) 0xFF, 0x00, 0x04}; + tcpClient.sendBytes(testData); + } + } else if (v == allView.iv_ptz_right) { + Log.d("MainClick", "iv_ptz_right被按下"); + if (!tcpClient.isConnected()) { + Toast.makeText(mainActivity, "未连接到服务器", Toast.LENGTH_SHORT).show(); + } else { + byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x02, (byte) 0xFF, 0x00, 0x02}; + tcpClient.sendBytes(testData); + } + } else if (v == allView.iv_ptz_bottom) { + Log.d("MainClick", "iv_ptz_bottom被按下"); + if (!tcpClient.isConnected()) { + Toast.makeText(mainActivity, "未连接到服务器", Toast.LENGTH_SHORT).show(); + } else { + byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x10, 0x00, (byte) 0xFF, 0x10}; + tcpClient.sendBytes(testData); + } + } else if (v == allView.ll_PTZ_amplify) { + Log.d("MainClick", "ll_PTZ_amplify被按下"); + if (!tcpClient.isConnected()) { + Toast.makeText(mainActivity, "未连接到服务器", Toast.LENGTH_SHORT).show(); + } else { + byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x40, 0x04, 0x00, 0x45}; + tcpClient.sendBytes(testData); + } + } else if (v == allView.ll_PTZ_reduce) { + Log.d("MainClick", "ll_PTZ_reduce被按下"); + if (!tcpClient.isConnected()) { + Toast.makeText(mainActivity, "未连接到服务器", Toast.LENGTH_SHORT).show(); + } else { + byte[] testData = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x20, 0x04, 0x00, 0x25}; + tcpClient.sendBytes(testData); + } + } + } + + // 处理PTZ触摸抬起 + private void handlePTZTouchUp() { + if (!tcpClient.isConnected()) { + Toast.makeText(mainActivity, "未连接到服务器", Toast.LENGTH_SHORT).show(); + } else { + byte[] testData1 = new byte[]{(byte) 0xFF, 0x01, 0x00, 0x60, 0x00, 0x00, 0x61}; + tcpClient.sendBytes(testData1); + } + } + + // 获取地图点击监听器 + public com.amap.api.maps.AMap.OnMapClickListener getMapClickListener() { + return latLng -> { + if (isSetLink) { + addWaypoint(latLng); + } + }; + } + + // 获取地图长按监听器 + public com.amap.api.maps.AMap.OnMapLongClickListener getMapLongClickListener() { + return latLng -> { + if (isAdviseFly) { + addOrUpdateOrangeMarker(latLng); + mainActivity.pointFlyDialog.setLatLng(latLng); + mainActivity.pointFlyDialog.show(); + } else { + Toast.makeText(mainActivity, "当前状态不可使用", Toast.LENGTH_SHORT).show(); + } + }; + } + + // 获取标记点击监听器 + public com.amap.api.maps.AMap.OnMarkerClickListener getMarkerClickListener() { + return marker -> { + if (isSetLink) { + int index = findWaypointMarkerIndex(marker); + if (index != -1) { + selectMarker = marker; + allView.rv_create_link_list.smoothScrollToPosition(index); + if (allView.ll_marker_ctrl.getVisibility() == View.GONE) { + allView.ll_marker_ctrl.setVisibility(VISIBLE); + } else { + allView.ll_marker_ctrl.setVisibility(GONE); + } + return true; + } + } + return false; + }; + } + + // 获取地图加载监听器 + public com.amap.api.maps.AMap.OnMapLoadedListener getMapLoadedListener() { + return () -> { + if (isSetLink) { + for (Marker marker : waypointMarkers) { + marker.showInfoWindow(); + } + } + }; + } + + // 获取文本变化监听器 + public TextWatcher getTextWatcher() { + return new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) {} + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + filterLinkList(s.toString()); + } + + @Override + public void afterTextChanged(Editable s) {} + }; + } + + // 添加航点 + private void addWaypoint(LatLng latLng) { + View markerView = mainActivity.getLayoutInflater().inflate(R.layout.custom_marker_layout, null); + TextView markerText = markerView.findViewById(R.id.marker_text); + markerText.setText("" + (waypointMarkers.size() + 1)); + + markerView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); + markerView.layout(0, 0, markerView.getMeasuredWidth(), markerView.getMeasuredHeight()); + markerView.buildDrawingCache(); + Bitmap markerBitmap = markerView.getDrawingCache(); + + MarkerOptions markerOptions = new MarkerOptions().position(latLng) + .icon(BitmapDescriptorFactory.fromBitmap(markerBitmap)).draggable(false); + + Marker marker = allView.map.getMap().addMarker(markerOptions); + + waypointMarkers.add(marker); + waypointPositions.add(latLng); + + CreateLink createLink = new CreateLink( + waypointMarkers.size() + "", + 20, + 3, + waypointMarkers.size() - 1, + latLng, + 0, + true, + true); + createLinkList.add(createLink); + createLinkAdapter.setCreateLinkList(createLinkList); + } + + // 过滤航线列表 + private void filterLinkList(String query) { + if (sqlClass != null && allLinkAdapter != null) { + if (query.isEmpty()) { + List allList = sqlClass.getAllLinkListInfo(); + allLinkAdapter.updateDataList(allList); + } else { + List filteredList = new ArrayList<>(); + List fullList = sqlClass.getAllLinkListInfo(); + + for (SQLClass.LinkListInfo item : fullList) { + if (item.getListName().toLowerCase().contains(query.toLowerCase())) { + filteredList.add(item); + } + } + + allLinkAdapter.updateDataList(filteredList); + } + } + } +} diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Service/MyBoundService.java b/app/src/main/java/com/example/longyi_groundstation/Main/Service/MyBoundService.java index 8e45121..f448fc9 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Service/MyBoundService.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Service/MyBoundService.java @@ -41,6 +41,8 @@ import com.example.longyi_groundstation.MAVLink.common.msg_request_data_stream; import com.example.longyi_groundstation.Main.Base.MLData; import com.example.longyi_groundstation.Main.Setting.Base.Param; import com.example.longyi_groundstation.Main.Void.FlyVoid; +import com.example.longyi_groundstation.Main.Void.HeartbeatManager; +import com.example.longyi_groundstation.Main.Void.LidarDataParser; import com.example.longyi_groundstation.Main.Void.LogCat.LogUtil; import com.example.longyi_groundstation.Main.Void.MyTool; import com.example.longyi_groundstation.Util.BroadcastUtil; @@ -116,14 +118,23 @@ public class MyBoundService extends Service { private Parser parser = new Parser(); private MAVLinkMessage msgOld = null; + // 在类成员变量区域添加以下两个标志位 + private boolean isAttitudeDataRequested = false; + private boolean isParamReadListRequested = false; + // 在成员变量区域添加 + private HeartbeatManager heartbeatManager; + + + private void getData() { // 启动定时器 paramTimeoutHandler.post(paramTimeoutRunnable); isRunning = true; // serialPortFinder = new SerialPortFinder(); - //判断打开方式0:串口 2:UDP + //判断打开方式0:串口 1:UDP if (type == 0) { serialHelper = new SerialHelper("/dev/ttyHS0", 115200) { +// serialHelper = new SerialHelper("/dev/ttyHS0", 57600) { @Override protected void onDataReceived(final ComBean comBean) { // Log.d("cuijingzhou", Tool.bytesToHex(comBean.bRec)); @@ -134,10 +145,6 @@ public class MyBoundService extends Service { }; try { serialHelper.open(); - // 可以在这里添加回复逻辑 - requestAttitudeData(); - requestParamReadList(); -// wordT1(); } catch (IOException e) { // throw new RuntimeException(e); Log.d(TAG, e.toString()); @@ -148,27 +155,19 @@ public class MyBoundService extends Service { new Thread(() -> { try { serverSocket = new DatagramSocket(Integer.parseInt(serverPort)); - // 可以在这里添加回复逻辑 - requestAttitudeData(); - requestParamReadList(); - byte[] buffer = new byte[1024]; + byte[] buffer = new byte[512]; while (isRunning) { try { DatagramPacket packet = new DatagramPacket(buffer, buffer.length); serverSocket.receive(packet); + Log.d("cesssss", "接收数据: " + bytesToHex(packet.getData())); // 获取客户端IP和端口 InetAddress clientAddress = packet.getAddress(); int clientPort = packet.getPort(); // 处理接收到的数据 -// String receivedData = MyTool.bytesToHex(packet.getData(), packet.getLength()); -// Log.e("cuijingzhou-size", packet.getLength()+""); - String logMsg = "来自 " + clientAddress.getHostAddress() + ":" + clientPort + " 的消息: "; -// Log.e("cuijingzhou-IP:", logMsg); - dataWork(packet.getData(), packet.getLength()); -// requestParamRead(); } catch (Exception e) { Log.e(TAG, "接收数据错误: " + e.getMessage()); @@ -186,69 +185,87 @@ public class MyBoundService extends Service { wordT(); } + /** + * 方法:初始化数据请求,确保只执行一次 + */ + private void requestInitialData() { + // 请求参数列表(只执行一次) + requestParamReadList(); + // 请求姿态数据(只执行一次) + requestAttitudeData(); + } + + + private LidarDataParser lidarParser = new LidarDataParser(); + /** * 方法:连接串口2,获取高度或一些其他的硬件设施 * * @cuijingzhou */ private void getDataSerial() { - - if (type == 0){ - serialHelper2 = new SerialHelper("/dev/ttyHS2", 9600) { - @Override - protected void onDataReceived(final ComBean comBean) { -// Log.d("cuijingzhou", Tool.bytesToHex(comBean.bRec)); - // 接收数据 - byte[] receivedData = comBean.bRec; - int[] parseSerialData = parseSerialData(receivedData); - // 保存接收到的数据 - FlyVoid.parseSerialData = parseSerialData; - Log.d("cuijingzhou_getDataSerial", parseSerialData[0]+"-"+parseSerialData[1]); -// dataWork(receivedData, receivedData.length); - } - }; + if (type == 0) { try { + serialHelper2 = new SerialHelper("/dev/ttyHS2", 9600) { + @Override + protected void onDataReceived(final ComBean comBean) { + // 接收数据 + byte[] receivedData = comBean.bRec; + int maxLoop = 100; // 最大解析次数,防止耗时过长 + + // 200Hz以上高频率调用 + for (int i = 0; i < receivedData.length && maxLoop > 0; i++) { + lidarParser.parseByte(receivedData[i]); + maxLoop--; + } + } + }; serialHelper2.open(); -// wordT1(); } catch (IOException e) { -// throw new RuntimeException(e); - Log.d(TAG, e.toString()); + Log.d("getDataSerialE", e.toString()); } - }else { + } else { new Thread(() -> { try { serverSocket2 = new DatagramSocket(13551); - byte[] buffer = new byte[1024]; + // 增加缓冲区大小以适应完整数据包 + byte[] buffer = new byte[10]; while (isRunning) { try { DatagramPacket packet = new DatagramPacket(buffer, buffer.length); serverSocket2.receive(packet); - // 获取客户端IP和端口 - int[] parseSerialData = parseSerialData(packet.getData()); - // 保存接收到的数据 - FlyVoid.parseSerialData = parseSerialData; - Log.d("cuijingzhou_getDataSerial", parseSerialData[0]+"-"+parseSerialData[1]); -// Log.e("cuijingzhou-IP:", logMsg); + if (packet.getData() != null && packet.getLength() > 0) { + // 使用新方法解析数据 +// int maxLoop = 100; // 最大解析次数,防止耗时过长 + // 200Hz以上高频率调用 + for (int i = 0; i < packet.getData().length; i++) { + lidarParser.parseByte(packet.getData()[i]); +// maxLoop--; + } + } } catch (Exception e) { - Log.e(TAG, "接收数据错误: " + e.getMessage()); + Log.d("cuijingzhou_getDataSerial", "处理数据包时出错: " + e.toString()); } } } catch (SocketException e) { - Log.e(TAG, "启动服务端失败: " + e.getMessage()); - + Log.d("cuijingzhou_getDataSerial", "启动失败"); } finally { stopUdpServer(); } }).start(); } - - } /** * 方法:发送请求姿态数据的MAVLink指令 */ public void requestAttitudeData() { + // 确保只执行一次 + if (isAttitudeDataRequested) { + return; + } + isAttitudeDataRequested = true; + // 构造REQUEST_DATA_STREAM消息 msg_request_data_stream request = new msg_request_data_stream(); request.target_system = 1; // 飞机系统ID @@ -289,6 +306,11 @@ public class MyBoundService extends Service { * 请求特定参数 (MAVLINK_MSG_ID_PARAM_REQUEST_READ) */ public void requestParamReadList() { + // 确保只执行一次 + if (isParamReadListRequested) { + return; + } + isParamReadListRequested = true; msg_param_request_list request = new msg_param_request_list(); request.target_system = 1; // 飞控系统ID @@ -323,6 +345,8 @@ public class MyBoundService extends Service { } + + /** * 方法:处理返回的mavlink协议(byte[]) * receivedData:字节[] @@ -336,23 +360,51 @@ public class MyBoundService extends Service { MAVLinkPacket mavLinkPacket = parser.mavlink_parse_char(receivedData[i]); if (mavLinkPacket != null) { MAVLinkMessage msg = mavLinkPacket.unpack(); + +// new_ts = get_sys_ms; +// switch (msg.id) +// { +// case 0: +// if (new_ts - id_0_ts > 100 ) { +// MAV.heartbeat = msg.payload; +// id_0_ts = new_ts; +// } +// break; +// +// case 121: +// id_121_down_sample_count ++; +// if (id_121_down_sample_count % 10 == 0) { +// MAV.gps = msg.payload; +// } +// break; +// +// default: +// break; +// } + + if (msg.msgid == 0) { +// Log.d("msg.msgid", "213"); +// Log.d("msg.msgid", MsgList.get(msg.msgid)+""); + requestInitialData(); + } //判断当前索引下的数据是否有变动,如过没有变动,就不储存,用一个判断增加性能 if (!msg.toString().equals(MsgList.get(msg.msgid))) { // Log.d("cuijigzhou_msg_all", msg.toString()); - LogUtil.d("cuijigzhou_msg_all", msg.toString()); - +// LogUtil.d("cuijigzhou_msg_all", msg.toString()); MsgList.set(msg.msgid, msg.toString()); if (msgOld == null) { MsgList.set(msg.msgid, msg.toString()); msgOld = msg; } else { +// if (msg.msgid == 0) { +// Log.d("msg.msgid", MsgList.get(msg.msgid)); +// } //主要是应对STATUSTEXT(253)这样的特殊数据 wordT1(msg); msgOld = msg; - if (msg.msgid == MAVLINK_MSG_ID_MISSION_ACK){ - Log.d("msg.msgid", MsgList.get(msg.msgid)); - } - +// if (msg.msgid == MAVLINK_MSG_ID_MISSION_ACK) { +// Log.d("msg.msgid", MsgList.get(msg.msgid)); +// } } } @@ -401,10 +453,6 @@ public class MyBoundService extends Service { BroadcastUtil.Broadcast_MISSION_CURRENT(getApplication(), MsgList.get(MAVLINK_MSG_ID_MISSION_CURRENT)); } - - - - Thread.sleep(50); } diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Activity/SettingActivity.java b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Activity/SettingActivity.java index e2cd36c..56ea1b8 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Activity/SettingActivity.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Activity/SettingActivity.java @@ -118,13 +118,18 @@ public class SettingActivity extends AppCompatActivity { private void initView() { allView = new AllView(this); - // 只预加载默认的 MotorFragment + // 预加载默认的 FoundationFragment 和 SettingsFragment androidx.fragment.app.FragmentManager fragmentManager = getSupportFragmentManager(); androidx.fragment.app.FragmentTransaction transaction = fragmentManager.beginTransaction(); foundationFragment = new FoundationFragment(); transaction.add(R.id.fragment_container, foundationFragment, "FoundationFragment"); + + settingsFragment = new SettingsFragment(); // 同时预加载 SettingsFragment + transaction.add(R.id.fragment_container, settingsFragment, "SettingsFragment"); + transaction.commit(); + } /** @@ -153,10 +158,10 @@ public class SettingActivity extends AppCompatActivity { private void selectItem(int index) { for (int i = 0; i < allView.views.size(); i++) { if (index == i) { - allView.views.get(i).setBackgroundResource(R.drawable.ff029a45_2round_1stroke_bg); + allView.views.get(i).setBackgroundResource(R.drawable.ff029a45_4round_1stroke_bg); allView.views.get(i).setTextColor(Color.parseColor("#ffffff")); } else { - allView.views.get(i).setBackgroundResource(R.drawable.b2303030_4round_1stroke_bg); + allView.views.get(i).setBackgroundResource(R.drawable.ffffffff_4round_bg); allView.views.get(i).setTextColor(Color.parseColor("#303030")); } } diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Adapter/MultiSelectAdapter.java b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Adapter/MultiSelectAdapter.java index 49be845..8ec08ed 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Adapter/MultiSelectAdapter.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Adapter/MultiSelectAdapter.java @@ -40,7 +40,7 @@ public class MultiSelectAdapter extends RecyclerView.Adapter { if (position < paramList.size()) { // 再次检查索引有效性 diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Adapter/ParamGroupAdapter.java b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Adapter/ParamGroupAdapter.java index 2e3b052..27ce8ce 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Adapter/ParamGroupAdapter.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Adapter/ParamGroupAdapter.java @@ -9,7 +9,6 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; -import com.example.longyi_groundstation.Main.Setting.Base.Param; import com.example.longyi_groundstation.Main.Setting.Base.ParamGroup; import com.example.longyi_groundstation.R; @@ -46,9 +45,9 @@ public class ParamGroupAdapter extends RecyclerView.Adapter { setSelect(position); diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/ControlFragment.java b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/ControlFragment.java index 0ef10d1..41181a9 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/ControlFragment.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/ControlFragment.java @@ -81,7 +81,7 @@ public class ControlFragment extends Fragment { adapter = new ParamGridAdapter(paramItems); updata(); - // 设置GridLayoutManager,每行显示2个item + // 设置GridLayoutManager,每行显示3个item rv_data.setLayoutManager(new GridLayoutManager(getContext(), 3)); rv_data.setAdapter(adapter); } @@ -104,10 +104,10 @@ public class ControlFragment extends Fragment { //广播接收-RcChannelsRawlistener mBroadcast_RC_CHANNELS.setRcChannelsRawlistener(data -> { - Log.d("cuijingzhou_ctrl", data.toString()); +// Log.d("cuijingzhou_ctrl", data.toString()); try { JSONObject jsonObject = new JSONObject(data.toString()); - for (int i = 0; i < 12; i++){ + for (int i = 0; i < 14; i++){ paramItems.get(i).setCurrentValue(jsonObject.optString("chan" + (i + 1) + "_raw")); } }catch (Exception e){ @@ -236,6 +236,21 @@ public class ControlFragment extends Fragment { FlyVoid.paramList.get("RC12_TRIM").getParam_value(), "待定", "待定")); + // 添加数据 + paramItems.add(new ParamGridAdapter.ParamItem( + "通道13", + FlyVoid.paramList.get("RC13_MAX").getParam_value(), + FlyVoid.paramList.get("RC13_MIN").getParam_value(), + FlyVoid.paramList.get("RC13_TRIM").getParam_value(), + "待定", + "待定")); + paramItems.add(new ParamGridAdapter.ParamItem( + "通道14", + FlyVoid.paramList.get("RC14_MAX").getParam_value(), + FlyVoid.paramList.get("RC14_MIN").getParam_value(), + FlyVoid.paramList.get("RC14_TRIM").getParam_value(), + "待定", + "待定")); } diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/FlyFragment.java b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/FlyFragment.java index 04ad716..211e7c5 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/FlyFragment.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/FlyFragment.java @@ -50,6 +50,7 @@ public class FlyFragment extends Fragment { if (FlyVoid.isParamUpdateComplete()){ initData(); initView(view); + getData(); initOnClick(); } return view; @@ -201,7 +202,7 @@ public class FlyFragment extends Fragment { int progress = seekBar_horizontal_angle.getProgress(); if (progress > 1000) { seekBar_horizontal_angle.setProgress(progress - 100); - tv_horizontal_angle.setText(seekBar_horizontal_angle.getProgress() + "cdeg"); + tv_horizontal_angle.setText((seekBar_horizontal_angle.getProgress() / 100) + "度"); } }); @@ -209,14 +210,14 @@ public class FlyFragment extends Fragment { int progress = seekBar_horizontal_angle.getProgress(); if (progress < seekBar_horizontal_angle.getMax()) { seekBar_horizontal_angle.setProgress(progress + 100); - tv_horizontal_angle.setText(seekBar_horizontal_angle.getProgress() + "cdeg"); + tv_horizontal_angle.setText(((seekBar_horizontal_angle.getProgress() / 100)) + "度"); } }); seekBar_horizontal_angle.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - tv_horizontal_angle.setText(progress + "度"); + tv_horizontal_angle.setText((progress / 100) + "度"); } @Override @@ -271,13 +272,11 @@ public class FlyFragment extends Fragment { seekBar_decline_speed.setProgress(0); tv_decline_speed.setText(seekBar_decline_speed.getProgress() + "m/s"); seekBar_horizontal_angle.setProgress(3000); - tv_horizontal_angle.setText(seekBar_horizontal_angle.getProgress() + "cdeg"); + tv_horizontal_angle.setText((seekBar_horizontal_angle.getProgress()/100) + "度"); seekBar_rotation_rate.setProgress(2025); tv_rotation_rate.setText(((double)seekBar_rotation_rate.getProgress()/10) + "度/s"); Toast.makeText(getActivity(), "初始化完成", Toast.LENGTH_SHORT).show(); }); - - } /** @@ -293,7 +292,7 @@ public class FlyFragment extends Fragment { seekBar_decline_speed.setProgress(Integer.parseInt(FlyVoid.paramList.get("PILOT_SPEED_DN").getParam_value())); tv_decline_speed.setText(seekBar_decline_speed.getProgress() + "m/s"); seekBar_horizontal_angle.setProgress(Integer.parseInt(FlyVoid.paramList.get("ANGLE_MAX").getParam_value())); - tv_horizontal_angle.setText(seekBar_horizontal_angle.getProgress() + "cdeg"); + tv_horizontal_angle.setText((seekBar_horizontal_angle.getProgress()/100) + "度"); //旋转速率单独运算一下 float rotation_rate = Float.parseFloat(FlyVoid.paramList.get("PILOT_Y_RATE").getParam_value())*10; seekBar_rotation_rate.setProgress((int) rotation_rate); @@ -316,6 +315,6 @@ public class FlyFragment extends Fragment { @Override public void onStart() { super.onStart(); - getData(); + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/FoundationFragment.java b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/FoundationFragment.java index 4dc81e7..8a2a81c 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/FoundationFragment.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/FoundationFragment.java @@ -35,7 +35,7 @@ public class FoundationFragment extends Fragment { private RelativeLayout rl_low_end,rl_mid_range,rl_high_end; private Spinner sp_low_end,sp_mid_range,sp_high_end; private TextView tv_low_end_text,tv_mid_range_text,tv_high_end_text,tv_save; - + private TextView et_speed_text; private FlyVoid flyVoid = new FlyVoid(); @Override @@ -75,6 +75,7 @@ public class FoundationFragment extends Fragment { tv_low_end_text = view.findViewById(R.id.tv_low_end_text); tv_mid_range_text = view.findViewById(R.id.tv_mid_range_text); tv_high_end_text = view.findViewById(R.id.tv_high_end_text); + et_speed_text = view.findViewById(R.id.et_speed_text); tv_save = view.findViewById(R.id.tv_save); initSpinnerData(); initText(); @@ -183,6 +184,12 @@ public class FoundationFragment extends Fragment { FlyVoid.paramList.get("FLTMODE5").getParam_type()); flyVoid.requestParamSet("FLTMODE6", getSelectedChannelValue(sp_high_end) + ""); + Thread.sleep(100); + + flyVoid.requestParamSet("WPNAV_SPEED", + et_speed_text.getText().toString(), + FlyVoid.paramList.get("WPNAV_SPEED").getParam_type()); + Thread.sleep(100); Toast.makeText(requireContext(), "保存成功", Toast.LENGTH_SHORT).show(); }catch (Exception e){ @@ -199,6 +206,7 @@ public class FoundationFragment extends Fragment { setSelectedChannel(sp_low_end, Integer.parseInt(FlyVoid.paramList.get("FLTMODE1").getParam_value())); setSelectedChannel(sp_mid_range, Integer.parseInt(FlyVoid.paramList.get("FLTMODE3").getParam_value())); setSelectedChannel(sp_high_end, Integer.parseInt(FlyVoid.paramList.get("FLTMODE5").getParam_value())); + et_speed_text.setText(FlyVoid.paramList.get("WPNAV_SPEED").getParam_value()); } /** diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/LoadFragment.java b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/LoadFragment.java index 4fd66b7..5b83bb6 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/LoadFragment.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/LoadFragment.java @@ -216,8 +216,6 @@ public class LoadFragment extends Fragment { // 给flyTextViews里面所有的view添加点击事件:点击后会打开对应的Spinner initFlyTextViewClickListeners(); - - } /** diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/MotorFragment.java b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/MotorFragment.java index f250809..c3c5883 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/MotorFragment.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/MotorFragment.java @@ -66,9 +66,9 @@ public class MotorFragment extends Fragment { for (int i = 1; i <= 12; i++) { if (i <= 6) { - list.add(new Motor("电机" + i, i, true)); + list.add(new Motor("" + i, i, true)); } else { - list.add(new Motor("电机" + i, i, false)); + list.add(new Motor("" + i, i, false)); } } diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/SettingsFragment.java b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/SettingsFragment.java index a669cc8..537bd19 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/SettingsFragment.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Setting/Fragment/SettingsFragment.java @@ -43,6 +43,7 @@ import com.example.longyi_groundstation.R; import com.google.gson.Gson; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.List; @@ -428,6 +429,8 @@ public class SettingsFragment extends Fragment { // 将 Map 中的值转换为 List 并添加到 paramGroupsList paramGroupsList.addAll(groupMap.values()); + // 添加这行代码来执行排序 + sortParamGroupsByName(); // 通知适配器刷新数据 if (!paramGroupsList.isEmpty()) { @@ -460,6 +463,22 @@ public class SettingsFragment extends Fragment { }); } + /** + * 方法:按照参数组名称字母顺序排序 + * + * @cuijingzhou + */ + private void sortParamGroupsByName() { + if (paramGroupsList != null && !paramGroupsList.isEmpty()) { + paramGroupsList.sort((group1, group2) -> { + if (group1 == null || group2 == null) return 0; + if (group1.getParam_name() == null || group2.getParam_name() == null) return 0; + return group1.getParam_name().compareToIgnoreCase(group2.getParam_name()); + }); + } + } + + @Override public void onResume() { diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/View/BombingDialog.java b/app/src/main/java/com/example/longyi_groundstation/Main/View/BombingDialog.java index cda9ef1..def6e10 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/View/BombingDialog.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/View/BombingDialog.java @@ -85,18 +85,24 @@ public class BombingDialog { window.setBackgroundDrawableResource(R.drawable.ffffffff_4round_bg); } - unlockView.setText("滑动执行"); + unlockView.setText("滑动确认"); unlockView.setOnUnlockListener(new SlideToUnlockView.OnUnlockListener() { @Override public void onUnlock() { // 发送命令 // flyVoid.sendMavlinkMessage(MyBoundService.type,command); - flyVoid.requestBombing(et_height.getText().toString()); + if (et_height.getText().toString().length() > 0){ + flyVoid.requestBombing(et_height.getText().toString()); + // 滑动到阈值后触发(如关闭对话框或执行操作) + Toast.makeText(context, "操作已确认", Toast.LENGTH_SHORT).show(); + }else { + unlockView.resetProgress(); + Toast.makeText(context, "请输入高度", Toast.LENGTH_SHORT).show(); + } dialog.dismiss(); - // 滑动到阈值后触发(如关闭对话框或执行操作) - Toast.makeText(context, "操作已确认", Toast.LENGTH_SHORT).show(); MyTool.hideBottomNavigationBar(context); + } }); diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/View/PointFlyDialog.java b/app/src/main/java/com/example/longyi_groundstation/Main/View/PointFlyDialog.java index 57e9097..011d6cf 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/View/PointFlyDialog.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/View/PointFlyDialog.java @@ -8,6 +8,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; +import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; @@ -19,9 +20,8 @@ import com.example.longyi_groundstation.R; public class PointFlyDialog { private final Activity context; - private String title; - private String message; - private String positiveButtonText; + private String speed; + private String height; private LatLng latLng; private FlyVoid flyVoid = new FlyVoid(); @@ -29,10 +29,9 @@ public class PointFlyDialog { public PointFlyDialog(Activity context) { this.context = context; - this.title = "错误日志"; - this.message = ""; - this.positiveButtonText = "确定"; - this.latLng = latLng; + this.speed = "3"; + this.height = "30"; + this.latLng = null; } @@ -43,22 +42,18 @@ public class PointFlyDialog { } // 设置弹窗标题 - public PointFlyDialog setTitle(String title) { - this.title = title; + public PointFlyDialog setSpeed(String speed) { + this.speed = speed; return this; } // 设置弹窗内容 - public PointFlyDialog setMessage(String message) { - this.message = message; + public PointFlyDialog setHeight(String height) { + this.height = height; return this; } - // 设置确认按钮文字 - public PointFlyDialog setPositiveButtonText(String text) { - this.positiveButtonText = text; - return this; - } + // 显示弹窗 public void show() { @@ -70,9 +65,22 @@ public class PointFlyDialog { @SuppressLint({"MissingInflatedId", "LocalSuppress"}) TextView tvMessage = view.findViewById(R.id.tv_message); // 滑动模块 @SuppressLint({"MissingInflatedId", "LocalSuppress"}) SlideToUnlockView unlockView = view.findViewById(R.id.unlockView); + //经度 + @SuppressLint({"MissingInflatedId", "LocalSuppress"}) EditText et_lon = view.findViewById(R.id.et_lon); + //纬度 + @SuppressLint({"MissingInflatedId", "LocalSuppress"}) EditText et_lat = view.findViewById(R.id.et_lat); + //高度 + @SuppressLint({"MissingInflatedId", "LocalSuppress"}) EditText et_height = view.findViewById(R.id.et_height); + //速度 + @SuppressLint({"MissingInflatedId", "LocalSuppress"}) EditText et_speed = view.findViewById(R.id.et_speed); + + if (latLng != null){ - tvMessage.setText("经度:" + latLng.latitude + "\n纬度:" + latLng.latitude); + et_lon.setText(String.valueOf(latLng.longitude)); + et_lat.setText(String.valueOf(latLng.latitude)); + et_height.setText(height); + et_speed.setText(speed); } // 添加日志 @@ -95,8 +103,28 @@ public class PointFlyDialog { unlockView.setOnUnlockListener(new SlideToUnlockView.OnUnlockListener() { @Override public void onUnlock() { -// // 发送命令 + if (et_lat.getText().toString().isEmpty() || et_lon.getText().toString().isEmpty()){ + Toast.makeText(context, "请填写经纬度", Toast.LENGTH_SHORT).show(); + return; + } + if (et_height.getText().toString().isEmpty()){ + Toast.makeText(context, "请填写高度", Toast.LENGTH_SHORT).show(); + return; + } + if (Integer.parseInt(et_height.getText().toString()) < 5){ + Toast.makeText(context, "高度过低", Toast.LENGTH_SHORT).show(); + return; + } +// // 发送命令 + flyVoid.adviseFly( + context, + new LatLng( + Double.parseDouble(et_lat.getText().toString()), + Double.parseDouble(et_lon.getText().toString())) + , + Double.parseDouble(et_height.getText().toString()), + Double.parseDouble(et_speed.getText().toString())); MyTool.hideBottomNavigationBar( context); dialog.dismiss(); // 滑动到阈值后触发(如关闭对话框或执行操作) @@ -108,7 +136,6 @@ public class PointFlyDialog { tvMessage.setOnClickListener(v -> { dialog.dismiss(); MyTool.hideBottomNavigationBar(context); - }); } diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/View/SaveLinkNameDialog.java b/app/src/main/java/com/example/longyi_groundstation/Main/View/SaveLinkNameDialog.java index 6d918bf..e793b2e 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/View/SaveLinkNameDialog.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/View/SaveLinkNameDialog.java @@ -92,9 +92,6 @@ public class SaveLinkNameDialog { }else { context.saveLink(null); } - - - MyTool.hideBottomNavigationBar( context); dialog.dismiss(); // 滑动到阈值后触发(如关闭对话框或执行操作) Toast.makeText(context, "操作已确认", Toast.LENGTH_SHORT).show(); diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Void/AllView.java b/app/src/main/java/com/example/longyi_groundstation/Main/Void/AllView.java index dea08f1..a714e4c 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Void/AllView.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Void/AllView.java @@ -94,14 +94,19 @@ public class AllView { public ImageView iv_open_link_list; public LinearLayout ll_clear_fly_line; public LinearLayout ll_create_link_item_layout; - - + public ImageView iv_marker_top; + public ImageView iv_marker_left; + public ImageView iv_marker_right; + public ImageView iv_marker_bottom; + public LinearLayout ll_marker_ctrl; + public EditText et_marker_distance; // public SlideToUnlockView unlockView; // public RelativeLayout rl_unlock; public EditText et_start_execute_height; + public AllView(Activity activity) { this.activity = activity; init(); @@ -182,6 +187,11 @@ public class AllView { ll_clear_fly_line = activity.findViewById(R.id.ll_clear_fly_line); ll_create_link_item_layout = activity.findViewById(R.id.ll_create_link_item_layout); iv_open_link_list = activity.findViewById(R.id.iv_open_link_list); - + iv_marker_top = activity.findViewById(R.id.iv_marker_top); + iv_marker_left = activity.findViewById(R.id.iv_marker_left); + iv_marker_right = activity.findViewById(R.id.iv_marker_right); + iv_marker_bottom = activity.findViewById(R.id.iv_marker_bottom); + ll_marker_ctrl = activity.findViewById(R.id.ll_marker_ctrl); + et_marker_distance = activity.findViewById(R.id.et_marker_distance); } } diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Void/FlyVoid.java b/app/src/main/java/com/example/longyi_groundstation/Main/Void/FlyVoid.java index 4a873ac..c3ae162 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Void/FlyVoid.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Void/FlyVoid.java @@ -34,6 +34,7 @@ import com.example.longyi_groundstation.MAVLink.common.msg_mission_request_int; import com.example.longyi_groundstation.MAVLink.common.msg_mission_request_list; import com.example.longyi_groundstation.MAVLink.common.msg_param_request_read; import com.example.longyi_groundstation.MAVLink.common.msg_param_set; +import com.example.longyi_groundstation.MAVLink.common.msg_set_position_target_global_int; import com.example.longyi_groundstation.MAVLink.enums.MAV_CMD; import com.example.longyi_groundstation.MAVLink.enums.MAV_COMPONENT; import com.example.longyi_groundstation.MAVLink.enums.MAV_FRAME; @@ -365,113 +366,9 @@ public class FlyVoid { * @param createLinkList 航线航点列表 * @cuijingzhou */ - public void sendMissionToFlightController(Activity context, ArrayList createLinkList, String height) { - if (createLinkList == null || createLinkList.isEmpty()) { - return; - } - if (height == null){ - height = "10"; - } - - // 创建 ProgressDialog - android.app.ProgressDialog progressDialog = new android.app.ProgressDialog(context); - progressDialog.setTitle("任务上传中"); - progressDialog.setMessage("正在发送航线到飞控..."); - progressDialog.setProgressStyle(android.app.ProgressDialog.STYLE_HORIZONTAL); - progressDialog.setCancelable(false); // 设置不可手动关闭 - progressDialog.setMax(100); - progressDialog.show(); - MsgList.set(MAVLINK_MSG_ID_MISSION_REQUEST,null); - String finalHeight = height; - new Thread(() -> { - try { - // 2. 发送航点计数 - msg_mission_count count = new msg_mission_count(); - count.target_system = 1; - count.target_component = 1; - count.count = createLinkList.size() + 2; // 航点数量 - sendMavlinkMessage(type, count); - - Log.d("Missions-count", "--" + ( createLinkList.size() + 2)); - -// 在FlyVoid.java的sendMissionToFlightController方法中,找到以下代码块并修改: - - boolean isOk = true; - int sentWaypoints = 0; - int totalWaypoints = createLinkList.size() + 2; - int lastSeq = -1; // 添加这一行来记录上一次的seq值 - - while (isOk) { - try { - String msgRequest = MsgList.get(MAVLINK_MSG_ID_MISSION_REQUEST); - if (msgRequest != null) { - JSONObject jsonObject = new JSONObject(msgRequest); - int seq = jsonObject.optInt("seq"); - - // 添加判断:如果seq值没有改变,跳过本次循环 - if (seq == lastSeq) { - Thread.sleep(100); // 短暂休眠避免过度占用CPU - continue; // 跳过本次循环 - } - - upDataLinkPoint(seq, createLinkList, finalHeight); - lastSeq = seq; // 更新lastSeq值 - sentWaypoints = seq + 1; - - // 更新发送进度 - final int progress = (int) ((sentWaypoints / (float) totalWaypoints) * 92); // 发送占50%进度 - context.runOnUiThread(() -> { - progressDialog.setProgress(progress); - }); - - // 如果当前序号+1大于等于航点总数,则结束循环 - if ((seq + 1) >= createLinkList.size()+2) { - isOk = false; - } - } - - // 添加短暂延迟以避免过度占用CPU - Thread.sleep(100); - } catch (Exception e) { - Log.e("Mission", "Error processing mission request: " + e.getMessage()); - // 出错时也退出循环避免无限循环 - isOk = false; - } - } - context.runOnUiThread(() -> { - progressDialog.setMessage("正在校验航线..."); - }); - Log.d("Missions", "verifyResult"); - - // 校验点位是否正常上传 - boolean verifyResult = verifyPoint(createLinkList); - - // 更新校验进度 - context.runOnUiThread(() -> { - progressDialog.setProgress(100); - progressDialog.dismiss(); - - if (verifyResult) { - Toast.makeText(context, "航线上传成功", Toast.LENGTH_SHORT).show(); - } else { - Toast.makeText(context, "航线发送完成但校验失败", Toast.LENGTH_SHORT).show(); - } - - }); - - } catch (Exception e) { - context.runOnUiThread(() -> { - progressDialog.dismiss(); - Toast.makeText(context, "航线发送过程中出现错误", Toast.LENGTH_SHORT).show(); - }); - e.printStackTrace(); - } - - }).start(); - } /** @@ -479,8 +376,94 @@ public class FlyVoid { * * @cuijingzhou * */ - private void creatDataList (ArrayList createLinkList, String height) { - ArrayList dataList = new ArrayList<>(); + public static ArrayList createLinkListToFlyList = null;//当前飞行计划 + public void creatDataList (Activity context,ArrayList createLinkList, String height) { + try { + + //转换一下 + ArrayList list1 = createLinkListToFlyList(createLinkList); + Log.d("sss", "creatDataList: "); + if (createLinkList == null || createLinkList.isEmpty()) { + return; + } + if (height == null){ + height = "10"; + } + +// // 创建 ProgressDialog +// android.app.ProgressDialog progressDialog = new android.app.ProgressDialog(context); +// progressDialog.setTitle("任务上传中"); +// progressDialog.setMessage("正在发送航线到飞控..."); +// progressDialog.setProgressStyle(android.app.ProgressDialog.STYLE_HORIZONTAL); +// progressDialog.setCancelable(false); // 设置不可手动关闭 +// progressDialog.setMax(100); +// progressDialog.show(); + + MsgList.set(MAVLINK_MSG_ID_MISSION_REQUEST,null); + String finalHeight = height; + new Thread(() -> { + try { + // 2. 发送航点计数 + msg_mission_count count = new msg_mission_count(); + count.target_system = 1; + count.target_component = 1; + count.count = list1.size(); // 航点数量 + sendMavlinkMessage(type, count); + + Log.d("Missions-count", "--" + ( list1.size())); + + boolean isOk = true; + int lastSeq = -1; // 添加这一行来记录上一次的seq值 + + while (isOk) { + try { + String msgRequest = MsgList.get(MAVLINK_MSG_ID_MISSION_REQUEST); + if (msgRequest != null) { + JSONObject jsonObject = new JSONObject(msgRequest); + int seq = jsonObject.optInt("seq"); + + // 添加判断:如果seq值没有改变,跳过本次循环 + if (seq <= lastSeq) { + Thread.sleep(100); // 短暂休眠避免过度占用CPU + continue; // 跳过本次循环 + } + lastSeq = seq; // 更新lastSeq值 + // 发送消息请求航点列表 + sendMavlinkMessage(type, list1.get( lastSeq)); + // 如果当前序号+1大于等于航点总数,则结束循环 + if ((lastSeq + 1) >= list1.size()) { + Log.d("cjz_航线上传", "上传成功"); + context.runOnUiThread(() -> { + Toast.makeText(context, "上传成功", Toast.LENGTH_SHORT).show(); + }); + isOk = false; + } + } + + // 添加短暂延迟以避免过度占用CPU + Thread.sleep(100); + } catch (Exception e) { + Log.e("Mission", "Error processing mission request: " + e.getMessage()); + // 出错时也退出循环避免无限循环 + isOk = false; + } + } + + } catch (Exception e) { + e.printStackTrace(); + } + + }).start(); + + + } catch (Exception e) { + e.printStackTrace(); + Log.d("问题1", "creatDataList: "+e); + } + } + + public ArrayList createLinkListToFlyList(ArrayList createLinkList){ + ArrayList list1 = new ArrayList<>(); //home点,默认第一个为home点 msg_mission_item_int waypoint = new msg_mission_item_int(); waypoint.target_system = 1; // 无人机系统ID @@ -497,7 +480,8 @@ public class FlyVoid { waypoint.x = 0; waypoint.y = 0; waypoint.z = 0; // 高度(相对) - dataList.add(waypoint); + list1.add(waypoint); + //起飞,将飞机拉起来 msg_mission_item_int waypoint1 = new msg_mission_item_int(); waypoint1.target_system = 1; // 无人机系统ID @@ -513,103 +497,137 @@ public class FlyVoid { waypoint1.param4 = 0; // 航向角 waypoint1.x = 0; waypoint1.y = 0; - waypoint1.z = Float.parseFloat(height); // 高度(相对) + waypoint1.z = Float.parseFloat("10"); // 高度(相对) waypoint1.mission_type = MAV_MISSION_TYPE.MAV_MISSION_TYPE_MISSION; + list1.add(waypoint1); -// //添加航点 -// for (int i = 0; i < createLinkList.size(); i++) { -// if (){ -// -// } -// } + for (int i = 0; i < createLinkList.size(); i++) { + CreateLink link = createLinkList.get(i); + // 在特定航点前添加速度变化指令 + msg_mission_item_int speedChange = new msg_mission_item_int(); + speedChange.target_system = 1; + speedChange.target_component = 1; + speedChange.seq = list1.size(); // 序号 + speedChange.frame = MAV_FRAME.MAV_FRAME_GLOBAL_RELATIVE_ALT; + speedChange.command = MAV_CMD.MAV_CMD_DO_CHANGE_SPEED; + speedChange.current = 0; + speedChange.autocontinue = 1; + speedChange.param1 = 1; // 地速 + speedChange.param2 = (float) link.getSpeed(); // 使用CreateLink中的速度值 + speedChange.param3 = 0; // 不限制推力 + speedChange.param4 = 0; // 绝对速度 + speedChange.x = 0; + speedChange.y = 0; + speedChange.z = Float.parseFloat("10"); + list1.add(speedChange); + //第一个点特殊处理 + if ( i-1 == -1){ + msg_mission_item_int command = new msg_mission_item_int(); + command.target_system = 1; + command.target_component = 1; + command.seq = list1.size(); // 序号 + command.frame = MAV_FRAME.MAV_FRAME_GLOBAL_RELATIVE_ALT; + command.command = MAV_CMD.MAV_CMD_CONDITION_YAW; +// 设置偏航参数 + command.param1 = getYaw( + MainActivity.homeLatLng.latitude, + MainActivity.homeLatLng.longitude, + link.getLatLng().latitude, + link.getLatLng().longitude); // 目标偏航角度 + command.param2 = 0; // 偏航角变化速率 + command.param3 = 0; // 方向(-1=逆时针,1=顺时针) + command.param4 = 0; // 相对或绝对偏航(0=绝对,1=相对) + list1.add(command); + } - } + if (link.getStop_time() > 0 && i <= createLinkList.size()-1 && i-1 != -1){ + msg_mission_item_int command = new msg_mission_item_int(); + command.target_system = 1; + command.target_component = 1; + command.seq = list1.size(); // 序号 + command.frame = MAV_FRAME.MAV_FRAME_GLOBAL_RELATIVE_ALT; + command.command = MAV_CMD.MAV_CMD_CONDITION_YAW; +// 设置偏航参数 + command.param1 = getYaw( + createLinkList.get(i-1).getLatLng().latitude, + createLinkList.get(i-1).getLatLng().longitude, + link.getLatLng().latitude, + link.getLatLng().longitude); // 目标偏航角度 + command.param2 = 0; // 偏航角变化速率 + command.param3 = 0; // 方向(-1=逆时针,1=顺时针) + command.param4 = 0; // 相对或绝对偏航(0=绝对,1=相对) + list1.add(command); + } - - - /** - * 方法:给飞控发送点位 - * - * @cuijingzhou - */ - private void upDataLinkPoint(int i,ArrayList createLinkList,String height) throws InterruptedException { -// Log.d("Missions", "--" + i); -// Log.d("Missions", "myReceiver_MISSION_ACK: "); - //由于第一个点是home点,所以要从第2个点开始上传 - if (i == 0){ - - msg_mission_item_int waypoint = new msg_mission_item_int(); - waypoint.target_system = 1; // 无人机系统ID - waypoint.target_component = 1; // 无人机组件ID - waypoint.seq = 0; // 航点序号 - waypoint.frame = MAV_FRAME.MAV_FRAME_GLOBAL_RELATIVE_ALT; // 坐标系 - waypoint.command = MAV_CMD.MAV_CMD_NAV_WAYPOINT; // 航点指令 - waypoint.current = 1 ; // 第一个航点设为当前航点 - waypoint.autocontinue = 1; // 自动继续到下一个航点 - waypoint.param1 = 0; // 停留时间(秒) - waypoint.param2 = 0; // 接受半径(m) - waypoint.param3 = 0; // 通过半径(m) - waypoint.param4 = 0; // 航向角 - waypoint.x = 0; - waypoint.y = 0; - waypoint.z = 0; // 高度(相对) - sendMavlinkMessage(type, waypoint); - Log.d("Missions", i+"--"+ waypoint.toString()); - Thread.sleep(100); - } else if (i == 1) { - msg_mission_item_int waypoint1 = new msg_mission_item_int(); - waypoint1.target_system = 1; // 无人机系统ID - waypoint1.target_component = 1; // 无人机组件ID - waypoint1.seq = i; // 航点序号 - waypoint1.frame = MAV_FRAME.MAV_FRAME_GLOBAL_RELATIVE_ALT; // 坐标系 - waypoint1.command = MAV_CMD.MAV_CMD_NAV_TAKEOFF; // 航点指令 - waypoint1.current = 0; // 第一个航点设为当前航点 - waypoint1.autocontinue = 1; // 自动继续到下一个航点 - waypoint1.param1 = 0; // 停留时间(秒) - waypoint1.param2 = 0; // 接受半径(m) - waypoint1.param3 = 0; // 通过半径(m) - waypoint1.param4 = 0; // 航向角 - waypoint1.x = 0; - waypoint1.y = 0; - waypoint1.z = Float.parseFloat(height); // 高度(相对) - waypoint1.mission_type = MAV_MISSION_TYPE.MAV_MISSION_TYPE_MISSION; - sendMavlinkMessage(type, waypoint1); - Log.d("Missions", i+"--"+ waypoint1.toString()); - Thread.sleep(100); - } - //正常上传 - else { - CreateLink link = createLinkList.get(i-2); LatLng latLng = link.getLatLng(); double[] doubles = CoordinateConverter.gcj02ToWgs84(latLng.longitude, latLng.latitude); - if (doubles != null) { - msg_mission_item_int waypoint = new msg_mission_item_int(); - waypoint.target_system = 1; // 无人机系统ID - waypoint.target_component = 1; // 无人机组件ID - waypoint.seq = i; // 航点序号 - waypoint.frame = MAV_FRAME.MAV_FRAME_GLOBAL_RELATIVE_ALT; // 坐标系 - waypoint.command = MAV_CMD.MAV_CMD_NAV_WAYPOINT; // 航点指令 - waypoint.current = 0; // 第一个航点设为当前航点 - waypoint.autocontinue = 1; // 自动继续到下一个航点 - waypoint.param1 = 0; // 停留时间(秒) - waypoint.param2 = 0; // 接受半径(m) - waypoint.param3 = 0; // 通过半径(m) - waypoint.param4 = 0; // 航向角 - waypoint.x = (int) (doubles[1] * 10000000); - waypoint.y = (int) (doubles[0] * 10000000); - // 经度 - waypoint.z = (float) link.getHeight(); // 高度(相对) - sendMavlinkMessage(type, waypoint); - Log.d("Missions", i+"--"+ waypoint.toString()); - Thread.sleep(100); - } + //点位,其中包含停留时间 + msg_mission_item_int waypointss = new msg_mission_item_int(); + waypointss.target_system = 1; // 无人机系统ID + waypointss.target_component = 1; // 无人机组件ID + waypointss.seq = list1.size(); // 航点序号 + waypointss.frame = MAV_FRAME.MAV_FRAME_GLOBAL_RELATIVE_ALT; // 坐标系 + waypointss.command = MAV_CMD.MAV_CMD_NAV_WAYPOINT; // 航点指令 + waypointss.current = 0; // 第一个航点设为当前航点 + waypointss.autocontinue = 1; // 自动继续到下一个航点 + waypointss.param1 = link.getStop_time(); // 停留时间(秒) + waypointss.param2 = 0; // 接受半径(m) + waypointss.param3 = 0; // 通过半径(m) + waypointss.param4 = 0; // 航向角 + waypointss.x = (int) (doubles[1] * 10000000); + waypointss.y = (int) (doubles[0] * 10000000); + // 经度 + waypointss.z = (float) link.getHeight(); // 高度(相对) + waypointss.mission_type = MAV_MISSION_TYPE.MAV_MISSION_TYPE_MISSION; + list1.add(waypointss); + + } - - + return list1; } + /** + * 方法:计算从当前点到下一个点的方位角(Yaw) + * 以正北为0度,顺时针方向为正 + * + * @param currentLat 当前点纬度 + * @param currentLon 当前点经度 + * @param nextLat 下一个点纬度 + * @param nextLon 下一个点经度 + * @return 方位角(0-360度,正北为0度) + */ + public static float getYaw(double currentLat, double currentLon, double nextLat, double nextLon) { + // 将角度转换为弧度 + double lat1 = Math.toRadians(currentLat); + double lon1 = Math.toRadians(currentLon); + double lat2 = Math.toRadians(nextLat); + double lon2 = Math.toRadians(nextLon); + + // 计算经度差 + double dLon = lon2 - lon1; + + // 使用球面三角法计算方位角 + double y = Math.sin(dLon) * Math.cos(lat2); + double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon); + double bearing = Math.atan2(y, x); + + // 将结果从弧度转换为度 + bearing = Math.toDegrees(bearing); + + // 规范化到0-360度范围 + bearing = (bearing + 360) % 360; + + return (int) bearing; + } + + + + + + + /** * 方法:校验发送的点位是否正确 * @@ -790,6 +808,73 @@ public class FlyVoid { } + /** + * 方法:指点飞行 + * + * @cuijingzhou + */ + public void adviseFly(Activity context, LatLng latLng, double height, double speed) { + // 先切换到GUIDED模式 + setFlightMode(4); + // 延时一段时间确保模式切换完成 + new Thread(() -> { + try { + Thread.sleep(1000); + // 使用 SET_POSITION_TARGET_GLOBAL_INT 消息发送目标位置 + adviseFlyWithGlobalPosition(latLng, height, speed); + } catch (InterruptedException e) { + e.printStackTrace(); + } + }).start(); + } + + + /** + * 方法:使用 SET_POSITION_TARGET_GLOBAL_INT 消息进行指点飞行 + * + * @param latLng 目标位置坐标 + * @param altitude 目标高度 + * @param speed 目标速度 + */ + public void adviseFlyWithGlobalPosition(LatLng latLng, double altitude, double speed) { + try { + // 转换坐标系 (GCJ02转WGS84) + double[] wgs84Coords = CoordinateConverter.gcj02ToWgs84(latLng.longitude, latLng.latitude); + + // 创建 SET_POSITION_TARGET_GLOBAL_INT 消息 + msg_set_position_target_global_int positionTarget = new msg_set_position_target_global_int(); + positionTarget.target_system = 1; // 目标系统ID + positionTarget.target_component = 1; // 目标组件ID + positionTarget.coordinate_frame = MAV_FRAME.MAV_FRAME_GLOBAL_RELATIVE_ALT; // 坐标系 + positionTarget.type_mask = 0b0000111111111000; // 仅位置控制,速度和加速度不控制 + + // 设置目标位置 + positionTarget.lat_int = (int) (wgs84Coords[1] * 10000000); // 纬度 (单位: 1e-7度) + positionTarget.lon_int = (int) (wgs84Coords[0] * 10000000); // 经度 (单位: 1e-7度) + positionTarget.alt = (float) altitude; // 高度 (单位: 米) + + // 设置目标速度 + positionTarget.vx = 0; // X轴速度 (单位: m/s) + positionTarget.vy = 0; // Y轴速度 (单位: m/s) + positionTarget.vz = 0; // Z轴速度 (单位: m/s) + + // 其他参数设置为0 + positionTarget.afx = 0; + positionTarget.afy = 0; + positionTarget.afz = 0; + positionTarget.yaw = 0; + positionTarget.yaw_rate = 0; + + // 发送消息 + sendMavlinkMessage(MyBoundService.type, positionTarget); + + } catch (Exception e) { + Log.e("FlyVoid", "adviseFlyWithGlobalPosition error: " + e.getMessage()); + } + } + + + /** * 方法:切换无人机飞行模式 * @@ -816,4 +901,35 @@ public class FlyVoid { } + /** + * 控制通道 + * @param servoInstance 舵机编号 (1-8) + * @param pwmValue PWM值 (1000-2000微秒) + * 使用示例:将第1个舵机设置到中立位置 + * controlServo(1, 1500); + */ + public void controlServo(int servoInstance, int pwmValue) { + // 构造命令 + msg_command_long command = new msg_command_long(); + + command.target_system = 1; // 目标系统ID(飞控) + command.target_component = 1; // 目标组件ID + command.command = MAV_CMD.MAV_CMD_DO_SET_SERVO; // 设置舵机命令 + command.confirmation = 0; // 确认位 + + // 设置舵机参数 + command.param1 = servoInstance; // 舵机实例号 + command.param2 = pwmValue; // PWM值 + command.param3 = 0; // 保留 + command.param4 = 0; // 保留 + command.param5 = 0; // 保留 + command.param6 = 0; // 保留 + command.param7 = 0; // 保留 + + // 发送命令 + sendMavlinkMessage(MyBoundService.type, command); + } + + + } diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Void/HeartbeatManager.java b/app/src/main/java/com/example/longyi_groundstation/Main/Void/HeartbeatManager.java new file mode 100644 index 0000000..e459632 --- /dev/null +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Void/HeartbeatManager.java @@ -0,0 +1,140 @@ +// 新建文件 HeartbeatManager.java +package com.example.longyi_groundstation.Main.Void; + +import android.os.Handler; +import android.os.Looper; +import android.util.Log; + +import com.example.longyi_groundstation.MAVLink.MAVLinkPacket; +import com.example.longyi_groundstation.MAVLink.minimal.msg_heartbeat; + +import java.net.DatagramPacket; +import java.net.InetAddress; + +import tp.xmaihh.serialport.SerialHelper; + +/** + * 心跳管理器类,用于管理与飞控的心跳通信 + */ +public class HeartbeatManager { + private static final String TAG = "HeartbeatManager"; + private static final long HEARTBEAT_INTERVAL = 1000; // 心跳间隔1秒 + + private Handler heartbeatHandler; + private Runnable heartbeatRunnable; + private boolean isHeartbeatRunning = false; + private int connectionType; // 0: 串口, 1: UDP + private SerialHelper serialHelper; + private java.net.DatagramSocket serverSocket; + + public HeartbeatManager(int type, SerialHelper serialHelper, java.net.DatagramSocket serverSocket) { + this.connectionType = type; + this.serialHelper = serialHelper; + this.serverSocket = serverSocket; + this.heartbeatHandler = new Handler(Looper.getMainLooper()); + } + + /** + * 方法:启动心跳包发送 + */ + public void startHeartbeat() { + if (!isHeartbeatRunning) { + isHeartbeatRunning = true; + heartbeatRunnable = new Runnable() { + @Override + public void run() { + if (isHeartbeatRunning) { + sendHeartbeat(); + heartbeatHandler.postDelayed(this, HEARTBEAT_INTERVAL); + } + } + }; + heartbeatHandler.post(heartbeatRunnable); + } + } + + /** + * 方法:停止心跳包发送 + */ + public void stopHeartbeat() { + isHeartbeatRunning = false; + if (heartbeatHandler != null && heartbeatRunnable != null) { + heartbeatHandler.removeCallbacks(heartbeatRunnable); + } + } + + /** + * 方法:发送心跳包到飞控 + */ + private void sendHeartbeat() { + try { + // 创建心跳消息 + msg_heartbeat heartbeat = new msg_heartbeat(); + + // 设置心跳参数 + heartbeat.type = 6; // GCS类型 + heartbeat.autopilot = 8; // MAV_AUTOPILOT_INVALID + heartbeat.base_mode = 0; + heartbeat.custom_mode = 0; + heartbeat.system_status = 0; // MAV_STATE_UNINIT + + // 编码为MAVLinkPacket + MAVLinkPacket packet = heartbeat.pack(); + + // 发送数据(根据连接方式选择) + if (connectionType == 0) { + // 串口发送 + if (serialHelper != null) { + serialHelper.send(packet.encodePacket()); + } + } else { + // UDP发送 + try { + if (serverSocket != null && !serverSocket.isClosed()) { + InetAddress targetAddress = InetAddress.getByName("127.0.0.1"); + int targetPort = 14553; // 默认MAVLink端口 + DatagramPacket udpPacket = new DatagramPacket( + packet.encodePacket(), + packet.encodePacket().length, + targetAddress, + targetPort + ); + serverSocket.send(udpPacket); + } + } catch (Exception e) { + Log.e(TAG, "发送心跳包失败: " + e.getMessage()); + } + } + } catch (Exception e) { + Log.e(TAG, "构建心跳包失败: " + e.getMessage()); + } + } + + /** + * 方法:设置连接类型 + */ + public void setConnectionType(int type) { + this.connectionType = type; + } + + /** + * 方法:设置串口助手 + */ + public void setSerialHelper(SerialHelper serialHelper) { + this.serialHelper = serialHelper; + } + + /** + * 方法:设置UDP套接字 + */ + public void setServerSocket(java.net.DatagramSocket serverSocket) { + this.serverSocket = serverSocket; + } + + /** + * 方法:检查心跳是否正在运行 + */ + public boolean isRunning() { + return isHeartbeatRunning; + } +} diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Void/LidarDataParser.java b/app/src/main/java/com/example/longyi_groundstation/Main/Void/LidarDataParser.java new file mode 100644 index 0000000..7c44f09 --- /dev/null +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Void/LidarDataParser.java @@ -0,0 +1,212 @@ +package com.example.longyi_groundstation.Main.Void; + +import android.os.Handler; +import android.os.Looper; +import android.util.Log; +import android.widget.TextView; + +/** + * 雷达高度数据解析器 + * 用于解析以0xFF开头的数据包格式:FF + 高度高字节 + 高度低字节 + 引爆高度 + 校验字节 + * 支持高频率调用(200Hz以上)和传感器失效监测 + */ +public class LidarDataParser { + + // 解析状态定义 + public static final int PARSE_STATE_HEAD = 0; // 等待包头 + public static final int PARSE_STATE_PAYLOAD = 1; // 接收数据载荷 + public static final int PARSE_STATE_CHECKSUM = 2; // 校验和检查 + + // 协议定义 + public static final byte PROTOCOL_HEAD = (byte) 0xFF; + public static final int PROTOCOL_LENGTH = 5; // 总长度:FF + 2字节高度 + 1字节引爆高度 + 1字节校验 + + // 监测相关常量 + public static final int SENSOR_FAILURE_THRESHOLD = 5; // 失效阈值 + public static final int UPDATE_INTERVAL = 1000; // 更新间隔(毫秒) + + // 解析状态变量 + public int parseStep = PARSE_STATE_HEAD; // 当前解析步骤 + public int packetIndex = 0; // 数据包索引 + public byte[] packetBuffer = new byte[5]; // 数据包缓冲区 + + // 监测相关变量 + public int invalidCount = 0; // 无效计数 + public boolean isSensorFailed = false; // 传感器是否失效 + public static int[] parsedData = null; // 解析后的数据 [雷达高度, 引爆高度] + + // UI更新相关 + public static Handler uiHandler; + public static Runnable updateRunnable; + public static boolean isUpdating = false; + + /** + * 解析单个字节数据(高频率调用版本) + * 建议在200Hz以上频率调用 + * + * @param data 单个接收到的字节 + * @return 1表示解析成功并更新了数据,0表示未完成解析 + */ + public int parseByte(byte data) { + int result = 0; + + switch (parseStep) { + // 等待包头 + case PARSE_STATE_HEAD: + if (data == PROTOCOL_HEAD) { + packetBuffer[packetIndex++] = data; + parseStep = PARSE_STATE_PAYLOAD; + } + break; + + // 接收数据载荷 + case PARSE_STATE_PAYLOAD: + packetBuffer[packetIndex++] = data; + + // 检查是否收到完整数据包 + if (packetIndex >= PROTOCOL_LENGTH) { + parseStep = PARSE_STATE_CHECKSUM; + } + break; + + // 校验和检查 + case PARSE_STATE_CHECKSUM: + int calculatedChecksum = 0; + // 计算前4个字节的校验和(累加求和方式) + for (int i = 0; i < 4; i++) { + calculatedChecksum += (packetBuffer[i] & 0xFF); + } + calculatedChecksum &= 0xFF; // 取低8位作为校验和 + + // 校验 + if (calculatedChecksum == (packetBuffer[4] & 0xFF)) { + // 解析成功,更新数据 + int radarHeight = ((packetBuffer[1] & 0xFF) << 8) | (packetBuffer[2] & 0xFF); + int triggerHeight = packetBuffer[3] & 0xFF; +// Log.d("LidarDataParser", radarHeight + "m"); + // 保存解析结果 + parsedData = new int[]{radarHeight, triggerHeight}; + + // 重置监测计数 + invalidCount = 0; + isSensorFailed = false; + + result = 1; + } else { + // 校验失败,增加错误计数 + invalidCount++; + checkSensorFailure(); + } + + // 重置状态,准备接收下一数据包 + packetIndex = 0; + parseStep = PARSE_STATE_HEAD; + break; + } + + return result; + } + + /** + * 监测传感器状态 + * 建议以10Hz频率定期调用 + */ + private void checkSensorFailure() { + if (invalidCount > SENSOR_FAILURE_THRESHOLD) { + isSensorFailed = true; + } + } + + /** + * 获取传感器失效状态 + * + * @return true表示传感器失效,false表示正常 + */ + public boolean isSensorFailed() { + return isSensorFailed; + } + + /** + * 获取解析后的数据 + * + * @return int数组,[0]为雷达高度,[1]为引爆高度,如果无有效数据则返回null + */ + public static int[] getParsedData() { + return parsedData; + } + + /** + * 启动高度显示更新线程 + * 每隔1秒更新TextView显示雷达高度数据 + * + * @param textView 要更新的TextView + */ + public static void startHeightUpdate(TextView textView) { + if (isUpdating) { + stopHeightUpdate(); + } + + isUpdating = true; + uiHandler = new Handler(Looper.getMainLooper()); + updateRunnable = new Runnable() { + @Override + public void run() { + if (isUpdating) { + int[] data = getParsedData(); + if (data != null && textView != null) { +// Log.d("startHeightUpdate", "激光:"+data[0]+"m"+" 引爆:"+data[1]+"m"); + textView.setText(data[0] + "m"); + } else if (textView != null) { + textView.setText("--"); + } + + // 每隔1秒更新一次 + uiHandler.postDelayed(this, UPDATE_INTERVAL); + } + } + }; + + // 立即开始更新 + uiHandler.post(updateRunnable); + } + + /** + * 停止高度显示更新 + */ + public static void stopHeightUpdate() { + isUpdating = false; + if (uiHandler != null && updateRunnable != null) { + uiHandler.removeCallbacks(updateRunnable); + uiHandler = null; + updateRunnable = null; + } + } + + /** + * 检查是否正在更新UI + * + * @return true表示正在更新,false表示未更新 + */ + public boolean isUpdating() { + return isUpdating; + } + + /** + * 重置传感器状态和解析器状态 + */ + public void reset() { + invalidCount = 0; + isSensorFailed = false; + packetIndex = 0; + parseStep = PARSE_STATE_HEAD; + parsedData = null; + } + + /** + * 增加无效计数(用于外部监测调用) + */ + public void incrementInvalidCount() { + invalidCount++; + checkSensorFailure(); + } +} diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Void/LogCat/LogUtil.java b/app/src/main/java/com/example/longyi_groundstation/Main/Void/LogCat/LogUtil.java index a9efc8d..067514c 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Void/LogCat/LogUtil.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Void/LogCat/LogUtil.java @@ -6,10 +6,10 @@ import android.util.Log; public class LogUtil { public static void d(String tag, String msg) { // 正常打印日志 -// Log.d(tag, msg); + Log.d(tag, msg); // 保存日志到文件 - LogManager.getInstance().saveLog(tag, msg); +// LogManager.getInstance().saveLog(tag, msg); } // 可以添加其他级别的日志方法 (e, w, i等) diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Void/MapVoid.java b/app/src/main/java/com/example/longyi_groundstation/Main/Void/MapVoid.java index 50152d4..d1a237e 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Void/MapVoid.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Void/MapVoid.java @@ -163,7 +163,7 @@ public class MapVoid { } } catch (Exception e) { // e.printStackTrace(); - Log.d(TAG, "error: "+e); + Log.d("cui_error", "error: "+e); // 2秒后再次执行 flightTrackHandler.postDelayed(this, 600); } @@ -194,17 +194,17 @@ public class MapVoid { flightTrackPolyline.remove(); } - // 控制轨迹点数量不超过20个 - if (flightTrackPoints.size() > 2048) { - flightTrackPoints.remove(0); // 删除最后一个点 - } - List sparsePoints = new ArrayList<>(); // 每5个点取1个点,减少点密度 - for (int i = 0; i < flightTrackPoints.size(); i += 5) { + for (int i = 0; i < flightTrackPoints.size(); i++) { sparsePoints.add(flightTrackPoints.get(i)); } + // 控制轨迹点数量不超过20个 + if (flightTrackPoints.size() > 300) { + flightTrackPoints.remove(0); // 删除最后一个点 + } + flightTrackPolyline = allView.map.getMap().addPolyline(new PolylineOptions() .addAll(sparsePoints) .width(12) @@ -230,6 +230,33 @@ public class MapVoid { flightTrackPoints.clear(); } + /** + * 计算两个带高度的坐标点之间的直线距离(单位:厘米,返回整数) + * @param latLng1 第一个坐标点(包含纬度、经度) + * @param altitude1 第一个点的高度(米) + * @param latLng2 第二个坐标点(包含纬度、经度) + * @param altitude2 第二个点的高度(米) + * @return 距离(厘米,整数) + */ + public static int calculateDistanceWithAltitudeInCm(LatLng latLng1, double altitude1, + LatLng latLng2, double altitude2) { + if (latLng1 == null || latLng2 == null) { + return 0; + } + + // 计算水平距离(米) + double horizontalDistance = AMapUtils.calculateLineDistance(latLng1, latLng2); + + // 计算高度差(米) + double altitudeDifference = Math.abs(altitude2 - altitude1); + + // 使用三维勾股定理计算直线距离(米) + double straightDistance = Math.sqrt(horizontalDistance * horizontalDistance + + altitudeDifference * altitudeDifference); + + // 转换为厘米并返回整数 + return (int) Math.round(straightDistance * 100); + } diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Void/SQLClass.java b/app/src/main/java/com/example/longyi_groundstation/Main/Void/SQLClass.java index fbee95f..769728b 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Void/SQLClass.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Void/SQLClass.java @@ -47,7 +47,7 @@ public class SQLClass extends SQLiteOpenHelper { // 数据库名称和版本 private static final String DATABASE_NAME = "create_link_list.db"; - private static final int DATABASE_VERSION = 1; + private static final int DATABASE_VERSION = 4; // 更新版本号以支持stop_time字段 // 主表 - 存储列表信息 private static final String TABLE_LINK_LIST = "link_list"; @@ -65,9 +65,15 @@ public class SQLClass extends SQLiteOpenHelper { private static final String COLUMN_WAYPOINT_INDEX = "waypoint_index"; private static final String COLUMN_LATITUDE = "latitude"; private static final String COLUMN_LONGITUDE = "longitude"; - private static final String COLUMN_BOM1_SELECT = "bom1_select"; - private static final String COLUMN_BOM2_SELECT = "bom2_select"; + // CreateLink类中的字段 + private static final String COLUMN_BOM1_SELECT = "bom1_select"; + private static final String COLUMN_BOM1_SHOW = "bom1_show"; + private static final String COLUMN_BOM1_HEIGHT = "bom1_height"; + private static final String COLUMN_BOM2_SELECT = "bom2_select"; + private static final String COLUMN_BOM2_SHOW = "bom2_show"; + private static final String COLUMN_BOM2_HEIGHT = "bom2_height"; + private static final String COLUMN_STOP_TIME = "stop_time"; // 新增字段 private static final String COLUMN_ITEM_ORDER = "item_order"; // 项在列表中的顺序 @@ -78,7 +84,7 @@ public class SQLClass extends SQLiteOpenHelper { COLUMN_LIST_NAME + " TEXT NOT NULL, " + COLUMN_CREATED_TIME + " INTEGER NOT NULL)"; - // 创建详情表的SQL语句 + // 创建详情表的SQL语句(包含所有字段) private static final String CREATE_ITEMS_TABLE_SQL = "CREATE TABLE " + TABLE_LINK_ITEMS + " (" + COLUMN_ITEM_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + @@ -89,6 +95,13 @@ public class SQLClass extends SQLiteOpenHelper { COLUMN_WAYPOINT_INDEX + " INTEGER NOT NULL, " + COLUMN_LATITUDE + " REAL, " + COLUMN_LONGITUDE + " REAL, " + + COLUMN_BOM1_SELECT + " INTEGER DEFAULT 0, " + + COLUMN_BOM1_SHOW + " INTEGER DEFAULT 0, " + + COLUMN_BOM1_HEIGHT + " INTEGER DEFAULT 0, " + + COLUMN_BOM2_SELECT + " INTEGER DEFAULT 0, " + + COLUMN_BOM2_SHOW + " INTEGER DEFAULT 0, " + + COLUMN_BOM2_HEIGHT + " INTEGER DEFAULT 0, " + + COLUMN_STOP_TIME + " INTEGER DEFAULT 0, " + // 新增字段 COLUMN_ITEM_ORDER + " INTEGER NOT NULL, " + "FOREIGN KEY(" + COLUMN_LIST_REF_ID + ") REFERENCES " + TABLE_LINK_LIST + "(" + COLUMN_LIST_ID + ") ON DELETE CASCADE)"; @@ -105,9 +118,31 @@ public class SQLClass extends SQLiteOpenHelper { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - db.execSQL("DROP TABLE IF EXISTS " + TABLE_LINK_ITEMS); - db.execSQL("DROP TABLE IF EXISTS " + TABLE_LINK_LIST); - onCreate(db); + if (oldVersion < 2) { + // 添加第2版新增的列 + db.execSQL("ALTER TABLE " + TABLE_LINK_ITEMS + " ADD COLUMN " + COLUMN_BOM1_SELECT + " INTEGER DEFAULT 0"); + db.execSQL("ALTER TABLE " + TABLE_LINK_ITEMS + " ADD COLUMN " + COLUMN_BOM2_SELECT + " INTEGER DEFAULT 0"); + } + + if (oldVersion < 3) { + // 添加第3版新增的列 + db.execSQL("ALTER TABLE " + TABLE_LINK_ITEMS + " ADD COLUMN " + COLUMN_BOM1_SHOW + " INTEGER DEFAULT 0"); + db.execSQL("ALTER TABLE " + TABLE_LINK_ITEMS + " ADD COLUMN " + COLUMN_BOM1_HEIGHT + " INTEGER DEFAULT 0"); + db.execSQL("ALTER TABLE " + TABLE_LINK_ITEMS + " ADD COLUMN " + COLUMN_BOM2_SHOW + " INTEGER DEFAULT 0"); + db.execSQL("ALTER TABLE " + TABLE_LINK_ITEMS + " ADD COLUMN " + COLUMN_BOM2_HEIGHT + " INTEGER DEFAULT 0"); + } + + if (oldVersion < 4) { + // 添加第4版新增的列(stop_time字段) + db.execSQL("ALTER TABLE " + TABLE_LINK_ITEMS + " ADD COLUMN " + COLUMN_STOP_TIME + " INTEGER DEFAULT 0"); + } + + if (oldVersion < 1 || oldVersion >= 4) { + // 原有的升级逻辑(版本1或更高版本时) + db.execSQL("DROP TABLE IF EXISTS " + TABLE_LINK_ITEMS); + db.execSQL("DROP TABLE IF EXISTS " + TABLE_LINK_LIST); + onCreate(db); + } } @Override @@ -155,6 +190,16 @@ public class SQLClass extends SQLiteOpenHelper { itemValues.put(COLUMN_SPEED, createLink.getSpeed()); itemValues.put(COLUMN_WAYPOINT_INDEX, createLink.getWaypointIndex()); + // 添加所有字段的处理 + itemValues.put(COLUMN_BOM1_SELECT, createLink.isBom1_select() ? 1 : 0); + itemValues.put(COLUMN_BOM1_SHOW, createLink.isBom1_show() ? 1 : 0); + itemValues.put(COLUMN_BOM1_HEIGHT, createLink.getBom1_height()); + itemValues.put(COLUMN_BOM2_SELECT, createLink.isBom2_select() ? 1 : 0); + itemValues.put(COLUMN_BOM2_SHOW, createLink.isBom2_show() ? 1 : 0); + itemValues.put(COLUMN_BOM2_HEIGHT, createLink.getBom2_height()); + // 新增字段处理 + itemValues.put(COLUMN_STOP_TIME, createLink.getStop_time()); + if (createLink.getLatLng() != null) { itemValues.put(COLUMN_LATITUDE, createLink.getLatLng().latitude); itemValues.put(COLUMN_LONGITUDE, createLink.getLatLng().longitude); @@ -239,11 +284,28 @@ public class SQLClass extends SQLiteOpenHelper { int waypointIndex = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_WAYPOINT_INDEX)); double latitude = cursor.getDouble(cursor.getColumnIndexOrThrow(COLUMN_LATITUDE)); double longitude = cursor.getDouble(cursor.getColumnIndexOrThrow(COLUMN_LONGITUDE)); -// boolean bom1_select = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_BOM1_SELECT)) == 1; -// boolean bom2_select = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_BOM2_SELECT)) == 1; + + // 获取字段的值 + boolean bom1_select = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_BOM1_SELECT)) == 1; + boolean bom1_show = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_BOM1_SHOW)) == 1; + int bom1_height = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_BOM1_HEIGHT)); + boolean bom2_select = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_BOM2_SELECT)) == 1; + boolean bom2_show = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_BOM2_SHOW)) == 1; + int bom2_height = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_BOM2_HEIGHT)); + // 新增字段读取 + int stop_time = cursor.getInt(cursor.getColumnIndexOrThrow(COLUMN_STOP_TIME)); LatLng latLng = new LatLng(latitude, longitude); - CreateLink createLink = new CreateLink(name, height, speed, waypointIndex, latLng); + CreateLink createLink = new CreateLink(name, height, speed, waypointIndex, latLng,stop_time, bom1_show, bom2_show); + // 设置其他字段 + createLink.setBom1_select(bom1_select); + createLink.setBom1_height(bom1_height); + createLink.setBom2_select(bom2_select); + createLink.setBom2_height(bom2_height); + createLink.setBom2_show(bom2_show); + // 设置新增字段 + createLink.setStop_time(stop_time); + createLinkList.add(createLink); } while (cursor.moveToNext()); } @@ -299,6 +361,16 @@ public class SQLClass extends SQLiteOpenHelper { itemValues.put(COLUMN_SPEED, createLink.getSpeed()); itemValues.put(COLUMN_WAYPOINT_INDEX, createLink.getWaypointIndex()); + // 添加所有字段的处理 + itemValues.put(COLUMN_BOM1_SELECT, createLink.isBom1_select() ? 1 : 0); + itemValues.put(COLUMN_BOM1_SHOW, createLink.isBom1_show() ? 1 : 0); + itemValues.put(COLUMN_BOM1_HEIGHT, createLink.getBom1_height()); + itemValues.put(COLUMN_BOM2_SELECT, createLink.isBom2_select() ? 1 : 0); + itemValues.put(COLUMN_BOM2_SHOW, createLink.isBom2_show() ? 1 : 0); + itemValues.put(COLUMN_BOM2_HEIGHT, createLink.getBom2_height()); + // 新增字段处理 + itemValues.put(COLUMN_STOP_TIME, createLink.getStop_time()); + if (createLink.getLatLng() != null) { itemValues.put(COLUMN_LATITUDE, createLink.getLatLng().latitude); itemValues.put(COLUMN_LONGITUDE, createLink.getLatLng().longitude); diff --git a/app/src/main/java/com/example/longyi_groundstation/Main/Void/SerialTool.java b/app/src/main/java/com/example/longyi_groundstation/Main/Void/SerialTool.java index e2ad7ee..e8fea2f 100644 --- a/app/src/main/java/com/example/longyi_groundstation/Main/Void/SerialTool.java +++ b/app/src/main/java/com/example/longyi_groundstation/Main/Void/SerialTool.java @@ -80,12 +80,12 @@ public class SerialTool { * @return 包含解析结果的数组,[0]为第2、3字节组合的值,[1]为第4字节的值;校验失败返回null */ public static int[] parseSerialData(byte[] data) { - if (data == null || data.length < 4) { + if (data == null || data.length < 5) { throw new IllegalArgumentException("数据长度不足,无法解析"); } // 校验:第4个字节应该等于前三个字节之和的低8位 - int checksum = (data[0] & 0xFF) + (data[1] & 0xFF) + (data[2] & 0xFF); + int checksum = (data[1] & 0xFF) + (data[2] & 0xFF) + (data[3] & 0xFF); checksum = checksum & 0xFF; // 取低8位 // 如果校验失败,返回null diff --git a/app/src/main/java/com/example/longyi_groundstation/Util/Http/HttpUrl.java b/app/src/main/java/com/example/longyi_groundstation/Util/Http/HttpUrl.java new file mode 100644 index 0000000..5cad2a8 --- /dev/null +++ b/app/src/main/java/com/example/longyi_groundstation/Util/Http/HttpUrl.java @@ -0,0 +1,8 @@ +package com.example.longyi_groundstation.Util.Http; + +public class HttpUrl { + + public static final String BASE_URL = "https://api.longyi-uav-cloud.com"; + public static final String LOGIN = BASE_URL + "/admin-api/system/auth/login"; + +} diff --git a/app/src/main/java/com/example/longyi_groundstation/Util/Http/HttpUtil.java b/app/src/main/java/com/example/longyi_groundstation/Util/Http/HttpUtil.java new file mode 100644 index 0000000..060f2be --- /dev/null +++ b/app/src/main/java/com/example/longyi_groundstation/Util/Http/HttpUtil.java @@ -0,0 +1,130 @@ +package com.example.longyi_groundstation.Util.Http; + +import java.io.IOException; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import okhttp3.Callback; +import okhttp3.MediaType; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +/** + * 基于OkHttp3的网络请求工具类 + */ +public class HttpUtil { + private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8"); + private static final MediaType MEDIA_TYPE_FORM = MediaType.parse("application/x-www-form-urlencoded"); + + private OkHttpClient client; + + public HttpUtil() { + this.client = new OkHttpClient.Builder() + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .writeTimeout(30, TimeUnit.SECONDS) + .retryOnConnectionFailure(true) + .build(); + } + + /** + * GET请求 + * @param url 请求地址 + * @param headers 请求头 + * @param callback 回调函数 + */ + public void get(String url, Map headers, Callback callback) { + Request.Builder builder = new Request.Builder().url(url); + + // 添加请求头 + addHeaders(builder, headers); + + Request request = builder.get().build(); + client.newCall(request).enqueue(callback); + } + + /** + * POST请求 - JSON格式 + * @param url 请求地址 + * @param json JSON数据 + * @param headers 请求头 + * @param callback 回调函数 + */ + public void postJson(String url, String json, Map headers, Callback callback) { + RequestBody body = RequestBody.create(json, MEDIA_TYPE_JSON); + Request.Builder builder = new Request.Builder() + .url(url) + .post(body); + + addHeaders(builder, headers); + + Request request = builder.build(); + client.newCall(request).enqueue(callback); + } + + /** + * POST请求 - 表单格式 + * @param url 请求地址 + * @param formData 表单数据 + * @param headers 请求头 + * @param callback 回调函数 + */ + public void postForm(String url, String formData, Map headers, Callback callback) { + RequestBody body = RequestBody.create(formData, MEDIA_TYPE_FORM); + Request.Builder builder = new Request.Builder() + .url(url) + .post(body); + + addHeaders(builder, headers); + + Request request = builder.build(); + client.newCall(request).enqueue(callback); + } + + /** + * 同步GET请求 + * @param url 请求地址 + * @param headers 请求头 + * @return Response响应对象 + * @throws IOException IO异常 + */ + public Response executeGet(String url, Map headers) throws IOException { + Request.Builder builder = new Request.Builder().url(url); + addHeaders(builder, headers); + + Request request = builder.get().build(); + return client.newCall(request).execute(); + } + + /** + * 同步POST请求 - JSON格式 + * @param url 请求地址 + * @param json JSON数据 + * @param headers 请求头 + * @return Response响应对象 + * @throws IOException IO异常 + */ + public Response executePostJson(String url, String json, Map headers) throws IOException { + RequestBody body = RequestBody.create(json, MEDIA_TYPE_JSON); + Request.Builder builder = new Request.Builder().url(url).post(body); + addHeaders(builder, headers); + + Request request = builder.build(); + return client.newCall(request).execute(); + } + + /** + * 添加请求头 + * @param builder Request.Builder构建器 + * @param headers 请求头Map + */ + private void addHeaders(Request.Builder builder, Map headers) { + if (headers != null) { + for (Map.Entry entry : headers.entrySet()) { + builder.addHeader(entry.getKey(), entry.getValue()); + } + } + } +} diff --git a/app/src/main/java/com/example/longyi_groundstation/Util/SharedPreferencesTool.java b/app/src/main/java/com/example/longyi_groundstation/Util/SharedPreferencesTool.java new file mode 100644 index 0000000..b0275fb --- /dev/null +++ b/app/src/main/java/com/example/longyi_groundstation/Util/SharedPreferencesTool.java @@ -0,0 +1,65 @@ +package com.example.longyi_groundstation.Util; + +import static android.content.Context.MODE_PRIVATE; + +import android.content.Context; +import android.util.Log; + +import org.json.JSONObject; + +public class SharedPreferencesTool { + + private static String TAG = "SharedPreferencesTool"; + + public static void saveLogin(Context context, JSONObject userData) { + try { + // 使用 SharedPreferences 保存用户信息 + android.content.SharedPreferences sharedPreferences = + context.getSharedPreferences("user_info", MODE_PRIVATE); + android.content.SharedPreferences.Editor editor = sharedPreferences.edit(); + + editor.putInt("id", userData.getInt("id")); + editor.putString("avatar", userData.getString("avatar")); + editor.putString("nickname", userData.getString("nickname")); + editor.putString("mobile", userData.getString("mobile")); + editor.putLong("create_time", userData.getLong("create_time")); + editor.putLong("update_time", userData.getLong("update_time")); + editor.putInt("is_active", userData.getInt("is_active")); + editor.putInt("sort", userData.getInt("sort")); + editor.putString("token", userData.getString("token")); + editor.apply(); // 异步保存 + }catch (Exception e){ + Log.d(TAG, "saveLogin:error " + e); + } + + } + + public static String getToken(Context context){ + android.content.SharedPreferences sharedPreferences = + context.getSharedPreferences("user_info", MODE_PRIVATE); + String token = sharedPreferences.getString("token", null); + return token; + } + + public static JSONObject getUserInfo(Context context){ + + android.content.SharedPreferences sharedPreferences = + context.getSharedPreferences("user_info", MODE_PRIVATE); + JSONObject userInfo = new JSONObject(); + try { + userInfo.put("id", sharedPreferences.getInt("id", 0)); + userInfo.put("avatar", sharedPreferences.getString("avatar", "")); + userInfo.put("nickname", sharedPreferences.getString("nickname", "")); + userInfo.put("mobile", sharedPreferences.getString("mobile", "")); + userInfo.put("create_time", sharedPreferences.getLong("create_time", 0)); + userInfo.put("update_time", sharedPreferences.getLong( "update_time", 0)); + userInfo.put("is_active", sharedPreferences.getInt("is_active", 0)); + userInfo.put("sort", sharedPreferences.getInt("sort", 0)); + userInfo.put("token", sharedPreferences.getString("token", "")); + return userInfo; + }catch (Exception e){ + return null; + } + } + +} diff --git a/app/src/main/java/com/example/longyi_groundstation/Util/Url.java b/app/src/main/java/com/example/longyi_groundstation/Util/Url.java deleted file mode 100644 index 7c49cb6..0000000 --- a/app/src/main/java/com/example/longyi_groundstation/Util/Url.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.example.longyi_groundstation.Util; - -public class Url { - - public static String getBaseUrl() { - return "https://api.longyi-uav-cloud.com"; - } - - /** - * 方法:登录接口 - * - * @cuijingzhou - */ - public static String LoginUrl() { - return getBaseUrl() + "/admin-api/system/auth/login"; - } - -} diff --git a/app/src/main/res/drawable/b2101010_4round_1stroke_bg.xml b/app/src/main/res/drawable/b2101010_4round_1stroke_bg.xml index 3b839f5..ca8c203 100644 --- a/app/src/main/res/drawable/b2101010_4round_1stroke_bg.xml +++ b/app/src/main/res/drawable/b2101010_4round_1stroke_bg.xml @@ -5,7 +5,7 @@ + android:color="#3A3A3A"/> diff --git a/app/src/main/res/drawable/b2303030_4round_1stroke_bg.xml b/app/src/main/res/drawable/b2303030_4round_1stroke_bg.xml index 2fa423e..7a0376e 100644 --- a/app/src/main/res/drawable/b2303030_4round_1stroke_bg.xml +++ b/app/src/main/res/drawable/b2303030_4round_1stroke_bg.xml @@ -7,6 +7,6 @@ android:width="0.5dp" android:color="#303030"/> - + \ No newline at end of file diff --git a/app/src/main/res/drawable/x94555f75_16round_bg.xml b/app/src/main/res/drawable/cc3d4453_16round_bg.xml similarity index 79% rename from app/src/main/res/drawable/x94555f75_16round_bg.xml rename to app/src/main/res/drawable/cc3d4453_16round_bg.xml index c8c6a6e..5812a49 100644 --- a/app/src/main/res/drawable/x94555f75_16round_bg.xml +++ b/app/src/main/res/drawable/cc3d4453_16round_bg.xml @@ -3,7 +3,7 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/x94555f75_4round_bg.xml b/app/src/main/res/drawable/cc3d4453_4round_bg.xml similarity index 79% rename from app/src/main/res/drawable/x94555f75_4round_bg.xml rename to app/src/main/res/drawable/cc3d4453_4round_bg.xml index 0871e3e..dde9832 100644 --- a/app/src/main/res/drawable/x94555f75_4round_bg.xml +++ b/app/src/main/res/drawable/cc3d4453_4round_bg.xml @@ -3,7 +3,7 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/ff8decec_2round_bg.xml b/app/src/main/res/drawable/ff029b45_2round_bg.xml similarity index 80% rename from app/src/main/res/drawable/ff8decec_2round_bg.xml rename to app/src/main/res/drawable/ff029b45_2round_bg.xml index b971a11..dc2016a 100644 --- a/app/src/main/res/drawable/ff8decec_2round_bg.xml +++ b/app/src/main/res/drawable/ff029b45_2round_bg.xml @@ -3,6 +3,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/ff101010_2round_1stroke_bg.xml b/app/src/main/res/drawable/ff101010_2round_1stroke_bg.xml new file mode 100644 index 0000000..6be7704 --- /dev/null +++ b/app/src/main/res/drawable/ff101010_2round_1stroke_bg.xml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ff112446_4round_bg.xml b/app/src/main/res/drawable/ff112446_4round_bg.xml index a5988f8..39d5779 100644 --- a/app/src/main/res/drawable/ff112446_4round_bg.xml +++ b/app/src/main/res/drawable/ff112446_4round_bg.xml @@ -3,6 +3,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/ff33b138_1round_1stroke.xml b/app/src/main/res/drawable/ff33b138_1round_1stroke.xml index d60c5c0..01fdcdd 100644 --- a/app/src/main/res/drawable/ff33b138_1round_1stroke.xml +++ b/app/src/main/res/drawable/ff33b138_1round_1stroke.xml @@ -2,6 +2,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/ff909090_2round_1stroke_bg.xml b/app/src/main/res/drawable/ff909090_2round_1stroke_bg.xml new file mode 100644 index 0000000..e474389 --- /dev/null +++ b/app/src/main/res/drawable/ff909090_2round_1stroke_bg.xml @@ -0,0 +1,12 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/x94555f75_8round_bg.xml b/app/src/main/res/drawable/x94555f75_8round_bg.xml index 4976d1c..cafc7c7 100644 --- a/app/src/main/res/drawable/x94555f75_8round_bg.xml +++ b/app/src/main/res/drawable/x94555f75_8round_bg.xml @@ -3,7 +3,7 @@ - + diff --git a/app/src/main/res/drawable/xbb303030_4round_bg.xml b/app/src/main/res/drawable/xbb303030_4round_bg.xml index 57dc37a..dff2df1 100644 --- a/app/src/main/res/drawable/xbb303030_4round_bg.xml +++ b/app/src/main/res/drawable/xbb303030_4round_bg.xml @@ -3,6 +3,6 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/xff555f75_4round_bg.xml b/app/src/main/res/drawable/xff555f75_4round_bg.xml new file mode 100644 index 0000000..3b7c1f9 --- /dev/null +++ b/app/src/main/res/drawable/xff555f75_4round_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_funcation.xml b/app/src/main/res/layout/activity_funcation.xml index f0f9d2b..b692e17 100644 --- a/app/src/main/res/layout/activity_funcation.xml +++ b/app/src/main/res/layout/activity_funcation.xml @@ -153,7 +153,7 @@ android:layout_marginTop="10dp" android:layout_width="180dp" android:layout_height="40dp" - android:background="@drawable/x94555f75_4round_bg" + android:background="@drawable/cc3d4453_4round_bg" android:gravity="center" android:orientation="horizontal"> diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 6461afe..ff5b756 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -14,7 +14,7 @@ android:layout_height="wrap_content" android:orientation="vertical" android:padding="20dp" - android:background="@drawable/x94555f75_16round_bg" + android:background="@drawable/cc3d4453_16round_bg" android:elevation="4dp"> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 58ad39b..2ed4ce5 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -311,8 +311,8 @@ @@ -446,7 +446,7 @@ android:background="@drawable/b2ffffff_4round_1stroke_bg" android:gravity="center" android:padding="5dp" - android:visibility="gone"> + android:visibility="visible"> - - - + android:visibility="gone"> @@ -1510,14 +1507,17 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1631,7 +1763,6 @@ - + + diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml index 381fc84..662517f 100644 --- a/app/src/main/res/layout/activity_setting.xml +++ b/app/src/main/res/layout/activity_setting.xml @@ -55,7 +55,7 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/adapter_create_link_item.xml b/app/src/main/res/layout/adapter_create_link_item.xml index e16d525..d1b020a 100644 --- a/app/src/main/res/layout/adapter_create_link_item.xml +++ b/app/src/main/res/layout/adapter_create_link_item.xml @@ -2,6 +2,7 @@ + + + - - - - - - - - - - - - - - - - - - - - - + + diff --git a/app/src/main/res/layout/adapter_motor_data_item.xml b/app/src/main/res/layout/adapter_motor_data_item.xml index d7215e3..d983154 100644 --- a/app/src/main/res/layout/adapter_motor_data_item.xml +++ b/app/src/main/res/layout/adapter_motor_data_item.xml @@ -4,9 +4,10 @@ android:layout_height="wrap_content"> @@ -15,7 +15,7 @@ android:id="@+id/param_name" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:textSize="14sp" /> + android:textSize="11sp" /> diff --git a/app/src/main/res/layout/adapter_param_item.xml b/app/src/main/res/layout/adapter_param_item.xml index 1be3b25..e7e3231 100644 --- a/app/src/main/res/layout/adapter_param_item.xml +++ b/app/src/main/res/layout/adapter_param_item.xml @@ -4,7 +4,7 @@ android:layout_height="wrap_content" android:layout_margin="2dp" android:id="@+id/ll_main" - android:background="@drawable/ff8decec_2round_bg" + android:background="@drawable/ff029b45_2round_bg" android:orientation="horizontal" android:layout_centerInParent="true" android:padding="8dp"> @@ -16,7 +16,7 @@ android:layout_weight="1" android:layout_width="0dp" android:layout_height="wrap_content" - android:textSize="14sp" /> + android:textSize="11sp" /> + android:textSize="11sp" /> diff --git a/app/src/main/res/layout/adapter_secure_item.xml b/app/src/main/res/layout/adapter_secure_item.xml index 11d6fd5..4fb8856 100644 --- a/app/src/main/res/layout/adapter_secure_item.xml +++ b/app/src/main/res/layout/adapter_secure_item.xml @@ -33,7 +33,7 @@ android:layout_height="22dp" android:layout_marginLeft="5dp" android:layout_weight="1" - android:background="@drawable/ff029a45_2round_1stroke_bg" + android:background="@drawable/ff029a45_4round_1stroke_bg" android:orientation="vertical"> diff --git a/app/src/main/res/layout/dialog_point_fly.xml b/app/src/main/res/layout/dialog_point_fly.xml index dc50d07..f6e5279 100644 --- a/app/src/main/res/layout/dialog_point_fly.xml +++ b/app/src/main/res/layout/dialog_point_fly.xml @@ -92,6 +92,7 @@ android:layout_height="wrap_content"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> - + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_load.xml b/app/src/main/res/layout/fragment_load.xml index b6473cf..e3e7fad 100644 --- a/app/src/main/res/layout/fragment_load.xml +++ b/app/src/main/res/layout/fragment_load.xml @@ -134,7 +134,7 @@ android:layout_height="22dp" android:layout_marginLeft="5dp" android:layout_weight="1" - android:background="@drawable/ff029a45_2round_1stroke_bg" + android:background="@drawable/ff029a45_4round_1stroke_bg" android:orientation="vertical"> @@ -29,7 +28,7 @@ @@ -46,6 +45,8 @@ + android:layout_marginBottom="8dp"> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> @@ -95,13 +96,13 @@ android:text="+" android:textColor="#ffffff" android:textSize="10sp" - android:background="@drawable/ff029a45_2round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:layout_marginBottom="7dp"> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:progress="5" /> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> diff --git a/app/src/main/res/layout/fragment_payload.xml b/app/src/main/res/layout/fragment_payload.xml index afc73b8..f0e276b 100644 --- a/app/src/main/res/layout/fragment_payload.xml +++ b/app/src/main/res/layout/fragment_payload.xml @@ -15,7 +15,7 @@ diff --git a/app/src/main/res/layout/fragment_secure.xml b/app/src/main/res/layout/fragment_secure.xml index f0c6951..0aafdfb 100644 --- a/app/src/main/res/layout/fragment_secure.xml +++ b/app/src/main/res/layout/fragment_secure.xml @@ -76,7 +76,7 @@ android:text="-" android:textColor="#ffffff" android:textSize="10sp" - android:background="@drawable/ff029a45_2round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:background="@drawable/ff029a45_4round_1stroke_bg"/> + android:textColor="#ffffff" + android:textSize="12sp" /> + android:textColor="#ffffff" + android:textSize="12sp" /> + android:textColor="#ffffff" + android:textSize="12sp" /> + android:textColor="#ffffff" + android:textSize="12sp" /> + android:textColor="#ffffff" + android:textSize="12sp" /> + android:textColor="#ffffff" + android:textSize="12sp" /> + android:textColor="#ffffff" + android:textSize="12sp" /> + android:textColor="#ffffff" + android:textSize="12sp" /> @@ -65,29 +65,30 @@ + android:layout_height="32dp"> @@ -96,48 +97,84 @@ android:id="@+id/tv_updata_param" android:layout_marginRight="5dp" android:textColor="#ffffff" - android:background="@drawable/ff8decec_2round_bg" + android:background="@drawable/ff029b45_2round_bg" android:gravity="center" - android:textSize="12sp" + android:textSize="11sp" android:padding="5dp" android:text="重新获取参数" - android:layout_width="100dp" - android:layout_height="wrap_content"/> + android:layout_width="84dp" + android:layout_height="28dp"/> + android:layout_height="28dp"/> + android:layout_height="28dp"/> - - + android:layout_height="match_parent"> + + + + + + + + + + + + + + @@ -145,8 +182,9 @@