dsx %!s(int64=2) %!d(string=hai) anos
pai
achega
a891a1ad98

+ 7 - 0
pom.xml

@@ -115,6 +115,13 @@
       <version>1.3.6</version>
     </dependency>
 
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpmime</artifactId>
+      <version>4.5.8</version>
+    </dependency>
+
+
   </dependencies>
 
   <build>

+ 19 - 0
src/main/java/com/fdkankan/extend/TowerSceneBean.java

@@ -0,0 +1,19 @@
+package com.fdkankan.extend;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TowerSceneBean {
+
+    private String sceneId;//站址id
+
+    private String name;//场景名称
+
+    private String roomId;//机房id
+}

+ 140 - 5
src/main/java/com/fdkankan/extend/controller/TowerController.java

@@ -1,15 +1,35 @@
 package com.fdkankan.extend.controller;
 
 import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpUtil;
+import com.fdkankan.common.util.FileUtils;
 import com.fdkankan.extend.service.ITowerService;
+import com.fdkankan.extend.util.FileUtil;
 import com.fdkankan.web.response.ResultData;
+import okhttp3.MultipartBody;
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.mime.HttpMultipartMode;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
 
+import javax.servlet.http.HttpServletRequest;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.Charset;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
@@ -20,7 +40,7 @@ public class TowerController {
     @Autowired
     private ITowerService towerService;
 
-    @GetMapping("/packSceneData")
+    @PostMapping("/packSceneData")
     public ResultData packSceneData(Long companyId, String nums){
         List<String> numList = null;
         if(StrUtil.isNotEmpty(nums)){
@@ -30,4 +50,119 @@ public class TowerController {
         return ResultData.ok();
     }
 
+    @PostMapping("/testUpload")
+    public ResultData testUpload(@RequestParam(value = "file") MultipartFile file, String arg1, HttpServletRequest request){//StandardMultipartHttpServletRequest request
+
+        String header = request.getHeader("Content-Type");
+        System.out.println(header);
+
+        System.out.println(arg1);
+
+
+//        MultipartFile file = request.getFile("file");
+        String originalFilename = file.getOriginalFilename();
+
+        return ResultData.ok(originalFilename);
+    }
+
+    /**
+     * 使用httpclint 发送文件,如果不传输文件,直接设置fileParams=null,
+     * 如果不设置请求头参数,直接设置headerParams=null,就可以进行普通参数的POST请求了
+     *
+     * @param url          请求路径
+     * @param fileParams   文件参数
+     * @param otherParams  其他字符串参数
+     * @param headerParams 请求头参数
+     * @return
+     */
+    public static String uploadFile(String url, Map<String, MultipartFile> fileParams, Map<String, String> otherParams, Map<String, String> headerParams) {
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        String result = "";
+        try {
+            HttpPost httpPost = new HttpPost(url);
+            //设置请求头
+            if (headerParams != null && headerParams.size() > 0) {
+                for (Map.Entry<String, String> e : headerParams.entrySet()) {
+                    String value = e.getValue();
+                    String key = e.getKey();
+                    if (StringUtils.isNotBlank(value)) {
+                        httpPost.setHeader(key, value);
+                    }
+                }
+            }
+            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
+            builder.setCharset(Charset.forName("utf-8"));
+            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);//加上此行代码解决返回中文乱码问题
+            //    文件传输http请求头(multipart/form-data)
+            if (fileParams != null && fileParams.size() > 0) {
+                for (Map.Entry<String, MultipartFile> e : fileParams.entrySet()) {
+                    String fileParamName = e.getKey();
+                    MultipartFile file = e.getValue();
+                    if (file != null) {
+                        String fileName = file.getOriginalFilename();
+                        builder.addBinaryBody(fileParamName, file.getInputStream(), ContentType.MULTIPART_FORM_DATA, fileName);// 文件流
+                    }
+                }
+            }
+            //    字节传输http请求头(application/json)
+            ContentType contentType = ContentType.create("application/json", Charset.forName("UTF-8"));
+            if (otherParams != null && otherParams.size() > 0) {
+                for (Map.Entry<String, String> e : otherParams.entrySet()) {
+                    String value = e.getValue();
+                    if (StringUtils.isNotBlank(value)) {
+                        builder.addTextBody(e.getKey(), value, contentType);// 类似浏览器表单提交,对应input的name和value
+                    }
+                }
+            }
+            HttpEntity entity = builder.build();
+            httpPost.setEntity(entity);
+            HttpResponse response = httpClient.execute(httpPost);// 执行提交
+            HttpEntity responseEntity = response.getEntity();
+            if (responseEntity != null) {
+                // 将响应内容转换为字符串
+                result = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                httpClient.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return result;
+    }
+
+    public static void main(String[] args) throws Exception{
+        String urlStr = "http://localhost:8361/extend/china/tower/testUpload";
+//        String picPath1 = "D://apache-maven-3.8.1-bin.zip";
+//        String arg1 = "入参1";
+//        Map<String, String> headerParams = new HashMap<>();
+//        headerParams.put("token", "testToken");
+//
+//        Map<String, MultipartFile> fileParams = new HashMap<>();
+//        //本地文件转为MultipartFile
+////        String picPath = "/var/111.png";
+//        MultipartFile file1 = FileUtil.pathToMultipartFile(picPath1);
+//        //url转为MultipartFile
+//        fileParams.put("file", file1);
+//
+//        Map<String, String> otherParams = new HashMap<>();
+//        otherParams.put("arg1", arg1);
+//
+//        String res = uploadFile(URL, fileParams, otherParams, headerParams);
+        Map<String, Object> map = new HashMap<>();
+//        map.put("file", FileUtil.createFileItem("D://apache-maven-3.8.1-bin.zip"));
+        map.put("file", new File("D://apache-maven-3.8.1-bin.zip"));
+        map.put("arg1", "第一个参数");
+        String post = HttpUtil.post(urlStr, map);
+//        String body = HttpRequest.post(urlStr).form(map).contentType("multipart/form-data").execute().body();
+
+    }
+
+
+
 }

+ 82 - 0
src/main/java/com/fdkankan/extend/entity/Camera.java

@@ -0,0 +1,82 @@
+package com.fdkankan.extend.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * <p>
+ * 相机主表
+ * </p>
+ *
+ * @author 
+ * @since 2022-07-05
+ */
+@Getter
+@Setter
+@TableName("t_camera")
+public class Camera implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 相机的Mac地址
+     */
+    @TableField("child_name")
+    private String childName;
+
+    /**
+     * 激活时间
+     */
+    @TableField("activated_time")
+    private Date activatedTime;
+
+    /**
+     * 相机密码
+     */
+    @TableField("child_password")
+    private String childPassword;
+
+    /**
+     * sn码
+     */
+    @TableField("sn_code")
+    private String snCode;
+
+    /**
+     * wifi名称
+     */
+    @TableField("wifi_name")
+    private String wifiName;
+
+    /**
+     * wifi密码
+     */
+    @TableField("wifi_password")
+    private String wifiPassword;
+
+    /**
+     * 创建时间
+     */
+    @TableField("create_time")
+    private Date createTime;
+
+    /**
+     * 更新时间
+     */
+    @TableField("update_time")
+    private Date updateTime;
+
+    /**
+     * 记录的状态,A: 生效,I: 禁用
+     */
+    @TableField("rec_status")
+    @TableLogic(value = "A", delval = "I")
+    private String recStatus;
+}

+ 41 - 38
src/main/java/com/fdkankan/extend/listener/RabbitMqListener.java

@@ -2,6 +2,7 @@ package com.fdkankan.extend.listener;
 
 import cn.hutool.core.exceptions.ExceptionUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.fdkankan.common.constant.CommonSuccessStatus;
 import com.fdkankan.extend.service.ITowerService;
 import com.fdkankan.redis.util.RedisUtil;
@@ -30,44 +31,46 @@ import java.util.Map;
 @Component
 public class RabbitMqListener {
 
-//    @Value("${queue.modeling.extend.tower.data-push}")
-//    private String queueName;
-//    @Autowired
-//    private ITowerService towerService;
-//    @Autowired
-//    private RedisUtil redisUtil;
-//
-//    /**
-//     * 铁塔项目数据推送监听器
-//     * @param channel
-//     * @param message
-//     * @throws Exception
-//     */
-//    @RabbitListener(
-//        queuesToDeclare = @Queue("${queue.modeling.extend.tower.data-push}")
-//    )
-//    public void transferTourVideo(Channel channel, Message message) throws Exception {
-//        String key = "tower:scene:data:download";
-//        String messageId = message.getMessageProperties().getMessageId();
-//        String num = new String(message.getBody(), StandardCharsets.UTF_8);
-//        log.info("开始消费消息,id:{},queue:{},content:{}", messageId, queueName, num);
-//        Map<String, Object> map = new HashMap<>();
-//        try {
-//            String zipPath = towerService.packSceneDataHandler(num);
-//            // TODO: 2023/6/20 推送到铁塔
-//
-//            map.put("status", CommonSuccessStatus.SUCCESS.code());
-//            map.put("zipPath", zipPath);
-//            redisUtil.hset(key, num, JSON.toJSONString(map));
-//        }catch (Exception e){
-//            map.put("status", CommonSuccessStatus.FAIL.code());
-//            map.put("error", ExceptionUtil.stacktraceToString(e, 3000));
-//            redisUtil.hset(key, num, JSON.toJSONString(map));
-//        }
-//
-//        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
-//        log.info("结束消费消息,id:{}", messageId);
-//    }
+    @Value("${queue.modeling.extend.tower.data-push}")
+    private String queueName;
+    @Autowired
+    private ITowerService towerService;
+    @Autowired
+    private RedisUtil redisUtil;
+
+    /**
+     * 铁塔项目数据推送监听器
+     * @param channel
+     * @param message
+     * @throws Exception
+     */
+    @RabbitListener(
+        queuesToDeclare = @Queue("${queue.modeling.extend.tower.data-push}")
+    )
+    public void towerSceneDataPush(Channel channel, Message message) throws Exception {
+        String key = "tower:scene:data:download";
+        String messageId = message.getMessageProperties().getMessageId();
+        String content = new String(message.getBody(), StandardCharsets.UTF_8);
+        JSONObject jsonObject = JSON.parseObject(content);
+        String num = jsonObject.getString("num");
+        String title = jsonObject.getString("title");
+        log.info("开始消费消息,id:{},queue:{},content:{}", messageId, queueName, content);
+        Map<String, Object> map = new HashMap<>();
+        map.put("title", title);
+        try {
+            String zipPath = towerService.packSceneDataHandler(num, title);
+            map.put("status", CommonSuccessStatus.SUCCESS.code());
+            map.put("zipPath", zipPath);
+            redisUtil.hset(key, num, JSON.toJSONString(map));
+        }catch (Exception e){
+            map.put("status", CommonSuccessStatus.FAIL.code());
+            map.put("error", ExceptionUtil.stacktraceToString(e, 3000));
+            redisUtil.hset(key, num, JSON.toJSONString(map));
+        }
+
+        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+        log.info("结束消费消息,id:{}", messageId);
+    }
 
 
 

+ 18 - 0
src/main/java/com/fdkankan/extend/mapper/ICameraMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.extend.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.fdkankan.extend.entity.Camera;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 相机主表 Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2022-07-05
+ */
+@Mapper
+public interface ICameraMapper extends BaseMapper<Camera> {
+
+}

+ 23 - 0
src/main/java/com/fdkankan/extend/service/ICameraService.java

@@ -0,0 +1,23 @@
+package com.fdkankan.extend.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.fdkankan.extend.entity.Camera;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 相机主表 服务类
+ * </p>
+ *
+ * @author 
+ * @since 2022-07-05
+ */
+public interface ICameraService extends IService<Camera> {
+
+    Camera findByChildName(String childName);
+
+    List<Camera> listBySnCodes(List<String> snCodes);
+
+
+}

+ 11 - 1
src/main/java/com/fdkankan/extend/service/ITowerService.java

@@ -2,12 +2,22 @@ package com.fdkankan.extend.service;
 
 import com.fdkankan.web.response.ResultData;
 
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
 import java.util.List;
 
 public interface ITowerService {
 
-    public String packSceneDataHandler(String num);
+    public String packSceneDataHandler(String num, String title) throws Exception;
 
     public void packSceneData(Long companyId, List<String> nums);
 
+    public void dataPush(String num, String title, String sceneId, String roomId, String zipPath) throws NoSuchPaddingException, NoSuchAlgorithmException, IOException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidKeySpecException, Exception;
+
+
 }

+ 36 - 0
src/main/java/com/fdkankan/extend/service/impl/CameraServiceImpl.java

@@ -0,0 +1,36 @@
+package com.fdkankan.extend.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fdkankan.extend.entity.Camera;
+import com.fdkankan.extend.mapper.ICameraMapper;
+import com.fdkankan.extend.service.ICameraService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 相机主表 服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2022-07-05
+ */
+@Service
+public class CameraServiceImpl extends ServiceImpl<ICameraMapper, Camera> implements ICameraService {
+
+    @Override
+    public Camera findByChildName(String childName) {
+        return this.getOne(new LambdaQueryWrapper<Camera>().eq(Camera::getChildName, childName));
+    }
+
+    @Override
+    public List<Camera> listBySnCodes(List<String> snCodes) {
+        if(CollUtil.isEmpty(snCodes)){
+            return null;
+        }
+        return this.list(new LambdaQueryWrapper<Camera>().in(Camera::getSnCode, snCodes));
+    }
+}

+ 129 - 34
src/main/java/com/fdkankan/extend/service/impl/TowerServiceImpl.java

@@ -5,35 +5,66 @@ import cn.hutool.core.exceptions.ExceptionUtil;
 import cn.hutool.core.io.FileUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.ZipUtil;
+import cn.hutool.http.HttpUtil;
 import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.fdkankan.common.constant.CommonSuccessStatus;
+import com.fdkankan.extend.TowerSceneBean;
+import com.fdkankan.extend.entity.Camera;
 import com.fdkankan.extend.entity.CameraDetail;
 import com.fdkankan.extend.entity.ScenePlus;
 import com.fdkankan.extend.service.ICameraDetailService;
+import com.fdkankan.extend.service.ICameraService;
 import com.fdkankan.extend.service.IScenePlusService;
 import com.fdkankan.extend.service.ITowerService;
+import com.fdkankan.extend.util.RsaCryptTools;
 import com.fdkankan.fyun.face.FYunFileServiceInterface;
 import com.fdkankan.redis.constant.RedisKey;
 import com.fdkankan.redis.util.RedisUtil;
 import com.fdkankan.web.response.ResultData;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
 import org.springframework.stereotype.Service;
 import com.fdkankan.model.constants.UploadFilePath;
 
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+import java.util.*;
 import java.util.stream.Collectors;
 
+@RefreshScope
 @Slf4j
 @Service
 public class TowerServiceImpl implements ITowerService {
 
     private static String parentPath = "/home/backend/4dkankan_v4/modeling-extend/download/";
 
+    private static String ossParentPath = "customer-projects/china-tower/";
+
+    private static String ossScenePoolFilePath = ossParentPath.concat("scene.txt");
+
+    private static String ossCameraPoolFilePath = ossParentPath.concat("camera.txt");
+
+    private static String pushLogPath = parentPath.concat("log.txt");
+
+    @Value("${tower.manufact}")
+    private String manufact;
+
+    @Value("${tower.private-key}")
+    private String privateKey;
+
+    @Value("${tower.url}")
+    private String url;
+
     @Autowired
     private FYunFileServiceInterface fYunFileService;
     @Autowired
@@ -44,18 +75,33 @@ public class TowerServiceImpl implements ITowerService {
     private IScenePlusService scenePlusService;
     @Autowired
     private ITowerService towerService;
+    @Autowired
+    private ICameraService cameraService;
 
     @Override
-    public String packSceneDataHandler(String num) {
+    public String packSceneDataHandler(String num, String title) throws Exception {
+
+        //校验场景名称是否正确
+        String sceneStr = fYunFileService.getFileContent(ossScenePoolFilePath);
+        List<TowerSceneBean> towerSceneBeans = JSON.parseArray(sceneStr, TowerSceneBean.class);
+        if(CollUtil.isEmpty(towerSceneBeans)){
+            return null;
+        }
+        TowerSceneBean towerSceneBean = towerSceneBeans.stream().filter(bean -> title.equals(bean.getName())).findFirst().get();
+        if(Objects.isNull(towerSceneBean)){
+            return null;
+        }
+
 
         log.info("开始下载:{}", num);
 
         //场景本地数据父目录
-        String sceneSourcePath = parentPath + num + "/";
-        String zipPath = parentPath + num + ".zip";
+        String scenePath = parentPath.concat(num).concat("/");
+        String sceneSourcePath = scenePath.concat(towerSceneBean.getSceneId()).concat("_").concat(towerSceneBean.getRoomId());
+        String zipPath = sceneSourcePath.concat(".zip");
 
         //data数据下载
-        String dataPath = sceneSourcePath + "data/";
+        String dataPath = sceneSourcePath + "/data/";
         String ossDataPath = String.format(UploadFilePath.DATA_VIEW_PATH, num);
         //下载floorplan.json
         fYunFileService.downloadFile(ossDataPath.concat("floorplan.json"), dataPath.concat("floorplan.json"));
@@ -70,26 +116,44 @@ public class TowerServiceImpl implements ITowerService {
         FileUtil.writeUtf8String(sceneJsonObj.toJSONString(), sceneJsonPath);
 
         //下载mesh
-        fYunFileService.downloadFileByCommand(dataPath, ossDataPath.concat("mesh"));
+        FileUtil.mkdir(dataPath.concat("mesh/"));
+        List<String> meshList = fYunFileService.listRemoteFiles(ossDataPath.concat("mesh"));
+        meshList.parallelStream().forEach(key -> fYunFileService.downloadFile(key, dataPath.concat("mesh/")));
 
         //images数据下载
-        String imagesPath = sceneSourcePath + "images/";
+        String imagesPath = sceneSourcePath + "/images/";
         String ossImagesPath = String.format(UploadFilePath.IMG_VIEW_PATH, num);
         //下载high图
-        fYunFileService.downloadFileByCommand(imagesPath.concat("4k/"), ossImagesPath.concat("pan/high/"));
+        List<String> highList = fYunFileService.listRemoteFiles(ossImagesPath.concat("pan/high/"));
+        FileUtil.mkdir(imagesPath.concat("4k/"));
+        highList.parallelStream().forEach(key -> fYunFileService.downloadFile(key, imagesPath.concat("4k/")));
         //下载low图
-        fYunFileService.downloadFileByCommand(imagesPath.concat("512/"), ossImagesPath.concat("pan/low/"));
+        FileUtil.mkdir(imagesPath.concat("512/"));
+        List<String> lowList = fYunFileService.listRemoteFiles(ossImagesPath.concat("pan/low/"));
+        lowList.parallelStream().forEach(key -> fYunFileService.downloadFile(key, imagesPath.concat("512/")));
         //下载vision.txt
         fYunFileService.downloadFile(ossImagesPath.concat("vision.txt"), imagesPath.concat("vision.txt"));
 
         //打包
-        ZipUtil.zip(sceneSourcePath, zipPath);
+        ZipUtil.zip(sceneSourcePath, zipPath, true);
+
+        log.info("结束下载,开始推送:{}", num);
 
-        log.info("结束下载:{}", num);
+        try {
+//            this.dataPush(num, title, towerSceneBean.getSceneId(), towerSceneBean.getRoomId(), zipPath);
+        }finally {
+            FileUtil.del(scenePath);
+            FileUtil.del(sceneSourcePath);
+        }
 
         return zipPath;
     }
 
+    public static void main(String[] args) {
+        boolean directory = FileUtil.isDirectory("/home/backend/4dkankan_v4/modeling-extend/download/KK-t-rXyBOE9LG8F/123123_456456/images/4k/");
+        System.out.println(directory);
+    }
+
     @Override
     public void packSceneData(Long companyId, List<String> nums) {
 
@@ -108,6 +172,15 @@ public class TowerServiceImpl implements ITowerService {
             scenePlusList = scenePlusService.getByCameraIds(cameraIds);
         }else if(CollUtil.isNotEmpty(nums)){
             scenePlusList = scenePlusService.list(new LambdaQueryWrapper<ScenePlus>().in(ScenePlus::getNum, nums));
+        }else{
+            String snCodeStr = fYunFileService.getFileContent(ossCameraPoolFilePath);
+            List<String> snCodeList = Arrays.asList(snCodeStr.split(","));
+            List<Camera> cameraList = cameraService.listBySnCodes(snCodeList);
+            List<Long> cameraIdList = cameraList.stream().map(Camera::getId).collect(Collectors.toList());
+            String sceneStr = fYunFileService.getFileContent(ossScenePoolFilePath);
+            List<TowerSceneBean> towerSceneBeans = JSON.parseArray(sceneStr, TowerSceneBean.class);
+            List<String> titleList = towerSceneBeans.stream().map(TowerSceneBean::getName).collect(Collectors.toList());
+            scenePlusList = scenePlusService.list(new LambdaQueryWrapper<ScenePlus>().in(ScenePlus::getCameraId, cameraIdList).in(ScenePlus::getTitle, titleList));
         }
         if(CollUtil.isEmpty(scenePlusList)){
             return;
@@ -115,28 +188,50 @@ public class TowerServiceImpl implements ITowerService {
 
         //遍历场景列表开始下载
         scenePlusList.stream().forEach(plus -> {
-            JSONObject jsonObject = null;
-            String str = redisUtil.hget(key, plus.getNum());
-            if(StrUtil.isNotEmpty(str)){
-                jsonObject = JSON.parseObject(str);
-            }
-            if(Objects.isNull(jsonObject) || jsonObject.getInteger("status") == CommonSuccessStatus.FAIL.code()){
-                try {
-                    jsonObject = new JSONObject();
-                    jsonObject.put("num", plus.getNum());
-                    String zipPath = towerService.packSceneDataHandler(plus.getNum());
-
-                    // TODO: 2023/6/20 推送到铁塔
-
-                    jsonObject.put("status", CommonSuccessStatus.SUCCESS.code());
-                    jsonObject.put("zipPath", zipPath);
-                    redisUtil.hset(key, plus.getNum(), JSON.toJSONString(jsonObject));
-                }catch (Exception e){
-                    jsonObject.put("status", CommonSuccessStatus.FAIL.code());
-                    jsonObject.put("error", ExceptionUtil.stacktraceToString(e, 3000));
-                    redisUtil.hset(key, plus.getNum(), JSON.toJSONString(jsonObject));
-                }
+            JSONObject jsonObject = new JSONObject();
+            try {
+                jsonObject = new JSONObject();
+                jsonObject.put("title", plus.getTitle());
+                jsonObject.put("num", plus.getNum());
+                String zipPath = towerService.packSceneDataHandler(plus.getNum(), plus.getTitle());
+                jsonObject.put("status", CommonSuccessStatus.SUCCESS.code());
+                jsonObject.put("zipPath", zipPath);
+                redisUtil.hset(key, plus.getNum(), JSON.toJSONString(jsonObject));
+            }catch (Exception e){
+                log.error("推送失败,num:{},title:{}", plus.getNum(), plus.getTitle(), e);
+                jsonObject.put("status", CommonSuccessStatus.FAIL.code());
+                jsonObject.put("error", ExceptionUtil.stacktraceToString(e, 3000));
+                redisUtil.hset(key, plus.getNum(), JSON.toJSONString(jsonObject));
             }
         });
     }
+
+    @Override
+    public void dataPush(String num, String title, String sceneId, String roomId, String zipPath) throws Exception {
+
+        String fileMd5 = com.fdkankan.extend.util.FileUtil.getMulFileMD5(FileUtil.getInputStream(zipPath));
+        String compose = sceneId.concat("+").concat(roomId).concat("+").concat(fileMd5);
+        String encrypt = RsaCryptTools.encryptData(compose, privateKey);
+
+        Map<String, Object> params = new HashMap<>();
+        params.put("stationCode", sceneId);
+        params.put("roomEntityID", roomId);
+        params.put("file", FileUtil.file(zipPath));
+        params.put("manufact", manufact);
+        params.put("encrypt", encrypt);
+        String post = HttpUtil.post(url, params);
+        JSONObject jsonObject = JSON.parseObject(post);
+
+        this.dataPushLog(num, title, jsonObject.getString("resultCode"), jsonObject.getString("resultMsg"));
+
+    }
+
+    private void dataPushLog(String num, String title, String resultCode, String resultMsg){
+        String content = num.concat("-").concat(title).concat(" : ").concat(resultCode);
+        if(StrUtil.isNotEmpty(resultMsg)){
+            content = content.concat("-").concat(resultMsg);
+        }
+        content = content.concat("\r\n");
+        FileUtil.writeUtf8String(content, parentPath);
+    }
 }

+ 95 - 0
src/main/java/com/fdkankan/extend/util/FileUtil.java

@@ -0,0 +1,95 @@
+package com.fdkankan.extend.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.commons.CommonsMultipartFile;
+
+import java.io.*;
+import java.security.MessageDigest;
+
+@Slf4j
+public class FileUtil {
+ 
+    /**
+     * 本地文件转为MultipartFile
+     *
+     * @param picPath
+     * @return
+     */
+    public static MultipartFile pathToMultipartFile(String picPath) throws Exception{
+        FileItem fileItem = createFileItem(picPath);
+        MultipartFile mfile = new CommonsMultipartFile(fileItem);
+        return mfile;
+    }
+ 
+    /**
+     * 将file转换成fileItem
+     *
+     * @param filePath
+     * @return
+     */
+    public static FileItem createFileItem(String filePath) throws Exception{
+        FileItemFactory factory = new DiskFileItemFactory(16, null);
+        String textFieldName = "textField";
+ 
+        FileItem item = factory.createItem(textFieldName, "text/plain", true, "MyFileName");
+        File newfile = new File(filePath);
+        int bytesRead = 0;
+        byte[] buffer = new byte[8192];
+        FileInputStream fis = null;
+        OutputStream os = null;
+        try {
+            fis = new FileInputStream(newfile);
+            os = item.getOutputStream();
+            while ((bytesRead = fis.read(buffer, 0, 8192)) != -1) {
+                os.write(buffer, 0, bytesRead);
+            }
+        } catch (IOException e) {
+            log.error("createFileItem:文件转换异常!",e);
+            throw e;
+        } finally {
+            try {
+                if (null != os){
+                    os.close();
+                }
+                if (null != fis){
+                    fis.close();
+                }
+            } catch (IOException e) {
+                log.error("createFileItem:关流异常!",e);
+            }
+        }
+        return item;
+    }
+
+    /**
+     * 获取一个文件的md5值(可处理大文件)
+     * @return md5 value
+     */
+    public static String getMulFileMD5(InputStream fileInputStream) {
+        try {
+            MessageDigest MD5 = MessageDigest.getInstance("MD5");
+            byte[] buffer = new byte[8192];
+            int length;
+            while ((length = fileInputStream.read(buffer)) != -1) {
+                MD5.update(buffer, 0, length);
+            }
+            return new String(Hex.encodeHex(MD5.digest()));
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        } finally {
+            try {
+                if (fileInputStream != null){
+                    fileInputStream.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}

+ 163 - 0
src/main/java/com/fdkankan/extend/util/RsaCryptTools.java

@@ -0,0 +1,163 @@
+package com.fdkankan.extend.util;
+
+import org.bouncycastle.crypto.InvalidCipherTextException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.*;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+import java.util.Base64;
+
+/**
+ * RSA 加密工具 参考:https://www.devglan.com/java8/rsa-encryption-decryption-java
+ * 加密过长的会报错:
+ Data must not be longer than 245 bytes
+ 原因是应为不同长度的密钥对应可以加密不同最大长度的原文,2048就对应245
+ 解决办法是:
+ 1.分段
+ 2.RSA加密是有长度限制的.单纯用RSA加密较长数据时得使用分段加密,效率低下.用RSA+AES是比较主流的做法:AES加密数据产生密文,RSA加密AES密钥产生加密后的AES密钥,然后将密文和加密后的AES密钥一起传输
+ * @author wangjianjin
+ */
+public class RsaCryptTools {
+    private static final String CHARSET = "utf-8";
+    private static final Base64.Decoder decoder64 = Base64.getDecoder();
+    private static final Base64.Encoder encoder64 = Base64.getEncoder();
+
+    /**
+     *
+     * 生成公私钥 范围: 512 - 2048
+     *
+     * @param keySize
+     * @return
+     * @throws NoSuchAlgorithmException
+     */
+    public static SecretKey generateSecretKey(int keySize) throws NoSuchAlgorithmException {
+        //生成密钥对
+        KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
+        keyGen.initialize(keySize, new SecureRandom());
+        KeyPair pair = keyGen.generateKeyPair();
+        PrivateKey privateKey = pair.getPrivate();
+        PublicKey publicKey = pair.getPublic();
+        //这里可以将密钥对保存到本地
+        return new SecretKey(encoder64.encodeToString(publicKey.getEncoded()), encoder64.encodeToString(privateKey.getEncoded()));
+    }
+    /**
+     * 私钥加密
+     * @param data
+     * @param privateInfoStr
+     * @return
+     * @throws IOException
+     * @throws InvalidCipherTextException
+     */
+    public static String encryptData(String data, String privateInfoStr) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, BadPaddingException, IllegalBlockSizeException {
+
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+        cipher.init(Cipher.ENCRYPT_MODE, getPrivateKey(privateInfoStr));
+        return encoder64.encodeToString(cipher.doFinal(data.getBytes(CHARSET)));
+    }
+
+    /**
+     * 公钥解密
+     * @param data
+     * @param publicInfoStr
+     * @return
+     */
+    public static String decryptData(String data, String publicInfoStr) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
+        byte[] encryptDataBytes=decoder64.decode(data.getBytes(CHARSET));
+        //解密
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
+        cipher.init(Cipher.DECRYPT_MODE, getPublicKey(publicInfoStr));
+        return new String(cipher.doFinal(encryptDataBytes), CHARSET);
+    }
+
+    private static PublicKey getPublicKey(String base64PublicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(base64PublicKey.getBytes()));
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        return keyFactory.generatePublic(keySpec);
+    }
+
+    private static PrivateKey getPrivateKey(String base64PrivateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        PrivateKey privateKey = null;
+        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(base64PrivateKey.getBytes()));
+        KeyFactory keyFactory = null;
+        keyFactory = KeyFactory.getInstance("RSA");
+        privateKey = keyFactory.generatePrivate(keySpec);
+        return privateKey;
+    }
+
+    /**
+     * 密钥实体
+     * @author wangjj
+     */
+    public static class SecretKey {
+        /**
+         * 公钥
+         */
+        private String publicKey;
+        /**
+         * 私钥
+         */
+        private String privateKey;
+
+        public SecretKey(String publicKey, String privateKey) {
+            this.publicKey = publicKey;
+            this.privateKey = privateKey;
+        }
+
+        public String getPublicKey() {
+            return publicKey;
+        }
+
+        public void setPublicKey(String publicKey) {
+            this.publicKey = publicKey;
+        }
+
+        public String getPrivateKey() {
+            return privateKey;
+        }
+
+        public void setPrivateKey(String privateKey) {
+            this.privateKey = privateKey;
+        }
+
+        @Override
+        public String toString() {
+            return "SecretKey{" +
+                    "publicKey='" + publicKey + '\'' +
+                    ", privateKey='" + privateKey + '\'' +
+                    '}';
+        }
+    }
+
+    private static void writeToFile(String path, byte[] key) throws IOException {
+        File f = new File(path);
+        f.getParentFile().mkdirs();
+
+        try(FileOutputStream fos = new FileOutputStream(f)) {
+            fos.write(key);
+            fos.flush();
+        }
+    }
+
+    public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchPaddingException, IOException, BadPaddingException, IllegalBlockSizeException, InvalidKeyException, InvalidKeySpecException {
+        SecretKey secretKey = generateSecretKey(512);
+        System.out.println(secretKey.toString());
+        String enStr = encryptData("stationCode_entityID_fileMd5", secretKey.getPrivateKey());
+        System.out.println(enStr);
+        String deStr = decryptData(enStr, secretKey.getPublicKey());
+        System.out.println(deStr);
+        enStr = encryptData("站址编码_机房实体ID_文件Md5", secretKey.getPrivateKey());
+        System.out.println(enStr);
+        deStr = decryptData(enStr, secretKey.getPublicKey());
+        System.out.println(deStr);
+    }
+
+}