package com.xiaopeng.map.service.serviceimpl; import com.xiaopeng.map.config.VinSaltProperties; import com.xiaopeng.map.dto.AreaInput; import com.xiaopeng.map.service.AdcOssHandleService; import com.xiaopeng.map.service.RobotaxiOssService; import com.xiaopeng.map.utils.MapAreaVersionProtoWriter; import com.xiaopeng.map.utils.VehicleCodec; import com.xiaopeng.map.utils.XngpAreaRTreeFbsUtil; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.util.List; /** * ADC OSS 处理服务实现,根据坐标点生成 RTree fbs 并上传至 OSS。 */ @Slf4j @Service @RequiredArgsConstructor @ConditionalOnBean(RobotaxiOssService.class) public class AdcOssHandleServiceImpl implements AdcOssHandleService { private final RobotaxiOssService robotaxiOssService; private final VinSaltProperties vinSaltProperties; @Override public String uploadOddLayerFile(List areas, String vin) { validateParams(areas, vin); String vehicleUuid = VehicleCodec.vinToUUID(vin, vinSaltProperties.getSalt1(), vinSaltProperties.getSalt2()); byte[] fbsBytes = XngpAreaRTreeFbsUtil.buildRTreeBytesFromMultiAreas(areas); if (fbsBytes == null || fbsBytes.length == 0) { throw new IllegalStateException("Failed to build RTree fbs from areas"); } int version = (int) (System.currentTimeMillis() / 1000); String binFileName = version + "_xngp_area_data.bin"; String objectKey = robotaxiOssService.uploadOddLayerFile(fbsBytes, binFileName, vehicleUuid); byte[] pbBytes = MapAreaVersionProtoWriter.toByteArray(version, fbsBytes.length); robotaxiOssService.uploadOddLayerFile(pbBytes, "xngp_area_version.pb", vehicleUuid); log.debug("AdcOssHandle uploaded ODD layer file, areasCount={}, objectKey={}", areas.size(), objectKey); return objectKey; } @Override public List deleteOddLayerFiles(String vin) { if (!StringUtils.hasText(vin)) { throw new IllegalArgumentException("vin cannot be empty"); } String vehicleUuid = VehicleCodec.vinToUUID(vin, vinSaltProperties.getSalt1(), vinSaltProperties.getSalt2()); List deleted = robotaxiOssService.deleteOddLayerFilesByPrefix(vehicleUuid); log.debug("AdcOssHandle deleted ODD layer files, vin={}, count={}", vin, deleted.size()); return deleted; } private void validateParams(List areas, String vin) { if (CollectionUtils.isEmpty(areas)) { throw new IllegalArgumentException("areas cannot be empty"); } for (AreaInput area : areas) { if (CollectionUtils.isEmpty(area.getPoints())) { throw new IllegalArgumentException("each area must have non-empty points"); } } if (!StringUtils.hasText(vin)) { throw new IllegalArgumentException("vin cannot be empty"); } } }