| | |
| | | <artifactId>xp-common-log</artifactId> |
| | | </dependency> |
| | | |
| | | <!-- xiaopeng Common Redis(XpMapController、XpElectronicFenceAreaServiceImpl、HolidayUtil 等使用 RedisService) --> |
| | | <dependency> |
| | | <groupId>com.xiaopeng</groupId> |
| | | <artifactId>xp-common-redis</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.xiaopeng</groupId> |
| | | <artifactId>xp-common-swagger</artifactId> |
| | |
| | | /** |
| | | * 根据坐标点生成 RTree fbs 并上传至 OSS |
| | | * |
| | | * @param points 多边形顶点(使用 XngpAreaRTreeFbsUtil.LonLat) |
| | | * @param areaId 区域 areaId |
| | | * @param vin 车辆 VIN 码 |
| | | * @param areaCode 区域编码 |
| | | * @param points 多边形顶点(使用 XngpAreaRTreeFbsUtil.LonLat) |
| | | * @param areaId 区域 areaId |
| | | * @param vin 车辆 VIN 码 |
| | | * @return 上传后的 objectKey,失败抛异常 |
| | | */ |
| | | String uploadOddLayerFile(List<XngpAreaRTreeFbsUtil.LonLat> points, int areaId, String vin, String areaCode); |
| | | String uploadOddLayerFile(List<XngpAreaRTreeFbsUtil.LonLat> points, int areaId, String vin); |
| | | |
| | | /** |
| | | * 删除指定车辆在指定区域下的 ODD 图层文件 |
| | | * 删除指定车辆下的 ODD 图层文件 |
| | | * |
| | | * @param vin 车辆 VIN 码 |
| | | * @param areaCode 区域编码 |
| | | * @param vin 车辆 VIN 码 |
| | | * @return 成功删除的 objectKey 列表 |
| | | */ |
| | | List<String> deleteOddLayerFiles(String vin, String areaCode); |
| | | List<String> deleteOddLayerFiles(String vin); |
| | | } |
| | |
| | | |
| | | /** |
| | | * ROBOTAXI OSS 服务,用于上传 ODD 图层文件到阿里云 OSS。 |
| | | * 路径格式:ROBOTAXI_ODD_layer/{区域编码}/{环境}/{车辆uuid}/{fileName} |
| | | * 路径格式:ROBOTAXI_ODD_layer/{环境}/{车辆uuid}/{fileName} |
| | | */ |
| | | public interface RobotaxiOssService { |
| | | |
| | | /** |
| | | * 上传 ODD 图层文件到 OSS |
| | | * 路径:{pathPrefix}/{areaCode}/{env}/{vehicleUuid}/{fileName} |
| | | * 路径:{pathPrefix}/{env}/{vehicleUuid}/{fileName} |
| | | * |
| | | * @param data 文件内容 |
| | | * @param fileName 文件名(如 map_area_data.bin、map_area_rtree.fbs) |
| | | * @param areaCode 区域编码(动态) |
| | | * @param vehicleUuid 车辆 UUID(动态) |
| | | * @return 上传成功后的 objectKey,失败时抛异常 |
| | | */ |
| | | String uploadOddLayerFile(byte[] data, String fileName, String areaCode, String vehicleUuid); |
| | | String uploadOddLayerFile(byte[] data, String fileName, String vehicleUuid); |
| | | |
| | | /** |
| | | * 上传 ODD 图层文件到 OSS(InputStream 重载) |
| | |
| | | * @param inputStream 文件输入流 |
| | | * @param contentLength 文件大小 |
| | | * @param fileName 文件名 |
| | | * @param areaCode 区域编码 |
| | | * @param vehicleUuid 车辆 UUID |
| | | * @return 上传成功后的 objectKey,失败时抛异常 |
| | | */ |
| | | String uploadOddLayerFile(InputStream inputStream, long contentLength, String fileName, |
| | | String areaCode, String vehicleUuid); |
| | | String vehicleUuid); |
| | | |
| | | /** |
| | | * 根据 OSS objectKey 删除单个文件 |
| | | * |
| | | * @param objectKey OSS 对象键,如 ROBOTAXI_ODD_layer/440100/test/vehicle-001/map_area_rtree.fbs |
| | | * @param objectKey OSS 对象键,如 ROBOTAXI_ODD_layer/test/vehicle-001/map_area_rtree.fbs |
| | | * @return 是否删除成功 |
| | | */ |
| | | boolean deleteByObjectKey(String objectKey); |
| | |
| | | |
| | | /** |
| | | * 按前缀删除 ODD 路径下所有文件 |
| | | * 路径前缀:{pathPrefix}/{areaCode}/{env}/{vehicleUuid}/ |
| | | * 路径前缀:{pathPrefix}/{env}/{vehicleUuid}/ |
| | | * |
| | | * @param areaCode 区域编码 |
| | | * @param vehicleUuid 车辆 UUID |
| | | * @return 成功删除的 objectKey 列表 |
| | | */ |
| | | List<String> deleteOddLayerFilesByPrefix(String areaCode, String vehicleUuid); |
| | | List<String> deleteOddLayerFilesByPrefix(String vehicleUuid); |
| | | |
| | | /** |
| | | * 根据 objectKey 生成文件下载临时链接(Presigned URL) |
| | |
| | | private final VinSaltProperties vinSaltProperties; |
| | | |
| | | @Override |
| | | public String uploadOddLayerFile(List<XngpAreaRTreeFbsUtil.LonLat> points, int areaId, String vin, String areaCode) { |
| | | validateParams(points, vin, areaCode); |
| | | public String uploadOddLayerFile(List<XngpAreaRTreeFbsUtil.LonLat> points, int areaId, String vin) { |
| | | validateParams(points, vin); |
| | | |
| | | String vehicleUuid = VehicleCodec.vinToUUID(vin, vinSaltProperties.getSalt1(), vinSaltProperties.getSalt2()); |
| | | |
| | |
| | | int version = (int) (System.currentTimeMillis() / 1000); |
| | | String binFileName = version + "_xngp_area_data.bin"; |
| | | |
| | | String objectKey = robotaxiOssService.uploadOddLayerFile(fbsBytes, binFileName, areaCode, vehicleUuid); |
| | | String objectKey = robotaxiOssService.uploadOddLayerFile(fbsBytes, binFileName, vehicleUuid); |
| | | |
| | | byte[] pbBytes = MapAreaVersionProtoWriter.toByteArray(version, fbsBytes.length); |
| | | robotaxiOssService.uploadOddLayerFile(pbBytes, "xngp_area_version.pb", areaCode, vehicleUuid); |
| | | robotaxiOssService.uploadOddLayerFile(pbBytes, "xngp_area_version.pb", vehicleUuid); |
| | | |
| | | log.debug("AdcOssHandle uploaded ODD layer file, areaId={}, areaCode={}, objectKey={}", areaId, areaCode, objectKey); |
| | | log.debug("AdcOssHandle uploaded ODD layer file, areaId={}, objectKey={}", areaId, objectKey); |
| | | return objectKey; |
| | | } |
| | | |
| | | @Override |
| | | public List<String> deleteOddLayerFiles(String vin, String areaCode) { |
| | | public List<String> deleteOddLayerFiles(String vin) { |
| | | if (!StringUtils.hasText(vin)) { |
| | | throw new IllegalArgumentException("vin cannot be empty"); |
| | | } |
| | | if (!StringUtils.hasText(areaCode)) { |
| | | throw new IllegalArgumentException("areaCode cannot be empty"); |
| | | } |
| | | String vehicleUuid = VehicleCodec.vinToUUID(vin, vinSaltProperties.getSalt1(), vinSaltProperties.getSalt2()); |
| | | List<String> deleted = robotaxiOssService.deleteOddLayerFilesByPrefix(areaCode, vehicleUuid); |
| | | log.debug("AdcOssHandle deleted ODD layer files, vin={}, areaCode={}, count={}", vin, areaCode, deleted.size()); |
| | | List<String> deleted = robotaxiOssService.deleteOddLayerFilesByPrefix(vehicleUuid); |
| | | log.debug("AdcOssHandle deleted ODD layer files, vin={}, count={}", vin, deleted.size()); |
| | | return deleted; |
| | | } |
| | | |
| | | private void validateParams(List<XngpAreaRTreeFbsUtil.LonLat> points, String vin, String areaCode) { |
| | | private void validateParams(List<XngpAreaRTreeFbsUtil.LonLat> points, String vin) { |
| | | if (CollectionUtils.isEmpty(points)) { |
| | | throw new IllegalArgumentException("points cannot be empty"); |
| | | } |
| | | if (!StringUtils.hasText(vin)) { |
| | | throw new IllegalArgumentException("vin cannot be empty"); |
| | | } |
| | | if (!StringUtils.hasText(areaCode)) { |
| | | throw new IllegalArgumentException("areaCode cannot be empty"); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | /** |
| | | * ROBOTAXI OSS 服务实现,使用阿里云官方 OSS SDK 上传 ODD 图层文件。 |
| | | * 路径格式:ROBOTAXI_ODD_layer/{区域编码}/{环境}/{车辆uuid}/{fileName} |
| | | * 路径格式:ROBOTAXI_ODD_layer/{环境}/{车辆uuid}/{fileName} |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | |
| | | private final OssProperties ossProperties; |
| | | |
| | | @Override |
| | | public String uploadOddLayerFile(byte[] data, String fileName, String areaCode, String vehicleUuid) { |
| | | public String uploadOddLayerFile(byte[] data, String fileName, String vehicleUuid) { |
| | | if (data == null) { |
| | | throw new IllegalArgumentException("data cannot be null"); |
| | | } |
| | | return uploadOddLayerFile(new ByteArrayInputStream(data), data.length, fileName, areaCode, vehicleUuid); |
| | | return uploadOddLayerFile(new ByteArrayInputStream(data), data.length, fileName, vehicleUuid); |
| | | } |
| | | |
| | | @Override |
| | | public String uploadOddLayerFile(InputStream inputStream, long contentLength, String fileName, |
| | | String areaCode, String vehicleUuid) { |
| | | validateParams(fileName, areaCode, vehicleUuid); |
| | | String vehicleUuid) { |
| | | validateParams(fileName, vehicleUuid); |
| | | |
| | | String objectKey = buildObjectKey(areaCode, vehicleUuid, fileName); |
| | | String objectKey = buildObjectKey(vehicleUuid, fileName); |
| | | String bucketName = ossProperties.getBucketName(); |
| | | |
| | | OSS ossClient = null; |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<String> deleteOddLayerFilesByPrefix(String areaCode, String vehicleUuid) { |
| | | validateParamsForPrefix(areaCode, vehicleUuid); |
| | | public List<String> deleteOddLayerFilesByPrefix(String vehicleUuid) { |
| | | validateParamsForPrefix(vehicleUuid); |
| | | |
| | | String prefix = buildObjectKeyPrefix(areaCode, vehicleUuid); |
| | | String prefix = buildObjectKeyPrefix(vehicleUuid); |
| | | String bucketName = ossProperties.getBucketName(); |
| | | |
| | | OSS ossClient = null; |
| | |
| | | } |
| | | } |
| | | |
| | | private void validateParamsForPrefix(String areaCode, String vehicleUuid) { |
| | | if (!StringUtils.hasText(areaCode)) { |
| | | throw new IllegalArgumentException("areaCode cannot be empty"); |
| | | } |
| | | private void validateParamsForPrefix(String vehicleUuid) { |
| | | if (!StringUtils.hasText(vehicleUuid)) { |
| | | throw new IllegalArgumentException("vehicleUuid cannot be empty"); |
| | | } |
| | | } |
| | | |
| | | private String buildObjectKeyPrefix(String areaCode, String vehicleUuid) { |
| | | private String buildObjectKeyPrefix(String vehicleUuid) { |
| | | String pathPrefix = ossProperties.getPathPrefix(); |
| | | if (!StringUtils.hasText(pathPrefix)) { |
| | | pathPrefix = "ROBOTAXI_ODD_layer"; |
| | | } |
| | | String env = StringUtils.hasText(ossProperties.getEnv()) ? ossProperties.getEnv() : "test"; |
| | | return String.format("%s/%s/%s/%s/", pathPrefix, areaCode, env, vehicleUuid); |
| | | return String.format("%s/%s/%s/", pathPrefix, env, vehicleUuid); |
| | | } |
| | | |
| | | private void validateParams(String fileName, String areaCode, String vehicleUuid) { |
| | | private void validateParams(String fileName, String vehicleUuid) { |
| | | if (!StringUtils.hasText(fileName)) { |
| | | throw new IllegalArgumentException("fileName cannot be empty"); |
| | | } |
| | | if (!StringUtils.hasText(areaCode)) { |
| | | throw new IllegalArgumentException("areaCode cannot be empty"); |
| | | } |
| | | if (!StringUtils.hasText(vehicleUuid)) { |
| | | throw new IllegalArgumentException("vehicleUuid cannot be empty"); |
| | | } |
| | | } |
| | | |
| | | private String buildObjectKey(String areaCode, String vehicleUuid, String fileName) { |
| | | private String buildObjectKey(String vehicleUuid, String fileName) { |
| | | String pathPrefix = ossProperties.getPathPrefix(); |
| | | if (!StringUtils.hasText(pathPrefix)) { |
| | | pathPrefix = "ROBOTAXI_ODD_layer"; |
| | | } |
| | | String env = StringUtils.hasText(ossProperties.getEnv()) ? ossProperties.getEnv() : "test"; |
| | | return String.format("%s/%s/%s/%s/%s", pathPrefix, areaCode, env, vehicleUuid, fileName); |
| | | return String.format("%s/%s/%s/%s", pathPrefix, env, vehicleUuid, fileName); |
| | | } |
| | | |
| | | private OSS createOssClient() { |
| | |
| | | |
| | | int areaId = 1; |
| | | String vin = "21312323333333312"; // 替换为实际测试 VIN |
| | | String areaCode = "510100"; |
| | | |
| | | String objectKey = adcOssHandleService.uploadOddLayerFile(points, areaId, vin, areaCode); |
| | | String objectKey = adcOssHandleService.uploadOddLayerFile(points, areaId, vin); |
| | | log.info("uploadOddLayerFile objectKey={}", objectKey); |
| | | |
| | | assertNotNull(objectKey); |
| | | assertTrue(objectKey.contains("ROBOTAXI_ODD_layer") && objectKey.contains(areaCode), |
| | | "返回 objectKey 应包含路径前缀和区域编码"); |
| | | assertTrue(objectKey.contains("ROBOTAXI_ODD_layer"), |
| | | "返回 objectKey 应包含路径前缀"); |
| | | |
| | | // 获取 bin 文件下载临时链接(Presigned URL) |
| | | String downloadUrl = robotaxiOssService.generatePresignedDownloadUrl(objectKey, 3600); |