#
luxiaotao1123
2021-06-03 958b12cccc9e0043eb0c6b9bb84ebdf554ebe1a1
#
5个文件已添加
11个文件已修改
561 ■■■■■ 已修改文件
pom.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/WorkController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/param/CombParam.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/mapper/BasDevpMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/BasAgvService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/BasDevpService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/BasAgvServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/BasDevpServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/model/agv/AgvCommand.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/model/agv/AgvInfo.java 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/model/agv/AgvResult.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/model/enums/AgvStatusType.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/common/utils/HttpHandler.java 213 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/application.yml 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/views/pda/combAgv.html 49 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -97,6 +97,11 @@
            <version>1.16.22</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>3.10.0</version>
        </dependency>
    </dependencies>
    <build>
src/main/java/com/zy/asrs/controller/WorkController.java
@@ -29,6 +29,12 @@
    @Autowired
    private BasDevpService basDevpService;
    @RequestMapping("/agv/put/site")
    @ManagerAuth(memo = "获取AGV工作区")
    public R availableAgvSite(){
        return R.ok().add(basDevpService.getAgvAvailableInSite());
    }
    @RequestMapping("/available/put/site")
    @ManagerAuth(memo = "获取入库站点")
    public R availablePutSite(){
src/main/java/com/zy/asrs/entity/param/CombParam.java
@@ -23,6 +23,9 @@
    private String billNo;
    // 小车取货点
    private Integer agvSite;
    public String getWarehouse() {
        return warehouse;
    }
@@ -117,4 +120,12 @@
    public void setBillNo(String billNo) {
        this.billNo = billNo;
    }
    public Integer getAgvSite() {
        return agvSite;
    }
    public void setAgvSite(Integer agvSite) {
        this.agvSite = agvSite;
    }
}
src/main/java/com/zy/asrs/mapper/BasDevpMapper.java
@@ -4,6 +4,7 @@
import com.zy.asrs.entity.BasDevp;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import java.util.List;
@@ -12,6 +13,9 @@
@Repository
public interface BasDevpMapper extends BaseMapper<BasDevp> {
    @Select("select dev_no from asr_bas_devp where 1=1 and fronting = 'Y' order by dev_no")
    List<Integer> getAgvInArea();
    List<Integer> getAvailableInSite(@Param("typeNo") Integer typeNo);
    List<Integer> getAvailableOutSite(@Param("typeNo") Integer typeNo);
src/main/java/com/zy/asrs/service/BasAgvService.java
@@ -5,4 +5,6 @@
public interface BasAgvService extends IService<BasAgv> {
    BasAgv selectIdleAgv();
}
src/main/java/com/zy/asrs/service/BasDevpService.java
@@ -8,6 +8,12 @@
public interface BasDevpService extends IService<BasDevp> {
    /**
     * Agv工作区
     * @return
     */
    List<Integer> getAgvAvailableInSite();
    /**
     * 入库站
     * @return
     */
src/main/java/com/zy/asrs/service/impl/BasAgvServiceImpl.java
@@ -1,12 +1,32 @@
package com.zy.asrs.service.impl;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.Cools;
import com.core.exception.CoolException;
import com.zy.asrs.mapper.BasAgvMapper;
import com.zy.asrs.entity.BasAgv;
import com.zy.asrs.service.BasAgvService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service("basAgvService")
public class BasAgvServiceImpl extends ServiceImpl<BasAgvMapper, BasAgv> implements BasAgvService {
    @Override
    public BasAgv selectIdleAgv() {
        List<BasAgv> idleAgvs = this.selectList(new EntityWrapper<BasAgv>()
                .eq("in_enable", "Y")
                .eq("is_user", 1)
                .eq("status", 6)
        );
        if (Cools.isEmpty(idleAgvs)) {
            log.warn("没有空闲的Agv小车");
            throw new CoolException("没有空闲的Agv小车");
        }
        return idleAgvs.get(0);
    }
}
src/main/java/com/zy/asrs/service/impl/BasDevpServiceImpl.java
@@ -18,6 +18,11 @@
    private WrkMastService wrkMastService;
    @Override
    public List<Integer> getAgvAvailableInSite() {
        return this.baseMapper.getAgvInArea();
    }
    @Override
    public List<Integer> getAvailableInSite() {
        return this.baseMapper.getAvailableInSite(1);
    }
src/main/java/com/zy/asrs/service/impl/MobileServiceImpl.java
@@ -1,34 +1,48 @@
package com.zy.asrs.service.impl;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.core.common.BaseRes;
import com.core.common.Cools;
import com.core.exception.CoolException;
import com.zy.asrs.entity.BasAgv;
import com.zy.asrs.entity.MatCode;
import com.zy.asrs.entity.WaitPakin;
import com.zy.asrs.entity.param.CombParam;
import com.zy.asrs.service.BasAgvService;
import com.zy.asrs.service.MatCodeService;
import com.zy.asrs.service.MobileService;
import com.zy.asrs.service.WaitPakinService;
import com.zy.asrs.utils.VersionUtils;
import com.zy.common.model.agv.AgvCommand;
import com.zy.common.model.agv.AgvResult;
import com.zy.common.utils.HttpHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.util.Date;
/**
 * 移动端服务核心类
 * Created by vincent on 2020/6/28
 */
@Slf4j
@Service
public class MobileServiceImpl implements MobileService {
    @Value("${agv.url}")
    private String agvUrl;
    @Autowired
    private MatCodeService matCodeService;
    @Autowired
    private WaitPakinService waitPakinService;
    @Autowired
    private BasAgvService basAgvService;
    @Override
    @Transactional
@@ -66,6 +80,34 @@
                        throw new CoolException("保存数据失败");
                    }
                }
                // 小车入库搬运命令 ----------------------------------------------------
                if (!Cools.isEmpty(param.getAgvSite())) {
                    BasAgv idleAgv = basAgvService.selectIdleAgv();
                    AgvCommand command = new AgvCommand();
                    command.setAgvId(idleAgv.getAgvId());
                    command.setInterCode("8888");
                    command.setBeginLoc(String.valueOf(param.getAgvSite()));
                    command.setEndLoc("10");
                    log.info(JSON.toJSONString(command));
                    String result;
                    try {
                        result = new HttpHandler.Builder()
                                .setUri(agvUrl + "/api/interfaceTask/SendTaskByThirdParty")
                                .setJson(JSON.toJSONString(command))
                                .build()
                                .doPost();
                    } catch (IOException e) {
                        e.printStackTrace();
                        throw new CoolException("访问AGV接口失败");
                    }
                    AgvResult agvResult = JSON.parseObject(result, AgvResult.class);
                    log.info(JSON.toJSONString(agvResult));
                    if (!agvResult.getResult()) {
                        log.error("agv命令发送失败[agvId={}],错误信息={}", command.getAgvId(), agvResult.getExplain());
                        throw new CoolException("agv命令发送失败[agvId=" + command.getAgvId() + "],错误信息=" + agvResult.getExplain());
                    }
                }
            } else {
                WaitPakin waitPakin = new WaitPakin();
                waitPakin.setZpallet(param.getBarcode());   // 托盘码
src/main/java/com/zy/common/model/agv/AgvCommand.java
New file
@@ -0,0 +1,41 @@
package com.zy.common.model.agv;
import lombok.Data;
/**
 * Created by vincent on 2021/5/19
 */
@Data
public class AgvCommand {
    // 小车号
    private Integer AgvId;
    // 任务号
    private String InterCode;
    // 任务优先级 固定 - 5
    private String Sort = "5";
    // 开始货位
    private String BeginLoc;
    // 开始货位层级 固定 - 1
    private String BeginLevel = "1";
    // 目的货位
    private String EndLoc;
    // 目的货位层级
    private String EndLevel = "1";
    // 任务类型(3:取放货;5:取货+载货行走;6: 载货行走+放货) 固定 3
    private String TaskType = "3";
    // 托盘码
    private String TrayCode;
    // 托盘类型 固定 1
    private String SalverType = "1";
}
src/main/java/com/zy/common/model/agv/AgvInfo.java
New file
@@ -0,0 +1,76 @@
package com.zy.common.model.agv;
import com.alibaba.fastjson.annotation.JSONField;
import com.core.common.Cools;
import com.zy.asrs.entity.BasAgv;
import com.zy.common.model.enums.AgvStatusType;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
 * Created by vincent on 2021/5/19
 */
@Data
public class AgvInfo implements Cloneable, Serializable {
    private static final long serialVersionUID = 1L;
    // 小车编号
    private Integer Id;
    // 是否启用(true:启用,false:禁用)
    private Boolean IsUse;
    // 当前位置点位
    private String CurrentNode;
    // 当前电量
    private String Power;
    // 一般状态(01:前往取货点,02:取货点取货,03:前往送货点,04:送货点放货,05:任务完成,06:空闲,07:故障,08:充电中,09:手动,10:失联,11:离线,12:行走)
    private String Status;
    @JSONField(serialize = false)
    private transient AgvStatusType agvStatus;
    // 故障码
    private String Fault;
    // 任务号
    private String taskcode;
    // 任务点
    private String Point_Number;
    // 任务类型(1:行走,2:取货,3:放货,4:充电)
    private String ActionType;
    @Override
    public AgvInfo clone() {
        try {
            return (AgvInfo) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
    public BasAgv toSqlModel(){
        BasAgv basAgv = new BasAgv();
        basAgv.setAgvId(this.getId());
        basAgv.setIsUser(this.getIsUse()?1:0);
        basAgv.setCurrentNode(this.getCurrentNode());
        basAgv.setPower(this.getPower());
        basAgv.setStatus(Cools.isEmpty(this.getAgvStatus())?0:Integer.parseInt(this.getAgvStatus().id));
        basAgv.setFault(this.getFault());
        basAgv.setTaskCode(this.getTaskcode());
        basAgv.setEndLoc(this.getPoint_Number());
        basAgv.setAction(Cools.isEmpty(this.getActionType())?0:Integer.parseInt(this.getActionType()));
        basAgv.setModiTime(new Date());
        return basAgv;
    }
}
src/main/java/com/zy/common/model/agv/AgvResult.java
New file
@@ -0,0 +1,25 @@
package com.zy.common.model.agv;
import lombok.Data;
/**
 * Created by vincent on 2021/5/19
 */
@Data
public class AgvResult {
    // 反馈结果
    private Boolean Result;
    // 结果说明
    private String Explain;
    public AgvResult() {
    }
    public AgvResult(Boolean result, String explain) {
        Result = result;
        Explain = explain;
    }
}
src/main/java/com/zy/common/model/enums/AgvStatusType.java
New file
@@ -0,0 +1,51 @@
package com.zy.common.model.enums;
public enum AgvStatusType {
    GOTO_TAKE("01", "前往取货点"),
    TAKING("02", "取货点取货"),
    GOTO_PUT("03", "前往送货点"),
    PUTTING("04", "送货点放货"),
    COMPLETE("05", "任务完成"),
    IDLE("06", "空闲"),
    ERROR("07", "故障"),
    CHARGING("08", "充电中"),
    HANDLE("09", "手动"),
    DISPLAY("010", "失联"),
    SOS("011" , "离线"),
    WORKING("012", "行走"),
    ;
    public String id;
    public String desc;
    AgvStatusType(String id, String desc) {
        this.id = id;
        this.desc = desc;
    }
    public static AgvStatusType get(String id) {
        if (null == id) {
            return null;
        }
        for (AgvStatusType type : AgvStatusType.values()) {
            if (type.id.equals(id)) {
                return type;
            }
        }
        return null;
    }
    public static AgvStatusType get(AgvStatusType type) {
        if (null == type) {
            return null;
        }
        for (AgvStatusType agvStatusType : AgvStatusType.values()) {
            if (agvStatusType == type) {
                return agvStatusType;
            }
        }
        return null;
    }
}
src/main/java/com/zy/common/utils/HttpHandler.java
New file
@@ -0,0 +1,213 @@
package com.zy.common.utils;
import okhttp3.*;
import java.io.IOException;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
/**
 * Http协议客户端
 * @author luxiaotao
 * @date 2018-9-27
 */
public class HttpHandler {
    private static final Integer DEFAULT_TIMEOUT_SECONDS = 5;
    private static final MediaType MEDIA_TYPE = MediaType.parse("application/json;charset=utf-8");
    private String uri;
    private String path;
    private String json;
    private Map<String, Object> params;
    private Map<String, Object> headers;
    private boolean https;
    private Integer timeout;
    private TimeUnit timeUnit;
    public HttpHandler(Builder builder){
        this.uri = builder.uri;
        this.path = builder.path;
        this.json = builder.json;
        this.params = builder.params;
        this.headers = builder.headers;
        this.https = builder.https;
        this.timeout = builder.timeout;
        this.timeUnit = builder.timeUnit;
    }
    /**
     * GET请求执行
     * @return the HttpHandler response
     */
    public String doGet() throws IOException {
        String url = paramsToUrl(uri, path, params, https);
        Request.Builder headerBuilder = new Request.Builder();
        if (headers != null && headers.size()>0){
            for (Map.Entry<String, Object> entry : headers.entrySet()){
                headerBuilder.addHeader(entry.getKey(), String.valueOf(entry.getValue()));
            }
        }
        Request request = headerBuilder.url(url).build();
        Response response = getClient(timeout, timeUnit).newCall(request).execute();
        return response.isSuccessful() ? response.body().string() : null;
    }
    /**
     * POST请求执行
     * @return the HttpHandler response
     */
    public String doPost() throws IOException {
        Request request;
        Request.Builder headerBuilder = new Request.Builder();
        if (headers != null && headers.size()>0){
            for (Map.Entry<String, Object> entry : headers.entrySet()){
                headerBuilder.addHeader(entry.getKey(), String.valueOf(entry.getValue()));
            }
        }
        if (json == null || "".equals(json)){
            FormBody.Builder builder = new FormBody.Builder();
            for (Map.Entry<String, Object> entry : params.entrySet()){
                builder.add(entry.getKey(), String.valueOf(entry.getValue()));
            }
            FormBody body = builder.build();
            request = headerBuilder
                    .url((https?"https://":"http://")+uri+path)
                    .post(body)
                    .build();
        } else {
            RequestBody body = RequestBody.create(MEDIA_TYPE, json);
            Request.Builder builder = headerBuilder.url((https?"https://":"http://")+uri+path);
            builder.header("Content-Type", "application/json;charset=UTF-8");
            request = builder.post(body).build();
        }
        Call call = getClient(timeout, timeUnit).newCall(request);
        Response response = call.execute();
        return response.body().string();
    }
    /**
     * get请求参数拼接方法
     * @return 请求行
     */
    private String paramsToUrl(String uri, String path, Map<String, Object> params, boolean isHttps) {
        StringBuilder res = new StringBuilder();
        res.append(isHttps ? "https://" : "http://");
        res.append(uri);
        if (path.length() > 0 && !(path.charAt(0) == '/')){
            res.append("/");
        }
        res.append(path);
        Optional.ofNullable(params).ifPresent(
                args -> {
                    res.append("?");
                    args.forEach((key, value) -> {
                        res.append(key);
                        res.append("=");
                        res.append(value);
                        res.append("&");
                    });
                }
        );
        String url = res.toString();
        if ("&".equals(url.substring(url.length()-1, url.length()))){
            url = url.substring(0, url.length()-1);
        }
        return url;
    }
    /**
     * 获取 okHttpClient
     * @return the HttpHandler instance
     */
    private OkHttpClient getClient(Integer timeout, TimeUnit timeUnit){
        return new OkHttpClient
                .Builder()
                .connectTimeout(timeout, timeUnit)
                .readTimeout(timeout, timeUnit)
                .build();
    }
    /**
     * Http协议报文建造者
     */
    public static class Builder {
        private String uri;
        private String path;
        private String json;
        private Map<String, Object> params;
        private Map<String, Object> headers;
        private boolean https;
        private Integer timeout;
        private TimeUnit timeUnit;
        {
            // 默认5s超时
            timeout = DEFAULT_TIMEOUT_SECONDS;
            timeUnit = TimeUnit.SECONDS;
            path = "";
        }
        /**
         * 建造器
         * @return the HttpHandler instance
         */
        public HttpHandler build(){
            if (null == this.uri || "".equals(this.uri)){
                throw new RuntimeException("uri is null");
            }
            if (this.uri.startsWith("http://")){
                this.uri = this.uri.substring(6,uri.length());
            } else if (this.uri.startsWith("https://")){
                this.uri = this.uri.substring(7,uri.length());
            }
            return new HttpHandler(this);
        }
        public Builder setUri(String uri) {
            this.uri = uri;
            return this;
        }
        public Builder setPath(String path) {
            if (!path.startsWith("/")){
                path = "/" + path;
            }
            this.path = path;
            return this;
        }
        public Builder setTimeout(Integer timeout, TimeUnit timeUnit) {
            this.timeout = timeout;
            this.timeUnit = timeUnit;
            return this;
        }
        public Builder setParams(Map<String, Object> params) {
            this.params = params;
            return this;
        }
        public Builder setHeaders(Map<String, Object> headers) {
            this.headers = headers;
            return this;
        }
        public Builder setHttps(boolean https) {
            this.https = https;
            return this;
        }
        public Builder setJson(String json) {
            this.json = json;
            return this;
        }
    }
}
src/main/resources/application.yml
@@ -8,7 +8,7 @@
    name: @pom.build.finalName@
  datasource:
    driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
    url: jdbc:sqlserver://192.168.0.252:1433;databasename=xtyasrs
    url: jdbc:sqlserver://localhost:1433;databasename=xtyasrs
    username: sa
    password: sa@123
  mvc:
@@ -56,3 +56,6 @@
  doubleLocs: 1,4,5,8,9,12
  # 一个堆垛机负责的货架排数
  groupCount: 4
agv:
  url: http://192.168.0.251:8088
src/main/webapp/views/pda/combAgv.html
@@ -30,7 +30,6 @@
            <!-- 工作区 -->
            <div class="layui-inline" style="width: 100px; margin-left: 10px">
                <select id="devpSelect">
                    <option value="">工作区</option>
                </select>
            </div>
        </div>
@@ -81,12 +80,13 @@
    // 获取工作区
    function getDevp(){
        $.ajax({
            url: baseUrl+"/available/put/site",
            url: baseUrl+"/agv/put/site",
            headers: {'token': localStorage.getItem('token')},
            method: 'POST',
            async: false,
            success: function (res) {
                if (res.code === 200){
                    $('#devpSelect').html('');
                    var tpl = $("#devpSelectTemplate").html();
                    var template = Handlebars.compile(tpl);
                    var html = template(res);
@@ -177,28 +177,28 @@
            tips("请选择工作区", true);
            return;
        }
        alert("小车组托入库完成(功能还未实现)");
//        $.ajax({
//            url: baseUrl+"/mobile/comb/auth",
//            headers: {'token': localStorage.getItem('token')},
//            data: JSON.stringify({
//                barcode: barcode,
//                combMats: matData
//            }),
//            contentType:'application/json;charset=UTF-8',
//            method: 'POST',
//            async: false,
//            success: function (res) {
//                if (res.code === 200) {
//                    reset();
//                    tips("组托成功")
//                } else if (res.code === 403) {
//                    top.location.href = baseUrl + "/pda";
//                } else {
//                    tips(res.msg, true)
//                }
//            }
//        })
       $.ajax({
           url: baseUrl+"/mobile/comb/auth",
           headers: {'token': localStorage.getItem('token')},
           data: JSON.stringify({
               barcode: barcode,
               combMats: matData,
               agvSite: devp
           }),
           contentType:'application/json;charset=UTF-8',
           method: 'POST',
           async: false,
           success: function (res) {
               if (res.code === 200) {
                   reset();
                   tips("组托成功")
               } else if (res.code === 403) {
                   top.location.href = baseUrl + "/pda";
               } else {
                   tips(res.msg, true)
               }
           }
       })
    }
    /**
@@ -232,6 +232,7 @@
</script>
<script type="text/template" id="devpSelectTemplate">
    <option value="">工作区</option>
    {{#each data}}
    <option value="{{this}}">{{this}}</option>
    {{/each}}