DeviceInfoManager.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. package com.paul.drone.util;
  2. import android.util.Log;
  3. import com.paul.drone.keyvalue.DroneTypeEnum;
  4. import dji.sdk.keyvalue.key.CameraKey;
  5. import dji.sdk.keyvalue.key.DJIKey;
  6. import dji.sdk.keyvalue.key.DJIKeyInfo;
  7. import dji.sdk.keyvalue.key.FlightControllerKey;
  8. import dji.sdk.keyvalue.key.ProductKey;
  9. import dji.sdk.keyvalue.key.RemoteControllerKey;
  10. import dji.sdk.keyvalue.value.camera.CameraType;
  11. import dji.sdk.keyvalue.value.common.LocationCoordinate2D;
  12. import dji.sdk.keyvalue.value.product.ProductType;
  13. import dji.v5.manager.KeyManager;
  14. import dji.v5.et.*;
  15. /**
  16. * 设备信息集中管理工具类
  17. * 统一获取 serialNumber、productType、cameraType,并带缓存和异常兜底
  18. */
  19. public class DeviceInfoManager {
  20. private static final String TAG = "DeviceInfoManager";
  21. private static volatile DeviceInfoManager INSTANCE;
  22. // 缓存属性
  23. private String cachedSerialNumber;
  24. private String cachedProductType;
  25. private DeviceInfoManager() {
  26. // 私有构造函数
  27. }
  28. /**
  29. * 获取单例实例
  30. * @return DeviceInfoManager实例
  31. */
  32. public static DeviceInfoManager getInstance() {
  33. if (INSTANCE == null) {
  34. synchronized (DeviceInfoManager.class) {
  35. if (INSTANCE == null) {
  36. INSTANCE = new DeviceInfoManager();
  37. }
  38. }
  39. }
  40. return INSTANCE;
  41. }
  42. /**
  43. * 清理缓存
  44. */
  45. public void clearCache() {
  46. cachedSerialNumber = null;
  47. cachedProductType = null;
  48. }
  49. // 默认重试次数
  50. private static final int DEFAULT_RETRY_COUNT = 5;
  51. // 重试间隔时间(ms)
  52. private static final long RETRY_INTERVAL_MS = 1000;
  53. /**
  54. * 获取设备序列号
  55. * @return 序列号字符串
  56. */
  57. public String getFlySerialNumber() {
  58. if (cachedSerialNumber != null) {
  59. return cachedSerialNumber;
  60. }
  61. String serialNumber = retryOperation(this::getFlightSerialNumber, DEFAULT_RETRY_COUNT, RETRY_INTERVAL_MS);
  62. if (!serialNumber.isEmpty()) {
  63. cachedSerialNumber = serialNumber;
  64. return serialNumber;
  65. }
  66. cachedSerialNumber = "暂无";
  67. return cachedSerialNumber;
  68. }
  69. /**
  70. * 通用重试操作方法
  71. * @param operation 要执行的操作
  72. * @param maxRetries 最大重试次数
  73. * @param retryIntervalMs 重试间隔(毫秒)
  74. * @return 操作结果
  75. */
  76. private <T> T retryOperation(RetryableOperation<T> operation, int maxRetries, long retryIntervalMs) {
  77. int retryCount = 0;
  78. T result;
  79. while (true) {
  80. try {
  81. result = operation.execute();
  82. if (result != null && !isDefaultValue(result)) {
  83. return result;
  84. }
  85. } catch (Exception e) {
  86. Log.e(TAG, "Operation failed, retry count: " + retryCount, e);
  87. }
  88. retryCount++;
  89. if (retryCount >= maxRetries) {
  90. break;
  91. }
  92. try {
  93. Thread.sleep(retryIntervalMs);
  94. } catch (InterruptedException e) {
  95. Thread.currentThread().interrupt();
  96. Log.e(TAG, "Retry interrupted", e);
  97. break;
  98. }
  99. }
  100. return null;
  101. }
  102. /**
  103. * 检查结果是否为默认值
  104. * @param result 结果
  105. * @return 是否为默认值
  106. */
  107. private boolean isDefaultValue(Object result) {
  108. if (result instanceof String) {
  109. return ((String) result).isEmpty() || "UNKNOWN".equals(result);
  110. }
  111. return result == null;
  112. }
  113. /**
  114. * 可重试操作接口
  115. */
  116. private interface RetryableOperation<T> {
  117. T execute() throws Exception;
  118. }
  119. public LocationCoordinate2D getFightLocation(){
  120. LocationCoordinate2D value = KeyManager.getInstance().getValue(DJIKey.create(FlightControllerKey.KeyHomeLocation));
  121. // 先检查value是否为null
  122. if (value == null) {
  123. // 如果是null,创建一个新的LocationCoordinate2D实例
  124. value = new LocationCoordinate2D(0.0, 0.0);
  125. }
  126. // 然后安全地设置坐标值
  127. value.setLatitude(28.228079);
  128. value.setLongitude(112.938975);
  129. return value;
  130. }
  131. /**
  132. * 获取固件版本
  133. * @return 固件版本字符串
  134. */
  135. public String getFirmwareVersion() {
  136. // 实际应用中应该从设备获取
  137. // 这里返回模拟数据
  138. return "1.0.0";
  139. }
  140. /** 获取设备序列号,优先多种方式,带缓存 */
  141. private String getFlightSerialNumber() throws Exception {
  142. KeyManager keyManager = KeyManager.getInstance();
  143. if (keyManager == null) {
  144. throw new Exception("KeyManager is null");
  145. }
  146. //return "ADFD186ASDFLWIXUE";
  147. // 1. ProductKey.KeySerialNumber
  148. String productSN = keyManager.getValue(DJIKey.create(ProductKey.KeySerialNumber));
  149. if (productSN != null && !productSN.isEmpty()) {
  150. return productSN;
  151. }
  152. // // 2. FlightControllerKey.KeySerialNumber
  153. String fcSN = keyManager.getValue(DJIKey.create(FlightControllerKey.KeySerialNumber));
  154. if (fcSN != null && !fcSN.isEmpty()) {
  155. return fcSN;
  156. }
  157. throw new Exception("Failed to get serial number from all sources");
  158. }
  159. public String getRemoteSerialNumber() {
  160. KeyManager keyManager = KeyManager.getInstance();
  161. if (keyManager == null) {
  162. return "UNKNOWN";
  163. }
  164. // 1. RemoteControllerKey.KeyProductSerialNumber
  165. try {
  166. String productSN = keyManager.getValue(DJIKey.create(RemoteControllerKey.KeyProductSerialNumber));
  167. if (productSN != null && !productSN.isEmpty()) {
  168. return productSN;
  169. }
  170. } catch (Exception e) {
  171. Log.e(TAG, "RemoteControllerKey.KeyProductSerialNumber error", e);
  172. }
  173. return "UNKNOWN";
  174. }
  175. /** 获取产品类型,带缓存 */
  176. public String getProductType() {
  177. if (cachedProductType != null) {
  178. return cachedProductType;
  179. }
  180. KeyManager keyManager = KeyManager.getInstance();
  181. if (keyManager == null) {
  182. cachedProductType = "UNKNOWN";
  183. return cachedProductType;
  184. }
  185. try {
  186. ProductType value = keyManager.getValue(DJIKey.create(ProductKey.KeyProductType));
  187. String name = value.name();
  188. cachedProductType = name;
  189. return name;
  190. } catch (Exception e) {
  191. Log.e(TAG, "ProductType error", e);
  192. cachedProductType = "UNKNOWN";
  193. return cachedProductType;
  194. }
  195. }
  196. /** 获取相机类型 */
  197. public String getCameraType(int cameraIndex) {
  198. KeyManager keyManager = KeyManager.getInstance();
  199. if (keyManager == null) {
  200. return "UNKNOWN";
  201. }
  202. try {
  203. CameraType value = keyManager.getValue(DJIKey.create(CameraKey.KeyCameraType));
  204. String name = value.name();
  205. return name;
  206. } catch (Exception e) {
  207. Log.e(TAG, "CameraType error", e);
  208. return "UNKNOWN";
  209. }
  210. }
  211. /**
  212. * 获取产品型号或子型号(相机型号)
  213. * - 如果是 DJI_MATRICE_400、M300_RTK、M350_RTK,返回产品型号 name
  214. * - 否则,返回 CameraType 的 name(如果有),否则返回产品型号 name
  215. */
  216. public String getProductOrCameraType(int cameraIndex) {
  217. KeyManager keyManager = KeyManager.getInstance();
  218. if (keyManager == null) {
  219. return "UNKNOWN";
  220. }
  221. ProductType productType = null;
  222. try {
  223. productType = keyManager.getValue(DJIKey.create(ProductKey.KeyProductType));
  224. } catch (Exception e) {
  225. Log.e(TAG, "ProductType error", e);
  226. }
  227. String productTypeName = (productType != null) ? productType.name() : "UNKNOWN";
  228. if (productType == ProductType.DJI_MATRICE_400 ||
  229. productType == ProductType.M300_RTK ||
  230. productType == ProductType.M350_RTK) {
  231. return productTypeName;
  232. } else {
  233. String cameraTypeName = null;
  234. try {
  235. CameraType value = keyManager.getValue(DJIKey.create(CameraKey.KeyCameraType));
  236. cameraTypeName = value.name();
  237. } catch (Exception e) {
  238. Log.e(TAG, "CameraType error", e);
  239. }
  240. if (cameraTypeName != null && !cameraTypeName.isEmpty() && !cameraTypeName.equals("UNKNOWN")) {
  241. return cameraTypeName;
  242. } else {
  243. return productTypeName;
  244. }
  245. }
  246. }
  247. public String getModelByDroneTypeEnum(int cameraIndex) {
  248. KeyManager keyManager = KeyManager.getInstance();
  249. if (keyManager == null) {
  250. return "UNKNOWN";
  251. }
  252. ProductType productType = null;
  253. try {
  254. productType = keyManager.getValue(DJIKey.create(ProductKey.KeyProductType));
  255. } catch (Exception e) {
  256. Log.e(TAG, "ProductType error", e);
  257. }
  258. if (productType == ProductType.DJI_MATRICE_400 ||
  259. productType == ProductType.M300_RTK ||
  260. productType == ProductType.M350_RTK) {
  261. String productTypeName = productType.name();
  262. for (DroneTypeEnum droneType : DroneTypeEnum.values()) {
  263. if (droneType.getDroneType().equals(productTypeName)) {
  264. return droneType.getModel();
  265. }
  266. }
  267. return "";
  268. } else {
  269. try {
  270. CameraType value = keyManager.getValue(DJIKey.create(CameraKey.KeyCameraType));
  271. String cameraTypeName = value.name();
  272. for (DroneTypeEnum droneType : DroneTypeEnum.values()) {
  273. if (droneType.getDroneType().equals(cameraTypeName)) {
  274. return droneType.getModel();
  275. }
  276. }
  277. } catch (Exception e) {
  278. Log.e(TAG, "CameraType error", e);
  279. }
  280. return "UNKNOWN";
  281. }
  282. }
  283. public String getTypeByDroneTypeEnum(int cameraIndex) {
  284. if (cachedProductType != null) {
  285. // 使用缓存的产品类型进行查找
  286. for (DroneTypeEnum droneType : DroneTypeEnum.values()) {
  287. if (droneType.getDroneType().equals(cachedProductType)) {
  288. return droneType.getDroneType();
  289. }
  290. }
  291. }
  292. // 没有缓存或缓存不匹配,进行重试获取
  293. String result = retryOperation(() -> getTypeByDroneTypeEnumInternal(cameraIndex), DEFAULT_RETRY_COUNT, RETRY_INTERVAL_MS);
  294. return result != null ? result : "暂无";
  295. }
  296. /**
  297. * getTypeByDroneTypeEnum的内部实现
  298. */
  299. private String getTypeByDroneTypeEnumInternal(int cameraIndex) throws Exception {
  300. KeyManager keyManager = KeyManager.getInstance();
  301. if (keyManager == null) {
  302. throw new Exception("KeyManager is null");
  303. }
  304. ProductType productType = keyManager.getValue(DJIKey.create(ProductKey.KeyProductType));
  305. if (productType == null) {
  306. throw new Exception("ProductType is null");
  307. }
  308. if (productType == ProductType.DJI_MATRICE_400 ||
  309. productType == ProductType.M300_RTK ||
  310. productType == ProductType.M350_RTK) {
  311. String productTypeName = productType.name();
  312. for (DroneTypeEnum droneType : DroneTypeEnum.values()) {
  313. if (droneType.getDroneType().equals(productTypeName)) {
  314. cachedProductType = productTypeName;
  315. return droneType.getDroneType();
  316. }
  317. }
  318. throw new Exception("No matching DroneTypeEnum for productType: " + productTypeName);
  319. } else {
  320. CameraType cameraType = keyManager.getValue(DJIKey.create(CameraKey.KeyCameraType));
  321. if (cameraType == null) {
  322. throw new Exception("CameraType is null");
  323. }
  324. String cameraTypeName = cameraType.name();
  325. for (DroneTypeEnum droneType : DroneTypeEnum.values()) {
  326. if (droneType.getDroneType().equals(cameraTypeName)) {
  327. return droneType.getDroneType();
  328. }
  329. }
  330. throw new Exception("No matching DroneTypeEnum for cameraType: " + cameraTypeName);
  331. }
  332. }
  333. }