From 07a648c3f50206b1f16b52a271bb031a132a993b Mon Sep 17 00:00:00 2001 From: limqhz <540344226@qq.com> Date: Fri, 24 Nov 2023 22:37:12 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BA=BF=E4=B8=8B=E8=AE=A2=E5=8D=95=E9=A9=B1?= =?UTF-8?q?=E5=8A=A8=E5=BC=80=E9=97=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sv/api/controller/VenueController.java | 24 +- .../controller/AdminNettyController.java | 111 ++++++- .../com/sv/netty/netty/ServerHandler.java | 6 + .../netty/netty/service/MessageService.java | 4 +- .../impl/ServerMessageHandlerAdapter.java | 69 +++- .../java/com/sv/entity/BarcodeEnterLog.java | 111 +++++++ .../java/com/sv/entity/BarcodeOffline.java | 122 +++++++ .../sv/intergration/impl/OldDoorService.java | 23 +- .../java/com/sv/netty/MessageHandler.java | 11 +- netty-client/src/main/resources/venue.conf | 2 +- .../java/com/sv/netty/utils/MakeCode.java | 15 + .../sv/oms/controller/DeviceController.java | 76 +++++ .../com/ydd/oms/util/VenueBarcodeUtil.java | 109 ++++++ .../config/application-development.yml | 2 +- .../com/sv/mapper/BarcodeEnterLogMapper.java | 21 ++ .../com/sv/mapper/BarcodeOfflineMapper.java | 19 ++ .../java/com/sv/service/api/VenueService.java | 12 +- .../com/sv/service/common/DoorLockUtil.java | 60 ++++ .../com/sv/service/common/RedisCache.java | 264 +++++++++++++++ .../com/sv/service/oms/DeviceService.java | 20 +- .../sv/service/utils/VenueBarcodeUtil.java | 109 ++++++ .../mapper/sv/BarcodeEnterLogMapper.xml | 152 +++++++++ .../mapper/sv/BarcodeOfflineMapper.xml | 314 ++++++++++++++++++ .../main/resources/tools/generatorConfig.xml | 2 +- 24 files changed, 1621 insertions(+), 37 deletions(-) create mode 100644 entity/src/main/java/com/sv/entity/BarcodeEnterLog.java create mode 100644 entity/src/main/java/com/sv/entity/BarcodeOffline.java create mode 100644 oms/src/main/java/com/ydd/oms/util/VenueBarcodeUtil.java create mode 100644 service/src/main/java/com/sv/mapper/BarcodeEnterLogMapper.java create mode 100644 service/src/main/java/com/sv/mapper/BarcodeOfflineMapper.java create mode 100644 service/src/main/java/com/sv/service/common/DoorLockUtil.java create mode 100644 service/src/main/java/com/sv/service/common/RedisCache.java create mode 100644 service/src/main/java/com/sv/service/utils/VenueBarcodeUtil.java create mode 100644 service/src/main/resources/mybatis/mapper/sv/BarcodeEnterLogMapper.xml create mode 100644 service/src/main/resources/mybatis/mapper/sv/BarcodeOfflineMapper.xml diff --git a/api/src/main/java/com/sv/api/controller/VenueController.java b/api/src/main/java/com/sv/api/controller/VenueController.java index 7b81bdb..3a5aff2 100644 --- a/api/src/main/java/com/sv/api/controller/VenueController.java +++ b/api/src/main/java/com/sv/api/controller/VenueController.java @@ -7,13 +7,17 @@ import com.sv.entity.Barcode; import com.sv.entity.Device; import com.sv.entity.Venue; import com.sv.mapper.BarcodeMapper; +import com.sv.netty.config.NettyConstant; import com.sv.netty.utils.AesUtil; import com.sv.netty.utils.MakeCode; import com.sv.service.api.VenueService; +import com.sv.service.common.DoorLockUtil; +import com.sv.service.common.RedisCache; import com.sv.service.oms.DeviceService; import com.ydd.framework.core.common.Pagination; import com.ydd.framework.core.common.dto.ResponseDTO; import com.ydd.framework.core.controller.BaseApiController; +import com.ydd.framework.core.exception.ServiceException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.transaction.annotation.Transactional; @@ -21,6 +25,7 @@ import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import java.util.concurrent.TimeUnit; /** * Controller - 场馆 @@ -35,6 +40,8 @@ public class VenueController extends BaseApiController { @Resource private VenueService venueService; + @Resource + private DoorLockUtil doorLockUtil; /** * 分页查询场馆列表 @@ -119,8 +126,14 @@ public class VenueController extends BaseApiController { join.setFlg(999); join.setMsg("通讯异常,门禁设备离线中"); }else { - String barcode = newBarcode(byDevice.getName(), EnterEnum.ENTER, venueId, memberId); + String doorSn = byDevice.getName(); + boolean lockStat = doorLockUtil.checkDoorLock(doorSn); + if (lockStat) { + throw new ServiceException("有人正在使用门禁,请稍后再试"); + } + String barcode = newBarcode(doorSn, EnterEnum.ENTER, venueId, memberId); join.setBarcode(barcode); + doorLockUtil.lockDoor(doorSn); } } return ResponseDTO.ok().addAttribute("join", join); @@ -144,14 +157,19 @@ public class VenueController extends BaseApiController { out.setFlg(999); out.setMsg("通讯异常,门禁设备离线中"); }else { - String barcode = newBarcode(byDevice.getName(),EnterEnum.OUT,venueId,memberId); + String doorSn = byDevice.getName(); + boolean lockStat = doorLockUtil.checkDoorLock(doorSn); + if (lockStat) { + throw new ServiceException("有人正在使用门禁,请稍后再试"); + } + String barcode = newBarcode(doorSn,EnterEnum.OUT,venueId,memberId); out.setBarcode(barcode); + doorLockUtil.lockDoor(doorSn); } } return ResponseDTO.ok().addAttribute("out", out); } - private String newBarcode (String deviceName,EnterEnum enterEnum,Integer venueId,Integer memberId){ String barcode = ""; Barcode res = barcodeMapper.findBarcode(venueId, memberId); diff --git a/api/src/main/java/com/sv/netty/controller/AdminNettyController.java b/api/src/main/java/com/sv/netty/controller/AdminNettyController.java index 2abd30e..b460eb2 100644 --- a/api/src/main/java/com/sv/netty/controller/AdminNettyController.java +++ b/api/src/main/java/com/sv/netty/controller/AdminNettyController.java @@ -4,15 +4,23 @@ import com.enums.DeviceStatusEnum; import com.sv.entity.Device; import com.sv.netty.config.NettyConstant; import com.sv.netty.netty.service.MessageService; +import com.sv.netty.utils.MakeCode; +import com.sv.service.common.DoorLockUtil; import com.sv.service.oms.DeviceService; +import com.sv.service.utils.VenueBarcodeUtil; import com.ydd.framework.core.common.dto.ResponseDTO; import com.ydd.framework.core.controller.BaseApiController; import com.ydd.framework.core.exception.ServiceException; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.util.Units; +import org.apache.poi.xwpf.usermodel.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.io.*; /** * 小程序二维码进场Controller @@ -25,6 +33,8 @@ public class AdminNettyController extends BaseApiController { DeviceService deviceService; @Resource private MessageService messageService; + @Resource + DoorLockUtil doorLockUtil; /** * 进场指令发布 */ @@ -81,13 +91,102 @@ public class AdminNettyController extends BaseApiController { * 检验客户端读取能力 * @return */ - @RequestMapping("/checkAlive") - public ResponseDTO checkAlive(@RequestParam String id) { - Integer venueId = getVenueId(id); - String deviceName = getDeviceName(id); - logger.info("验证设备"+ id + "通讯情况"); - messageService.testLoad(deviceName,venueId); + @RequestMapping("/checkAlive/{id}") + public ResponseDTO checkAlive(@PathVariable("id") Integer id) { + Device device = deviceService.findById(id); + if (device == null){ + throw new ServiceException("设备不存在"); + } + if (!DeviceStatusEnum.ONLINE.value.equals(device.getStatus())){ + throw new ServiceException("设备离线!请检查连接"); + } + messageService.testLoad(device.getName(),device.getVenueId()); return ResponseDTO.ok(); } + /** + * 下载线下入场凭证(二维码) + * @param id + * @param response + * @throws IOException + * @throws InvalidFormatException + */ + @RequestMapping(value = "/qrcode/print/{id}") + public void print(@PathVariable("id") Integer id, HttpServletResponse response) throws IOException, InvalidFormatException { + Device device = deviceService.findById(id); + if (device == null){ + response.setContentType("text/html"); + response.setCharacterEncoding("UTF-8"); + PrintWriter writer = response.getWriter(); + writer.write("设备不存在!!!"); + writer.flush(); + writer.close(); + return; + } + String doorSn = device.getName(); + if(doorLockUtil.checkBarcode(doorSn)){ + response.setContentType("text/html"); + response.setCharacterEncoding("UTF-8"); + PrintWriter writer = response.getWriter(); + writer.write("生成二维码过于频繁,请稍候再试!!!"); + writer.flush(); + writer.close(); + return; + } + + long l = System.currentTimeMillis(); + String barcodeSn = "venue-" + l; + String barcode = MakeCode.makeOfflineCode(barcodeSn); + deviceService.makeDeviceBarcode(device.getName(),device.getVenueId(),barcode); + + String documentPath = getDocument(barcodeSn); + response.setHeader("Content-disposition","attachment; filename=" + barcodeSn + ".docx"); + response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); + response.setCharacterEncoding("UTF-8"); + OutputStream out = response.getOutputStream(); + BufferedInputStream fin = new BufferedInputStream(new FileInputStream(documentPath)); + try { + byte[] content = new byte[1024]; + int length; + while ((length = fin.read(content, 0, content.length)) != -1) { + out.write(content, 0, length); + } + doorLockUtil.lockBarcode(doorSn); + } catch (Exception e) { + logger.error(e.getMessage(), e); + logger.info("文件下载失败", e.getMessage()); + throw e; + } finally { + fin.close(); + out.flush(); + out.close(); + } + } + + private static String getDocument(String barcodeSn) throws IOException, InvalidFormatException { + String newFilePath = "/Users/limqhz/home/test/document.docx"; + XWPFDocument document = new XWPFDocument(); + XWPFParagraph paragraph = document.createParagraph(); + paragraph.setAlignment(ParagraphAlignment.CENTER); + XWPFRun run = paragraph.createRun(); + + // 入场二维码 + run.setText("订单号:" + barcodeSn); + run.addBreak(); + String imgFile = VenueBarcodeUtil.generateBarcode("jdoiawjdoiawioe1","202311161.jpg"); + int imgFormat = XWPFDocument.PICTURE_TYPE_JPEG; + run.addPicture(new FileInputStream(imgFile), imgFormat, "image description", + Units.toEMU(200), Units.toEMU(200)); +// run.addBreak(BreakType.PAGE); +// // 出场二维码 +// run.setText("出场二维码"); +// run.addBreak(); +// String imgFile2 = VenueBarcodeUtil.generateBarcode("jdoiawjdoiawioe2","202311162.jpg"); +// run.addPicture(new FileInputStream(imgFile2), imgFormat, "image description", +// Units.toEMU(200), Units.toEMU(200)); + // 保存文件 + document.write(new FileOutputStream(newFilePath)); + document.close(); + return newFilePath; + } } diff --git a/api/src/main/java/com/sv/netty/netty/ServerHandler.java b/api/src/main/java/com/sv/netty/netty/ServerHandler.java index c075c63..9ea123d 100644 --- a/api/src/main/java/com/sv/netty/netty/ServerHandler.java +++ b/api/src/main/java/com/sv/netty/netty/ServerHandler.java @@ -3,6 +3,7 @@ package com.sv.netty.netty; import com.enums.EnterEnum; import com.sv.netty.config.*; import com.sv.netty.netty.service.MessageService; +import com.sv.netty.utils.AesUtil; import com.sv.netty.utils.JsonUtils; import com.sv.netty.utils.MakeCode; import io.netty.channel.*; @@ -62,6 +63,11 @@ public class ServerHandler extends SimpleChannelInboundHandler { break; case SCAN_CODE: logger.info("客户端【" + clientIp + "】开门了..."); + String offline = MakeCode.decodeOfflineCode(message.getMessage()); + if (offline.startsWith("venue-")) { + // 这是线下开门的逻辑 + messageService.offlineOpenDoor(message.getMessage()); + } VenueBarCode venueBarCode = MakeCode.decodeCode(message.getMessage()); if (EnterEnum.ENTER.getValue() == venueBarCode.getDirection()) { messageService.enterVenue(message.getMessage()); diff --git a/api/src/main/java/com/sv/netty/netty/service/MessageService.java b/api/src/main/java/com/sv/netty/netty/service/MessageService.java index efdb85f..6ea67aa 100644 --- a/api/src/main/java/com/sv/netty/netty/service/MessageService.java +++ b/api/src/main/java/com/sv/netty/netty/service/MessageService.java @@ -1,8 +1,6 @@ package com.sv.netty.netty.service; -import com.sv.entity.Venue; import com.sv.netty.config.HeartBeat; -import com.sv.netty.config.VenueBarCode; import io.netty.channel.Channel; import java.util.Set; @@ -53,4 +51,6 @@ public interface MessageService { public void adminOut(String deviceName, Integer venueId); void testLoad(String deviceName, Integer venueId); + + void offlineOpenDoor(String message); } diff --git a/api/src/main/java/com/sv/netty/netty/service/impl/ServerMessageHandlerAdapter.java b/api/src/main/java/com/sv/netty/netty/service/impl/ServerMessageHandlerAdapter.java index 848e485..5cbeed8 100644 --- a/api/src/main/java/com/sv/netty/netty/service/impl/ServerMessageHandlerAdapter.java +++ b/api/src/main/java/com/sv/netty/netty/service/impl/ServerMessageHandlerAdapter.java @@ -3,7 +3,9 @@ package com.sv.netty.netty.service.impl; import com.enums.BarCodeStatusEnum; import com.enums.EnterEnum; import com.sv.entity.*; +import com.sv.mapper.BarcodeEnterLogMapper; import com.sv.mapper.BarcodeMapper; +import com.sv.mapper.BarcodeOfflineMapper; import com.sv.netty.config.*; import com.sv.netty.netty.service.MessageService; import com.sv.netty.utils.JsonUtils; @@ -13,6 +15,7 @@ import com.sv.service.api.MemberEnterVenueLogService; import com.sv.service.api.MemberMoneyLogService; import com.sv.service.api.MemberService; import com.sv.service.api.VenueService; +import com.sv.service.common.DoorLockUtil; import com.sv.service.oms.DeviceService; import com.ydd.framework.core.exception.ServiceException; import io.netty.channel.Channel; @@ -25,7 +28,6 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.*; import java.util.concurrent.ConcurrentMap; - /** * 消息实现类 * @@ -62,6 +64,14 @@ public class ServerMessageHandlerAdapter implements MessageService { @Resource private BarcodeMapper barcodeMapper; + @Resource + private DoorLockUtil doorLockUtil; + + @Resource + private BarcodeOfflineMapper barcodeOfflineMapper; + + @Resource + private BarcodeEnterLogMapper barcodeEnterLogMapper; /** * 处理心跳信息,存储心跳信息 * @param clientId @@ -107,11 +117,16 @@ public class ServerMessageHandlerAdapter implements MessageService { @Transactional public void outVenue(String barcode) { VenueBarCode venueBarCode = MakeCode.decodeCode(barcode); + String doorSn = venueBarCode.getDeviceName(); + boolean lockStat = doorLockUtil.checkDoorLock(doorSn); + if (lockStat) { + throw new ServiceException("有人正在操作,请稍后再试"); + } barcode = MakeCode.reWriteBarcode(barcode); if (!checkBarcode(barcode)){ throw new ServiceException("二维码已经使用"); } - Channel channel = getCurrentChannel(venueBarCode.getDeviceName(),venueBarCode.getVenueId()); + Channel channel = getCurrentChannel(doorSn,venueBarCode.getVenueId()); Member member = memberService.findByMember(venueBarCode.getMemberId()); if (member != null) { MemberMoneyLog memberMoneyLog = memberMoneyLogService.selectLastLog(member.getId(), venueBarCode.getVenueId()); @@ -125,6 +140,7 @@ public class ServerMessageHandlerAdapter implements MessageService { memberEnterVenueLog.setPayType(memberMoneyLog.getPayType()); } memberEnterVenueLogService.save(memberEnterVenueLog); + doorLockUtil.lockDoor(doorSn); logger.info("用户" + member.getNickname() + "出场"); writeOffCode(barcode); ServerMessageUtils.INSTANCE.sendMsg(channel,new VenueMessage(MessageType.OUT_DOOR,"OK")); @@ -139,11 +155,16 @@ public class ServerMessageHandlerAdapter implements MessageService { @Transactional public void enterVenue(String barcode) { VenueBarCode venueBarCode = MakeCode.decodeCode(barcode); + String doorSn = venueBarCode.getDeviceName(); + boolean lockStat = doorLockUtil.checkDoorLock(doorSn); + if (lockStat) { + throw new ServiceException("有人正在操作,请稍后再试"); + } barcode = MakeCode.reWriteBarcode(barcode); if (!checkBarcode(barcode)){ throw new ServiceException("二维码已经使用"); } - Channel channel = getCurrentChannel(venueBarCode.getDeviceName(), venueBarCode.getVenueId()); + Channel channel = getCurrentChannel(doorSn, venueBarCode.getVenueId()); Member member = memberService.findByMember(venueBarCode.getMemberId()); if (member != null) { MemberEnterVenueLog memberEnterVenueLog = new MemberEnterVenueLog(); @@ -153,6 +174,7 @@ public class ServerMessageHandlerAdapter implements MessageService { memberEnterVenueLog.setPlatformId(member.getPlatformId() == null ? 1 : member.getPlatformId()); memberEnterVenueLog.setVenueId(venueBarCode.getVenueId()); memberEnterVenueLogService.save(memberEnterVenueLog); + doorLockUtil.lockDoor(doorSn); writeOffCode(barcode); logger.info("用户" + member.getNickname() + "入场"); ServerMessageUtils.INSTANCE.sendMsg(channel,new VenueMessage(MessageType.ENTER_DOOR,"OK")); @@ -199,6 +221,47 @@ public class ServerMessageHandlerAdapter implements MessageService { ServerMessageUtils.INSTANCE.sendMsg(currentChannel,new VenueMessage(MessageType.HB,"测试链接")); } + /** + * 线下订单 + */ + @Override + public void offlineOpenDoor(String message) { + String barcode = MakeCode.reWriteBarcode(message); + BarcodeOffline barcodeOffline = barcodeOfflineMapper.selectByBarcode(barcode); + String doorSn = barcodeOffline.getDeviceName(); + // 校验barcode是否失效 + Date endTime = barcodeOffline.getEndTime(); + if (endTime.before(new Date())) { + // 二维码已经失效了 + throw new ServiceException("二维码已经失效,无法继续使用"); + } + boolean lockStat = doorLockUtil.checkDoorLock(doorSn); + if (lockStat) { + throw new ServiceException("有人正在操作,请稍后再试"); + } + BarcodeEnterLog lastByBarcode = barcodeEnterLogMapper.findLastByBarcode(barcode); + Integer venueId = barcodeOffline.getVenueId(); + Channel channel = getCurrentChannel(doorSn, venueId); + if (lastByBarcode != null && EnterEnum.ENTER.getValue().equals(lastByBarcode.getType())) { + //出场 + BarcodeEnterLog barcodeEnterLog = new BarcodeEnterLog(); + barcodeEnterLog.setBarcode(barcode); + barcodeEnterLog.setType(EnterEnum.OUT.getValue()); + barcodeEnterLog.setVenueId(venueId); + barcodeEnterLogMapper.insert(barcodeEnterLog); + doorLockUtil.lockDoor(doorSn); + ServerMessageUtils.INSTANCE.sendMsg(channel,new VenueMessage(MessageType.OUT_DOOR,"OK")); + return; + } + BarcodeEnterLog barcodeEnterLog = new BarcodeEnterLog(); + barcodeEnterLog.setBarcode(barcode); + barcodeEnterLog.setType(EnterEnum.ENTER.getValue()); + barcodeEnterLog.setVenueId(venueId); + barcodeEnterLogMapper.insert(barcodeEnterLog); + doorLockUtil.lockDoor(doorSn); + ServerMessageUtils.INSTANCE.sendMsg(channel,new VenueMessage(MessageType.ENTER_DOOR,"OK")); + } + /** * 管理员入场 * @return diff --git a/entity/src/main/java/com/sv/entity/BarcodeEnterLog.java b/entity/src/main/java/com/sv/entity/BarcodeEnterLog.java new file mode 100644 index 0000000..db0bd1b --- /dev/null +++ b/entity/src/main/java/com/sv/entity/BarcodeEnterLog.java @@ -0,0 +1,111 @@ +package com.sv.entity; + +import java.util.Date; + +public class BarcodeEnterLog { + private Integer id; + + private String barcode; + + private Integer venueId; + + private Integer platformId; + + private Integer createdId; + + private Integer modifiedId; + + private Date createdTime; + + private Date modifiedTime; + + private Integer type; + + public BarcodeEnterLog(Integer id, String barcode, Integer venueId, Integer platformId, Integer createdId, Integer modifiedId, Date createdTime, Date modifiedTime, Integer type) { + this.id = id; + this.barcode = barcode; + this.venueId = venueId; + this.platformId = platformId; + this.createdId = createdId; + this.modifiedId = modifiedId; + this.createdTime = createdTime; + this.modifiedTime = modifiedTime; + this.type = type; + } + + public BarcodeEnterLog() { + super(); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getBarcode() { + return barcode; + } + + public void setBarcode(String barcode) { + this.barcode = barcode == null ? null : barcode.trim(); + } + + public Integer getVenueId() { + return venueId; + } + + public void setVenueId(Integer venueId) { + this.venueId = venueId; + } + + public Integer getPlatformId() { + return platformId; + } + + public void setPlatformId(Integer platformId) { + this.platformId = platformId; + } + + public Integer getCreatedId() { + return createdId; + } + + public void setCreatedId(Integer createdId) { + this.createdId = createdId; + } + + public Integer getModifiedId() { + return modifiedId; + } + + public void setModifiedId(Integer modifiedId) { + this.modifiedId = modifiedId; + } + + public Date getCreatedTime() { + return createdTime; + } + + public void setCreatedTime(Date createdTime) { + this.createdTime = createdTime; + } + + public Date getModifiedTime() { + return modifiedTime; + } + + public void setModifiedTime(Date modifiedTime) { + this.modifiedTime = modifiedTime; + } + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } +} \ No newline at end of file diff --git a/entity/src/main/java/com/sv/entity/BarcodeOffline.java b/entity/src/main/java/com/sv/entity/BarcodeOffline.java new file mode 100644 index 0000000..110dc1b --- /dev/null +++ b/entity/src/main/java/com/sv/entity/BarcodeOffline.java @@ -0,0 +1,122 @@ +package com.sv.entity; + +import java.util.Date; + +public class BarcodeOffline { + private Integer id; + + private String barcode; + + private Date startTime; + + private Date endTime; + + private Integer venueId; + + private Integer createdId; + + private Integer modifiedId; + + private Date createdTime; + + private Date modifiedTime; + + private String deviceName; + + public BarcodeOffline(Integer id, String barcode, Date startTime, Date endTime, Integer venueId, Integer createdId, Integer modifiedId, Date createdTime, Date modifiedTime, String deviceName) { + this.id = id; + this.barcode = barcode; + this.startTime = startTime; + this.endTime = endTime; + this.venueId = venueId; + this.createdId = createdId; + this.modifiedId = modifiedId; + this.createdTime = createdTime; + this.modifiedTime = modifiedTime; + this.deviceName = deviceName; + } + + public BarcodeOffline() { + super(); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getBarcode() { + return barcode; + } + + public void setBarcode(String barcode) { + this.barcode = barcode == null ? null : barcode.trim(); + } + + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + public Date getEndTime() { + return endTime; + } + + public void setEndTime(Date endTime) { + this.endTime = endTime; + } + + public Integer getVenueId() { + return venueId; + } + + public void setVenueId(Integer venueId) { + this.venueId = venueId; + } + + public Integer getCreatedId() { + return createdId; + } + + public void setCreatedId(Integer createdId) { + this.createdId = createdId; + } + + public Integer getModifiedId() { + return modifiedId; + } + + public void setModifiedId(Integer modifiedId) { + this.modifiedId = modifiedId; + } + + public Date getCreatedTime() { + return createdTime; + } + + public void setCreatedTime(Date createdTime) { + this.createdTime = createdTime; + } + + public Date getModifiedTime() { + return modifiedTime; + } + + public void setModifiedTime(Date modifiedTime) { + this.modifiedTime = modifiedTime; + } + + public String getDeviceName() { + return deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName == null ? null : deviceName.trim(); + } +} \ No newline at end of file diff --git a/netty-client/src/main/java/com/sv/intergration/impl/OldDoorService.java b/netty-client/src/main/java/com/sv/intergration/impl/OldDoorService.java index 1c4dbd2..202c2b2 100644 --- a/netty-client/src/main/java/com/sv/intergration/impl/OldDoorService.java +++ b/netty-client/src/main/java/com/sv/intergration/impl/OldDoorService.java @@ -8,20 +8,23 @@ import Net.PC15.FC8800.Command.Door.OpenDoor; import Net.PC15.FC8800.Command.Door.Parameter.OpenDoor_Parameter; import Net.PC15.FC8800.FC8800Identity; import com.sv.intergration.DoorService; +import com.sv.netty.config.NettyConstant; public class OldDoorService implements DoorService { @Override public void enterOpenDoor() { try { - logger.info("----init open door tcp ----"); ConnectorAllocator connector = ConnectorAllocator.GetAllocator(); TCPClientDetial tcpClientDetial = new TCPClientDetial("192.168.1.150", Integer.valueOf("8000")); connector.GetCommandCount(tcpClientDetial); connector.OpenForciblyConnect(tcpClientDetial); CommandDetial detial = new CommandDetial(); detial.Connector = tcpClientDetial; - detial.Identity = new FC8800Identity("MC-5824T23014127", "12345678", E_ControllerType.FC8900); + String clientSn = System.getProperty(NettyConstant.VENUE_CLIENT_SN); + System.out.println(clientSn); +// detial.Identity = new FC8800Identity("MC-5824T23014127", "12345678", E_ControllerType.FC8900); + detial.Identity = new FC8800Identity(clientSn, "12345678", E_ControllerType.FC8900); OpenDoor_Parameter openDoorParameter = new OpenDoor_Parameter(detial); openDoorParameter.Door.SetDoor(1, 1); OpenDoor openDoor = new OpenDoor(openDoorParameter); @@ -40,19 +43,19 @@ public class OldDoorService implements DoorService { @Override public void outOpenDoor() { try { - logger.info("----init open door tcp ----"); ConnectorAllocator connector = ConnectorAllocator.GetAllocator(); TCPClientDetial tcpClientDetial = new TCPClientDetial("192.168.1.150", Integer.valueOf("8000")); connector.GetCommandCount(tcpClientDetial); connector.OpenForciblyConnect(tcpClientDetial); CommandDetial detial = new CommandDetial(); detial.Connector = tcpClientDetial; - detial.Identity = new FC8800Identity("MC-5824T23014127", "12345678", E_ControllerType.FC8900); + String clientSn = System.getProperty(NettyConstant.VENUE_CLIENT_SN); +// detial.Identity = new FC8800Identity("MC-5824T23014127", "12345678", E_ControllerType.FC8900); + detial.Identity = new FC8800Identity(clientSn, "12345678", E_ControllerType.FC8900); OpenDoor_Parameter openDoorParameter = new OpenDoor_Parameter(detial); openDoorParameter.Door.SetDoor(2, 1); OpenDoor openDoor = new OpenDoor(openDoorParameter); boolean command = connector.AddCommand(openDoor); - System.out.println(command); if (!command) { logger.error("出场开门命令执行失败"); } @@ -65,9 +68,9 @@ public class OldDoorService implements DoorService { } // 测试 - public static void main(String[] args) { - OldDoorService oldDoorService = new OldDoorService(); - oldDoorService.enterOpenDoor(); - oldDoorService.outOpenDoor(); - } +// public static void main(String[] args) { +// OldDoorService oldDoorService = new OldDoorService(); +// oldDoorService.enterOpenDoor(); +// oldDoorService.outOpenDoor(); +// } } diff --git a/netty-client/src/main/java/com/sv/netty/MessageHandler.java b/netty-client/src/main/java/com/sv/netty/MessageHandler.java index 0dff37b..0d94b90 100644 --- a/netty-client/src/main/java/com/sv/netty/MessageHandler.java +++ b/netty-client/src/main/java/com/sv/netty/MessageHandler.java @@ -1,6 +1,7 @@ package com.sv.netty; import com.sv.netty.config.*; +import com.sv.netty.utils.AesUtil; import com.sv.netty.utils.EncodeMsg; import com.sv.netty.utils.JsonUtils; import com.sv.netty.utils.MakeCode; @@ -27,10 +28,14 @@ public class MessageHandler { * @return */ public static String checkBarcode(String barcode) { + String decrypt = AesUtil.decrypt(barcode); + // 这个二维码是线下的二维码 + if (!decrypt.startsWith("venue-")){ VenueBarCode venueBarCode = MakeCode.decodeCode(barcode); - if (venueBarCode == null) { - logger.error("二维码不合法" + barcode); - return null; + if (venueBarCode == null) { + logger.error("二维码不合法" + barcode); + return null; + } } VenueMessage venueMessage = new VenueMessage(); venueMessage.setMessageType(MessageType.SCAN_CODE); diff --git a/netty-client/src/main/resources/venue.conf b/netty-client/src/main/resources/venue.conf index 2f631c9..ac21643 100644 --- a/netty-client/src/main/resources/venue.conf +++ b/netty-client/src/main/resources/venue.conf @@ -1 +1 @@ -{"serverIp":"127.0.0.1","serverPort":"56792","clientSN":"20230901venue","clientVid":"41"} +{"serverIp":"127.0.0.1","serverPort":"56792","clientSN":"MC-5824T23014127","clientVid":"41"} diff --git a/netty-model/src/main/java/com/sv/netty/utils/MakeCode.java b/netty-model/src/main/java/com/sv/netty/utils/MakeCode.java index b61dc83..7dc390b 100644 --- a/netty-model/src/main/java/com/sv/netty/utils/MakeCode.java +++ b/netty-model/src/main/java/com/sv/netty/utils/MakeCode.java @@ -14,6 +14,14 @@ public class MakeCode { return NettyConstant.BARCODE_BEGIN + AesUtil.encrypt(information) + NettyConstant.BARCODE_END; } + /** + * 生成二维码 + * @return + */ + public static String makeOfflineCode (String barcodeSn) { + return NettyConstant.BARCODE_BEGIN + AesUtil.encrypt(barcodeSn) + NettyConstant.BARCODE_END; + } + /** * 解析二维码 */ @@ -36,6 +44,13 @@ public class MakeCode { return venueBarCode; } + /** + * 解析二维码 + */ + public static String decodeOfflineCode (String barcodeSn) { + return AesUtil.decrypt(barcodeSn); + } + /** * 还原二维码 */ diff --git a/oms/src/main/java/com/sv/oms/controller/DeviceController.java b/oms/src/main/java/com/sv/oms/controller/DeviceController.java index 616e74f..805e2e1 100644 --- a/oms/src/main/java/com/sv/oms/controller/DeviceController.java +++ b/oms/src/main/java/com/sv/oms/controller/DeviceController.java @@ -1,16 +1,24 @@ package com.sv.oms.controller; +import com.enums.DeviceStatusEnum; import com.enums.EnterEnum; import com.sv.service.oms.DeviceService; import com.ydd.framework.core.common.Pagination; import com.ydd.framework.core.common.dto.ResponseDTO; +import com.ydd.framework.core.exception.ServiceException; import com.ydd.oms.controller.OmsController; import com.sv.entity.Device; +import com.ydd.oms.util.VenueBarcodeUtil; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.util.Units; +import org.apache.poi.xwpf.usermodel.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.io.*; /** * Controller - 门禁设备 @@ -95,4 +103,72 @@ public class DeviceController extends OmsController { return ResponseDTO.ok("出场开门成功!"); } + /** + * 重新连接 + * @param deviceId + * @return + */ + @RequestMapping("device/checkAlive/{id}") + public ResponseDTO checkAlive(@PathVariable("id") Integer deviceId){ + Device device = deviceService.findById(deviceId); + if (device == null) { + throw new ServiceException("设备离线!请检查连接"); + } + if (!DeviceStatusEnum.ONLINE.value.equals(device.getStatus())){ + throw new ServiceException("设备离线!请检查连接"); + } + return ResponseDTO.ok(); + } + + @RequestMapping(value = "/qrcode/print/{id}") + public void print(@PathVariable("id") Integer id, HttpServletResponse response) throws IOException, InvalidFormatException { + String documentPath = getDocument(); + response.setHeader("Content-disposition","attachment; filename=venue.docx"); + response.setContentType("application/vnd.ms-excel"); + response.setCharacterEncoding("UTF-8"); + OutputStream out = response.getOutputStream(); + BufferedInputStream fin = new BufferedInputStream(new FileInputStream(documentPath)); + try { + byte[] content = new byte[1024]; + int length; + while ((length = fin.read(content, 0, content.length)) != -1) { + out.write(content, 0, length); + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + logger.info("文件下载失败", e.getMessage()); + throw e; + } finally { + fin.close(); + out.flush(); + out.close(); + } + } + + private static String getDocument() throws IOException, InvalidFormatException { + String newFilePath = "/Users/limqhz/home/test/document.docx"; + XWPFDocument document = new XWPFDocument(); + XWPFParagraph paragraph = document.createParagraph(); + paragraph.setAlignment(ParagraphAlignment.CENTER); + XWPFRun run = paragraph.createRun(); + // 入场二维码 + run.setText("入场二维码"); + run.addBreak(); + String imgFile = VenueBarcodeUtil.generateBarcode("jdoiawjdoiawioe1","202311161.jpg"); + int imgFormat = XWPFDocument.PICTURE_TYPE_JPEG; + run.addPicture(new FileInputStream(imgFile), imgFormat, "image description", + Units.toEMU(200), Units.toEMU(200)); + run.addBreak(BreakType.PAGE); + // 出场二维码 + run.setText("出场二维码"); + run.addBreak(); + String imgFile2 = VenueBarcodeUtil.generateBarcode("jdoiawjdoiawioe2","202311162.jpg"); + run.addPicture(new FileInputStream(imgFile2), imgFormat, "image description", + Units.toEMU(200), Units.toEMU(200)); + // 保存文件 + document.write(new FileOutputStream(newFilePath)); + document.close(); + return newFilePath; + } + } diff --git a/oms/src/main/java/com/ydd/oms/util/VenueBarcodeUtil.java b/oms/src/main/java/com/ydd/oms/util/VenueBarcodeUtil.java new file mode 100644 index 0000000..df79af3 --- /dev/null +++ b/oms/src/main/java/com/ydd/oms/util/VenueBarcodeUtil.java @@ -0,0 +1,109 @@ +package com.ydd.oms.util; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; +import com.ydd.framework.core.exception.ServiceException; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Hashtable; + +public class VenueBarcodeUtil { + + private static final int BLACK = 0xFF000000; + private static final int WHITE = 0xFFFFFFFF; + private static final int margin = 0; + + public static String generateBarcode(String barcodeValue,String fileName) { + try { + String geneFilePath = "/Users/limqhz/home/test/" + fileName; + makeBarcode(geneFilePath,barcodeValue); + return geneFilePath; + }catch (WriterException e) { + throw new ServiceException("生成二维码图片文件有问题"); + } + } + + private static void makeBarcode(String path, String barcodeValue) throws WriterException { + //二维码内容 + String content = barcodeValue; + String format = "jpg"; + int width = 200; // 二维码宽度 + int height = 200;// 二维码高度 + // 设置二维码矩阵的信息 + BitMatrix bitMatrix = setBitMatrix(content, width, height); + // 设置输出流 + OutputStream outStream = null; + try { + outStream = new FileOutputStream(new File(path)); + // 目前 针对容错等级为H reduceWhiteArea 二维码空白区域的大小 根据实际情况设置,如果二维码内容长度不固定的话 需要自己根据实际情况计算reduceWhiteArea的大小 + writeToFile(bitMatrix, format, outStream, 5); + outStream.close(); + } catch (Exception e) { + e.printStackTrace(); + }finally { + try { + outStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * 设置生成二维码矩阵信息 + * @param content 二维码图片内容 + * @param width 二维码图片宽度 + * @param height 二维码图片高度 + * @throws WriterException + */ + private static BitMatrix setBitMatrix(String content, int width, int height) throws WriterException { + BitMatrix bitMatrix = null; + Hashtable hints = new Hashtable(); + hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 指定编码方式,避免中文乱码 + hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 指定纠错等级 如果二维码里面的内容比较多的话推荐使用H 容错率30%, 这样可以避免一些扫描不出来的问题 + hints.put(EncodeHintType.MARGIN, margin); // 指定二维码四周白色区域大小 官方的这个方法目前没有没有作用默认设置为0 + bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints); + return bitMatrix; + } + + /** + * @param matrix + * @param format + * @param outStream + * @param reduceWhiteArea 二维码空白区域设置 + * @throws IOException + */ + + private static void writeToFile(BitMatrix matrix, String format, OutputStream outStream, int reduceWhiteArea) throws IOException { + BufferedImage image = toBufferedImage(matrix, reduceWhiteArea); + ImageIO.write(image, format, outStream); + } + + /** + * + * @param matrix + * @param reduceWhiteArea + * @return + */ + private static BufferedImage toBufferedImage(BitMatrix matrix, int reduceWhiteArea) { + int width = matrix.getWidth(); + int height = matrix.getHeight(); + BufferedImage image = new BufferedImage(width - 2 * reduceWhiteArea, height - 2 * reduceWhiteArea, BufferedImage.TYPE_3BYTE_BGR); + for (int x = reduceWhiteArea; x < width - reduceWhiteArea; x++) { + for (int y = reduceWhiteArea; y < height - reduceWhiteArea; y++) { + image.setRGB(x - reduceWhiteArea, y - reduceWhiteArea, matrix.get(x, y) ? BLACK : WHITE); + } + } + return image; + } + +} diff --git a/oms/src/main/resources/config/application-development.yml b/oms/src/main/resources/config/application-development.yml index 9605ab3..872f427 100644 --- a/oms/src/main/resources/config/application-development.yml +++ b/oms/src/main/resources/config/application-development.yml @@ -3,7 +3,7 @@ spring: # url: jdbc:mysql://yingdiandian.mysql.rds.aliyuncs.com:3306/smart_venue?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2b8 # username: yingdd # password: Yingdd2015 - url: jdbc:mysql://127.0.0.1:3306/smart_venue?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2b8&useAffectedRows=true + url: jdbc:mysql://127.0.0.1:3306/smart_venue?useUnicode=true&characterEncoding=utf-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2b8&useAffectedRows=true&useSSL=false username: root password: 123456 redis: diff --git a/service/src/main/java/com/sv/mapper/BarcodeEnterLogMapper.java b/service/src/main/java/com/sv/mapper/BarcodeEnterLogMapper.java new file mode 100644 index 0000000..783b06d --- /dev/null +++ b/service/src/main/java/com/sv/mapper/BarcodeEnterLogMapper.java @@ -0,0 +1,21 @@ +package com.sv.mapper; + +import com.sv.entity.BarcodeEnterLog; +import com.sv.entity.BarcodeOffline; + +public interface BarcodeEnterLogMapper { + int deleteByPrimaryKey(Integer id); + + int insert(BarcodeEnterLog record); + + int insertSelective(BarcodeEnterLog record); + + BarcodeEnterLog selectByPrimaryKey(Integer id); + + int updateByPrimaryKeySelective(BarcodeEnterLog record); + + int updateByPrimaryKey(BarcodeEnterLog record); + + BarcodeEnterLog findLastByBarcode(String barcode); + +} diff --git a/service/src/main/java/com/sv/mapper/BarcodeOfflineMapper.java b/service/src/main/java/com/sv/mapper/BarcodeOfflineMapper.java new file mode 100644 index 0000000..a0c26b6 --- /dev/null +++ b/service/src/main/java/com/sv/mapper/BarcodeOfflineMapper.java @@ -0,0 +1,19 @@ +package com.sv.mapper; + +import com.sv.entity.BarcodeOffline; + +public interface BarcodeOfflineMapper { + int deleteByPrimaryKey(Integer id); + + int insert(BarcodeOffline record); + + int insertSelective(BarcodeOffline record); + + BarcodeOffline selectByPrimaryKey(Integer id); + + int updateByPrimaryKeySelective(BarcodeOffline record); + + int updateByPrimaryKey(BarcodeOffline record); + + BarcodeOffline selectByBarcode(String barcode); +} diff --git a/service/src/main/java/com/sv/service/api/VenueService.java b/service/src/main/java/com/sv/service/api/VenueService.java index e148421..5b70866 100644 --- a/service/src/main/java/com/sv/service/api/VenueService.java +++ b/service/src/main/java/com/sv/service/api/VenueService.java @@ -294,7 +294,7 @@ public class VenueService extends BaseServiceImpl { } if (useCard != null) { //使用会员卡入场 - logger.info("用户" + member.getNickname() + "使用" + useCard.getCardType() + "入场"); + logger.info("用户" + member.getNickname() + "使用" + useCard.getCardType() + "核销"); // 会员卡入场,增加记录 createMemberMoneyLog(MoneyLogEnum.JOIN.value, venue.getPrice(), member.getId(), member.getPlatformId(), PayTypeEnum.MEMBER_CARD.value, useCard.getCardType(), venue.getId(), venue.getType()); @@ -305,21 +305,21 @@ public class VenueService extends BaseServiceImpl { } }else { //查无可用会员卡 - logger.info("用户" + member.getNickname() + "您好!请先购买会员卡再进场"); + logger.info("用户" + member.getNickname() + "您好!请先购买会员卡再出场核销"); result.setFlg(1); - result.setMsg("未查询到会员卡,请先购买"); + result.setMsg("未查询到会员卡,请先购买会员卡"); } }else { - //判断余额是否够 TODO 应该从入场订单里面去取 + //判断余额是否够 String time = DateUtilCard.nowTime().toString(); VenuePrice venuePrice = venuePriceService.findPrice(venueId, time); if (memberService.isMoneyEnough(member.getId(), venuePrice.getPrice())) { - logger.info("用户" + member.getNickname() + "使用余额进场"); + logger.info("用户" + member.getNickname() + "使用余额核销订单"); createMemberMoneyLog(MoneyLogEnum.JOIN.value, venuePrice.getPrice(), member.getId(), member.getPlatformId(), PayTypeEnum.BALANCE.value, null, venue.getId(), venue.getType()); } else { //余额不足 - logger.error("用户" + member.getNickname() + "余额不足进场失败"); + logger.error("用户" + member.getNickname() + "余额不足核销失败"); result.setFlg(1); result.setMsg("余额不足,请先充值"); } diff --git a/service/src/main/java/com/sv/service/common/DoorLockUtil.java b/service/src/main/java/com/sv/service/common/DoorLockUtil.java new file mode 100644 index 0000000..2a5f50d --- /dev/null +++ b/service/src/main/java/com/sv/service/common/DoorLockUtil.java @@ -0,0 +1,60 @@ +package com.sv.service.common; + +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.concurrent.TimeUnit; + +@Component +public class DoorLockUtil { + + private final static String DOOR_LOCK = "DOOR_LOCK_"; + private final static String DOOR_BARCODE_LOCK = "DOOR_BARCODE_LOCK_"; + private final static Integer LOCK_TIMEOUT = 30; + + @Resource + RedisCache redisCache; + + /** + * 门禁有人扫码之后,需要锁定门禁30s + * @return + */ + public boolean checkDoorLock(String doorSn){ + String doorKey = DOOR_LOCK + doorSn; + if (redisCache.getCacheObject(doorKey) == null){ + return false; + } + return true; + } + + /** + * 门禁有人扫码之后,需要锁定门禁30s + * @param doorSn + */ + public void lockDoor(String doorSn){ + String doorKey = DOOR_LOCK + doorSn; + redisCache.setCacheObject(doorKey,true,LOCK_TIMEOUT, TimeUnit.SECONDS); + } + + /** + * 门禁有人扫码之后,需要锁定门禁30s + * @return + */ + public boolean checkBarcode(String doorSn){ + String doorKey = DOOR_BARCODE_LOCK + doorSn; + if (redisCache.getCacheObject(doorKey) == null){ + return false; + } + return true; + } + + /** + * 门禁有人扫码之后,需要锁定门禁30s + * @param doorSn + */ + public void lockBarcode(String doorSn){ + String doorKey = DOOR_BARCODE_LOCK + doorSn; + redisCache.setCacheObject(doorKey,true,LOCK_TIMEOUT, TimeUnit.SECONDS); + } + +} diff --git a/service/src/main/java/com/sv/service/common/RedisCache.java b/service/src/main/java/com/sv/service/common/RedisCache.java new file mode 100644 index 0000000..e0bd63b --- /dev/null +++ b/service/src/main/java/com/sv/service/common/RedisCache.java @@ -0,0 +1,264 @@ +package com.sv.service.common; + +import org.springframework.data.redis.core.BoundSetOperations; +import org.springframework.data.redis.core.HashOperations; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * spring redis 工具类 + * + * @author quinn + **/ +@Component +public class RedisCache +{ + @Resource + public RedisTemplate redisTemplate; + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + */ + public void setCacheObject(final String key, final T value) + { + redisTemplate.opsForValue().set(key, value); + } + + /** + * 缓存基本的对象,Integer、String、实体类等 + * + * @param key 缓存的键值 + * @param value 缓存的值 + * @param timeout 时间 + * @param timeUnit 时间颗粒度 + */ + public void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) + { + redisTemplate.opsForValue().set(key, value, timeout, timeUnit); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @return true=设置成功;false=设置失败 + */ + public boolean expire(final String key, final long timeout) + { + return expire(key, timeout, TimeUnit.SECONDS); + } + + /** + * 设置有效时间 + * + * @param key Redis键 + * @param timeout 超时时间 + * @param unit 时间单位 + * @return true=设置成功;false=设置失败 + */ + public boolean expire(final String key, final long timeout, final TimeUnit unit) + { + return redisTemplate.expire(key, timeout, unit); + } + + /** + * 获取有效时间 + * + * @param key Redis键 + * @return 有效时间 + */ + public long getExpire(final String key) + { + return redisTemplate.getExpire(key); + } + + /** + * 判断 key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public Boolean hasKey(String key) + { + return redisTemplate.hasKey(key); + } + + /** + * 获得缓存的基本对象。 + * + * @param key 缓存键值 + * @return 缓存键值对应的数据 + */ + public T getCacheObject(final String key) + { + ValueOperations operation = redisTemplate.opsForValue(); + return operation.get(key); + } + + /** + * 删除单个对象 + * + * @param key + */ + public void deleteObject(final String key) + { + redisTemplate.delete(key); + } + + /** + * 删除集合对象 + * + * @param collection 多个对象 + * @return + */ + public void deleteObject(final Collection collection) + { + redisTemplate.delete(collection); + } + + /** + * 缓存List数据 + * + * @param key 缓存的键值 + * @param dataList 待缓存的List数据 + * @return 缓存的对象 + */ + public long setCacheList(final String key, final List dataList) + { + Long count = redisTemplate.opsForList().rightPushAll(key, dataList); + return count == null ? 0 : count; + } + + /** + * 获得缓存的list对象 + * + * @param key 缓存的键值 + * @return 缓存键值对应的数据 + */ + public List getCacheList(final String key) + { + return redisTemplate.opsForList().range(key, 0, -1); + } + + /** + * 缓存Set + * + * @param key 缓存键值 + * @param dataSet 缓存的数据 + * @return 缓存数据的对象 + */ + public BoundSetOperations setCacheSet(final String key, final Set dataSet) + { + BoundSetOperations setOperation = redisTemplate.boundSetOps(key); + Iterator it = dataSet.iterator(); + while (it.hasNext()) + { + setOperation.add(it.next()); + } + return setOperation; + } + + /** + * 获得缓存的set + * + * @param key + * @return + */ + public Set getCacheSet(final String key) + { + return redisTemplate.opsForSet().members(key); + } + + /** + * 缓存Map + * + * @param key + * @param dataMap + */ + public void setCacheMap(final String key, final Map dataMap) + { + if (dataMap != null) { + redisTemplate.opsForHash().putAll(key, dataMap); + } + } + + /** + * 获得缓存的Map + * + * @param key + * @return + */ + public Map getCacheMap(final String key) + { + return redisTemplate.opsForHash().entries(key); + } + + /** + * 往Hash中存入数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @param value 值 + */ + public void setCacheMapValue(final String key, final String hKey, final T value) + { + redisTemplate.opsForHash().put(key, hKey, value); + } + + /** + * 获取Hash中的数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @return Hash中的对象 + */ + public T getCacheMapValue(final String key, final String hKey) + { + HashOperations opsForHash = redisTemplate.opsForHash(); + return opsForHash.get(key, hKey); + } + + /** + * 获取多个Hash中的数据 + * + * @param key Redis键 + * @param hKeys Hash键集合 + * @return Hash对象集合 + */ + public List getMultiCacheMapValue(final String key, final Collection hKeys) + { + return redisTemplate.opsForHash().multiGet(key, hKeys); + } + + /** + * 删除Hash中的某条数据 + * + * @param key Redis键 + * @param hKey Hash键 + * @return 是否成功 + */ + public boolean deleteCacheMapValue(final String key, final String hKey) + { + return redisTemplate.opsForHash().delete(key, hKey) > 0; + } + + /** + * 获得缓存的基本对象列表 + * + * @param pattern 字符串前缀 + * @return 对象列表 + */ + public Collection keys(final String pattern) + { + return redisTemplate.keys(pattern); + } +} diff --git a/service/src/main/java/com/sv/service/oms/DeviceService.java b/service/src/main/java/com/sv/service/oms/DeviceService.java index e74e712..f66c3d4 100644 --- a/service/src/main/java/com/sv/service/oms/DeviceService.java +++ b/service/src/main/java/com/sv/service/oms/DeviceService.java @@ -4,12 +4,16 @@ import com.common.DeviceDTO; import com.enums.DeviceStatusEnum; import com.enums.EnterEnum; import com.github.pagehelper.PageHelper; +import com.sv.entity.BarcodeOffline; import com.sv.entity.Device; import com.sv.exception.oms.OmsException; +import com.sv.mapper.BarcodeOfflineMapper; import com.sv.mapper.DeviceMapper; +import com.sv.service.api.util.DateUtilCard; import com.ydd.framework.core.common.Pagination; import com.ydd.framework.core.common.dto.ResponseDTO; import com.ydd.framework.core.service.impl.BaseServiceImpl; +import org.apache.commons.lang.time.DateUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpEntity; @@ -21,6 +25,7 @@ import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; +import java.util.Date; import java.util.List; /** @@ -40,6 +45,9 @@ public class DeviceService extends BaseServiceImpl { @Resource private RestTemplate restTemplate; + @Resource + private BarcodeOfflineMapper barcodeOfflineMapper; + /** * 创建门禁设备 @@ -206,7 +214,6 @@ public class DeviceService extends BaseServiceImpl { } } - /** * find by DeviceName */ @@ -214,5 +221,16 @@ public class DeviceService extends BaseServiceImpl { return deviceMapper.findByDevice(venueId); } + public void makeDeviceBarcode(String deviceName, Integer venueId, String barcode) { + BarcodeOffline barcodeOffline = new BarcodeOffline(); + Date startTime = new Date(); + barcodeOffline.setStartTime(startTime); + barcodeOffline.setEndTime(DateUtils.addHours(startTime,2)); + barcodeOffline.setVenueId(venueId); + barcodeOffline.setDeviceName(deviceName); + barcodeOffline.setBarcode(barcode); + barcodeOfflineMapper.insert(barcodeOffline); + } + } diff --git a/service/src/main/java/com/sv/service/utils/VenueBarcodeUtil.java b/service/src/main/java/com/sv/service/utils/VenueBarcodeUtil.java new file mode 100644 index 0000000..eb81757 --- /dev/null +++ b/service/src/main/java/com/sv/service/utils/VenueBarcodeUtil.java @@ -0,0 +1,109 @@ +package com.sv.service.utils; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; +import com.ydd.framework.core.exception.ServiceException; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Hashtable; + +public class VenueBarcodeUtil { + + private static final int BLACK = 0xFF000000; + private static final int WHITE = 0xFFFFFFFF; + private static final int margin = 0; + + public static String generateBarcode(String barcodeValue,String fileName) { + try { + String geneFilePath = "/Users/limqhz/home/test/" + fileName; + makeBarcode(geneFilePath,barcodeValue); + return geneFilePath; + }catch (WriterException e) { + throw new ServiceException("生成二维码图片文件有问题"); + } + } + + private static void makeBarcode(String path, String barcodeValue) throws WriterException { + //二维码内容 + String content = barcodeValue; + String format = "jpg"; + int width = 200; // 二维码宽度 + int height = 200;// 二维码高度 + // 设置二维码矩阵的信息 + BitMatrix bitMatrix = setBitMatrix(content, width, height); + // 设置输出流 + OutputStream outStream = null; + try { + outStream = new FileOutputStream(new File(path)); + // 目前 针对容错等级为H reduceWhiteArea 二维码空白区域的大小 根据实际情况设置,如果二维码内容长度不固定的话 需要自己根据实际情况计算reduceWhiteArea的大小 + writeToFile(bitMatrix, format, outStream, 5); + outStream.close(); + } catch (Exception e) { + e.printStackTrace(); + }finally { + try { + outStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * 设置生成二维码矩阵信息 + * @param content 二维码图片内容 + * @param width 二维码图片宽度 + * @param height 二维码图片高度 + * @throws WriterException + */ + private static BitMatrix setBitMatrix(String content, int width, int height) throws WriterException { + BitMatrix bitMatrix = null; + Hashtable hints = new Hashtable(); + hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); // 指定编码方式,避免中文乱码 + hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // 指定纠错等级 如果二维码里面的内容比较多的话推荐使用H 容错率30%, 这样可以避免一些扫描不出来的问题 + hints.put(EncodeHintType.MARGIN, margin); // 指定二维码四周白色区域大小 官方的这个方法目前没有没有作用默认设置为0 + bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, width, height, hints); + return bitMatrix; + } + + /** + * @param matrix + * @param format + * @param outStream + * @param reduceWhiteArea 二维码空白区域设置 + * @throws IOException + */ + + private static void writeToFile(BitMatrix matrix, String format, OutputStream outStream, int reduceWhiteArea) throws IOException { + BufferedImage image = toBufferedImage(matrix, reduceWhiteArea); + ImageIO.write(image, format, outStream); + } + + /** + * + * @param matrix + * @param reduceWhiteArea + * @return + */ + private static BufferedImage toBufferedImage(BitMatrix matrix, int reduceWhiteArea) { + int width = matrix.getWidth(); + int height = matrix.getHeight(); + BufferedImage image = new BufferedImage(width - 2 * reduceWhiteArea, height - 2 * reduceWhiteArea, BufferedImage.TYPE_3BYTE_BGR); + for (int x = reduceWhiteArea; x < width - reduceWhiteArea; x++) { + for (int y = reduceWhiteArea; y < height - reduceWhiteArea; y++) { + image.setRGB(x - reduceWhiteArea, y - reduceWhiteArea, matrix.get(x, y) ? BLACK : WHITE); + } + } + return image; + } + +} diff --git a/service/src/main/resources/mybatis/mapper/sv/BarcodeEnterLogMapper.xml b/service/src/main/resources/mybatis/mapper/sv/BarcodeEnterLogMapper.xml new file mode 100644 index 0000000..41f4897 --- /dev/null +++ b/service/src/main/resources/mybatis/mapper/sv/BarcodeEnterLogMapper.xml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + id, barcode, venue_id, platform_id, created_id, modified_id, created_time, modified_time, + type + + + + delete from sv_barcode_enter_venue_log + where id = #{id,jdbcType=INTEGER} + + + insert into sv_barcode_enter_venue_log (id, barcode, venue_id, + platform_id, created_id, modified_id, + created_time, modified_time, type + ) + values (#{id,jdbcType=INTEGER}, #{barcode,jdbcType=VARCHAR}, #{venueId,jdbcType=INTEGER}, + #{platformId,jdbcType=INTEGER}, #{createdId,jdbcType=INTEGER}, #{modifiedId,jdbcType=INTEGER}, + #{createdTime,jdbcType=TIMESTAMP}, #{modifiedTime,jdbcType=TIMESTAMP}, #{type,jdbcType=INTEGER} + ) + + + insert into sv_barcode_enter_venue_log + + + id, + + + barcode, + + + venue_id, + + + platform_id, + + + created_id, + + + modified_id, + + + created_time, + + + modified_time, + + + type, + + + + + #{id,jdbcType=INTEGER}, + + + #{barcode,jdbcType=VARCHAR}, + + + #{venueId,jdbcType=INTEGER}, + + + #{platformId,jdbcType=INTEGER}, + + + #{createdId,jdbcType=INTEGER}, + + + #{modifiedId,jdbcType=INTEGER}, + + + #{createdTime,jdbcType=TIMESTAMP}, + + + #{modifiedTime,jdbcType=TIMESTAMP}, + + + #{type,jdbcType=INTEGER}, + + + + + update sv_barcode_enter_venue_log + + + barcode = #{barcode,jdbcType=VARCHAR}, + + + venue_id = #{venueId,jdbcType=INTEGER}, + + + platform_id = #{platformId,jdbcType=INTEGER}, + + + created_id = #{createdId,jdbcType=INTEGER}, + + + modified_id = #{modifiedId,jdbcType=INTEGER}, + + + created_time = #{createdTime,jdbcType=TIMESTAMP}, + + + modified_time = #{modifiedTime,jdbcType=TIMESTAMP}, + + + type = #{type,jdbcType=INTEGER}, + + + where id = #{id,jdbcType=INTEGER} + + + update sv_barcode_enter_venue_log + set barcode = #{barcode,jdbcType=VARCHAR}, + venue_id = #{venueId,jdbcType=INTEGER}, + platform_id = #{platformId,jdbcType=INTEGER}, + created_id = #{createdId,jdbcType=INTEGER}, + modified_id = #{modifiedId,jdbcType=INTEGER}, + created_time = #{createdTime,jdbcType=TIMESTAMP}, + modified_time = #{modifiedTime,jdbcType=TIMESTAMP}, + type = #{type,jdbcType=INTEGER} + where id = #{id,jdbcType=INTEGER} + + + + + diff --git a/service/src/main/resources/mybatis/mapper/sv/BarcodeOfflineMapper.xml b/service/src/main/resources/mybatis/mapper/sv/BarcodeOfflineMapper.xml new file mode 100644 index 0000000..bfda4ca --- /dev/null +++ b/service/src/main/resources/mybatis/mapper/sv/BarcodeOfflineMapper.xml @@ -0,0 +1,314 @@ + + + + + + + + + + + + + + + + + + + id, barcode, start_time, end_time, venue_id, created_id, modified_id, created_time, + modified_time, device_name + + + + delete from sv_barcode_offline + where id = #{id,jdbcType=INTEGER} + + + insert into sv_barcode_offline (id, barcode, start_time, + end_time, venue_id, created_id, + modified_id, created_time, modified_time, + device_name) + values (#{id,jdbcType=INTEGER}, #{barcode,jdbcType=VARCHAR}, #{startTime,jdbcType=TIMESTAMP}, + #{endTime,jdbcType=TIMESTAMP}, #{venueId,jdbcType=INTEGER}, #{createdId,jdbcType=INTEGER}, + #{modifiedId,jdbcType=INTEGER}, #{createdTime,jdbcType=TIMESTAMP}, #{modifiedTime,jdbcType=TIMESTAMP}, + #{deviceName,jdbcType=VARCHAR}) + + + insert into sv_barcode_offline + + + id, + + + barcode, + + + start_time, + + + end_time, + + + venue_id, + + + created_id, + + + modified_id, + + + created_time, + + + modified_time, + + + device_name, + + + + + #{id,jdbcType=INTEGER}, + + + #{barcode,jdbcType=VARCHAR}, + + + #{startTime,jdbcType=TIMESTAMP}, + + + #{endTime,jdbcType=TIMESTAMP}, + + + #{venueId,jdbcType=INTEGER}, + + + #{createdId,jdbcType=INTEGER}, + + + #{modifiedId,jdbcType=INTEGER}, + + + #{createdTime,jdbcType=TIMESTAMP}, + + + #{modifiedTime,jdbcType=TIMESTAMP}, + + + #{deviceName,jdbcType=VARCHAR}, + + + + + update sv_barcode_offline + + + barcode = #{barcode,jdbcType=VARCHAR}, + + + start_time = #{startTime,jdbcType=TIMESTAMP}, + + + end_time = #{endTime,jdbcType=TIMESTAMP}, + + + venue_id = #{venueId,jdbcType=INTEGER}, + + + created_id = #{createdId,jdbcType=INTEGER}, + + + modified_id = #{modifiedId,jdbcType=INTEGER}, + + + created_time = #{createdTime,jdbcType=TIMESTAMP}, + + + modified_time = #{modifiedTime,jdbcType=TIMESTAMP}, + + + device_name = #{deviceName,jdbcType=VARCHAR}, + + + where id = #{id,jdbcType=INTEGER} + + + update sv_barcode_offline + set barcode = #{barcode,jdbcType=VARCHAR}, + start_time = #{startTime,jdbcType=TIMESTAMP}, + end_time = #{endTime,jdbcType=TIMESTAMP}, + venue_id = #{venueId,jdbcType=INTEGER}, + created_id = #{createdId,jdbcType=INTEGER}, + modified_id = #{modifiedId,jdbcType=INTEGER}, + created_time = #{createdTime,jdbcType=TIMESTAMP}, + modified_time = #{modifiedTime,jdbcType=TIMESTAMP}, + device_name = #{deviceName,jdbcType=VARCHAR} + where id = #{id,jdbcType=INTEGER} + + + + + + + + + + + + + + + + + id, barcode, start_time, end_time, venue_id, created_id, modified_id, created_time, + modified_time, device_name + + + + delete from sv_barcode_offline + where id = #{id,jdbcType=INTEGER} + + + insert into sv_barcode_offline (id, barcode, start_time, + end_time, venue_id, created_id, + modified_id, created_time, modified_time, + device_name) + values (#{id,jdbcType=INTEGER}, #{barcode,jdbcType=VARCHAR}, #{startTime,jdbcType=TIMESTAMP}, + #{endTime,jdbcType=TIMESTAMP}, #{venueId,jdbcType=INTEGER}, #{createdId,jdbcType=INTEGER}, + #{modifiedId,jdbcType=INTEGER}, #{createdTime,jdbcType=TIMESTAMP}, #{modifiedTime,jdbcType=TIMESTAMP}, + #{deviceName,jdbcType=VARCHAR}) + + + insert into sv_barcode_offline + + + id, + + + barcode, + + + start_time, + + + end_time, + + + venue_id, + + + created_id, + + + modified_id, + + + created_time, + + + modified_time, + + + device_name, + + + + + #{id,jdbcType=INTEGER}, + + + #{barcode,jdbcType=VARCHAR}, + + + #{startTime,jdbcType=TIMESTAMP}, + + + #{endTime,jdbcType=TIMESTAMP}, + + + #{venueId,jdbcType=INTEGER}, + + + #{createdId,jdbcType=INTEGER}, + + + #{modifiedId,jdbcType=INTEGER}, + + + #{createdTime,jdbcType=TIMESTAMP}, + + + #{modifiedTime,jdbcType=TIMESTAMP}, + + + #{deviceName,jdbcType=VARCHAR}, + + + + + update sv_barcode_offline + + + barcode = #{barcode,jdbcType=VARCHAR}, + + + start_time = #{startTime,jdbcType=TIMESTAMP}, + + + end_time = #{endTime,jdbcType=TIMESTAMP}, + + + venue_id = #{venueId,jdbcType=INTEGER}, + + + created_id = #{createdId,jdbcType=INTEGER}, + + + modified_id = #{modifiedId,jdbcType=INTEGER}, + + + created_time = #{createdTime,jdbcType=TIMESTAMP}, + + + modified_time = #{modifiedTime,jdbcType=TIMESTAMP}, + + + device_name = #{deviceName,jdbcType=VARCHAR}, + + + where id = #{id,jdbcType=INTEGER} + + + update sv_barcode_offline + set barcode = #{barcode,jdbcType=VARCHAR}, + start_time = #{startTime,jdbcType=TIMESTAMP}, + end_time = #{endTime,jdbcType=TIMESTAMP}, + venue_id = #{venueId,jdbcType=INTEGER}, + created_id = #{createdId,jdbcType=INTEGER}, + modified_id = #{modifiedId,jdbcType=INTEGER}, + created_time = #{createdTime,jdbcType=TIMESTAMP}, + modified_time = #{modifiedTime,jdbcType=TIMESTAMP}, + device_name = #{deviceName,jdbcType=VARCHAR} + where id = #{id,jdbcType=INTEGER} + + + + + diff --git a/service/src/main/resources/tools/generatorConfig.xml b/service/src/main/resources/tools/generatorConfig.xml index 17af678..3739ca5 100644 --- a/service/src/main/resources/tools/generatorConfig.xml +++ b/service/src/main/resources/tools/generatorConfig.xml @@ -90,7 +90,7 @@ domainObjectName 给表对应的 model 起名字 注意:大小写敏感问题。 --> -