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<AreaInput> areas, String vin, long version) {
|
log.info("[ADC-OSS] uploadOddLayerFile 开始, vin={}, version={}, areasCount={}", vin, version, areas == null ? 0 : areas.size());
|
if (areas != null) {
|
for (int i = 0; i < areas.size(); i++) {
|
AreaInput a = areas.get(i);
|
log.info("[ADC-OSS] area[{}]: areaId={}, isBlacklist={}, pointsCount={}",
|
i, a.getAreaId(), a.isBlacklist(), a.getPoints() == null ? 0 : a.getPoints().size());
|
}
|
}
|
validateParams(areas, vin);
|
|
String vehicleUuid = VehicleCodec.vinToUUID(vin, vinSaltProperties.getSalt1(), vinSaltProperties.getSalt2());
|
log.info("[ADC-OSS] VIN={} -> UUID={}", vin, vehicleUuid);
|
|
byte[] fbsBytes = XngpAreaRTreeFbsUtil.buildRTreeBytesFromMultiAreas(areas);
|
if (fbsBytes == null || fbsBytes.length == 0) {
|
log.info("[ADC-OSS] buildRTreeBytesFromMultiAreas 返回空, vin={}", vin);
|
throw new IllegalStateException("Failed to build RTree fbs from areas");
|
}
|
log.info("[ADC-OSS] FBS构建成功, vin={}, fbsSize={}bytes", vin, fbsBytes.length);
|
|
String binFileName = version + "_xngp_area_data.bin";
|
|
String objectKey = robotaxiOssService.uploadOddLayerFile(fbsBytes, binFileName, vehicleUuid);
|
log.info("[ADC-OSS] bin文件上传成功, vin={}, objectKey={}", vin, objectKey);
|
|
byte[] pbBytes = MapAreaVersionProtoWriter.toByteArray((int) version, fbsBytes.length);
|
robotaxiOssService.uploadOddLayerFile(pbBytes, "xngp_area_version.pb", vehicleUuid);
|
log.info("[ADC-OSS] pb版本文件上传成功, vin={}, version={}", vin, version);
|
|
return objectKey;
|
}
|
|
@Override
|
public String uploadEmptyFence(String vin, long version) {
|
log.info("[ADC-OSS] uploadEmptyFence 开始, vin={}, version={}", vin, version);
|
if (!StringUtils.hasText(vin)) {
|
throw new IllegalArgumentException("vin cannot be empty");
|
}
|
|
String vehicleUuid = VehicleCodec.vinToUUID(vin, vinSaltProperties.getSalt1(), vinSaltProperties.getSalt2());
|
log.info("[ADC-OSS] VIN={} -> UUID={}", vin, vehicleUuid);
|
|
byte[] fbsBytes = XngpAreaRTreeFbsUtil.buildEmptyRTreeBytes();
|
if (fbsBytes == null || fbsBytes.length == 0) {
|
log.info("[ADC-OSS] buildEmptyRTreeBytes 返回空, vin={}", vin);
|
throw new IllegalStateException("Failed to build empty RTree fbs");
|
}
|
log.info("[ADC-OSS] 空FBS构建成功, vin={}, fbsSize={}bytes", vin, fbsBytes.length);
|
|
String binFileName = version + "_xngp_area_data.bin";
|
String objectKey = robotaxiOssService.uploadOddLayerFile(fbsBytes, binFileName, vehicleUuid);
|
log.info("[ADC-OSS] 空FBS bin文件上传成功, vin={}, objectKey={}", vin, objectKey);
|
|
byte[] pbBytes = MapAreaVersionProtoWriter.toByteArray((int) version, fbsBytes.length);
|
robotaxiOssService.uploadOddLayerFile(pbBytes, "xngp_area_version.pb", vehicleUuid);
|
log.info("[ADC-OSS] 空FBS pb版本文件上传成功, vin={}, version={}", vin, version);
|
|
return objectKey;
|
}
|
|
private void validateParams(List<AreaInput> areas, String vin) {
|
if (CollectionUtils.isEmpty(areas)) {
|
log.info("[ADC-OSS] validateParams失败: areas为空, vin={}", vin);
|
throw new IllegalArgumentException("areas cannot be empty");
|
}
|
for (int i = 0; i < areas.size(); i++) {
|
AreaInput area = areas.get(i);
|
if (CollectionUtils.isEmpty(area.getPoints())) {
|
log.info("[ADC-OSS] validateParams失败: area[{}] areaId={} points为空, vin={}", i, area.getAreaId(), vin);
|
throw new IllegalArgumentException("each area must have non-empty points, areaId=" + area.getAreaId());
|
}
|
}
|
if (!StringUtils.hasText(vin)) {
|
log.info("[ADC-OSS] validateParams失败: vin为空");
|
throw new IllegalArgumentException("vin cannot be empty");
|
}
|
}
|
}
|