From 52aa9659a23600a944b431b91e5476b3fcc3abdc Mon Sep 17 00:00:00 2001 From: limqhz <540344226@qq.com> Date: Tue, 5 Sep 2023 09:27:00 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=AB=E6=8F=8F=E4=BA=8C=E7=BB=B4=E7=A0=81?= =?UTF-8?q?=E5=85=A5=E5=9C=BA=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sv/api/controller/VenueController.java | 67 +++- ...troller.java => AdminNettyController.java} | 43 +-- .../com/sv/netty/netty/ServerHandler.java | 34 ++- .../netty/netty/service/MessageService.java | 19 +- .../impl/AppMessageHandlerAdapter.java | 279 ----------------- .../impl/ServerMessageHandlerAdapter.java | 262 ++++++++++++++++ .../java/com/enums/BarCodeStatusEnum.java | 42 +++ .../src/main/java/com/enums/MoneyLogEnum.java | 2 +- .../main/java/com/sv/dto/BarCodeResult.java | 12 +- .../src/main/java/com/sv/entity/Barcode.java | 122 ++++++++ .../src/main/java/com/sv/entity/Device.java | 20 -- .../java/com/sv/barcode/ClientConfig.java | 44 +++ .../java/com/sv/barcode/ListenKeyFrame.java | 27 ++ .../main/java/com/sv/barcode/ScanBarCode.java | 38 +++ .../java/com/sv/intergration/DoorService.java | 8 + .../MessageService.java | 19 +- .../main/java/com/sv/netty/ClientHandler.java | 17 +- .../main/java/com/sv/netty/ClientThread.java | 23 +- .../java/com/sv/netty/MessageHandler.java | 42 +++ .../java/com/sv/service/ClientService.java | 43 ++- netty-client/src/main/resources/logback.xml | 2 +- .../java/com/sv/netty/config/MessageType.java | 7 +- .../com/sv/netty/config/NettyConstant.java | 15 +- .../com/sv/netty/config/VenueBarCode.java | 46 +++ .../main/java/com/sv/netty/utils/AesUtil.java | 60 ++++ .../main/java/com/sv/netty/utils/Base64.java | 285 ++++++++++++++++++ .../java/com/sv/netty/utils/MakeCode.java | 46 +++ .../sv/oms/controller/DeviceController.java | 25 +- .../java/com/sv/mapper/BarcodeMapper.java | 26 ++ .../main/java/com/sv/mapper/DeviceMapper.java | 6 +- .../com/sv/mapper/MemberMoneyLogMapper.java | 4 +- .../sv/service/api/MemberFaceInfoService.java | 1 + .../sv/service/api/MemberMoneyLogService.java | 7 + .../java/com/sv/service/api/OrderService.java | 1 + .../java/com/sv/service/api/VenueService.java | 90 ++---- .../com/sv/service/oms/DeviceService.java | 30 +- .../mybatis/mapper/sv/BarcodeMapper.xml | 171 +++++++++++ .../mybatis/mapper/sv/DeviceMapper.xml | 43 +-- .../mapper/sv/MemberEnterVenueLogMapper.xml | 4 +- .../mapper/sv/MemberMoneyLogMapper.xml | 20 +- .../main/resources/tools/generatorConfig.xml | 2 +- 41 files changed, 1562 insertions(+), 492 deletions(-) rename api/src/main/java/com/sv/netty/controller/{QREnterController.java => AdminNettyController.java} (57%) delete mode 100644 api/src/main/java/com/sv/netty/netty/service/impl/AppMessageHandlerAdapter.java create mode 100644 api/src/main/java/com/sv/netty/netty/service/impl/ServerMessageHandlerAdapter.java create mode 100644 entity/src/main/java/com/enums/BarCodeStatusEnum.java create mode 100644 entity/src/main/java/com/sv/entity/Barcode.java create mode 100644 netty-client/src/main/java/com/sv/barcode/ClientConfig.java create mode 100644 netty-client/src/main/java/com/sv/barcode/ListenKeyFrame.java create mode 100644 netty-client/src/main/java/com/sv/barcode/ScanBarCode.java create mode 100644 netty-client/src/main/java/com/sv/intergration/DoorService.java rename netty-client/src/main/java/com/sv/{service => intergration}/MessageService.java (78%) create mode 100644 netty-client/src/main/java/com/sv/netty/MessageHandler.java create mode 100644 netty-model/src/main/java/com/sv/netty/config/VenueBarCode.java create mode 100644 netty-model/src/main/java/com/sv/netty/utils/AesUtil.java create mode 100644 netty-model/src/main/java/com/sv/netty/utils/Base64.java create mode 100644 netty-model/src/main/java/com/sv/netty/utils/MakeCode.java create mode 100644 service/src/main/java/com/sv/mapper/BarcodeMapper.java create mode 100644 service/src/main/resources/mybatis/mapper/sv/BarcodeMapper.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 40619a2..7b81bdb 100644 --- a/api/src/main/java/com/sv/api/controller/VenueController.java +++ b/api/src/main/java/com/sv/api/controller/VenueController.java @@ -1,12 +1,23 @@ package com.sv.api.controller; +import com.enums.BarCodeStatusEnum; +import com.enums.EnterEnum; +import com.sv.dto.BarCodeResult; +import com.sv.entity.Barcode; +import com.sv.entity.Device; import com.sv.entity.Venue; +import com.sv.mapper.BarcodeMapper; +import com.sv.netty.utils.AesUtil; +import com.sv.netty.utils.MakeCode; import com.sv.service.api.VenueService; +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 org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; @@ -83,10 +94,14 @@ public class VenueController extends BaseApiController { */ @RequestMapping(value = "/venue/detail", method = RequestMethod.POST) public ResponseDTO detail(@RequestParam("venueId") Integer venueId) { - Integer loginMemberId = getLoginMemberId(); + Integer loginMemberId = getMemberIdByAccessToken(); return ResponseDTO.ok().addAttribute("venues", venueService.findByVenueId(venueId,loginMemberId)); } + @Resource + DeviceService deviceService; + @Resource + BarcodeMapper barcodeMapper; /** * 我要进场 * @@ -94,8 +109,21 @@ public class VenueController extends BaseApiController { * @return */ @RequestMapping(value = "/venue/join", method = RequestMethod.GET) + @Transactional public ResponseDTO join(@RequestParam("venueId") Integer venueId) { - return ResponseDTO.ok().addAttribute("flg", venueService.join(getMemberIdByAccessToken(), venueId)); + Integer memberId = getMemberIdByAccessToken(); + BarCodeResult join = venueService.join(memberId, venueId); + if (join.getFlg() == 0) { + Device byDevice = deviceService.findByDevice(venueId); + if (byDevice == null) { + join.setFlg(999); + join.setMsg("通讯异常,门禁设备离线中"); + }else { + String barcode = newBarcode(byDevice.getName(), EnterEnum.ENTER, venueId, memberId); + join.setBarcode(barcode); + } + } + return ResponseDTO.ok().addAttribute("join", join); } /** @@ -105,9 +133,42 @@ public class VenueController extends BaseApiController { * @return */ @RequestMapping(value = "/venue/out", method = RequestMethod.GET) + @Transactional public ResponseDTO out(@RequestParam("venueId") Integer venueId) { - return ResponseDTO.ok().addAttribute("flg", venueService.join(getMemberIdByAccessToken(), venueId)); + + Integer memberId = getMemberIdByAccessToken(); + BarCodeResult out = venueService.out(memberId, venueId); + if (out.getFlg() == 0) { + Device byDevice = deviceService.findByDevice(venueId); + if (byDevice == null) { + out.setFlg(999); + out.setMsg("通讯异常,门禁设备离线中"); + }else { + String barcode = newBarcode(byDevice.getName(),EnterEnum.OUT,venueId,memberId); + out.setBarcode(barcode); + } + } + 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); + if (res == null) { + barcode = MakeCode.makeCode(venueId, memberId, deviceName, enterEnum.getValue() + ""); + Barcode b = new Barcode(); + logger.info("用户扫码【" + memberId + "$" + venueId + "】生成二维码为" + barcode); + b.setBarcode(barcode); + b.setStatus(BarCodeStatusEnum.INIT.getValue()); + b.setMemberId(memberId); + b.setVenueId(venueId); + b.setEnter(enterEnum.getValue()); + barcodeMapper.insert(b); + }else { + barcode = res.getBarcode(); + } + return barcode; + } + } diff --git a/api/src/main/java/com/sv/netty/controller/QREnterController.java b/api/src/main/java/com/sv/netty/controller/AdminNettyController.java similarity index 57% rename from api/src/main/java/com/sv/netty/controller/QREnterController.java rename to api/src/main/java/com/sv/netty/controller/AdminNettyController.java index f2c3a57..2abd30e 100644 --- a/api/src/main/java/com/sv/netty/controller/QREnterController.java +++ b/api/src/main/java/com/sv/netty/controller/AdminNettyController.java @@ -1,10 +1,13 @@ package com.sv.netty.controller; -import com.sv.entity.Venue; +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.service.oms.DeviceService; 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.web.bind.annotation.*; @@ -15,32 +18,36 @@ import javax.annotation.Resource; * 小程序二维码进场Controller */ @RestController -public class QREnterController extends BaseApiController { +public class AdminNettyController extends BaseApiController { - private final Logger logger = LoggerFactory.getLogger(QREnterController.class); + private final Logger logger = LoggerFactory.getLogger(AdminNettyController.class); + @Resource + DeviceService deviceService; @Resource private MessageService messageService; /** * 进场指令发布 */ - @RequestMapping(value = "/qrCode/enter", method = RequestMethod.GET) - public ResponseDTO enter(@RequestParam("deviceId") String deviceId) { - Integer memberId = getMemberIdByAccessToken(); - Integer venueId = getVenueId(deviceId); - String deviceName = getDeviceName(deviceId); - Venue venue = new Venue();// TODO - if (venue!=null){ - if (true){ - // 出场 - messageService.outVenue(deviceName,venueId,memberId,venue); - }else{ - // 进场 - messageService.enterVenue(deviceName,venueId,memberId,venue); - } + @RequestMapping(value = "/admin/enter/{id}", method = RequestMethod.POST) + public ResponseDTO enter(@PathVariable("id") Integer id) { + Device device = deviceService.findById(id); + if (!DeviceStatusEnum.ONLINE.value.equals(device.getStatus())){ + throw new ServiceException("设备离线!请检查连接"); } - return ResponseDTO.ok(); + messageService.adminEnter(device.getName(),device.getVenueId()); + return ResponseDTO.ok(); } + @RequestMapping(value = "/admin/out/{id}", method = RequestMethod.POST) + public ResponseDTO out(@PathVariable("id") Integer id) { + Device device = deviceService.findById(id); + if (!DeviceStatusEnum.ONLINE.value.equals(device.getStatus())){ + throw new ServiceException("设备离线!请检查连接"); + } + messageService.adminOut(device.getName(),device.getVenueId()); + return ResponseDTO.ok(); + } + /** * 根据字符串获取场馆 * @param deviceId 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 85bbac1..c075c63 100644 --- a/api/src/main/java/com/sv/netty/netty/ServerHandler.java +++ b/api/src/main/java/com/sv/netty/netty/ServerHandler.java @@ -1,11 +1,10 @@ package com.sv.netty.netty; -import com.sv.netty.config.ChannelParam; -import com.sv.netty.config.HeartBeat; -import com.sv.netty.config.NettyConstant; -import com.sv.netty.config.SpringContextHolder; +import com.enums.EnterEnum; +import com.sv.netty.config.*; import com.sv.netty.netty.service.MessageService; import com.sv.netty.utils.JsonUtils; +import com.sv.netty.utils.MakeCode; import io.netty.channel.*; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; @@ -50,12 +49,29 @@ public class ServerHandler extends SimpleChannelInboundHandler { @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) { String clientIp = ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().getClientIp(); + logger.info("接收服务器响应msg:[" + msg + "]"); try { - HeartBeat hb = JsonUtils.decode(msg,HeartBeat.class); - logger.info("客户端【" + clientIp + "】上报心跳..."); - ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().setVenueId(hb.getVenueId()); - ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().setDeviceName(hb.getDeviceName()); - messageService.online(clientIp,ctx.channel(), hb); + VenueMessage message = JsonUtils.decode(msg, VenueMessage.class); + switch (message.getMessageType()) { + case HB: + HeartBeat hb = JsonUtils.decode(message.getMessage(),HeartBeat.class); + logger.info("客户端【" + clientIp + "】上报心跳..."); + ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().setVenueId(hb.getVenueId()); + ctx.channel().attr(NettyConstant.CHANNEL_PARAM).get().setDeviceName(hb.getDeviceName()); + messageService.online(clientIp,ctx.channel(), hb); + break; + case SCAN_CODE: + logger.info("客户端【" + clientIp + "】开门了..."); + VenueBarCode venueBarCode = MakeCode.decodeCode(message.getMessage()); + if (EnterEnum.ENTER.getValue() == venueBarCode.getDirection()) { + messageService.enterVenue(message.getMessage()); + } else { + messageService.outVenue(message.getMessage()); + } + break; + default: + logger.info( "default"); + } } catch (Exception e) { logger.error("[" + clientIp + "] host unknown error",e); } 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 600be66..efdb85f 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 @@ -2,6 +2,7 @@ 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; @@ -37,21 +38,19 @@ public interface MessageService { Set countConnection(); /** * 出场 - * @param deviceName - * @param venueId - * @param memberId - * @param venue + * @param barcode */ - void outVenue(String deviceName, Integer venueId, Integer memberId, Venue venue); + void outVenue(String barcode); /** * 进场 - * @param deviceName - * @param venueId - * @param memberId - * @param venue + * @param barcode */ - void enterVenue(String deviceName, Integer venueId, Integer memberId, Venue venue); + void enterVenue(String barcode); + + public void adminEnter(String deviceName, Integer venueId); + + public void adminOut(String deviceName, Integer venueId); void testLoad(String deviceName, Integer venueId); } diff --git a/api/src/main/java/com/sv/netty/netty/service/impl/AppMessageHandlerAdapter.java b/api/src/main/java/com/sv/netty/netty/service/impl/AppMessageHandlerAdapter.java deleted file mode 100644 index 64b18e8..0000000 --- a/api/src/main/java/com/sv/netty/netty/service/impl/AppMessageHandlerAdapter.java +++ /dev/null @@ -1,279 +0,0 @@ -package com.sv.netty.netty.service.impl; - -import com.sv.entity.Member; -import com.sv.entity.MemberEnterVenueLog; -import com.sv.entity.Venue; -import com.sv.netty.config.*; -import com.sv.netty.netty.service.MessageService; -import com.sv.netty.utils.JsonUtils; -import com.sv.netty.utils.ServerMessageUtils; -import com.sv.service.api.MemberEnterVenueLogService; -import com.sv.service.api.MemberService; -import com.sv.service.api.VenueService; -import com.sv.service.oms.ConfigService; -import com.sv.service.oms.DeviceService; -import com.ydd.oms.entity.sys.Config; -import io.netty.channel.Channel; -import io.netty.util.internal.PlatformDependent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; -import java.text.MessageFormat; -import java.util.*; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; - - -/** - * 消息实现类 - * - * @Author peakren - * @Date 08/05/2017 10:43 PM - */ -@Service("messageService") -public class AppMessageHandlerAdapter implements MessageService { - - private Logger logger = LoggerFactory.getLogger(AppMessageHandlerAdapter.class); - - /** - * 存储设备通道类型 - * 此处存储客户端的channel 信息key 为 【deviceId + venueId】 - * value: 1Tcp 2WebSocket - */ - private ConcurrentMap links = PlatformDependent.newConcurrentHashMap(); - - @Resource - private MemberService memberService; - - @Resource - private VenueService venueService; - - @Resource - private DeviceService deviceService; - - @Resource - private ConfigService configService; - - @Resource(name = "scheduledExecutorService") - private ScheduledExecutorService scheduledExecutorService; - - @Resource - private MemberEnterVenueLogService memberEnterVenueLogService; - - /** - * 处理心跳信息,存储心跳信息 - * @param clientId - * @param channel - * @param heartBeat - */ - @Override - public void online(String clientId, Channel channel, HeartBeat heartBeat) { - logger.error("=========" + JsonUtils.encode(heartBeat) + clientId); - // 处理心跳信息 - if (!contains(heartBeat.getDeviceName(),heartBeat.getVenueId())){ - // 此处存储客户端的channel 信息key 为 deviceId + venueId - Venue thisVenue = venueService.findById(heartBeat.getVenueId()); - if (thisVenue == null ){ - logger.error("this client choose venue Error! venueId == " + heartBeat.getVenueId()); - } else { - deviceService.online(heartBeat.getDeviceName(),heartBeat.getVenueId(),thisVenue.getType(),clientId); - addLinks(heartBeat.getDeviceName(),heartBeat.getVenueId(),channel); - VenueMessage venueMessage = new VenueMessage(MessageType.LINK,"欢迎扫码进场!"); - ServerMessageUtils.INSTANCE.sendMsg(channel,venueMessage); - } - } - } - - /** - * 设备下线 - * @param deviceName - * @param venueId - */ - @Override - public void Offline(String deviceName, Integer venueId) { - if (deviceName != null && venueId != null){ - removeChannelType(deviceName,venueId); - deviceService.offline(deviceName,venueId); - } - } - - /** - * 测试客户端连接 - * @return - */ - @Override - public void testLoad(String deviceName, Integer venueId) { - Channel currentChannel = getCurrentChannel(deviceName, venueId); - ServerMessageUtils.INSTANCE.sendMsg(currentChannel,new VenueMessage(MessageType.LINK,"测试链接")); - } - - - @Override - public void outVenue(String deviceName, Integer venueId, Integer memberId, Venue venue) { - Channel channel = getCurrentChannel(deviceName,venueId); - Member member = memberService.findByMember(memberId); - if (member != null) { - //出场 不用判断直接出 - MemberEnterVenueLog memberEnterVenueLog = new MemberEnterVenueLog(); - memberEnterVenueLog.setOrderSn(""); - memberEnterVenueLog.setType(1); - memberEnterVenueLog.setMemberId(member.getId()); -// memberEnterVenueLog.setVeneuType(device.getVenueType()); -// memberEnterVenueLog.setVenueId(device.getVenueId()); - memberEnterVenueLog.setPlatformId(member.getPlatformId()); - memberEnterVenueLogService.save(memberEnterVenueLog); - logger.info("用户" + member.getNickname() + "出场"); -// MemberDto memberMessageDto = new MemberDto(); -// memberMessageDto.setAmount(member.getMoney()); -// memberMessageDto.setName(member.getNickname()); -// memberMessageDto.setAvatar(member.getAvatar()); -// memberMessageDto.setMobile(member.getMobile()); -// memberMessageDto.setPlaceName(""); -// memberMessageDto.setMessage("欢迎下次再来" + venue.getName()); -// memberMessageDto.setCode(2); -// VenueMessage VenueMessage = new VenueMessage(); -// VenueMessage.setCmdId(Cmd.OPEN_DOOR.id); -// VenueMessage.setDoor(2); -// sendOpenMessage(VenueMessage, device.getId()); - // 校验完就可以出场了 -// sendMessage(memberMessageDto, device.getId()); -// venueService.addNumber(venue.getId(), -1, member.getId()); -// venue = venueService.findById(venue.getId()); -// sendNumberChange(venue.getNumber()); - } - } - - /** - * 进场逻辑 - * @param deviceName - * @param venueId - * @param memberId - * @param venue - */ - @Override - public void enterVenue(String deviceName, Integer venueId, Integer memberId, Venue venue) { - Member member = memberService.findByMember(memberId); - Channel channel = getCurrentChannel(deviceName, venueId); - // 校验入场时间是否正常 - if (checkInterval(member,venueId)) { - if(venueService.qrCodeEnterVenue(memberId,deviceName,venueId,venue)){ - // 可以进场 - scheduledExecutorService.schedule(() -> { - ServerMessageUtils.INSTANCE.sendMsg(channel,new VenueMessage(MessageType.OPEN_DOOR,"OK")); - }, 5, TimeUnit.SECONDS); - } else { - // 进场失败 - ServerMessageUtils.INSTANCE.sendMsg(channel,new VenueMessage(MessageType.FAILED, ErrorCode.NO_USE_CARD.getMsg())); - } - } else { - logger.info(member == null ? "null" : member.getId() + "入场失败:连续入场"); - Config config = configService.findById(1); - ServerMessageUtils.INSTANCE.sendMsg(channel,new VenueMessage(MessageType.OPEN_DOOR, MessageFormat.format(ErrorCode.CHECK_ENTER_INTERVAL.getMsg(),config.getValue()))); - } - } - - private boolean checkInterval(Member member,Integer venueId){ - if (member == null || venueId == null) { - return false; - }else{ - //最后进场记录 - MemberEnterVenueLog enterVenueLog = memberEnterVenueLogService.findMemberLastLogNoType(member.getId(), venueId); - if (enterVenueLog != null) { - //有记录 查看 最后一次是否是出场 - if (true) {// TODO - return true; - } else { - //是进场 - Date date = new Date(); - //本日连续进场次数 - int continuityEnterCount = memberEnterVenueLogService.countEnterByDate(member.getId(), venueId, date); - logger.info("连续进场次数:" + continuityEnterCount); - //距离上次入场差多少秒 - int differenceSeconds = (int) (date.getTime() - enterVenueLog.getCreatedTime().getTime()) / (1000); - if (continuityEnterCount <= 0) { - //没有连续进场 间隔5分钟 - Config config = configService.findById(1); - if (differenceSeconds <= (Integer.parseInt(config.getValue()) * 60)) { - // - return false; - } - } else if (continuityEnterCount == 1) { - //有过一次连续进场 间隔20分钟 - Config config = configService.findById(2); - if (differenceSeconds <= (Integer.parseInt(config.getValue()) * 60)) { - //小于20分钟 不允许入场 - return false; - } - } else { - //当日超过两次连续入场 入场失败 - return false; - } - } - } - return true; - } - } - - /** - * 操作连接 - */ - /** - * 缓存通道 - */ - public void addLinks(String deviceName, Integer venueId, Channel channel) { - String clientId = deviceName + NettyConstant.SPIT_WORD + venueId; - links.put(clientId, channel); - } - - /** - * 获取当前通道 - */ - public Channel getCurrentChannel(String deviceName, Integer venueId){ - String clientId = deviceName + NettyConstant.SPIT_WORD + venueId; - return links.get(clientId); - } - - /** - * 获取通道 - */ - public boolean contains(String deviceName, Integer venueId) { - String clientId = deviceName + NettyConstant.SPIT_WORD + venueId + NettyConstant.SPIT_WORD; - return links.containsKey(clientId); - } - - /** - * 移除通道 - */ - public void removeChannelType(String deviceName, Integer venueId) { - String clientId = deviceName + NettyConstant.SPIT_WORD + venueId ; - links.remove(clientId); - } - - /** - * 统计目前有多少链接数 - * @return - */ - @Override - public Set countConnection() { - return links.keySet(); - } - - /** - * 控制硬件,篮球馆的门禁灯光控制 - * @param number - */ -// public void sendNumberChange(Integer number) { -// HttpHeaders headers = new HttpHeaders(); -// headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); -// MultiValueMap param = new LinkedMultiValueMap<>(); -// param.add("LingtekID", "5d14229fcb1f5c1a9046f429"); -// param.add("Number", number.toString()); -// HttpEntity> request = new HttpEntity<>(param, headers); -// ResponseEntity result = restTemplate.exchange("http://lingtek.jalasmart.com/api/v1/lingtek/number", HttpMethod.PUT, request, Result.class); -// logger.info("灯光结果" + JsonMapper.nonDefaultMapper().toJson(result)); -// } - -} 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 new file mode 100644 index 0000000..4f9c379 --- /dev/null +++ b/api/src/main/java/com/sv/netty/netty/service/impl/ServerMessageHandlerAdapter.java @@ -0,0 +1,262 @@ +package com.sv.netty.netty.service.impl; + +import com.enums.EnterEnum; +import com.sv.entity.Member; +import com.sv.entity.MemberEnterVenueLog; +import com.sv.entity.MemberMoneyLog; +import com.sv.entity.Venue; +import com.sv.mapper.BarcodeMapper; +import com.sv.netty.config.*; +import com.sv.netty.netty.service.MessageService; +import com.sv.netty.utils.JsonUtils; +import com.sv.netty.utils.MakeCode; +import com.sv.netty.utils.ServerMessageUtils; +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.oms.DeviceService; +import com.ydd.framework.core.exception.ServiceException; +import io.netty.channel.Channel; +import io.netty.util.internal.PlatformDependent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.*; +import java.util.concurrent.ConcurrentMap; + +/** + * 消息实现类 + * + * @Author peakren + * @Date 08/05/2017 10:43 PM + */ +@Service("messageService") +public class ServerMessageHandlerAdapter implements MessageService { + + private Logger logger = LoggerFactory.getLogger(ServerMessageHandlerAdapter.class); + + /** + * 存储设备通道类型 + * 此处存储客户端的channel 信息key 为 【deviceId + venueId】 + * value: 1Tcp 2WebSocket + */ + private ConcurrentMap links = PlatformDependent.newConcurrentHashMap(); + + @Resource + private MemberService memberService; + + @Resource + private VenueService venueService; + + @Resource + private DeviceService deviceService; + + @Resource + private MemberEnterVenueLogService memberEnterVenueLogService; + + @Resource + private MemberMoneyLogService memberMoneyLogService; + + @Resource + private BarcodeMapper barcodeMapper; + + /** + * 处理心跳信息,存储心跳信息 + * @param clientId + * @param channel + * @param heartBeat + */ + @Override + public void online(String clientId, Channel channel, HeartBeat heartBeat) { + logger.info("=========" + JsonUtils.encode(heartBeat) + clientId); + // 处理心跳信息 + if (!contains(heartBeat.getDeviceName(),heartBeat.getVenueId())){ + // 此处存储客户端的channel 信息key 为 deviceId + venueId + Venue thisVenue = venueService.findById(heartBeat.getVenueId()); + if (thisVenue == null ){ + logger.error("this client choose venue Error! venueId == " + heartBeat.getVenueId()); + } else { + deviceService.online(heartBeat.getDeviceName(),heartBeat.getVenueId(),thisVenue.getType(),clientId); + addLinks(heartBeat.getDeviceName(),heartBeat.getVenueId(),channel); +// VenueMessage venueMessage = new VenueMessage(MessageType.LINK,"欢迎扫码进场!"); +// ServerMessageUtils.INSTANCE.sendMsg(channel,venueMessage); + } + } + } + + /** + * 设备下线 + * @param deviceName + * @param venueId + */ + @Override + public void Offline(String deviceName, Integer venueId) { + if (deviceName != null && venueId != null){ + removeChannelType(deviceName,venueId); + deviceService.offline(deviceName,venueId); + } + } + + /** + * 核销扫码出场逻辑 + * @param barcode + */ + @Override + @Transactional + public void outVenue(String barcode) { + VenueBarCode venueBarCode = MakeCode.decodeCode(barcode); + barcode = MakeCode.reWriteBarcode(barcode); + Channel channel = getCurrentChannel(venueBarCode.getDeviceName(),venueBarCode.getVenueId()); + Member member = memberService.findByMember(venueBarCode.getMemberId()); + if (member != null) { + MemberMoneyLog memberMoneyLog = memberMoneyLogService.selectLastLog(member.getId(), venueBarCode.getVenueId()); + MemberEnterVenueLog memberEnterVenueLog = new MemberEnterVenueLog(); + memberEnterVenueLog.setOrderSn(barcode); + memberEnterVenueLog.setType(EnterEnum.OUT.getValue()); + memberEnterVenueLog.setMemberId(member.getId()); + memberEnterVenueLog.setPlatformId(member.getPlatformId() == null ? 1 : member.getPlatformId()); + memberEnterVenueLog.setVenueId(venueBarCode.getVenueId()); + if (memberMoneyLog != null) { + memberEnterVenueLog.setPayType(memberMoneyLog.getPayType()); + } + memberEnterVenueLogService.save(memberEnterVenueLog); + logger.info("用户" + member.getNickname() + "出场"); + writeOffCode(barcode); + ServerMessageUtils.INSTANCE.sendMsg(channel,new VenueMessage(MessageType.OUT_DOOR,"OK")); + } + } + + /** + * 核销扫码进场逻辑 + * @param barcode + */ + @Override + @Transactional + public void enterVenue(String barcode) { + VenueBarCode venueBarCode = MakeCode.decodeCode(barcode); + barcode = MakeCode.reWriteBarcode(barcode); + Channel channel = getCurrentChannel(venueBarCode.getDeviceName(), venueBarCode.getVenueId()); + Member member = memberService.findByMember(venueBarCode.getMemberId()); + if (member != null) { + MemberEnterVenueLog memberEnterVenueLog = new MemberEnterVenueLog(); + memberEnterVenueLog.setOrderSn(barcode); + memberEnterVenueLog.setType(EnterEnum.ENTER.getValue()); + memberEnterVenueLog.setMemberId(member.getId()); + memberEnterVenueLog.setPlatformId(member.getPlatformId() == null ? 1 : member.getPlatformId()); + memberEnterVenueLog.setVenueId(venueBarCode.getVenueId()); + memberEnterVenueLogService.save(memberEnterVenueLog); + writeOffCode(barcode); + logger.info("用户" + member.getNickname() + "入场"); + ServerMessageUtils.INSTANCE.sendMsg(channel,new VenueMessage(MessageType.ENTER_DOOR,"OK")); + } + } + + private void writeOffCode(String barcode) { + barcodeMapper.writeOffCode(barcode); + } + + /** + * 统计目前有多少链接数 + * @return + */ + @Override + public Set countConnection() { + return links.keySet(); + } + + + /** + * 测试客户端连接 + * @return + */ + @Override + public void testLoad(String deviceName, Integer venueId) { + Channel currentChannel = getCurrentChannel(deviceName, venueId); + ServerMessageUtils.INSTANCE.sendMsg(currentChannel,new VenueMessage(MessageType.HB,"测试链接")); + } + + /** + * 管理员入场 + * @return + */ + @Override + public void adminEnter(String deviceName, Integer venueId) { + Channel channel = getCurrentChannel(deviceName, venueId); + if (channel == null) { + throw new ServiceException("设备离线!请检查连接"); + } + logger.info("管理员入场"); + ServerMessageUtils.INSTANCE.sendMsg(channel,new VenueMessage(MessageType.ENTER_DOOR,"OK")); + } + + /** + * 管理员入场 + * @return + */ + @Override + public void adminOut(String deviceName, Integer venueId) { + Channel channel = getCurrentChannel(deviceName, venueId); + if (channel == null) { + throw new ServiceException("设备离线!请检查连接"); + } + logger.info("管理员入场"); + ServerMessageUtils.INSTANCE.sendMsg(channel,new VenueMessage(MessageType.OUT_DOOR,"OK")); + } + + /** + * 控制硬件,篮球馆的门禁灯光控制 + * @param number + */ +// public void sendNumberChange(Integer number) { +// HttpHeaders headers = new HttpHeaders(); +// headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); +// MultiValueMap param = new LinkedMultiValueMap<>(); +// param.add("LingtekID", "5d14229fcb1f5c1a9046f429"); +// param.add("Number", number.toString()); +// HttpEntity> request = new HttpEntity<>(param, headers); +// ResponseEntity result = restTemplate.exchange("http://lingtek.jalasmart.com/api/v1/lingtek/number", HttpMethod.PUT, request, Result.class); +// logger.info("灯光结果" + JsonMapper.nonDefaultMapper().toJson(result)); +// } + + + + /** + * 操作连接 + */ + /** + * 缓存通道 + */ + public void addLinks(String deviceName, Integer venueId, Channel channel) { + String clientId = deviceName + NettyConstant.SPIT_WORD + venueId; + links.put(clientId, channel); + } + + /** + * 获取当前通道 + */ + public Channel getCurrentChannel(String deviceName, Integer venueId){ + String clientId = deviceName + NettyConstant.SPIT_WORD + venueId; + return links.get(clientId); + } + + /** + * 判断是否有该通道 + */ + public boolean contains(String deviceName, Integer venueId) { + String clientId = deviceName + NettyConstant.SPIT_WORD + venueId + NettyConstant.SPIT_WORD; + return links.containsKey(clientId); + } + + /** + * 移除通道 + */ + public void removeChannelType(String deviceName, Integer venueId) { + String clientId = deviceName + NettyConstant.SPIT_WORD + venueId ; + links.remove(clientId); + } + +} diff --git a/entity/src/main/java/com/enums/BarCodeStatusEnum.java b/entity/src/main/java/com/enums/BarCodeStatusEnum.java new file mode 100644 index 0000000..dd53f45 --- /dev/null +++ b/entity/src/main/java/com/enums/BarCodeStatusEnum.java @@ -0,0 +1,42 @@ +package com.enums; + +/** + * Enum - 入场标志 + * + */ +public enum BarCodeStatusEnum { + INIT(0, "未核销"), + USED(1, "核销"); + public Integer value; + public String name; + + BarCodeStatusEnum(Integer value, String name) { + this.value = value; + this.name = name; + } + + public Integer getValue() { + return value; + } + + public void setValue(Integer value) { + this.value = value; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public static BarCodeStatusEnum getByValue(Integer value) { + for (BarCodeStatusEnum type : BarCodeStatusEnum.values()) { + if (type.value.equals(value)) { + return type; + } + } + return null; + } +} diff --git a/entity/src/main/java/com/enums/MoneyLogEnum.java b/entity/src/main/java/com/enums/MoneyLogEnum.java index 6760070..4b5191c 100644 --- a/entity/src/main/java/com/enums/MoneyLogEnum.java +++ b/entity/src/main/java/com/enums/MoneyLogEnum.java @@ -5,7 +5,7 @@ package com.enums; * */ public enum MoneyLogEnum { - JOIN(1, "进场"), + JOIN(1, "扫码订单"), VIPCARD(2, "购买会员卡"), BUY_LESSON(3, "购买课程"), RECHARGE(4, "充值"), diff --git a/entity/src/main/java/com/sv/dto/BarCodeResult.java b/entity/src/main/java/com/sv/dto/BarCodeResult.java index 5e4f950..cdd3068 100644 --- a/entity/src/main/java/com/sv/dto/BarCodeResult.java +++ b/entity/src/main/java/com/sv/dto/BarCodeResult.java @@ -7,9 +7,9 @@ public class BarCodeResult implements Serializable { private String barcode; /** - * 0 - 成功 1 - 失败 + * 返回的字符串,根据结果显示 */ - private String code; + private Integer flg; private String msg; @@ -21,12 +21,12 @@ public class BarCodeResult implements Serializable { this.barcode = barcode; } - public String getCode() { - return code; + public Integer getFlg() { + return flg; } - public void setCode(String code) { - this.code = code; + public void setFlg(Integer flg) { + this.flg = flg; } public String getMsg() { diff --git a/entity/src/main/java/com/sv/entity/Barcode.java b/entity/src/main/java/com/sv/entity/Barcode.java new file mode 100644 index 0000000..bc32d8b --- /dev/null +++ b/entity/src/main/java/com/sv/entity/Barcode.java @@ -0,0 +1,122 @@ +package com.sv.entity; + +import java.util.Date; + +public class Barcode { + private Integer id; + + private String barcode; + + private Integer status; + + private Integer memberId; + + private Integer venueId; + + private Integer enter; + + private Integer createdId; + + private Integer modifiedId; + + private Date createdTime; + + private Date modifiedTime; + + public Barcode(Integer id, String barcode, Integer status, Integer memberId, Integer venueId, Integer enter, Integer createdId, Integer modifiedId, Date createdTime, Date modifiedTime) { + this.id = id; + this.barcode = barcode; + this.status = status; + this.memberId = memberId; + this.venueId = venueId; + this.enter = enter; + this.createdId = createdId; + this.modifiedId = modifiedId; + this.createdTime = createdTime; + this.modifiedTime = modifiedTime; + } + + public Barcode() { + 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 getMemberId() { + return memberId; + } + + public void setMemberId(Integer memberId) { + this.memberId = memberId; + } + + public Integer getVenueId() { + return venueId; + } + + public void setVenueId(Integer venueId) { + this.venueId = venueId; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Integer getEnter() { + return enter; + } + + public void setEnter(Integer enter) { + this.enter = enter; + } + + 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; + } +} diff --git a/entity/src/main/java/com/sv/entity/Device.java b/entity/src/main/java/com/sv/entity/Device.java index 2e7c295..fe630f8 100644 --- a/entity/src/main/java/com/sv/entity/Device.java +++ b/entity/src/main/java/com/sv/entity/Device.java @@ -35,10 +35,6 @@ public class Device implements Serializable { private Integer venueId; private Integer venueType; - - private Integer bindMember; - - private Date bindTime; /** * 创建者编号 */ @@ -244,20 +240,4 @@ public class Device implements Serializable { public void setVenueType(Integer venueType) { this.venueType = venueType; } - - public Integer getBindMember() { - return bindMember; - } - - public void setBindMember(Integer bindMember) { - this.bindMember = bindMember; - } - - public Date getBindTime() { - return bindTime; - } - - public void setBindTime(Date bindTime) { - this.bindTime = bindTime; - } } diff --git a/netty-client/src/main/java/com/sv/barcode/ClientConfig.java b/netty-client/src/main/java/com/sv/barcode/ClientConfig.java new file mode 100644 index 0000000..29e7549 --- /dev/null +++ b/netty-client/src/main/java/com/sv/barcode/ClientConfig.java @@ -0,0 +1,44 @@ +package com.sv.barcode; + +import java.io.Serializable; + +public class ClientConfig implements Serializable { + + String serverIp; + String serverPort; + + String clientSN; + String clientVid; + + public String getServerIp() { + return serverIp; + } + + public void setServerIp(String serverIp) { + this.serverIp = serverIp; + } + + public String getServerPort() { + return serverPort; + } + + public void setServerPort(String serverPort) { + this.serverPort = serverPort; + } + + public String getClientSN() { + return clientSN; + } + + public void setClientSN(String clientSN) { + this.clientSN = clientSN; + } + + public String getClientVid() { + return clientVid; + } + + public void setClientVid(String clientVid) { + this.clientVid = clientVid; + } +} diff --git a/netty-client/src/main/java/com/sv/barcode/ListenKeyFrame.java b/netty-client/src/main/java/com/sv/barcode/ListenKeyFrame.java new file mode 100644 index 0000000..ce77a61 --- /dev/null +++ b/netty-client/src/main/java/com/sv/barcode/ListenKeyFrame.java @@ -0,0 +1,27 @@ +package com.sv.barcode; + +import javax.swing.*; +import java.awt.*; + +public class ListenKeyFrame extends Thread{ + + Frame frame; + + public void newFrame (int i) { + frame = new Frame("智慧云馆门禁" + i); + frame.setBounds(300,100,600,500); + frame.setLayout(new FlowLayout(FlowLayout.CENTER,5,200));//设计布局 + JLabel label = new JLabel("请保持该界面被选中,否则将无法监听二维码扫描!"); + frame.addKeyListener(new ScanBarCode()); + frame.add(label); + frame.setVisible(true); + frame.setFocusable(true); + } + + public void close() { + if (frame != null) { + frame.dispose(); + } + } + +} diff --git a/netty-client/src/main/java/com/sv/barcode/ScanBarCode.java b/netty-client/src/main/java/com/sv/barcode/ScanBarCode.java new file mode 100644 index 0000000..cba41af --- /dev/null +++ b/netty-client/src/main/java/com/sv/barcode/ScanBarCode.java @@ -0,0 +1,38 @@ +package com.sv.barcode; + +import com.sv.netty.ClientThread; +import com.sv.netty.config.NettyConstant; + +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.LinkedList; +import java.util.List; + +public class ScanBarCode extends KeyAdapter { + + private List barcode = new LinkedList<>(); + + @Override + public void keyTyped(KeyEvent e) { + if (barcode.size() > 200) { + barcode.clear(); + } + char keyChar = e.getKeyChar(); + if (NettyConstant.BARCODE_END == keyChar) { + String barStr = ""; + if (barcode.size() > 0 && barcode != null) { + for (Character character : barcode) { + barStr = barStr + character; + } + } + System.err.println(barStr); + ClientThread.getInstance().checkBarcode(barStr); + barcode.clear(); + } + barcode.add(keyChar); + if (NettyConstant.BARCODE_BEGIN == keyChar) { + barcode.clear(); + } + } + +} diff --git a/netty-client/src/main/java/com/sv/intergration/DoorService.java b/netty-client/src/main/java/com/sv/intergration/DoorService.java new file mode 100644 index 0000000..e025d0d --- /dev/null +++ b/netty-client/src/main/java/com/sv/intergration/DoorService.java @@ -0,0 +1,8 @@ +package com.sv.intergration; + +/** + * 对接场馆门禁 + */ +public interface DoorService { + +} diff --git a/netty-client/src/main/java/com/sv/service/MessageService.java b/netty-client/src/main/java/com/sv/intergration/MessageService.java similarity index 78% rename from netty-client/src/main/java/com/sv/service/MessageService.java rename to netty-client/src/main/java/com/sv/intergration/MessageService.java index 9012493..a6c9d37 100644 --- a/netty-client/src/main/java/com/sv/service/MessageService.java +++ b/netty-client/src/main/java/com/sv/intergration/MessageService.java @@ -1,4 +1,4 @@ -package com.sv.service; +package com.sv.intergration; import com.sv.netty.config.VenueMessage; import org.slf4j.Logger; @@ -34,8 +34,11 @@ public class MessageService { */ public void execute(VenueMessage message) { switch (message.getMessageType()) { - case OPEN_DOOR: - openDoor(); + case ENTER_DOOR: + enterDoor(); + break; + case OUT_DOOR: + outDoor(); break; default: logger.info( "default"); @@ -45,7 +48,15 @@ public class MessageService { /** * 门禁开门 */ - public void openDoor() { + public void enterDoor() { + // 开门 + logger.info("开门成功!!!"); + } + + /** + * 门禁开门 + */ + public void outDoor() { // 开门 logger.info("开门成功!!!"); } diff --git a/netty-client/src/main/java/com/sv/netty/ClientHandler.java b/netty-client/src/main/java/com/sv/netty/ClientHandler.java index 6121a2e..4f3e7ef 100644 --- a/netty-client/src/main/java/com/sv/netty/ClientHandler.java +++ b/netty-client/src/main/java/com/sv/netty/ClientHandler.java @@ -1,10 +1,8 @@ package com.sv.netty; -import com.sv.netty.config.HeartBeat; +import com.sv.intergration.MessageService; import com.sv.netty.config.VenueMessage; -import com.sv.netty.utils.EncodeMsg; import com.sv.netty.utils.JsonUtils; -import com.sv.service.MessageService; import io.netty.channel.Channel; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; @@ -69,23 +67,12 @@ public class ClientHandler extends SimpleChannelInboundHandler { if (IdleStateEvent.class.isAssignableFrom(evt.getClass())) { IdleStateEvent event = (IdleStateEvent) evt; if (event.state() == IdleState.ALL_IDLE) { - ctx.write(EncodeMsg.INSTANCE.encode(getHbMessage())); + ctx.write(MessageHandler.sendHeartBeat()); ctx.flush(); } } } - /** - * 封装心跳请求包 - * @throws Exception - */ - private HeartBeat getHbMessage() { - HeartBeat hb = new HeartBeat(); - hb.setDeviceName("dsadasdasd"); - hb.setVenueId(32); - return hb; - } - /** * 处理异常 * @param ctx diff --git a/netty-client/src/main/java/com/sv/netty/ClientThread.java b/netty-client/src/main/java/com/sv/netty/ClientThread.java index 172a775..76c0e23 100644 --- a/netty-client/src/main/java/com/sv/netty/ClientThread.java +++ b/netty-client/src/main/java/com/sv/netty/ClientThread.java @@ -1,10 +1,12 @@ package com.sv.netty; +import com.sv.netty.config.NettyConstant; import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.logging.LoggingHandler; +import io.netty.util.internal.StringUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,7 +38,9 @@ public class ClientThread extends Thread{ if (instance == null) { synchronized (ClientThread.class) { if (instance == null) { - instance = new ClientThread("127.0.0.1", 56792); + String serverIp = System.getProperty(NettyConstant.VENUE_SERVER_IP); + String serverPort = System.getProperty(NettyConstant.VENUE_SERVER_PORT); + instance = new ClientThread(serverIp, Integer.parseInt(serverPort)); } } } @@ -67,6 +71,23 @@ public class ClientThread extends Thread{ doConnect(); } + public void checkBarcode(String barcode) { + try { + if (future != null) { + Channel channel = future.channel(); + if (channel != null) { + String sendCode = MessageHandler.checkBarcode(barcode); + if (StringUtil.isNullOrEmpty(sendCode)){ + return; + } + channel.writeAndFlush(sendCode); + } + } + }catch (Exception e) { + logger.error("链接失败,发送二维码失败",e); + } + } + public void clearFuture(){ future = null; } diff --git a/netty-client/src/main/java/com/sv/netty/MessageHandler.java b/netty-client/src/main/java/com/sv/netty/MessageHandler.java new file mode 100644 index 0000000..0dff37b --- /dev/null +++ b/netty-client/src/main/java/com/sv/netty/MessageHandler.java @@ -0,0 +1,42 @@ +package com.sv.netty; + +import com.sv.netty.config.*; +import com.sv.netty.utils.EncodeMsg; +import com.sv.netty.utils.JsonUtils; +import com.sv.netty.utils.MakeCode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MessageHandler { + private static final Logger logger = LoggerFactory.getLogger(MessageHandler.class); + + public static String sendHeartBeat() { + VenueMessage venueMessage = new VenueMessage(); + venueMessage.setMessageType(MessageType.HB); + String clientSn = System.getProperty(NettyConstant.VENUE_CLIENT_SN); + String clientVid = System.getProperty(NettyConstant.VENUE_CLIENT_VID); + HeartBeat hb = new HeartBeat(); + hb.setDeviceName(clientSn); + hb.setVenueId(Integer.parseInt(clientVid)); + venueMessage.setMessage(JsonUtils.encode(hb)); + return EncodeMsg.INSTANCE.encode(venueMessage); + } + + /** + * 核销二维码 + * @return + */ + public static String checkBarcode(String barcode) { + VenueBarCode venueBarCode = MakeCode.decodeCode(barcode); + if (venueBarCode == null) { + logger.error("二维码不合法" + barcode); + return null; + } + VenueMessage venueMessage = new VenueMessage(); + venueMessage.setMessageType(MessageType.SCAN_CODE); + venueMessage.setMessage(barcode); + logger.info("核销二维码===" + barcode); + return EncodeMsg.INSTANCE.encode(venueMessage); + } + +} diff --git a/netty-client/src/main/java/com/sv/service/ClientService.java b/netty-client/src/main/java/com/sv/service/ClientService.java index 1c8c977..5bfc9f1 100644 --- a/netty-client/src/main/java/com/sv/service/ClientService.java +++ b/netty-client/src/main/java/com/sv/service/ClientService.java @@ -1,6 +1,15 @@ package com.sv.service; +import com.sv.barcode.ClientConfig; +import com.sv.barcode.ListenKeyFrame; import com.sv.netty.ClientThread; +import com.sv.netty.config.NettyConstant; +import com.sv.netty.utils.JsonUtils; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; /** * 启动socker和websocket服务 @@ -10,9 +19,41 @@ import com.sv.netty.ClientThread; */ public class ClientService { - public static void main(String[] args) { + public static void main(String[] args) throws IOException, InterruptedException { + File file = new File("/home/venue/client/venue.conf"); +// File file = new File("/Users/limqhz/home/venue/client/venue.conf"); + FileReader fileReader = new FileReader(file); + BufferedReader bufferedReader = new BufferedReader(fileReader); + String line = bufferedReader.readLine(); + if (line != null) { + ClientConfig decode = JsonUtils.decode(line, ClientConfig.class); + System.setProperty(NettyConstant.VENUE_SERVER_IP,decode.getServerIp()); + System.setProperty(NettyConstant.VENUE_SERVER_PORT,decode.getServerPort()); + System.setProperty(NettyConstant.VENUE_CLIENT_SN,decode.getClientSN()); + System.setProperty(NettyConstant.VENUE_CLIENT_VID,decode.getClientVid()); + } + bufferedReader.close(); + fileReader.close(); + ClientThread instance = ClientThread.getInstance(); instance.start(); + + Thread.sleep(3000); + ListenKeyFrame listenKeyFrame = new ListenKeyFrame(); + listenKeyFrame.newFrame(1); + Thread.sleep(3000); + listenKeyFrame.close(); + ListenKeyFrame listenKeyFrame1 = new ListenKeyFrame(); + listenKeyFrame1.newFrame(2); + Thread.sleep(3000); + listenKeyFrame1.close(); + ListenKeyFrame listenKeyFrame2 = new ListenKeyFrame(); + listenKeyFrame2.newFrame(3); + Thread.sleep(3000); + listenKeyFrame2.close(); + ListenKeyFrame listenKeyFrame3 = new ListenKeyFrame(); + listenKeyFrame3.newFrame(4); + } } diff --git a/netty-client/src/main/resources/logback.xml b/netty-client/src/main/resources/logback.xml index b1babd7..2bd98bc 100644 --- a/netty-client/src/main/resources/logback.xml +++ b/netty-client/src/main/resources/logback.xml @@ -1,7 +1,7 @@ - + diff --git a/netty-model/src/main/java/com/sv/netty/config/MessageType.java b/netty-model/src/main/java/com/sv/netty/config/MessageType.java index 7f70b2c..201a311 100644 --- a/netty-model/src/main/java/com/sv/netty/config/MessageType.java +++ b/netty-model/src/main/java/com/sv/netty/config/MessageType.java @@ -1,9 +1,10 @@ package com.sv.netty.config; public enum MessageType { - LINK("连接"), - OPEN_DOOR("开门"), - FAILED("开门校验失败"); + HB("心跳"), + SCAN_CODE("扫码"), + ENTER_DOOR("进门"), + OUT_DOOR("出门"); private String message; MessageType(String message) { diff --git a/netty-model/src/main/java/com/sv/netty/config/NettyConstant.java b/netty-model/src/main/java/com/sv/netty/config/NettyConstant.java index ccde7eb..30d9e27 100644 --- a/netty-model/src/main/java/com/sv/netty/config/NettyConstant.java +++ b/netty-model/src/main/java/com/sv/netty/config/NettyConstant.java @@ -3,14 +3,23 @@ package com.sv.netty.config; import io.netty.util.AttributeKey; public interface NettyConstant { - String SERVER_IP = "120.27.209.4"; - Integer SERVER_PORT = 56791; + + String VENUE_SERVER_IP = "VENUE_SERVER_IP"; + String VENUE_SERVER_PORT = "VENUE_SERVER_PORT"; + String VENUE_CLIENT_SN = "VENUE_CLIENT_SN"; + String VENUE_CLIENT_VID = "VENUE_CLIENT_VID"; /** * session中存储终端发送的额外参数 */ AttributeKey CHANNEL_PARAM = AttributeKey.newInstance("CHANNEL_PARAM"); - String SPIT_WORD = "#"; + /** + * 条形码 + */ + String SPIT_WORD = "&&&"; + + char BARCODE_BEGIN = '@'; + char BARCODE_END = '#'; } diff --git a/netty-model/src/main/java/com/sv/netty/config/VenueBarCode.java b/netty-model/src/main/java/com/sv/netty/config/VenueBarCode.java new file mode 100644 index 0000000..5c75eab --- /dev/null +++ b/netty-model/src/main/java/com/sv/netty/config/VenueBarCode.java @@ -0,0 +1,46 @@ +package com.sv.netty.config; + +import java.io.Serializable; + +public class VenueBarCode implements Serializable { + + private Integer venueId; + + private Integer memberId; + + private String deviceName; + + private Integer direction; + + public Integer getVenueId() { + return venueId; + } + + public void setVenueId(Integer venueId) { + this.venueId = venueId; + } + + public Integer getMemberId() { + return memberId; + } + + public void setMemberId(Integer memberId) { + this.memberId = memberId; + } + + public String getDeviceName() { + return deviceName; + } + + public void setDeviceName(String deviceName) { + this.deviceName = deviceName; + } + + public Integer getDirection() { + return direction; + } + + public void setDirection(Integer direction) { + this.direction = direction; + } +} diff --git a/netty-model/src/main/java/com/sv/netty/utils/AesUtil.java b/netty-model/src/main/java/com/sv/netty/utils/AesUtil.java new file mode 100644 index 0000000..d6e6e9c --- /dev/null +++ b/netty-model/src/main/java/com/sv/netty/utils/AesUtil.java @@ -0,0 +1,60 @@ +package com.sv.netty.utils; +import javax.crypto.Cipher; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +/** + * @author: wuyou + * @create: 2019-05-09 14:18 + **/ +public class AesUtil { + public static final String SECRET_KEY = "a69i3z8b516gd370"; + + /** + * Encrypt string. + * + * @param sSrc the s src + * @return the string + */ + public static String encrypt(String sSrc) { + try { + if (sSrc == null){ + return null; + } + byte[] raw = SECRET_KEY.getBytes(); + SecretKeySpec sKeySpec = new SecretKeySpec(raw, "AES"); + // "算法/模式/补码方式" + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + // 使用CBC模式,需要一个向量iv,可增加加密算法的强度 + IvParameterSpec iv = new IvParameterSpec("0102030405060708".getBytes()); + cipher.init(Cipher.ENCRYPT_MODE, sKeySpec, iv); + byte[] encrypted = cipher.doFinal(sSrc.getBytes()); + // 此处使用BASE64做转码功能,同时能起到2次加密的作用。 + return Base64.encodeS(encrypted); + } catch (Throwable e) { + return null; + } + } + + /** + * Decrypt string. + * + * @param sSrc the s src + * @return the string + */ + public static String decrypt(String sSrc) { + try { + byte[] raw = SECRET_KEY.getBytes("ASCII"); + SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + IvParameterSpec iv = new IvParameterSpec("0102030405060708".getBytes()); + cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv); + // 先用base64解密 + byte[] encrypted1 = Base64.decode(sSrc); + byte[] original = cipher.doFinal(encrypted1); + return new String(original); + } catch (Throwable th) { + return null; + } + } +} diff --git a/netty-model/src/main/java/com/sv/netty/utils/Base64.java b/netty-model/src/main/java/com/sv/netty/utils/Base64.java new file mode 100644 index 0000000..7774598 --- /dev/null +++ b/netty-model/src/main/java/com/sv/netty/utils/Base64.java @@ -0,0 +1,285 @@ +package com.sv.netty.utils; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.zip.Deflater; +import java.util.zip.Inflater; + +/** + * @author: wuyou + * @create: 2019-05-09 14:19 + **/ +public class Base64 { + + private static final byte[] ENCODING_TABLE = {(byte) 'A', (byte) 'B', + (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G', + (byte) 'H', (byte) 'I', (byte) 'J', (byte) 'K', (byte) 'L', + (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', (byte) 'Q', + (byte) 'R', (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V', + (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a', + (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', + (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j', (byte) 'k', + (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p', + (byte) 'q', (byte) 'r', (byte) 's', (byte) 't', (byte) 'u', + (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z', + (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', + (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9', + (byte) '+', (byte) '/'}; + private static final byte[] DECODING_TABLE; + + static { + DECODING_TABLE = new byte[128]; + for (int i = 0; i < 128; i++) { + DECODING_TABLE[i] = (byte) -1; + } + for (int i = 'A'; i <= 'Z'; i++) { + DECODING_TABLE[i] = (byte) (i - 'A'); + } + for (int i = 'a'; i <= 'z'; i++) { + DECODING_TABLE[i] = (byte) (i - 'a' + 26); + } + for (int i = '0'; i <= '9'; i++) { + DECODING_TABLE[i] = (byte) (i - '0' + 52); + } + DECODING_TABLE['+'] = 62; + DECODING_TABLE['/'] = 63; + } + + public static String encodeS(byte[] data) { + return new String(encode(data)); + } + + public static byte[] encode(byte[] data) { + byte[] bytes; + int modulus = data.length % 3; + if (modulus == 0) { + bytes = new byte[(4 * data.length) / 3]; + } else { + bytes = new byte[4 * ((data.length / 3) + 1)]; + } + int dataLength = (data.length - modulus); + int a1; + int a2; + int a3; + for (int i = 0, j = 0; i < dataLength; i += 3, j += 4) { + a1 = data[i] & 0xff; + a2 = data[i + 1] & 0xff; + a3 = data[i + 2] & 0xff; + bytes[j] = ENCODING_TABLE[(a1 >>> 2) & 0x3f]; + bytes[j + 1] = ENCODING_TABLE[((a1 << 4) | (a2 >>> 4)) & 0x3f]; + bytes[j + 2] = ENCODING_TABLE[((a2 << 2) | (a3 >>> 6)) & 0x3f]; + bytes[j + 3] = ENCODING_TABLE[a3 & 0x3f]; + } + int b1; + int b2; + int b3; + int d1; + int d2; + switch (modulus) { + //nothing left to do + case 0: + break; + case 1: + d1 = data[data.length - 1] & 0xff; + b1 = (d1 >>> 2) & 0x3f; + b2 = (d1 << 4) & 0x3f; + bytes[bytes.length - 4] = ENCODING_TABLE[b1]; + bytes[bytes.length - 3] = ENCODING_TABLE[b2]; + bytes[bytes.length - 2] = (byte) '='; + bytes[bytes.length - 1] = (byte) '='; + break; + case 2: + d1 = data[data.length - 2] & 0xff; + d2 = data[data.length - 1] & 0xff; + b1 = (d1 >>> 2) & 0x3f; + b2 = ((d1 << 4) | (d2 >>> 4)) & 0x3f; + b3 = (d2 << 2) & 0x3f; + bytes[bytes.length - 4] = ENCODING_TABLE[b1]; + bytes[bytes.length - 3] = ENCODING_TABLE[b2]; + bytes[bytes.length - 2] = ENCODING_TABLE[b3]; + bytes[bytes.length - 1] = (byte) '='; + break; + default: + break; + } + return bytes; + } + + public static byte[] decode(byte[] data) { + byte[] bytes; + byte b1; + byte b2; + byte b3; + byte b4; + data = discardNonBase64Bytes(data); + if (data[data.length - 2] == '=') { + bytes = new byte[(((data.length / 4) - 1) * 3) + 1]; + } else if (data[data.length - 1] == '=') { + bytes = new byte[(((data.length / 4) - 1) * 3) + 2]; + } else { + bytes = new byte[((data.length / 4) * 3)]; + } + for (int i = 0, j = 0; i < (data.length - 4); i += 4, j += 3) { + b1 = DECODING_TABLE[data[i]]; + b2 = DECODING_TABLE[data[i + 1]]; + b3 = DECODING_TABLE[data[i + 2]]; + b4 = DECODING_TABLE[data[i + 3]]; + bytes[j] = (byte) ((b1 << 2) | (b2 >> 4)); + bytes[j + 1] = (byte) ((b2 << 4) | (b3 >> 2)); + bytes[j + 2] = (byte) ((b3 << 6) | b4); + } + if (data[data.length - 2] == '=') { + b1 = DECODING_TABLE[data[data.length - 4]]; + b2 = DECODING_TABLE[data[data.length - 3]]; + bytes[bytes.length - 1] = (byte) ((b1 << 2) | (b2 >> 4)); + } else if (data[data.length - 1] == '=') { + b1 = DECODING_TABLE[data[data.length - 4]]; + b2 = DECODING_TABLE[data[data.length - 3]]; + b3 = DECODING_TABLE[data[data.length - 2]]; + bytes[bytes.length - 2] = (byte) ((b1 << 2) | (b2 >> 4)); + bytes[bytes.length - 1] = (byte) ((b2 << 4) | (b3 >> 2)); + } else { + b1 = DECODING_TABLE[data[data.length - 4]]; + b2 = DECODING_TABLE[data[data.length - 3]]; + b3 = DECODING_TABLE[data[data.length - 2]]; + b4 = DECODING_TABLE[data[data.length - 1]]; + bytes[bytes.length - 3] = (byte) ((b1 << 2) | (b2 >> 4)); + bytes[bytes.length - 2] = (byte) ((b2 << 4) | (b3 >> 2)); + bytes[bytes.length - 1] = (byte) ((b3 << 6) | b4); + } + return bytes; + } + + public static byte[] decode(String data) { + byte[] bytes; + byte b1; + byte b2; + byte b3; + byte b4; + data = discardNonBase64Chars(data); + if (data.charAt(data.length() - 2) == '=') { + bytes = new byte[(((data.length() / 4) - 1) * 3) + 1]; + } else if (data.charAt(data.length() - 1) == '=') { + bytes = new byte[(((data.length() / 4) - 1) * 3) + 2]; + } else { + bytes = new byte[((data.length() / 4) * 3)]; + } + for (int i = 0, j = 0; i < (data.length() - 4); i += 4, j += 3) { + b1 = DECODING_TABLE[data.charAt(i)]; + b2 = DECODING_TABLE[data.charAt(i + 1)]; + b3 = DECODING_TABLE[data.charAt(i + 2)]; + b4 = DECODING_TABLE[data.charAt(i + 3)]; + bytes[j] = (byte) ((b1 << 2) | (b2 >> 4)); + bytes[j + 1] = (byte) ((b2 << 4) | (b3 >> 2)); + bytes[j + 2] = (byte) ((b3 << 6) | b4); + } + if (data.charAt(data.length() - 2) == '=') { + b1 = DECODING_TABLE[data.charAt(data.length() - 4)]; + b2 = DECODING_TABLE[data.charAt(data.length() - 3)]; + bytes[bytes.length - 1] = (byte) ((b1 << 2) | (b2 >> 4)); + } else if (data.charAt(data.length() - 1) == '=') { + b1 = DECODING_TABLE[data.charAt(data.length() - 4)]; + b2 = DECODING_TABLE[data.charAt(data.length() - 3)]; + b3 = DECODING_TABLE[data.charAt(data.length() - 2)]; + bytes[bytes.length - 2] = (byte) ((b1 << 2) | (b2 >> 4)); + bytes[bytes.length - 1] = (byte) ((b2 << 4) | (b3 >> 2)); + } else { + b1 = DECODING_TABLE[data.charAt(data.length() - 4)]; + b2 = DECODING_TABLE[data.charAt(data.length() - 3)]; + b3 = DECODING_TABLE[data.charAt(data.length() - 2)]; + b4 = DECODING_TABLE[data.charAt(data.length() - 1)]; + bytes[bytes.length - 3] = (byte) ((b1 << 2) | (b2 >> 4)); + bytes[bytes.length - 2] = (byte) ((b2 << 4) | (b3 >> 2)); + bytes[bytes.length - 1] = (byte) ((b3 << 6) | b4); + } + return bytes; + } + + private static byte[] discardNonBase64Bytes(byte[] data) { + byte[] temp = new byte[data.length]; + int bytesCopied = 0; + for (int i = 0; i < data.length; i++) { + if (isValidBase64Byte(data[i])) { + temp[bytesCopied++] = data[i]; + } + } + byte[] newData = new byte[bytesCopied]; + System.arraycopy(temp, 0, newData, 0, bytesCopied); + return newData; + } + + private static String discardNonBase64Chars(String data) { + StringBuffer sb = new StringBuffer(); + int length = data.length(); + for (int i = 0; i < length; i++) { + if (isValidBase64Byte((byte) (data.charAt(i)))) { + sb.append(data.charAt(i)); + } + } + return sb.toString(); + } + + private static boolean isValidBase64Byte(byte b) { + if (b == '=') { + return true; + } else if ((b < 0) || (b >= 128)) { + return false; + } else if (DECODING_TABLE[b] == -1) { + return false; + } + return true; + } + + public static byte[] compressBytes(byte input[]) { + int cachesize = 1024; + + Deflater compresser = new Deflater(); + + compresser.reset(); + compresser.setInput(input); + compresser.finish(); + byte output[] = new byte[0]; + ByteArrayOutputStream o = new ByteArrayOutputStream(input.length); + try { + byte[] buf = new byte[cachesize]; + int got; + while (!compresser.finished()) { + got = compresser.deflate(buf); + o.write(buf, 0, got); + } + output = o.toByteArray(); + } finally { + try { + o.close(); + } catch (IOException e) { + } + } + return output; + } + + public static byte[] decompressBytes(byte input[]) { + int cachesize = 1024; + Inflater decompresser = new Inflater(); + + byte output[] = new byte[0]; + decompresser.reset(); + decompresser.setInput(input); + ByteArrayOutputStream o = new ByteArrayOutputStream(input.length); + try { + byte[] buf = new byte[cachesize]; + int got; + while (!decompresser.finished()) { + got = decompresser.inflate(buf); + o.write(buf, 0, got); + } + output = o.toByteArray(); + } catch (Exception e) { + } finally { + try { + o.close(); + } catch (IOException e) { + } + } + return output; + } +} 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 new file mode 100644 index 0000000..b61dc83 --- /dev/null +++ b/netty-model/src/main/java/com/sv/netty/utils/MakeCode.java @@ -0,0 +1,46 @@ +package com.sv.netty.utils; + +import com.sv.netty.config.NettyConstant; +import com.sv.netty.config.VenueBarCode; + +public class MakeCode { + + /** + * 生成二维码 + * @return + */ + public static String makeCode (Integer venueId, Integer memberId, String deviceName, String direction) { + String information = memberId + NettyConstant.SPIT_WORD + venueId + NettyConstant.SPIT_WORD + deviceName + NettyConstant.SPIT_WORD + direction; + return NettyConstant.BARCODE_BEGIN + AesUtil.encrypt(information) + NettyConstant.BARCODE_END; + } + + /** + * 解析二维码 + */ + public static VenueBarCode decodeCode (String barcode) { + VenueBarCode venueBarCode = null; + String decrypt = AesUtil.decrypt(barcode); + String [] list = new String[0]; + if (decrypt!=null && decrypt.contains(NettyConstant.SPIT_WORD)){ + list = decrypt.split(NettyConstant.SPIT_WORD); + } + if (list != null && list.length == 4) { + venueBarCode = new VenueBarCode(); + venueBarCode.setMemberId(Integer.parseInt(list[0])); + venueBarCode.setVenueId(Integer.parseInt(list[1])); + venueBarCode.setDeviceName(list[2]); + venueBarCode.setDirection(Integer.parseInt(list[3])); + } else { + return null; + } + return venueBarCode; + } + + /** + * 还原二维码 + */ + public static String reWriteBarcode(String barcode) { + return NettyConstant.BARCODE_BEGIN + barcode + NettyConstant.BARCODE_END; + } + +} 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 53ac2cc..616e74f 100644 --- a/oms/src/main/java/com/sv/oms/controller/DeviceController.java +++ b/oms/src/main/java/com/sv/oms/controller/DeviceController.java @@ -1,4 +1,5 @@ package com.sv.oms.controller; +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; @@ -21,7 +22,7 @@ import javax.annotation.Resource; public class DeviceController extends OmsController { private final Logger logger = LoggerFactory.getLogger(DeviceController.class); - + @Resource private DeviceService deviceService; @@ -72,4 +73,26 @@ public class DeviceController extends OmsController { return ResponseDTO.ok("开始连接,请等待连接完成"); } + /** + * 重新连接 + * @param deviceId + * @return + */ + @RequestMapping("/device/admin/enter/{id}") + public ResponseDTO adminEnter(@PathVariable("id") Integer deviceId){ + deviceService.adminOperate(deviceId,EnterEnum.ENTER); + return ResponseDTO.ok("入场开门成功!"); + } + + /** + * 重新连接 + * @param deviceId + * @return + */ + @RequestMapping("/device/admin/out/{id}") + public ResponseDTO adminOut(@PathVariable("id") Integer deviceId){ + deviceService.adminOperate(deviceId, EnterEnum.OUT); + return ResponseDTO.ok("出场开门成功!"); + } + } diff --git a/service/src/main/java/com/sv/mapper/BarcodeMapper.java b/service/src/main/java/com/sv/mapper/BarcodeMapper.java new file mode 100644 index 0000000..bc5d6d7 --- /dev/null +++ b/service/src/main/java/com/sv/mapper/BarcodeMapper.java @@ -0,0 +1,26 @@ +package com.sv.mapper; + +import com.sv.annotation.NoPlatform; +import com.sv.entity.Barcode; +import org.apache.ibatis.annotations.Param; + +public interface BarcodeMapper { + int deleteByPrimaryKey(Integer id); + + @NoPlatform + int insert(Barcode record); + + int insertSelective(Barcode record); + + Barcode selectByPrimaryKey(Integer id); + + int updateByPrimaryKeySelective(Barcode record); + + int updateByPrimaryKey(Barcode record); + + @NoPlatform + void writeOffCode(@Param("barcode") String barcode); + + @NoPlatform + Barcode findBarcode(@Param("venueId") Integer venueId,@Param("memberId") Integer memberId); +} diff --git a/service/src/main/java/com/sv/mapper/DeviceMapper.java b/service/src/main/java/com/sv/mapper/DeviceMapper.java index 587c8bf..d077665 100644 --- a/service/src/main/java/com/sv/mapper/DeviceMapper.java +++ b/service/src/main/java/com/sv/mapper/DeviceMapper.java @@ -1,5 +1,6 @@ package com.sv.mapper; import com.common.DeviceDTO; +import com.sv.annotation.NoPlatform; import com.sv.entity.Device; import org.apache.ibatis.annotations.Param; @@ -50,6 +51,7 @@ public interface DeviceMapper { * @param id 编号 * @return 门禁设备 */ + @NoPlatform Device findById(Integer id); /** @@ -78,11 +80,11 @@ public interface DeviceMapper { /** * 根据记录找设备 - * @param deviceName * @param venueId * @return */ - Device findByDevice(@Param("deviceName") String deviceName,@Param("venueId") Integer venueId); + @NoPlatform + Device findByDevice(@Param("venueId") Integer venueId); /** * 设备绑定正在扫码的用户 diff --git a/service/src/main/java/com/sv/mapper/MemberMoneyLogMapper.java b/service/src/main/java/com/sv/mapper/MemberMoneyLogMapper.java index de39ad3..7a650fa 100644 --- a/service/src/main/java/com/sv/mapper/MemberMoneyLogMapper.java +++ b/service/src/main/java/com/sv/mapper/MemberMoneyLogMapper.java @@ -71,4 +71,6 @@ public interface MemberMoneyLogMapper { * api 查询用户账单 */ List findAllBill(Integer memberId); -} \ No newline at end of file + + MemberMoneyLog selectLastLog(@Param("memberId")Integer memberId, @Param("venueId")Integer venueId); +} diff --git a/service/src/main/java/com/sv/service/api/MemberFaceInfoService.java b/service/src/main/java/com/sv/service/api/MemberFaceInfoService.java index 4254b60..07282a2 100644 --- a/service/src/main/java/com/sv/service/api/MemberFaceInfoService.java +++ b/service/src/main/java/com/sv/service/api/MemberFaceInfoService.java @@ -23,6 +23,7 @@ import javax.annotation.Resource; */ @Service @Transactional(readOnly = true) +@Deprecated public class MemberFaceInfoService extends BaseServiceImpl { private final Logger logger = LoggerFactory.getLogger(MemberFaceInfoService.class); diff --git a/service/src/main/java/com/sv/service/api/MemberMoneyLogService.java b/service/src/main/java/com/sv/service/api/MemberMoneyLogService.java index cfa70fd..45c9504 100644 --- a/service/src/main/java/com/sv/service/api/MemberMoneyLogService.java +++ b/service/src/main/java/com/sv/service/api/MemberMoneyLogService.java @@ -132,5 +132,12 @@ public class MemberMoneyLogService extends MemberMoney { public void insert(MemberMoneyLog memberMoneyLog){ memberMoneyLogMapper.insert(memberMoneyLog); } + + /** + * 插入 + */ + public MemberMoneyLog selectLastLog(Integer memberId,Integer venueId){ + return memberMoneyLogMapper.selectLastLog(memberId,venueId); + } } diff --git a/service/src/main/java/com/sv/service/api/OrderService.java b/service/src/main/java/com/sv/service/api/OrderService.java index 7192d08..30e92c7 100644 --- a/service/src/main/java/com/sv/service/api/OrderService.java +++ b/service/src/main/java/com/sv/service/api/OrderService.java @@ -251,6 +251,7 @@ public class OrderService extends BaseServiceImpl { * @param memberId * @return */ + @Deprecated public String createEnterVenueOrder(Venue venue, Integer memberId,PayTypeEnum payTypeEnum,BigDecimal price){ //创建订单 Order order = new Order(); 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 b462ecd..8ed78bc 100644 --- a/service/src/main/java/com/sv/service/api/VenueService.java +++ b/service/src/main/java/com/sv/service/api/VenueService.java @@ -11,7 +11,6 @@ import com.sv.exception.api.ExceptionCodeTemplate; import com.sv.mapper.VenueMapper; import com.sv.service.api.util.DateUtilCard; import com.sv.service.api.util.GeoHashUtils; -import com.sv.service.oms.DeviceService; import com.ydd.framework.core.common.Pagination; import com.ydd.framework.core.common.utils.ValidationUtils; import com.ydd.framework.core.exception.ServiceException; @@ -54,11 +53,6 @@ public class VenueService extends BaseServiceImpl { @Resource private MemberEnterVenueLogService memberEnterVenueLogService; - @Resource(name = "OrderServiceApi") - private OrderService orderService; - - @Resource - private DeviceService deviceService; @Resource private MemberMoneyLogService memberMoneyLogService; @Resource @@ -120,9 +114,14 @@ public class VenueService extends BaseServiceImpl { */ public VenueDTO findByVenueId(Integer id,Integer memberId) { VenueDTO getVenue = venueMapper.findByVenueId(id); - if (VenueTypeEnum.BASKETBALL.getValue().equals(getVenue.getType())){ - MemberEnterVenueLog memberLastLog = memberEnterVenueLogService.findMemberLastLog(memberId, id); - getVenue.setEnterFlag(memberLastLog.getType()); + if (getVenue != null) { + getVenue.setEnterFlag(EnterEnum.OUT.getValue()); + if (VenueTypeEnum.BASKETBALL.getValue().equals(getVenue.getType())){ + MemberEnterVenueLog memberLastLog = memberEnterVenueLogService.findMemberLastLog(memberId, id); + if (memberLastLog != null) { + getVenue.setEnterFlag(memberLastLog.getType()); + } + } } return getVenue; } @@ -206,8 +205,8 @@ public class VenueService extends BaseServiceImpl { * api 接口 * 我要进场 */ - public Integer join(Integer memberId, Integer venueId) { - + public BarCodeResult join(Integer memberId, Integer venueId) { + BarCodeResult barCodeResult = new BarCodeResult(); Integer flag = 0; // 判断用户是否登录 if (memberId == null) { @@ -215,17 +214,8 @@ public class VenueService extends BaseServiceImpl { } //参数校验 ValidationUtils.assertNotNull(venueId); - - /*// 1.判断用户有没有人脸识别的图像,根据用户ID查找,一个用户只能有一条 - MemberFaceInfo memberFaceInfo = memberFaceInfoService.findByMemberId(memberId); - if (memberFaceInfo == null) { - flag = 1; - return flag; - }*/ - // 1.判断用户有没有该馆的会员卡(有效期内,如果有免费卡和别的卡,优先使用别的卡),有不判断余额 List memberCards = memberCardService.findByMemberId(venueId, memberId); - // 2. 查询该场馆需要的费用,并比较用户余额是否足够 // 查询当前时间内,场馆对应的价格 String time = DateUtilCard.nowTime().toString(); @@ -233,23 +223,20 @@ public class VenueService extends BaseServiceImpl { if (venuePrice == null) { throw new ServiceException(ExceptionCodeTemplate.VENUE_ERROR); } - Venue venue = venueMapper.findById(venueId); if (memberCards.size() == 0) { Member member = memberService.findById(memberId); if (member.getMoney().compareTo(venuePrice.getPrice()) == -1) { flag = 2; - return flag; } } - + barCodeResult.setFlg(flag); // 3.判断用户有没有人脸识别的图像,根据用户ID查找,一个用户只能有一条 // MemberFaceInfo memberFaceInfo = memberFaceInfoService.findByMemberId(memberId); // if (memberFaceInfo == null) { // flag = 1; // return flag; // } - - return flag; + return barCodeResult; } /** @@ -260,7 +247,7 @@ public class VenueService extends BaseServiceImpl { */ public BarCodeResult out(Integer memberId, Integer venueId) { BarCodeResult result = new BarCodeResult(); - result.setCode("0"); + result.setFlg(0); // 判断用户是否登录 if (memberId == null) { throw new ServiceException(com.ydd.framework.core.exception.ExceptionCodeTemplate.NEED_LOGIN); @@ -268,17 +255,10 @@ public class VenueService extends BaseServiceImpl { //参数校验 ValidationUtils.assertNotNull(venueId); Venue venue = venueMapper.findById(venueId); - synchronized (("enter" + memberId).intern()) { + synchronized (("scancode" + memberId).intern()) { // 查询当前时间内,场馆对应的价格(健身房没有价格) Member member = memberService.findByMember(memberId); memberService.verify(member); - // 记录用户进场记录 - MemberEnterVenueLog log = new MemberEnterVenueLog(); - log.setMemberId(member.getId()); - log.setVeneuType(venue.getType()); - log.setVenueId(venue.getId()); - log.setPlatformId(member.getPlatformId()); - log.setType(0); //进场之前 查看是否有会员卡 List cards = memberCardService.findByMemberId(venue.getId(), member.getId()); if (cards.size() > 0) { @@ -309,24 +289,18 @@ public class VenueService extends BaseServiceImpl { if (useCard != null) { //使用会员卡入场 logger.info("用户" + member.getNickname() + "使用" + useCard.getCardType() + "入场"); - log.setMemberCardId(useCard.getId()); - log.setPayType(EnterVenuePayTypeEnum.MEMBER_CARD.value); - String orderSn = orderService.createEnterVenueOrder(venue, member.getId(), PayTypeEnum.MEMBER_CARD, BigDecimal.ZERO); // 会员卡入场,增加记录 createMemberMoneyLog(MoneyLogEnum.JOIN.value, venue.getPrice(), member.getId(), member.getPlatformId(), PayTypeEnum.MEMBER_CARD.value, useCard.getCardType(), venue.getId(), venue.getType()); - log.setOrderSn(orderSn); - memberEnterVenueLogService.save(log); // 如果是单次卡,清除单次卡 if (VipTypeEnum.ONCECARD.value.equals(useCard.getCardType()) || VipTypeEnum.PUB_ONCECARD.value.equals(useCard.getCardType())){ memberCardService.delete(useCard.getId()); } - result.setBarcode("test123456"); }else { //查无可用会员卡 logger.info("用户" + member.getNickname() + "您好!请先购买会员卡再进场"); - result.setCode("1"); + result.setFlg(1); result.setMsg("未查询到会员卡,请先购买"); } }else { @@ -335,15 +309,12 @@ public class VenueService extends BaseServiceImpl { VenuePrice venuePrice = venuePriceService.findPrice(venueId, time); if (memberService.isMoneyEnough(member.getId(), venuePrice.getPrice())) { logger.info("用户" + member.getNickname() + "使用余额进场"); - String orderSn = orderService.createEnterVenueOrder(venue, member.getId(), PayTypeEnum.BALANCE, venuePrice.getPrice()); - log.setOrderSn(orderSn); - log.setPayType(EnterVenuePayTypeEnum.WEI_XIN.value); - memberEnterVenueLogService.save(log); - result.setBarcode("test123456"); + createMemberMoneyLog(MoneyLogEnum.JOIN.value, venuePrice.getPrice(), member.getId(), member.getPlatformId(), PayTypeEnum.BALANCE.value, null, + venue.getId(), venue.getType()); } else { //余额不足 logger.error("用户" + member.getNickname() + "余额不足进场失败"); - result.setCode("1"); + result.setFlg(1); result.setMsg("余额不足,请先充值"); } } @@ -398,32 +369,11 @@ public class VenueService extends BaseServiceImpl { return StringUtils.isNotBlank(longitude) && StringUtils.isNotBlank(latitude); } - /** - * 二维码入场-判断是否成功入场 - * - * @return 0成功 -1失败 - */ - @Transactional - public synchronized boolean qrCodeEnterVenue(Integer memberId, String deviceName,Integer venueId,Venue venue) { - return false; - } - - - // 记录使用会员卡入场记录 + // 记录入场记录 @Transactional public void createMemberMoneyLog(Integer type, BigDecimal price, Integer memberId, Integer platformId, Integer payType, String cardType, Integer venueId, Integer venueType) { - MemberMoneyLog memberMoneyLog = new MemberMoneyLog(); - memberMoneyLog.setType(type); - memberMoneyLog.setMoney(price.negate()); - memberMoneyLog.setMemberId(memberId); - memberMoneyLog.setPlatformId(platformId); - memberMoneyLog.setPayType(payType); - memberMoneyLog.setCardType(cardType); - memberMoneyLog.setVenueId(venueId); - memberMoneyLog.setVenueType(venueType); -// memberMoneyLog.setLessonId(lessonId); - memberMoneyLogService.insert(memberMoneyLog); + memberMoneyLogService.create(memberId,platformId == null ? 1 : platformId,type,price.negate(),payType,cardType,venueId,venueType,null); } @Transactional(rollbackFor = Exception.class) 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 abd2fcf..e74e712 100644 --- a/service/src/main/java/com/sv/service/oms/DeviceService.java +++ b/service/src/main/java/com/sv/service/oms/DeviceService.java @@ -2,6 +2,7 @@ package com.sv.service.oms; import com.common.DeviceDTO; import com.enums.DeviceStatusEnum; +import com.enums.EnterEnum; import com.github.pagehelper.PageHelper; import com.sv.entity.Device; import com.sv.exception.oms.OmsException; @@ -20,8 +21,6 @@ import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; import javax.annotation.Resource; -import java.sql.SQLException; -import java.util.Date; import java.util.List; /** @@ -170,12 +169,13 @@ public class DeviceService extends BaseServiceImpl { deviceMapper.update(device); } + @Deprecated public void reconnect(Integer deviceId){ try { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); HttpEntity> request = new HttpEntity<>(null,headers); - ResponseDTO responseDTO = restTemplate.postForObject("http://127.0.0.1:8000/device/reconnect/"+deviceId, request, ResponseDTO.class); + ResponseDTO responseDTO = restTemplate.postForObject("http://127.0.0.1:8093/device/reconnect/"+deviceId, request, ResponseDTO.class); Integer code = (Integer) responseDTO.get(ResponseDTO.ERR_CODE); if(0 != code){ throw new OmsException("重启失败!"); @@ -183,15 +183,35 @@ public class DeviceService extends BaseServiceImpl { }catch (Exception e){ throw new OmsException("连接失败!"); } + } + public void adminOperate(Integer deviceId,EnterEnum enterEnum){ + try { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + HttpEntity> request = new HttpEntity<>(null,headers); + ResponseDTO responseDTO = null; + if (EnterEnum.ENTER.equals(enterEnum)){ + responseDTO = restTemplate.postForObject("http://127.0.0.1:8093/admin/enter/"+deviceId, request, ResponseDTO.class); + }else { + responseDTO = restTemplate.postForObject("http://127.0.0.1:8093/admin/out/"+deviceId, request, ResponseDTO.class); + } + Integer code = (Integer) responseDTO.get(ResponseDTO.ERR_CODE); + if(0 != code){ + throw new OmsException("开门失败,设备离线或者门禁异常!"); + } + }catch (Exception e){ + logger.error("设备离线或者门禁异常",e); + throw new OmsException("开门失败,设备离线或者门禁异常!"); + } } /** * find by DeviceName */ - public Device findByDevice(String deviceName, Integer venueId){ - return deviceMapper.findByDevice(deviceName,venueId); + public Device findByDevice(Integer venueId){ + return deviceMapper.findByDevice(venueId); } } diff --git a/service/src/main/resources/mybatis/mapper/sv/BarcodeMapper.xml b/service/src/main/resources/mybatis/mapper/sv/BarcodeMapper.xml new file mode 100644 index 0000000..2f55fbc --- /dev/null +++ b/service/src/main/resources/mybatis/mapper/sv/BarcodeMapper.xml @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + id, barcode, status, member_id, venue_id, enter, created_id, modified_id, created_time, + modified_time + + + + delete from sv_barcode + where id = #{id,jdbcType=INTEGER} + + + insert into sv_barcode (id, barcode, status, + member_id, venue_id, enter, + created_id, modified_id, created_time, + modified_time) + values (#{id,jdbcType=INTEGER}, #{barcode,jdbcType=VARCHAR}, #{status,jdbcType=INTEGER}, + #{memberId,jdbcType=INTEGER}, #{venueId,jdbcType=INTEGER}, #{enter,jdbcType=INTEGER}, + #{createdId,jdbcType=INTEGER}, #{modifiedId,jdbcType=INTEGER}, #{createdTime,jdbcType=TIMESTAMP}, + #{modifiedTime,jdbcType=TIMESTAMP}) + + + insert into sv_barcode + + + id, + + + barcode, + + + status, + + + member_id, + + + venue_id, + + + enter, + + + created_id, + + + modified_id, + + + created_time, + + + modified_time, + + + + + #{id,jdbcType=INTEGER}, + + + #{barcode,jdbcType=VARCHAR}, + + + #{status,jdbcType=INTEGER}, + + + #{memberId,jdbcType=INTEGER}, + + + #{venueId,jdbcType=INTEGER}, + + + #{enter,jdbcType=INTEGER}, + + + #{createdId,jdbcType=INTEGER}, + + + #{modifiedId,jdbcType=INTEGER}, + + + #{createdTime,jdbcType=TIMESTAMP}, + + + #{modifiedTime,jdbcType=TIMESTAMP}, + + + + + update sv_barcode + + + barcode = #{barcode,jdbcType=VARCHAR}, + + + status = #{status,jdbcType=INTEGER}, + + + member_id = #{memberId,jdbcType=INTEGER}, + + + venue_id = #{venueId,jdbcType=INTEGER}, + + + enter = #{enter,jdbcType=INTEGER}, + + + created_id = #{createdId,jdbcType=INTEGER}, + + + modified_id = #{modifiedId,jdbcType=INTEGER}, + + + created_time = #{createdTime,jdbcType=TIMESTAMP}, + + + modified_time = #{modifiedTime,jdbcType=TIMESTAMP}, + + + where id = #{id,jdbcType=INTEGER} + + + update sv_barcode + set barcode = #{barcode,jdbcType=VARCHAR}, + status = #{status,jdbcType=INTEGER}, + member_id = #{memberId,jdbcType=INTEGER}, + venue_id = #{venueId,jdbcType=INTEGER}, + enter = #{enter,jdbcType=INTEGER}, + created_id = #{createdId,jdbcType=INTEGER}, + modified_id = #{modifiedId,jdbcType=INTEGER}, + created_time = #{createdTime,jdbcType=TIMESTAMP}, + modified_time = #{modifiedTime,jdbcType=TIMESTAMP} + where id = #{id,jdbcType=INTEGER} + + + + update sv_barcode + set status = 1 + where barcode = #{barcode,jdbcType=VARCHAR} + + + + + diff --git a/service/src/main/resources/mybatis/mapper/sv/DeviceMapper.xml b/service/src/main/resources/mybatis/mapper/sv/DeviceMapper.xml index 76db3c0..b84a56c 100644 --- a/service/src/main/resources/mybatis/mapper/sv/DeviceMapper.xml +++ b/service/src/main/resources/mybatis/mapper/sv/DeviceMapper.xml @@ -8,8 +8,6 @@ - - @@ -35,9 +33,6 @@ venue_id, status, venue_type, - device_type, - bind_member, - bind_time, created_id, modified_id, created_time, @@ -52,8 +47,6 @@ #{stream, jdbcType=VARCHAR}, #{venue_id, jdbcType=INTEGER}, #{venue_type, jdbcType=INTEGER}, - #{bind_member, jdbcType=INTEGER}, - #{bind_time, jdbcType=TIMESTAMP}, #{createdId, jdbcType=INTEGER}, #{modifiedId, jdbcType=INTEGER}, #{createdTime, jdbcType=TIMESTAMP}, @@ -92,12 +85,6 @@ venue_type, - - bind_member, - - - bind_time, - status, @@ -133,12 +120,6 @@ #{venueType}, - - #{bindMember}, - - - #{bindTime}, - #{status}, @@ -203,12 +184,6 @@ venue_type = #{venueType}, - - bind_member = #{bindMember}, - - - bind_time = #{bindTime}, - created_id = #{createdId}, @@ -275,16 +250,16 @@ - - UPDATE sv_device set bind_member = #{bindMember},bind_time = now() - WHERE name = #{deviceName} and venue_id=#{venueId} - + + + + - - UPDATE sv_device set bind_member = null,bind_time = null - WHERE name = #{deviceName} and venue_id=#{venueId} - + + + + diff --git a/service/src/main/resources/mybatis/mapper/sv/MemberEnterVenueLogMapper.xml b/service/src/main/resources/mybatis/mapper/sv/MemberEnterVenueLogMapper.xml index 270d8b2..bd0051d 100644 --- a/service/src/main/resources/mybatis/mapper/sv/MemberEnterVenueLogMapper.xml +++ b/service/src/main/resources/mybatis/mapper/sv/MemberEnterVenueLogMapper.xml @@ -331,7 +331,7 @@ - \ No newline at end of file + diff --git a/service/src/main/resources/mybatis/mapper/sv/MemberMoneyLogMapper.xml b/service/src/main/resources/mybatis/mapper/sv/MemberMoneyLogMapper.xml index ce6774d..897e4a1 100644 --- a/service/src/main/resources/mybatis/mapper/sv/MemberMoneyLogMapper.xml +++ b/service/src/main/resources/mybatis/mapper/sv/MemberMoneyLogMapper.xml @@ -48,7 +48,7 @@ sv_member_money_log - + id, @@ -331,4 +331,20 @@ ORDER BY created_time DESC - \ No newline at end of file + + + + + diff --git a/service/src/main/resources/tools/generatorConfig.xml b/service/src/main/resources/tools/generatorConfig.xml index caefbc0..17af678 100644 --- a/service/src/main/resources/tools/generatorConfig.xml +++ b/service/src/main/resources/tools/generatorConfig.xml @@ -90,7 +90,7 @@ domainObjectName 给表对应的 model 起名字 注意:大小写敏感问题。 --> -