| | |
| | | package com.ard.work.service.impl; |
| | | |
| | | import com.ard.common.constant.CacheConstants; |
| | | import com.ard.common.core.domain.model.LoginUser; |
| | | import com.ard.common.core.redis.RedisCache; |
| | | import com.ard.common.utils.SecurityUtils; |
| | | import com.ard.work.domain.cache.UavStateCache; |
| | | import com.ard.work.domain.dto.control.SpeedControlDTO; |
| | | import com.ard.work.domain.dto.state.UavState; |
| | | import com.ard.work.service.IGimbalSpeedService; |
| | | import com.ard.work.service.ITyService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
| | | import org.springframework.security.core.context.SecurityContextHolder; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.Map; |
| | | import java.util.concurrent.*; |
| | | |
| | | /** |
| | | * 云台速度控制实现 |
| | | * |
| | | * @author lsy |
| | | * @date 2025/10/28 |
| | | */ |
| | | @Service |
| | | @Slf4j |
| | | public class GimbalSpeedService { |
| | | public class GimbalSpeedService implements IGimbalSpeedService { |
| | | |
| | | private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); |
| | | private final Map<String, ScheduledFuture<?>> tasks = new ConcurrentHashMap<>(); |
| | | |
| | | @Resource |
| | | private ITyService tyService; |
| | | @Resource |
| | | private RedisCache redisCache; |
| | | |
| | | @Override |
| | | public synchronized void startControl(SpeedControlDTO speed) { |
| | | String boxSn = speed.getBoxSn(); |
| | | |
| | | // ✅ 先判断是否在线 |
| | | if (!isUavOnline(boxSn)) { |
| | | throw new RuntimeException("无人机离线,无法启动云台控制: " + boxSn); |
| | | } |
| | | |
| | | if (tasks.containsKey(boxSn)) { |
| | | return; |
| | | } |
| | | LoginUser loginUser = SecurityUtils.getLoginUser();// 主线程获取 |
| | | // ✅ 启动前先试探一次,确保正常 |
| | | try { |
| | | SecurityContextHolder.getContext().setAuthentication( |
| | | new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities()) |
| | | ); |
| | | Boolean ok = tyService.speedControl(speed); |
| | | if (ok == null || !ok) { |
| | | throw new RuntimeException("初始速度控制指令失败"); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("初次控制指令异常: {}", e.getMessage()); |
| | | throw new RuntimeException("无法启动云台控制:" + e.getMessage()); |
| | | } |
| | | |
| | | ScheduledFuture<?> future = executor.scheduleAtFixedRate(() -> { |
| | | double currentYaw = getCurrentYaw(boxSn); |
| | | log.warn("currentYaw: {}", currentYaw); |
| | | if ((speed.getYawSpeed() < 0 && currentYaw <= -180) || |
| | | (speed.getYawSpeed() > 0 && currentYaw >= 180)) { |
| | | stopControl(boxSn); |
| | |
| | | |
| | | tasks.put(boxSn, future); |
| | | } |
| | | |
| | | @Override |
| | | public synchronized void stopControl(String boxSn) { |
| | | ScheduledFuture<?> future = tasks.remove(boxSn); |
| | | if (future != null) { |
| | |
| | | } |
| | | return uavState.getPtzState().getYaw(); |
| | | } |
| | | |
| | | private boolean isUavOnline(String boxSn) { |
| | | // 如果 Redis 中存在对应 key,则认为在线 |
| | | Object obj = redisCache.getCacheObject(CacheConstants.UAV_ONLINE_KEY + boxSn); |
| | | return obj != null; |
| | | } |
| | | |
| | | } |