Commit 37215eb9 LN

增加NeoScan和点料机等其他设备互联功能

1 个父辈 3884af58
正在显示 21 个修改的文件 包含 700 行增加2 行删除
......@@ -4,6 +4,7 @@ import com.neotel.smfcore.core.order.LiteOrderCache;
import com.neotel.smfcore.core.system.service.manager.IDataLogManager;
import com.neotel.smfcore.core.system.service.po.DataLog;
import com.neotel.smfcore.core.system.util.DevicesStatusUtil;
import com.neotel.smfcore.core.system.util.EquipStatusUtil;
import com.neotel.smfcore.core.system.util.TaskService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
......@@ -62,6 +63,9 @@ public class MainTimer {
//设备状态判断
DevicesStatusUtil.runTimer();
//其他设备状态判断
EquipStatusUtil.runTimer();
}catch (Exception e){
log.error("定时器执行出错",e);
}finally {
......
......@@ -39,7 +39,7 @@ import java.util.*;
@Slf4j
@RestController
@Api(tags = "设备通信")
@Api(tags = "设备通信(料仓)")
public class DeviceController {
@Autowired
......
......@@ -685,7 +685,7 @@ public class DataCache {
storage = storageManager.save(storage);
reloadStorage(storage, "");
log.info("AutoCreateStorage :自动创建料仓完成:cid["+storage.getCid()+"]name["+storage.getName()+"]type["+storage.getCompatibleType().name()+"]");
log.info("AutoCreateStorage :自动创建料仓完成:cid["+storage.getCid()+"]name["+storage.getName()+"]type["+storage.getType()+"]");
return storage;
}
public int getPNsluggishDay(String pn){
......
package com.neotel.smfcore.core.device.util;
import com.google.common.base.Strings;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.core.equipment.service.manager.IEquipmentManager;
import com.neotel.smfcore.core.equipment.service.po.Equipment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Repository
public class EquipmentCache {
@Autowired
private IEquipmentManager equipmentManager;
/**
* 所有的料仓 key 为 cid, value 为 Storage
*/
private static Map<String, Equipment> allEquipment = new ConcurrentHashMap<>();
public Map<String, Equipment> getAllEquipment(){
if(allEquipment.isEmpty()){
synchronized (allEquipment){
if(allEquipment.isEmpty()){
List<Equipment> all = equipmentManager.findAll();
if(all != null){
Map<String, Equipment> map = new ConcurrentHashMap<>();
for(Equipment equipment : all){
map.put(equipment.getCid(), equipment);
}
allEquipment = map;
log.info("加载所有料仓["+all.size()+"]信息到缓存");
}
}
}
}
return allEquipment;
}
public Equipment getEquipment(String cid){
if(Strings.isNullOrEmpty(cid)){
return null;
}
return getAllEquipment().get(cid);
}
public Equipment getEquipmentById(String id){
for(Equipment equipment : getAllEquipment().values()){
if(equipment.getId().equals(id)){
return equipment;
}
}
return null;
}
public Equipment getEquipmentByName(String name){
for(Equipment equipment : getAllEquipment().values()){
if(equipment.getName().equals(name)){
return equipment;
}
}
return null;
}
public Equipment reloadEquipment(Equipment equipment,String oldCid) throws ValidateException {
if (!oldCid.equals("") && allEquipment.containsKey(oldCid)) {
allEquipment.remove(oldCid);
}
equipment = equipmentManager.save(equipment);
allEquipment.put(equipment.getCid(), equipment);
return equipment;
}
public void removeEquipment(Equipment equipment) {
if (equipment.getCid() != null) {
if (allEquipment.containsKey(equipment.getCid())) {
allEquipment.remove(equipment.getCid());
log.info("从缓存中删除设备:" + equipment.getCid() + "_" + equipment.getName());
}
}
}
public Equipment autoCreateEquip(String cid, String type) {
//判断cid存在
Equipment equipment = null;
equipment = getEquipment(cid);
if (equipment != null) {
return equipment;
}
//判断cid是否和其他料仓名称重复,重复时无法自动创建
if (getEquipmentByName(cid) != null) {
return null;
}
equipment = new Equipment();
equipment.setCid(cid);
equipment.setType(type);
equipment.setName(cid);
equipment = equipmentManager.save(equipment);
reloadEquipment(equipment, "");
log.info("AutoCreateEquip :自动创建设备完成:cid["+equipment.getCid()+"]name["+equipment.getName()+"]type["+equipment.getType() +"]");
return equipment;
}
}
package com.neotel.smfcore.core.equipment.bean;
import lombok.Data;
import lombok.ToString;
@ToString
@Data
public class EquipMsg {
/**
* 设备模块
*/
private String module;
/**
* 消息类型,为:INFO,WARNING,ERROR,DATA
*/
private String type;
/**
* 中英文字符串 key
*/
private String msgCode;
/**
* 消息内容
*/
private String msg;
/**
* 参数
*/
private String[] msgParams;
}
package com.neotel.smfcore.core.equipment.bean;
import com.google.common.base.Strings;
import com.neotel.smfcore.core.equipment.enums.EquipmentType;
import lombok.Data;
import lombok.ToString;
import java.io.Serializable;
import java.util.*;
@ToString
@Data
public class EquipStatusBean implements Serializable {
/**
* 设备CID
*/
private String cid;
/**
* 设备类型 ,NEOSCAN=扫码贴标,COUNTING=点料机
*/
private String type = EquipmentType.AUTO.name();
/**
* 设备状态
*/
private int status;
/**
* 请求序列号
*/
private int seq;
/**
* 操作码(备用 )
*/
private int op;
/**
* 消息集合,key 为:INFO,WARNING,ERROR,DATA ,没有指定消息时可不发
*/
private List<EquipMsg> msgList = new ArrayList<>();
/**
* 发上来的数据
*/
private Map<String, Object> data = new HashMap<>();
/**
* 离线时间,用于判断是否已经处理过离线
*/
private long offlineTime=-1;
private long time = System.currentTimeMillis();
/**
* 客户端IP
*/
private String clientIp;
/**
* 是否超时(10秒)
*/
public boolean timeOut() {
return (System.currentTimeMillis() - time) > (10 * 1000);
}
/**
* 从Data中获取数据
*/
public String getFromData(String key) {
return data.get(key).toString();
}
/**
* 添加一些服务器的操作发送到客户端(批量入库)
*
* @param opMap
*/
public void addOp(Map<String, String> opMap) {
if (opMap != null && !opMap.isEmpty()) {
for (Map.Entry<String, String> op : opMap.entrySet()) {
data.put(op.getKey(), op.getValue());
}
}
}
public void addData(String key, String value) {
String oldValue = data.get(key).toString();
String valueStr = value;
if (!Strings.isNullOrEmpty(oldValue)) {
valueStr = valueStr + "|" + oldValue;
}
data.put(key, valueStr);
}
}
package com.neotel.smfcore.core.equipment.bean;
import com.neotel.smfcore.core.equipment.enums.EquipmentType;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class EquipStatusDto implements Serializable {
@ApiModelProperty("ID")
private String id;
@ApiModelProperty("名称")
private String name;
@ApiModelProperty("CID")
private String cid;
@ApiModelProperty("是否在线")
private boolean onLine=false;
@ApiModelProperty("设备状态,0=离线,1=正常运行中, 2=急停")
private int status=0;
@ApiModelProperty("文字显示")
private String msg = "";
@ApiModelProperty("设备类型,NEOSCAN=扫码贴标,COUNTING=点料机")
private String type = EquipmentType.AUTO.name();
}
package com.neotel.smfcore.core.equipment.enums;
/**
* 设备类型(非料仓)
*/
public enum EquipmentType {
/**
* 暂无
*/
AUTO(),
/**
* 1 扫码贴标
*/
NEOSCAN(),
/**
* 2 点料机
*/
COUNTING()
}
package com.neotel.smfcore.core.equipment.handler;
import com.neotel.smfcore.core.equipment.bean.EquipStatusBean;
import com.neotel.smfcore.core.equipment.enums.EquipmentType;
import javax.servlet.http.HttpServletRequest;
public interface IEquipmentHandler {
EquipStatusBean handleClientRequest(EquipStatusBean statusBean, HttpServletRequest request);
EquipmentType getEquipType();
}
package com.neotel.smfcore.core.equipment.handler.impl;
import com.neotel.smfcore.core.equipment.bean.EquipStatusBean;
import com.neotel.smfcore.core.equipment.enums.EquipmentType;
import com.neotel.smfcore.core.equipment.handler.IEquipmentHandler;
import com.neotel.smfcore.core.message.util.DeviceMessageUtil;
import com.neotel.smfcore.core.system.util.EquipStatusUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
@Service
@Slf4j
public class BaseEquipHandler implements IEquipmentHandler {
@Override
public EquipStatusBean handleClientRequest(EquipStatusBean statusBean, HttpServletRequest request) {
statusBean.setClientIp(request.getRemoteHost());
handleMsg(statusBean);
return statusBean;
}
/**
* 处理客户端发送上来的消息(保存故障信息,并显示界面)
*
* @param statusBean
*/
protected void handleMsg(EquipStatusBean statusBean) {
try {
//判断是否刚刚上线
EquipStatusBean bean = EquipStatusUtil.getStatusBean(statusBean.getCid());
if (bean == null) {
DeviceMessageUtil.addOnlineMessage(statusBean.getCid(), "", statusBean.getClientIp());
// EquipStatusUtil.updateClientMsg(statusBean.getCid(), "", "", "", null);
} else if (bean.timeOut() && (bean.getOfflineTime() > -1)) {
DeviceMessageUtil.addOnlineMessage(statusBean.getCid(), "", statusBean.getClientIp());
// EquipStatusUtil.updateClientMsg(statusBean.getCid(), "", "", "", null);
}
EquipStatusUtil.updateStatusBean(statusBean);
// }
} catch (Exception e) {
log.error("客户端故障消息处理出错", e);
}
}
@Override
public EquipmentType getEquipType() {
return EquipmentType.AUTO;
}
}
package com.neotel.smfcore.core.equipment.rest;
import com.neotel.smfcore.core.device.util.EquipmentCache;
import com.neotel.smfcore.core.equipment.bean.EquipStatusBean;
import com.neotel.smfcore.core.equipment.enums.EquipmentType;
import com.neotel.smfcore.core.equipment.handler.IEquipmentHandler;
import com.neotel.smfcore.core.equipment.service.po.Equipment;
import com.neotel.smfcore.security.annotation.AnonymousAccess;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@RestController
@Api(tags = "设备通信(非料仓)")
public class EquipCommunicationController {
@Autowired
private EquipmentCache equipmentCache;
private Map<String, IEquipmentHandler> handlerMap = new HashMap<>();
public EquipCommunicationController(List<IEquipmentHandler> equipHandlerList) {
for (IEquipmentHandler equipmentHandler : equipHandlerList) {
log.info("加载到" + equipmentHandler.getEquipType() + "处理类 :" + equipmentHandler.getClass());
handlerMap.put(equipmentHandler.getEquipType().name(), equipmentHandler);
}
}
@ApiOperation("设备客户端定时通信接口")
@PostMapping(value = "/service/equipment/communication")
@ResponseBody
@AnonymousAccess
public EquipStatusBean communication(@RequestBody final EquipStatusBean statusBean, HttpServletRequest request) {
try {
String cid = statusBean.getCid();
Equipment equipment = equipmentCache.getEquipment(cid);
if (equipment == null) {
equipment = equipmentCache.autoCreateEquip(cid, statusBean.getType());
if (equipment != null) {
log.error("设备cid: [" + cid + "]不存在,自动创建设备完成");
} else {
log.error("设备cid: [" + cid + "]不存在,自动创建设备失败");
return null;
}
}
synchronized (equipment) {
String deviceType = equipment.getType();
IEquipmentHandler equipHandler = handlerMap.get(deviceType);
if (equipHandler == null) {
//未找到处理类,使用默认处理类
equipHandler = handlerMap.get(EquipmentType.AUTO.name());
}
EquipStatusBean resultBean = equipHandler.handleClientRequest(statusBean, request);
return resultBean;
}
} catch (Exception e) {
log.error("", e);
}
return statusBean;
}
}
package com.neotel.smfcore.core.equipment.rest;
import com.neotel.smfcore.core.device.util.EquipmentCache;
import com.neotel.smfcore.core.equipment.bean.EquipStatusDto;
import com.neotel.smfcore.core.equipment.service.po.Equipment; ;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Slf4j
@RestController
@RequiredArgsConstructor
@Api(tags = "设备互联")
@RequestMapping("api/equipmentView")
public class EquipViewController {
@Autowired
private EquipmentCache equipmentCache;
@ApiOperation("获取看板数据")
@GetMapping
@PreAuthorize("@el.check('equipmentView:info')")
public List<EquipStatusDto> info(HttpServletRequest servletRequest) {
List<EquipStatusDto> resultList=new ArrayList<>();
Map<String,Equipment> allEquipList= equipmentCache.getAllEquipment();
for (Equipment equip :
allEquipList.values()) {
EquipStatusDto dto=new EquipStatusDto(equip.getId(),equip.getName(),equip.getCid(),false,0,"",equip.getType());
resultList.add(dto);
}
return resultList;
}
}
package com.neotel.smfcore.core.equipment.rest;
import io.swagger.annotations.Api;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequiredArgsConstructor
@Api(tags = "设备管理(非料仓)")
@RequestMapping("api/equipment")
public class EquipmentController {
}
package com.neotel.smfcore.core.equipment.rest.dto;
import com.neotel.smfcore.core.equipment.enums.EquipmentType;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class EquipmentDto {
@ApiModelProperty("设备名称")
private String name;
@ApiModelProperty("设备CID")
private String cid;
@ApiModelProperty("设备类型")
private String type = EquipmentType.AUTO.name();
@ApiModelProperty("是否可用")
private boolean available = true;
}
package com.neotel.smfcore.core.equipment.service.dao;
import com.neotel.smfcore.common.base.IBaseDao;
public interface IEquipmentDao extends IBaseDao {
}
package com.neotel.smfcore.core.equipment.service.dao.impl;
import com.neotel.smfcore.common.base.AbstractBaseDao;
import com.neotel.smfcore.core.equipment.service.dao.IEquipmentDao;
import com.neotel.smfcore.core.equipment.service.po.Equipment;
import org.springframework.stereotype.Service;
@Service
public class EquipmentDaoImpl extends AbstractBaseDao implements IEquipmentDao {
@Override
public Class getEntityClass() {
return Equipment.class;
}
}
package com.neotel.smfcore.core.equipment.service.manager;
import com.neotel.smfcore.common.base.IBaseManager;
import com.neotel.smfcore.core.equipment.service.po.Equipment;
import java.util.List;
public interface IEquipmentManager extends IBaseManager<Equipment> {
List<Equipment> findAll();
}
package com.neotel.smfcore.core.equipment.service.manager.impl;
import com.neotel.smfcore.common.bean.PageData;
import com.neotel.smfcore.common.exception.ValidateException;
import com.neotel.smfcore.core.equipment.service.dao.IEquipmentDao;
import com.neotel.smfcore.core.equipment.service.manager.IEquipmentManager;
import com.neotel.smfcore.core.equipment.service.po.Equipment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import java.util.List;
@Slf4j
@Service
public class EquipmentManagerImpl implements IEquipmentManager {
@Autowired
private IEquipmentDao equipmentDao;
@Override
public Equipment get(String id) {
return equipmentDao.findOneById(id);
}
@Override
public Equipment save(Equipment object) throws ValidateException {
return equipmentDao.save(object);
}
@Override
public void delete(Equipment object) throws ValidateException {
equipmentDao.removeOneById(object.getId());
}
@Override
public PageData<Equipment> findByPage(Query query, Pageable pageable) {
int totalCount = equipmentDao.countByQuery(query);
List<Equipment> list = equipmentDao.findByQuery(query, pageable);
return new PageData<Equipment>(list,totalCount);
}
@Override
public List<Equipment> findByQuery(Query query) {
return equipmentDao.findByQuery(query);
}
@Override
public List<Equipment> findAll(){
return equipmentDao.findAll();
}
}
package com.neotel.smfcore.core.equipment.service.po;
import com.neotel.smfcore.common.base.BasePo;
import com.neotel.smfcore.core.equipment.enums.EquipmentType;
import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;
import java.io.Serializable;
@Data
@Document
public class Equipment extends BasePo implements Serializable {
/**
* 设备名称
*/
private String name;
/**
* 设备CID
*/
private String cid;
/**
* 设备类型
*/
private String type = EquipmentType.AUTO.name();
/**
* 是否可用
*/
private boolean available = true;
}
......@@ -16,4 +16,9 @@ public enum MessageType {
* 2 错误
*/
ERROR,
/**
* 3 设备操作数据
*/
DATA,
}
package com.neotel.smfcore.core.system.util;
import com.google.common.collect.Maps;
import com.neotel.smfcore.core.equipment.bean.EquipStatusBean;
import com.neotel.smfcore.core.message.util.DeviceMessageUtil;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Slf4j
public class EquipStatusUtil {
/**
* 状态 map,key为 cid value 为状态 Bean
*/
protected static Map<String, EquipStatusBean> statusMap = Maps.newConcurrentMap();
/**
* CID的设备故障消息(key 为 cid)
*/
private static Map<String, EquipStatusBean> clientMsgs = Maps.newConcurrentMap();
/**
* 获取设备状态Bean
*/
public static EquipStatusBean getStatusBean(String cid) {
EquipStatusBean statusBean= statusMap.get(cid);
return statusBean;
}
/**
* 更新设备状态信息
*/
public static void updateStatusBean(EquipStatusBean statusBean) {
statusMap.put(statusBean.getCid(), statusBean);
}
public static void runTimer() {
try {
if(statusMap==null){
return;
}
List<String> cids = new ArrayList<>(statusMap.keySet());
for (String cid :
cids) {
EquipStatusBean bean = getStatusBean(cid);
if (bean != null) {
if (bean.getOfflineTime() == -1 && bean.timeOut()) {
bean.setOfflineTime(System.currentTimeMillis());
DeviceMessageUtil.addOfflineMessage(bean.getCid(), "");
}
}
}
} catch (Exception ex) {
log.error("设备状态定时器执行出错:", ex);
}
}
}
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!