2 files added
10 files modified
| | |
| | | # 开发环境配置 |
| | | server: |
| | | # 服务器的HTTP端口,默认为8080 |
| | | port: 8081 |
| | | |
| | | port: 8080 |
| | | # token配置 |
| | | token: |
| | | # 是否允许账户多终端同时登录(true允许 false不允许) |
| | | soloLogin: false |
| | | # 日志配置 |
| | | logging: |
| | | level: |
| | |
| | | password: ardkj12345 |
| | | |
| | | # 天宇服务器配置 |
| | | #tianyu: |
| | | # # 天宇http服务器地址 |
| | | # endpoint: 112.98.106.22:12000 |
| | | # accesskeyid: qmfmd3Ws7M4dMcylnrTU |
| | | # accesskeysecret: 5WBU2uEhHZaVefpZdaxpFh4LJW9fZZaa |
| | | # # 天宇tcp服务器地址 |
| | | # tcpserver: 123.56.170.94 |
| | | # tcpport: 12345 |
| | | |
| | | # 天宇服务器配置 |
| | | tianyu: |
| | | # 天宇http服务器地址 |
| | | endpoint: 112.98.106.22:12000 |
| | | accesskeyid: qmfmd3Ws7M4dMcylnrTU |
| | | accesskeysecret: 5WBU2uEhHZaVefpZdaxpFh4LJW9fZZaa |
| | | # 天宇tcp服务器地址 |
| | | tcpserver: 123.56.170.94 |
| | | tcpport: 12345 |
| | | # 天宇http服务器地址 |
| | | endpoint: 59.110.237.99:8060 |
| | | accesskeyid: wuwuwu |
| | | accesskeysecret: 9c9f139f63b343b0a9ef42e05ed29b0b |
| | | # 天宇tcp服务器地址 |
| | | tcpserver: 59.110.237.99 |
| | | tcpport: 8124 |
| | | #流媒体配置 |
| | | mediamtx: |
| | | # 流媒体服务器地址 |
| | |
| | | secret: abcdefghijklmnopqrstuvwxyz |
| | | # 令牌有效期(默认30分钟) |
| | | expireTime: 720 |
| | | |
| | | # 是否允许账户多终端同时登录(true允许 false不允许) |
| | | soloLogin: false |
| | | # MyBatis配置 |
| | | mybatis: |
| | | # 搜索指定包别名 |
| | |
| | | */ |
| | | public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml", |
| | | "org.springframework", "org.apache", "com.ard.common.utils.file", "com.ard.common.config", "com.ard.generator" }; |
| | | |
| | | /** |
| | | * 登录用户编号 redis key |
| | | */ |
| | | public static final String LOGIN_USERID_KEY = "login_userid:"; |
| | | } |
| | |
| | | { |
| | | String userName = loginUser.getUsername(); |
| | | // 删除用户缓存记录 |
| | | tokenService.delLoginUser(loginUser.getToken()); |
| | | tokenService.delLoginUser(loginUser.getToken(), loginUser.getUser().getUserId()); |
| | | // 记录用户退出日志 |
| | | AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, MessageUtils.message("user.logout.success"))); |
| | | } |
| | |
| | | |
| | | import javax.annotation.Resource; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.security.authentication.AuthenticationManager; |
| | | import org.springframework.security.authentication.BadCredentialsException; |
| | | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; |
| | |
| | | @Component |
| | | public class SysLoginService |
| | | { |
| | | // 是否允许账户多终端同时登录(true允许 false不允许) |
| | | @Value("${token.soloLogin}") |
| | | private boolean soloLogin; |
| | | |
| | | @Autowired |
| | | private TokenService tokenService; |
| | | |
| | |
| | | AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); |
| | | LoginUser loginUser = (LoginUser) authentication.getPrincipal(); |
| | | recordLoginInfo(loginUser.getUserId()); |
| | | if (!soloLogin) |
| | | { |
| | | // 如果用户不允许多终端同时登录,清除缓存信息 |
| | | String userIdKey = Constants.LOGIN_USERID_KEY + loginUser.getUser().getUserId(); |
| | | String userKey = redisCache.getCacheObject(userIdKey); |
| | | if (StringUtils.isNotEmpty(userKey)) |
| | | { |
| | | redisCache.deleteObject(userIdKey); |
| | | redisCache.deleteObject(userKey); |
| | | } |
| | | } |
| | | // 生成token |
| | | return tokenService.createToken(loginUser); |
| | | } |
| | |
| | | @Value("${token.expireTime}") |
| | | private int expireTime; |
| | | |
| | | // 是否允许账户多终端同时登录(true允许 false不允许) |
| | | @Value("${token.soloLogin}") |
| | | private boolean soloLogin; |
| | | |
| | | protected static final long MILLIS_SECOND = 1000; |
| | | |
| | | protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; |
| | |
| | | /** |
| | | * 删除用户身份信息 |
| | | */ |
| | | public void delLoginUser(String token) |
| | | public void delLoginUser(String token, Long userId) |
| | | { |
| | | if (StringUtils.isNotEmpty(token)) |
| | | { |
| | | String userKey = getTokenKey(token); |
| | | redisCache.deleteObject(userKey); |
| | | } |
| | | if (!soloLogin && StringUtils.isNotNull(userId)) |
| | | { |
| | | String userIdKey = getUserIdKey(userId); |
| | | redisCache.deleteObject(userIdKey); |
| | | } |
| | | } |
| | | |
| | |
| | | // 根据uuid将loginUser缓存 |
| | | String userKey = getTokenKey(loginUser.getToken()); |
| | | redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); |
| | | if (!soloLogin) |
| | | { |
| | | // 缓存用户唯一标识,防止同一帐号,同时登录 |
| | | String userIdKey = getUserIdKey(loginUser.getUser().getUserId()); |
| | | redisCache.setCacheObject(userIdKey, userKey, expireTime, TimeUnit.MINUTES); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | { |
| | | return CacheConstants.LOGIN_TOKEN_KEY + uuid; |
| | | } |
| | | |
| | | private String getUserIdKey(Long userId) |
| | | { |
| | | return Constants.LOGIN_USERID_KEY + userId; |
| | | } |
| | | } |
| New file |
| | |
| | | package com.ard.tianyu.controller; |
| | | |
| | | import com.ard.common.core.domain.AjaxResult; |
| | | import com.ard.tianyu.model.receiver.BoxStreamUrlReceiver; |
| | | import com.ard.tianyu.service.ITyService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | |
| | | import javax.annotation.Resource; |
| | | |
| | | /** |
| | | * @ClassName: UavVideoController |
| | | * @Description: 无人机视频控制器 |
| | | * @Author: liusuyi |
| | | * @Date: 2025年02月18日9:16 |
| | | **/ |
| | | @Api(tags = "无人机视频控制器接口") |
| | | @RequestMapping("/uav/video") |
| | | @RestController |
| | | public class UavVideoController { |
| | | |
| | | @Resource |
| | | private ITyService tyService; |
| | | |
| | | @ApiOperation("点播") |
| | | @PostMapping("/play/{boxSn}") |
| | | public AjaxResult play(@PathVariable("boxSn") String boxSn) { |
| | | return AjaxResult.success(tyService.play(boxSn)); |
| | | } |
| | | } |
| New file |
| | |
| | | package com.ard.tianyu.http; |
| | | |
| | | import com.ard.tianyu.config.TyConfiguration; |
| | | import com.ard.tianyu.model.receiver.AccessTokenReceiver; |
| | | import com.dtflys.forest.http.ForestRequest; |
| | | import com.dtflys.forest.interceptor.Interceptor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Component; |
| | | import javax.annotation.Resource; |
| | | |
| | | @Component |
| | | @Slf4j |
| | | public class TokenInterceptor<T> implements Interceptor<T> { |
| | | @Resource |
| | | private TyConfiguration tyConfiguration; |
| | | |
| | | /** |
| | | * 该方法在请求发送之前被调用, 若返回false则不会继续发送请求 |
| | | * |
| | | * @Param request Forest请求对象 |
| | | */ |
| | | @Override |
| | | public boolean beforeExecute(ForestRequest req) { |
| | | log.info("invoke Simple beforeExecute"); |
| | | // 执行在发送请求之前处理的代码 |
| | | // 从缓存里获取token |
| | | AccessTokenReceiver accessToken = tyConfiguration.getAccessToken(); |
| | | req.addHeader("x-cid", accessToken.getCompanyId()); |
| | | req.addHeader("x-token", accessToken.getAccessToken()); |
| | | // req.addHeader("Authorization", "")); // 添加Header |
| | | // req.addQuery("username", "foo"); // 添加URL的Query参数 |
| | | return true; // 继续执行请求返回true |
| | | } |
| | | } |
| | |
| | | /** |
| | | * 获取云盒列表 |
| | | */ |
| | | @Get(TyConst.GET_BOX_LIST) |
| | | TyHttpCommonReceiver<List<BoxInfoReceiver>> getBoxList(@Header Map<String, String> headers); |
| | | @Get(value = TyConst.GET_BOX_LIST,interceptor = TokenInterceptor.class) |
| | | TyHttpCommonReceiver<List<BoxInfoReceiver>> getBoxList(); |
| | | |
| | | /** |
| | | * 获取直播地址 |
| | | */ |
| | | @Get(TyConst.GET_BOX_LIVE_URL) |
| | | TyHttpCommonReceiver<BoxStreamUrlReceiver> getBoxLiveUrl(@Var("boxSn") String boxSn, @Header Map<String, String> headers); |
| | | @Get(value =TyConst.GET_BOX_LIVE_URL,interceptor = TokenInterceptor.class) |
| | | TyHttpCommonReceiver<BoxStreamUrlReceiver> getBoxLiveUrl(@Var("boxSn") String boxSn); |
| | | |
| | | /** |
| | | * 获取飞行历史 |
| | | */ |
| | | @Post(TyConst.POST_BOX_HISTORY) |
| | | TyHttpCommonReceiver<List<BoxHistoryReceiver>> getBoxHistory(@JSONBody BoxHistoryDTO boxHistoryDTO, @Header Map<String, String> headers); |
| | | @Post(value =TyConst.POST_BOX_HISTORY,interceptor = TokenInterceptor.class) |
| | | TyHttpCommonReceiver<List<BoxHistoryReceiver>> getBoxHistory(@JSONBody BoxHistoryDTO boxHistoryDTO); |
| | | |
| | | /** |
| | | * 获取任务照片 |
| | | */ |
| | | @Post(TyConst.POST_BOX_PHOTOS) |
| | | TyHttpCommonReceiver<List<BoxPhotosReceiver>> getBoxPhotos(@JSONBody BoxPhotosDTO boxPhotosDTO, @Header Map<String, String> headers); |
| | | @Post(value =TyConst.POST_BOX_PHOTOS,interceptor = TokenInterceptor.class) |
| | | TyHttpCommonReceiver<List<BoxPhotosReceiver>> getBoxPhotos(@JSONBody BoxPhotosDTO boxPhotosDTO); |
| | | |
| | | /** |
| | | * 修改云盒设置 |
| | | */ |
| | | @Post(TyConst.POST_BOX_UPDATE) |
| | | TyHttpCommonReceiver<?> updateBoxSettings(@JSONBody BoxSettingsDTO boxSettingsDTO, @Header Map<String, String> headers); |
| | | @Post(value =TyConst.POST_BOX_UPDATE,interceptor = TokenInterceptor.class) |
| | | TyHttpCommonReceiver<?> updateBoxSettings(@JSONBody BoxSettingsDTO boxSettingsDTO); |
| | | } |
| | |
| | | import io.netty.handler.timeout.IdleStateHandler; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.annotation.PostConstruct; |
| | | import javax.annotation.Resource; |
| | | import java.util.HashMap; |
| | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | }, 5, TimeUnit.SECONDS); |
| | | }, 10, TimeUnit.SECONDS); |
| | | } |
| | | }); |
| | | //将连接存入集合 |
| | |
| | | * 处理回复消息 |
| | | */ |
| | | void processReplyMessage(String key, BaseCmd tyMessage); |
| | | |
| | | /** |
| | | * 点播 |
| | | */ |
| | | String play(String boxSn); |
| | | |
| | | } |
| | |
| | | import com.ard.tianyu.netty.protobuf.TelemetryDataPB; |
| | | import com.ard.tianyu.service.ITyService; |
| | | import com.ard.tianyu.websocket.utils.WebSocketUtil; |
| | | import com.ard.vtdu.domain.ArdVtdu; |
| | | import com.ard.vtdu.service.IMediaService; |
| | | import io.netty.channel.Channel; |
| | | import io.netty.channel.ChannelFuture; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | @Resource |
| | | private TyConfiguration tyConfiguration; |
| | | |
| | | @Resource |
| | | private IMediaService mediaService; |
| | | |
| | | /** |
| | | * 获取天宇token信息 |
| | |
| | | public List<BoxInfoReceiver> getBoxList() { |
| | | //请求云盒列表 |
| | | try { |
| | | TyHttpCommonReceiver<List<BoxInfoReceiver>> boxListReveiver = tyClient.getBoxList(tyConfiguration.getAccessToken().convertFromDTO()); |
| | | TyHttpCommonReceiver<List<BoxInfoReceiver>> boxListReveiver = tyClient.getBoxList(); |
| | | return boxListReveiver.getContent(); |
| | | } catch (Exception e) { |
| | | log.error("获取云盒列表失败:{}", e.getMessage()); |
| | |
| | | @Override |
| | | public BoxStreamUrlReceiver getBoxLiveUrl(String boxSn) { |
| | | |
| | | TyHttpCommonReceiver<BoxStreamUrlReceiver> boxLiveUrl = tyClient.getBoxLiveUrl(boxSn, tyConfiguration.getAccessToken().convertFromDTO()); |
| | | TyHttpCommonReceiver<BoxStreamUrlReceiver> boxLiveUrl = tyClient.getBoxLiveUrl(boxSn); |
| | | return boxLiveUrl.getContent(); |
| | | } |
| | | |
| | |
| | | */ |
| | | @Override |
| | | public List<BoxHistoryReceiver> getBoxHistory(BoxHistoryDTO boxHistoryDTO) { |
| | | TyHttpCommonReceiver<List<BoxHistoryReceiver>> boxHistory = tyClient.getBoxHistory(boxHistoryDTO, tyConfiguration.getAccessToken().convertFromDTO()); |
| | | TyHttpCommonReceiver<List<BoxHistoryReceiver>> boxHistory = tyClient.getBoxHistory(boxHistoryDTO); |
| | | return boxHistory.getContent(); |
| | | } |
| | | |
| | |
| | | */ |
| | | @Override |
| | | public List<BoxPhotosReceiver> getBoxPhotos(BoxPhotosDTO boxPhotosDTO) { |
| | | TyHttpCommonReceiver<List<BoxPhotosReceiver>> boxPhotos = tyClient.getBoxPhotos(boxPhotosDTO, tyConfiguration.getAccessToken().convertFromDTO()); |
| | | TyHttpCommonReceiver<List<BoxPhotosReceiver>> boxPhotos = tyClient.getBoxPhotos(boxPhotosDTO); |
| | | return boxPhotos.getContent(); |
| | | } |
| | | |
| | |
| | | */ |
| | | @Override |
| | | public Boolean updateBoxSettings(BoxSettingsDTO boxSettingsDTO) { |
| | | TyHttpCommonReceiver<?> result = tyClient.updateBoxSettings(boxSettingsDTO, tyConfiguration.getAccessToken().convertFromDTO()); |
| | | TyHttpCommonReceiver<?> result = tyClient.updateBoxSettings(boxSettingsDTO); |
| | | return result.getState() == 1; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * 点播 |
| | | */ |
| | | @Override |
| | | public String play(String boxSn) { |
| | | BoxStreamUrlReceiver boxLiveUrl = getBoxLiveUrl(boxSn); |
| | | if(boxLiveUrl == null||boxLiveUrl.getRtsp() == null) { |
| | | return ""; |
| | | } |
| | | ArdVtdu ardVtdu = ArdVtdu.builder().name(boxSn).rtspSource(boxLiveUrl.getRtsp()).build(); |
| | | ardVtdu = mediaService.addPath(ardVtdu); |
| | | return ardVtdu.getWebrtcUrl(); |
| | | } |
| | | |
| | | /** |
| | | * 处理天宇服务器返回的消息 |
| | | */ |
| | | @Override |
| | |
| | | log.error("发送消息异常:{}", e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | } |