增加netty处理协议

This commit is contained in:
gaoben 2021-02-25 09:33:01 +08:00
parent a73d6457de
commit 0079beeac2
37 changed files with 1983 additions and 9 deletions

View File

@ -7,6 +7,7 @@ import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ImportResource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@ -15,6 +16,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication//(exclude = DataSourceAutoConfiguration.class)//排除DataSourceConfiguratrion
@EnableCaching
@EnableTransactionManagement
@ServletComponentScan
//@MapperScan("net.shapelight.modules.sys.dao")
public class AdminApplication {

View File

@ -90,5 +90,10 @@ public class GlobalValue {
@Value("${global.wx.secret}")
private String wxSecret;
@Value("${global.app.key}")
private String appKey;
@Value("${global.app.secret}")
private String appSecret;
}

View File

@ -1,6 +1,7 @@
package net.shapelight.common.utils;
import java.io.*;
import java.util.Base64;
import java.util.Date;
public class ImageUtils {
/**
@ -72,15 +73,17 @@ public class ImageUtils {
}
public static void main(String[] args) throws IOException {
String imageStr = GetImageBase64Str("/home/shapelight/upload/1/header.jpg");
System.out.println(imageStr);
Base64StrToImage(imageStr, "/home/shapelight/upload/1/61.jpg");
// String imageStr = GetImageBase64Str("d:/3.jpg");
// System.out.println(imageStr);
// Base64StrToImage(imageStr, "deviceEntity");
File img = new File("/home/shapelight/upload/1/header2.jpg");
File img = new File("d:/3.jpg");
if(img.exists()){
String faceStr = ImageUtils.GetImageBase64Str("/home/shapelight/upload/1/header2.jpg");
String faceStr = ImageUtils.GetImageBase64Str("d:/3.jpg");
long now = new Date().getTime();
String a = faceStr;
}else{
String a = "";

View File

@ -0,0 +1,90 @@
package net.shapelight.modules.nettyapi.config;
import io.netty.channel.Channel;
import io.netty.util.AttributeKey;
import lombok.Data;
import org.springframework.stereotype.Component;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
@Component
@Data
public class ClientMap {
//用户id=>channel示例
private final ConcurrentHashMap<String, Channel> channelMap = new ConcurrentHashMap<>();
/**
* 判断一个通道是否有用户在使用
* 可做信息转发时判断该通道是否合法
* @param channel
* @return
*/
public boolean hasUser(Channel channel) {
AttributeKey<String> key = AttributeKey.valueOf("user");
String kk = channel.attr(key).get();
return (channel.hasAttr(key) && channel.attr(key).get() != null);//netty移除了这个map的remove方法,这里的判断谨慎一点
}
/**
* 上线一个用户
*
* @param channel
* @param userId
*/
public void online(Channel channel, String userId) {
//先判断用户是否在web系统中登录?
//这部分代码个人实现,参考上面redis中的验证
this.channelMap.put(userId, channel);
AttributeKey<String> key = AttributeKey.valueOf("user");
channel.attr(key).set(userId);
}
/**
* 下线一个用户
*
* @param channel
*/
public void offline(Channel channel) {
Collection<Channel> col = this.channelMap.values();
while(true == col.contains(channel)) {
col.remove(channel);
}
}
/**
* 根据用户id获取该用户的通道
*
* @param userId
* @return
*/
public Channel getChannelByUserId(String userId) {
return this.channelMap.get(userId);
}
public String getUserIdByChannel(Channel channel) {
AttributeKey<String> key = AttributeKey.valueOf("user");
String kk = channel.attr(key).get();
if (channel.hasAttr(key) && channel.attr(key).get() != null){
return channel.attr(key).get();
}
return "";
}
/**
* 判断一个用户是否在线
*
* @param userId
* @return
*/
public Boolean isLogin(String userId) {
return this.channelMap.containsKey(userId) && this.channelMap.get(userId) != null;
}
}

View File

@ -0,0 +1,31 @@
package net.shapelight.modules.nettyapi.config;
/**
* 常量
*
*
*/
public class CmdConstant {
public static final byte CMD_LOGIN = 0x01;
public static final byte CMD_GETALL = 0x02;
public static final byte CMD_GETONE = 0x03;
public static final byte CMD_HART = 0x04;
public static final byte CMD_UPRECORD = 0x05;
public static final byte CMD_EXTRACT = 0x06;
public static final byte CMD_CONFIG = 0x50;
public static final byte CMD_CHANGE = 0x51;
public static final byte CMD_OPENDOOR = 0x52;
public static final byte CMD_RESTART = 0x53;
public static final byte CMD_APPUPDATE = 0x54;
public static final byte CMD_CLEANDATA = 0x55;
public static final byte CMD_ENABLE = 0x56;
}

View File

@ -0,0 +1,125 @@
package net.shapelight.modules.nettyapi.config;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
public class HttpRequest {
/**
* 向指定URL发送GET方法的请求
*
* @param url
* 发送请求的URL
* @param param
* 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return URL 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param) {
String result = "";
BufferedReader in = null;
try {
String urlNameString = url + "?" + param;
URL realUrl = new URL(urlNameString);
// 打开和URL之间的连接
URLConnection connection = realUrl.openConnection();
// 设置通用的请求属性
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 建立实际的连接
connection.connect();
// 获取所有响应头字段
Map<String, List<String>> map = connection.getHeaderFields();
// 遍历所有的响应头字段
for (String key : map.keySet()) {
// System.out.println(key + "--->" + map.get(key));
}
// 定义 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
// System.out.println("发送GET请求出现异常" + e);
e.printStackTrace();
}
// 使用finally块来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url
* 发送请求的 URL
* @param param
* 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
// System.out.println("发送 POST 请求出现异常!"+e);
e.printStackTrace();
}
//使用finally块来关闭输出流输入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
}

View File

@ -0,0 +1,28 @@
package net.shapelight.modules.nettyapi.config;
public class MyMessage {
/*
58 54 5A 47 //消息头 4字节 XTZG
01 //版本号 1字节
01 //数据类型 1字节 json
03 //消息命令 1字节
00 00 00 24 //数据长度 4字节 不包含以上头部数据
58 23 47 4A //数据 json
*/
public static final byte[] HEAD = {(byte)0X58,(byte)0X49,(byte)0X54,(byte)0X55}; //4个字节
public static final byte version = 0x01; //1个字节
public static final byte dataType = 0x01; //1个字节type负载数据格式0x01为Json0x02为xml,0x03为二进制数据
public final byte cmd; //1个字节
public final int dataLength; //数据长度4字节
public final byte[] content; //数据josn串
// public static final byte FOOT = (byte)0XFF;
public byte[] data;//所有的数据转换为16进制的东东
public MyMessage(byte cmd,int dataLength,byte[] content) {//decoder用
// this.data = data;
this.cmd = cmd;
this.dataLength = dataLength;
this.content = content;
}
}

View File

@ -0,0 +1,95 @@
package net.shapelight.modules.nettyapi.config;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
/**
*
* @author Administrator
*
*/
/*
58 54 5A 47 //消息头 4字节 XTZG
01 //版本号 1字节
01 //数据类型 1字节 json
03 //消息命令 1字节
00 00 00 24 //数据长度 4字节 不包含以上头部数据
54 34 27 8A //数据 json字符串
*/
@Slf4j
public class MyMessageDecoder extends ByteToMessageDecoder {
private static final int HEAD_LENGTH = 11;//要通过proto_type和msg_type来确定长度的有效性
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in,
List<Object> out) throws Exception {
if (in.readableBytes() < HEAD_LENGTH) {
return;
}
in.markReaderIndex();
final byte c0 = in.readByte();
if((c0&0xFF) != 0x58){
in.resetReaderIndex();
in.skipBytes(1);
// log.debug(String.format("c0:is 0x%x",c0));
return;
}
final byte c1 = in.readByte();
if((c1&0xFF) != 0x49){
in.resetReaderIndex();
in.skipBytes(1);
// log.debug(String.format("c1:is 0x%x",c1));
return;
}
final byte c2 = in.readByte();
if((c2&0xFF) != 0x54){
in.resetReaderIndex();
in.skipBytes(1);
// log.debug(String.format("c2:is 0x%x",c2));
return;
}
final byte c3 = in.readByte();
if((c3&0xFF) != 0x55){
in.resetReaderIndex();
in.skipBytes(1);
// log.debug(String.format("c3:is 0x%x",c3));
return;
}
final byte version = in.readByte();
final byte dataType = in.readByte();
final byte cmd = in.readByte();
final int dataLength = in.readInt();
if(in.readableBytes()<dataLength){
in.resetReaderIndex();
return;//数据不够继续读
}
byte[] contentBytes = new byte[dataLength];
in.readBytes(contentBytes);
// if ( (0xff&contentBytes[dataLength - 1]) != 0x7d ){ //0x7d }
// in.resetReaderIndex();
// in.skipBytes(1);
//// log.debug("数据结束符不是}");
// return;//in.clear();
// }
// String content = new String(contentBytes);
// log.debug("收到数据:"+content);
final MyMessage o = new MyMessage(cmd,dataLength,contentBytes);// convertToObject(body);
out.add(o);
}
}

View File

@ -0,0 +1,30 @@
package net.shapelight.modules.nettyapi.config;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
public class MyMessageEncoder extends MessageToByteEncoder<MyMessage> {
@Override
protected void encode(ChannelHandlerContext ctx, MyMessage msg, ByteBuf out)
throws Exception {
// if(msg.data!=null){//手动构建了data直接发就行了
// byte[] body = msg.data;
// out.writeBytes(body);//消息体中包含我们要发送的数据
// return;
// }
out.writeBytes(msg.HEAD);
out.writeByte(msg.version);//4个字节已经测试了
out.writeByte(msg.dataType);
out.writeByte(msg.cmd);
out.writeInt(msg.dataLength);
out.writeBytes(msg.content);
// if( null != msg.content ){
// out.writeBytes(msg.content.getBytes());
// }
}
}

View File

@ -0,0 +1,90 @@
package net.shapelight.modules.nettyapi.config;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class MyServer {
private Integer port = 9999;
//private final int port = 9102;
private static EventLoopGroup bossGroup = null; // (1)
private static EventLoopGroup workerGroup = null;//
// private ChannelFuture cf;
// private final IMyServerHandler uiHandler;
//
public MyServer(Integer port) {
this.port = port;
}
public void run() throws Exception {
try {
bossGroup = new NioEventLoopGroup(); // (1)
workerGroup = new NioEventLoopGroup();
ServerBootstrap b = new ServerBootstrap(); // (2)
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) // (3)
.childHandler(new ChannelInitializer<SocketChannel>() { // (4)
@Override
public void initChannel(SocketChannel ch) throws Exception {
final ChannelPipeline pipeline = ch.pipeline();
// Decoders
pipeline.addLast("decoder", new MyMessageDecoder());
// Encoder
pipeline.addLast("encoder", new MyMessageEncoder());
//pipeline.addLast("idleStateHandler", new IdleStateHandler(6, 3, 0));//心跳机制
pipeline.addLast("idleStateHandler", new IdleStateHandler(600, 600, 600));//心跳机制
pipeline.addLast(new MyServerHandler());
}
}).option(ChannelOption.SO_BACKLOG, 128) // (5)//BACKLOG用于构造服务端套接字ServerSocket对象标识当服务器请求处理线程全满时用于临时存放已完成三次握手的请求的队列的最大长度如果未设置或所设置的值小于1Java将使用默认值50
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
// Bind and start to accept incoming connections.
ChannelFuture cf = b.bind(port).sync(); // (7)
// cf = b.bind(port).sync(); // (7)
log.info("Netty已启动正在监听 " + cf.channel().localAddress());
// Wait until the server socket is closed.
// In this example, this does not happen, but you can do that to gracefully
// shut down your server.
cf.channel().closeFuture().sync();//保证了服务一直启动相当于一个死循环
} finally {
if (null != workerGroup) {
workerGroup.shutdownGracefully();
workerGroup = null;
}
if (null != bossGroup) {
bossGroup.shutdownGracefully();
bossGroup = null;
}
}
}
public void close() {
if (workerGroup != null) {
workerGroup.shutdownGracefully();
workerGroup = null;
}
}
// public void destroy() {
// log.info(MyServer.class + " netty服务监听关闭 " + cf.channel().localAddress());
// try {
// cf.channel().closeFuture().sync();// 关闭服务器通道
// } catch (Exception e) {
// e.printStackTrace();
// }finally{
// bossGroup.shutdownGracefully().syncUninterruptibly();
// workerGroup.shutdownGracefully().syncUninterruptibly();
// }
//
// }
}

View File

@ -0,0 +1,99 @@
package net.shapelight.modules.nettyapi.config;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import net.shapelight.common.utils.SpringContextUtils;
import net.shapelight.modules.nettyapi.service.MessageService;
@Slf4j
public class MyServerHandler extends SimpleChannelInboundHandler<MyMessage> {
private ClientMap clientMap = SpringContextUtils.getBean("clientMap", ClientMap.class);
private MessageService messageService = SpringContextUtils.getBean("messageService", MessageService.class);
private static ChannelGroup clients =new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
// private final IMyServerHandler uiHandler;
//
// public MyServerHandler(IMyServerHandler uiHandler) {
// super();
// this.uiHandler = uiHandler;
// }
@Override
protected void channelRead0(ChannelHandlerContext ctx, MyMessage msg)
throws Exception {
messageService.receive(ctx,msg);
// switch (msg.cmd) {
// //登录
// case 0x01: {
// deviceLogin(ctx, msg.content);
// log.debug("登录信息:" + msg.cmd);
// break;
// }
// case 0x05: {
// log.debug("设备注册:" + msg.cmd);
// break;
// }
// case 0x07: {
// log.debug("收到心跳:" + msg.cmd);
// break;
// }
// default:
// log.debug("unknown cmd type:" + msg.cmd);
// break;
// }
}
// 客户端连接之后获取客户端channel并放入group中管理
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
clients.add(ctx.channel());
}
// 移除对应客户端的channel
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
// 长短id
System.out.println(ctx.channel().id().asLongText());
System.out.println(ctx.channel().id().asShortText());
clients.remove(ctx.channel());
clientMap.offline(ctx.channel());
log.info("客户端断开");
}
/**
* 发生异常触发
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
clientMap.offline(ctx.channel());
log.error("发生异常设备离线"+cause.getMessage());
}
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
//心跳机制 配合ch.pipeline().addLast("idleStateHandler", new IdleStateHandler(60, 30, 0));使用
super.userEventTriggered(ctx, evt);
if (evt instanceof IdleStateEvent) {
IdleStateEvent e = (IdleStateEvent) evt;
if (e.state() == IdleState.READER_IDLE) {//没收到任何数据就关掉链接
ctx.close();
clientMap.offline(ctx.channel());
log.info("无数据设备离线");
} else if (e.state() == IdleState.WRITER_IDLE) {
}
}
}
}

View File

@ -0,0 +1,135 @@
package net.shapelight.modules.nettyapi.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@WebListener
@Slf4j
public class StartInit implements ServletContextListener {
@Value("${global.tcp_server.port}")
private Integer port;//读取yml的配置80
//public static final int ASSERT_MAX_SIZE = 2*10*1000;
public static final int ASSERT_MAX_SIZE = 10000;
public static final int ASSERT_MAX_TIME = 10;//s
// private final List<PlcMacEntity> list = new ArrayList<PlcMacEntity>(ASSERT_MAX_SIZE);
//
// private final List<PlcUeEntity> syncUE = new ArrayList<PlcUeEntity>(1);
private static final ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
private static final ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
//private PlcUeService plcUeSercice;
// private IMyServerHandler handler = new IMyServerHandler() {
//
// @Override
// public void do_receive() {
//
// cachedThreadPool.execute(new Runnable() {
//
// @Override
// public void run() {
//// synchronized (list) {
//// list.add(mac);
//// if(list.size()>ASSERT_MAX_SIZE) {
//// final String tableName = plcMacDao.PREFIX+plcMacDao.SDF.format(new Date());
//// //macMapper.tryCreateNewTable( tableName );
//// //macMapper.insertList(list, tableName );
////
//// plcMacDao.tryCreateNewTable(tableName);
//// plcMacDao.insertList(list, tableName);
//// list.clear();
//// }
//// }
// }
// });
//
// //HttpRequest.sendGet("http://127.0.0.1:8080/tl.web/common/macInsert",String.format( "mac=%s&rssi=%s&raw=%s", mac.getMac(),mac.getRssi(),mac.getRaw()));
// log.debug("mac...insert...");
// }
// };
private MyServer server;
@Override
public void contextDestroyed(ServletContextEvent arg0) {
server.close();
// server.destroy();
log.info("server closed");
// synchronized (list) {
// if(list.size()>0) {
// final String tableName = plcMacDao.PREFIX+plcMacDao.SDF.format(new Date());
// //macMapper.tryCreateNewTable( tableName );
// //macMapper.insertList(list, tableName );
// plcMacDao.tryCreateNewTable(tableName);
// plcMacDao.insertList(list, tableName);
// list.clear();
// }
// }
}
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
// System.out.println("Initialising listener...");
// 加入下面的这行代码
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
// System.out.println("username:" + username + "password:" + password);
WebApplicationContext webApplicationContext= WebApplicationContextUtils.getWebApplicationContext(servletContextEvent.getServletContext());
// System.out.println("webApplicationContext:"+webApplicationContext);
log.info("webApplicationContext"+webApplicationContext);
if(webApplicationContext!=null) {
log.info("not nul.....................................");
}
//macMapper =(MACMapper) webApplicationContext.getBean("macService");
//ueMapper =(UEMapper) webApplicationContext.getBean("ueService");
// plcMacDao = (PlcMacDao)webApplicationContext.getBean("plcMacDao");
// plcUeDao = (PlcUeDao)webApplicationContext.getBean("plcUeDao");
log.info("server will init ...");
server = new MyServer(port);
new Thread() {
public void run() {
try {
server.run();
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
// synchronized (list) {
// if(list.size()<=0) return;
// final String tableName = plcMacDao.PREFIX+plcMacDao.SDF.format(new Date());
// //macMapper.tryCreateNewTable( tableName );
// //macMapper.insertList(list, tableName );
// plcMacDao.tryCreateNewTable(tableName);
// plcMacDao.insertList(list, tableName);
// list.clear();
// }
}
},1, ASSERT_MAX_TIME, TimeUnit.SECONDS);
}
}

View File

@ -0,0 +1,17 @@
package net.shapelight.modules.nettyapi.service;
import io.netty.channel.Channel;
public interface DeviceApiService {
void login(Channel channel, String content);
void getAllMember(Channel channel, String content);
void getMemberInfo(Channel channel, String content);
void heartbeat(Channel channel, String content);
void saveRecord(Channel channel, String content);
void extract(Channel channel, String content);
boolean isOnline(String sn);
}

View File

@ -0,0 +1,10 @@
package net.shapelight.modules.nettyapi.service;
import io.netty.channel.ChannelHandlerContext;
import net.shapelight.modules.nettyapi.config.MyMessage;
public interface MessageService {
void receive(ChannelHandlerContext ctx, MyMessage content);
}

View File

@ -0,0 +1,22 @@
package net.shapelight.modules.nettyapi.service;
import net.shapelight.modules.vo.TenAppVerison;
import net.shapelight.modules.vo.TenDeviceConfig;
public interface ServerApiService {
int devConfig(String sn, TenDeviceConfig dc);
int restart(String sn);
int cleanData(String sn);
int openDoor(String sn, Long personId);
int enableDevice(String sn);
int appUpdate(String sn,TenAppVerison appVerison);
}

View File

@ -0,0 +1,422 @@
package net.shapelight.modules.nettyapi.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.netty.channel.Channel;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import net.shapelight.common.config.GlobalValue;
import net.shapelight.common.utils.DateUtils;
import net.shapelight.common.utils.ImageUtils;
import net.shapelight.common.utils.TreeUtils;
import net.shapelight.common.utils.UUIDUtil;
import net.shapelight.modules.nettyapi.config.ClientMap;
import net.shapelight.modules.nettyapi.config.CmdConstant;
import net.shapelight.modules.nettyapi.config.MyMessage;
import net.shapelight.modules.nettyapi.service.DeviceApiService;
import net.shapelight.modules.nettyapi.service.ServerApiService;
import net.shapelight.modules.nettyapi.utils.Result;
import net.shapelight.modules.ten.entity.*;
import net.shapelight.modules.ten.service.*;
import net.shapelight.modules.vo.TenPersonIdUpdateAllVo;
import net.shapelight.modules.vo.TenPersonIdUpdateVo;
import net.shapelight.modules.vo.TenUserVo;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.File;
import java.util.*;
@Slf4j
@Service("deviceApiService")
public class DeviceApiServiceImpl implements DeviceApiService {
@Autowired
ClientMap clientMap;
@Autowired
private TenDeviceService tenDeviceService;
@Autowired
private GlobalValue globalValue;
@Autowired
private TenRecordService tenRecordService;
@Autowired
private ServerApiService serverApiService;
@Autowired
private TenCellService tenCellService;
@Autowired
private TenPersonService tenPersonService;
@Autowired
private TenDeviceAlertService tenDeviceAlertService;
@Autowired
private TenPersonExtractService tenPersonExtractService;
/*
请求示例
{
"app_key": "0fksdjfkjd",
"app_secret":"239i0r230ur0932u",
"dev_id":"3cde32ef123"
}
返回示例
{
"code": 200,
"msg":"success",
"data": {
"area_id": "23948203",
"area_name": "山海城,软件园,航城一小",
"building_id": "123",
"buiding_name": "3栋1单元A2栋,1年级1班" ,
"config":{
"work_mode":0,
"recognize_interval":3,
"relay_suck_time":5,
"support_liveness":true,
"liveness_score":60,
"recognize_score":65,
"recognize_distance":2,
"alert_temp_threshold":37.3,
"upload_face_pic":true,
"upload_pic_mode":0,
"upload_http_url":"http://upload.face.com/face/pic/upload",
"support_stranger":false
}
}
}
*/
//0x01 0x02
public void login(Channel channel, String content) {
JSONObject loginJson = JSONObject.parseObject(content);
String gAppKey = globalValue.getAppKey();
String gAppSecret = globalValue.getAppSecret();
String appKey = loginJson.getString("app_key");
String appSecret = loginJson.getString("app_secret");
String devId = loginJson.getString("dev_id");
if(appKey==null || appKey.length()==0 || appSecret == null || appSecret.length()==0
|| !gAppKey.equals(appKey) || !gAppSecret.equals(appSecret)){
Result res = Result.error(203, "App key or App Secret Error");
String resContent = JSONObject.toJSONString(res);
MyMessage message = new MyMessage(CmdConstant.CMD_LOGIN,resContent.length(),resContent.getBytes());
channel.writeAndFlush(message);
return;
}
//设备sn不能为空
if (devId == null || devId.isEmpty()) {
Result res = Result.error(201, "Device Is Not Bind");
String resContent = JSONObject.toJSONString(res);
MyMessage message = new MyMessage(CmdConstant.CMD_LOGIN,resContent.length(),resContent.getBytes());
channel.writeAndFlush(message);
return;
}
//1.判断sn是否存在 设备不存在1002
TenDeviceEntity deviceEntity = tenDeviceService.findBySn(devId);
if(deviceEntity == null){
Result res = Result.error(201, "Device Is Not Bind");
String resContent = JSONObject.toJSONString(res);
MyMessage message = new MyMessage(CmdConstant.CMD_LOGIN,resContent.length(),resContent.getBytes());
channel.writeAndFlush(message);
return;
}
TenCellEntity cellEntity = tenCellService.getById(deviceEntity.getCellId());
Result res = new Result();
Map<String,Object> dataMap = new HashMap<>();
dataMap.put("area_id",cellEntity.getCellId().toString());
dataMap.put("area_name",cellEntity.getName());
dataMap.put("building_id",cellEntity.getCellId().toString());
dataMap.put("building_name",cellEntity.getName());
Map<String,Object> configMap = new HashMap<>();
configMap.put("work_mode",0);
configMap.put("recognize_interval",3);
configMap.put("relay_suck_time",5);
configMap.put("support_liveness",true);
configMap.put("liveness_score",60);
configMap.put("recognize_score",65);
configMap.put("recognize_distance",2);
configMap.put("alert_temp_threshold",37.3);
configMap.put("upload_face_pic",true);
configMap.put("upload_pic_mode",0);
configMap.put("upload_http_url","http://upload.face.com/face/pic/upload");
configMap.put("support_stranger",false);
dataMap.put("config",configMap);
res.put("data",dataMap);
String resContent = JSONObject.toJSONString(res);
MyMessage message = new MyMessage(CmdConstant.CMD_LOGIN,resContent.getBytes().length,resContent.getBytes());
channel.writeAndFlush(message);
clientMap.online(channel, devId);
tenDeviceService.updateById(deviceEntity);
log.debug("设备:" + devId + " 登录");
return;
}
/**
* {
* "dev_id":"3cde32ef123"
* }
*/
@Override
public void getAllMember(Channel channel, String content) {
JSONObject jsonContent = JSONObject.parseObject(content);
String devId = jsonContent.getString("dev_id");
TenDeviceEntity deviceEntity = tenDeviceService.findBySn(devId);
if(deviceEntity == null){
log.error("设备已删除");
return;
}
TenCellEntity cellEntity = tenCellService.getById(deviceEntity.getCellId());
List<TenPersonIdUpdateAllVo> all = tenPersonService.findAllPersonIdUpdateAll(cellEntity.getCellId(),null,null);
Result res = new Result();
res.put("data",all);
String resContent = JSONObject.toJSONString(res);
MyMessage message = new MyMessage(CmdConstant.CMD_GETALL,resContent.getBytes().length,resContent.getBytes());
channel.writeAndFlush(message);
}
/*
{
"dev_id":"3cde32ef123"
"uid":12000
}
*/
@Override
public void getMemberInfo(Channel channel, String content) {
JSONObject jsonContent = JSONObject.parseObject(content);
String devId = jsonContent.getString("dev_id");
Long uid = jsonContent.getLong("uid");
TenDeviceEntity deviceEntity = tenDeviceService.findBySn(devId);
if(deviceEntity == null){
log.error("设备已删除");
return;
}
TenCellEntity cellEntity = tenCellService.getById(deviceEntity.getCellId());
TenPersonEntity p = tenPersonService.getById(uid,cellEntity.getCellId());
TenUserVo puser = new TenUserVo();
puser.setUid(p.getPersonId());
puser.setUser_name(p.getName());
puser.setUser_type(0);
puser.setActive_start_time(0);
puser.setActive_end_time(0);
puser.setLast_update_stamp(p.getLastUpdateTime().getTime());
puser.setCard_id("");
puser.setFace_pic_download_url(globalValue.getMinioEndpoint()+"/"
+ globalValue.getMinioBucketName()+"/"
+ p.getOrgImage());
puser.setFace_pic_base64("");
Result res = new Result();
res.put("data",puser);
String resContent = JSONObject.toJSONString(res);
MyMessage message = new MyMessage(CmdConstant.CMD_GETONE,resContent.getBytes().length,resContent.getBytes());
channel.writeAndFlush(message);
}
/*
{
"dev_id":"3cde32ef123"
"face_count":3232,
"rgb_camera_status":0,
"ir_camera_status":0
"relay_status":0
}
*/
@Override
public void heartbeat(Channel channel, String content) {
JSONObject jsonContent = JSONObject.parseObject(content);
String sn = jsonContent.getString("dev_id");
Integer faceCount = jsonContent.getIntValue("face_count");
Integer rgbCameraStatus = jsonContent.getIntValue("rgb_camera_status");
Integer irCameraStatus = jsonContent.getIntValue("ir_camera_status");
Integer relayStatus = jsonContent.getIntValue("relay_status");
TenDeviceEntity deviceEntity = tenDeviceService.findBySn(sn);
if(deviceEntity == null){
log.error("设备已删除");
return;
}
//保存人脸个数
deviceEntity.setFaceCount(faceCount);
tenDeviceService.updateById(deviceEntity);
TenCellEntity cellEntity = tenCellService.getById(deviceEntity.getCellId());
Date now = new Date();
//保存告警信息
if(rgbCameraStatus.intValue() == 1){
TenDeviceAlertEntity da = new TenDeviceAlertEntity();
da.setSn(sn);
da.setCellId(cellEntity.getCellId());
da.setAlertLevel("严重");
da.setAlertType("故障");
da.setAlertTime(now);
da.setErrorLog("RGB摄像头故障");
tenDeviceAlertService.save(da);
}
if(irCameraStatus.intValue() == 1){
TenDeviceAlertEntity da = new TenDeviceAlertEntity();
da.setSn(sn);
da.setCellId(cellEntity.getCellId());
da.setAlertLevel("严重");
da.setAlertType("故障");
da.setAlertTime(now);
da.setErrorLog("红外摄像头故障");
tenDeviceAlertService.save(da);
}
if(relayStatus.intValue() == 1){
TenDeviceAlertEntity da = new TenDeviceAlertEntity();
da.setSn(sn);
da.setCellId(cellEntity.getCellId());
da.setAlertLevel("严重");
da.setAlertType("故障");
da.setAlertTime(now);
da.setErrorLog("继电器故障");
tenDeviceAlertService.save(da);
}
Result res = new Result();
String resContent = JSONObject.toJSONString(res);
MyMessage message = new MyMessage(CmdConstant.CMD_HART,resContent.getBytes().length,resContent.getBytes());
channel.writeAndFlush(message);
}
/*
{
"dev_id":"3cde32ef123"
"uid":10003,
"unlock_mode":0,
"unlock_time":156002322
"capture_face_pic":"base64 image"
}
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void saveRecord(Channel channel, String content) {
JSONObject jsonContent = JSONObject.parseObject(content);
String sn = jsonContent.getString("dev_id");
Long personId = jsonContent.getLongValue("uid");
Integer unlockMode = jsonContent.getIntValue("unlock_mode");
Long unlockTime = jsonContent.getLongValue("unlock_time");
unlockTime = unlockTime*1000;
String captureFacePic = jsonContent.getString("capture_face_pic");
TenDeviceEntity deviceEntity = tenDeviceService.findBySn(sn);
if(deviceEntity == null){
log.error("设备已删除");
return;
}
TenCellEntity cellEntity = tenCellService.getById(deviceEntity.getCellId());
TenRecordEntity record = new TenRecordEntity();
record.setDeviceSn(sn);
record.setDeviceName(deviceEntity.getName());
record.setCellId(deviceEntity.getCellId());
record.setPersonId(personId);
record.setOpenType(unlockMode);
record.setRecordTime(new Date(unlockTime));
record.setRecordFaceStr(captureFacePic);
record.setTenantId(deviceEntity.getTenantId());
// log.info("保存记录:----------------------"+record.getRecordTime()+"-"+record.getMemberId().intValue());
tenRecordService.saveForFace(record);
Result res = new Result();
String resContent = JSONObject.toJSONString(res);
MyMessage message = new MyMessage(CmdConstant.CMD_UPRECORD,resContent.getBytes().length,resContent.getBytes());
channel.writeAndFlush(message);
}
/*
{
"dev_id":"3cde32ef123"
"uid":3232,
"user_type":0,
"state":0
}
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void extract(Channel channel, String content) {
JSONObject jsonContent = JSONObject.parseObject(content);
String sn = jsonContent.getString("dev_id");
Long personId = jsonContent.getLongValue("uid");
Integer userType = jsonContent.getIntValue("user_type");
Integer state = jsonContent.getIntValue("state");
TenDeviceEntity deviceEntity = tenDeviceService.findBySn(sn);
if(deviceEntity == null){
log.error("设备已删除");
return;
}
TenCellEntity cellEntity = tenCellService.getById(deviceEntity.getCellId());
TenPersonExtractEntity extract = new TenPersonExtractEntity();
extract.setDeviceSn(sn);
extract.setExtractTime(new Date());
extract.setPersonId(personId);
extract.setPersonType(userType);
extract.setState(state);
extract.setCellId(cellEntity.getCellId());
extract.setTenantId(cellEntity.getTenantId());
tenPersonExtractService.save(extract);
Result res = new Result();
String resContent = JSONObject.toJSONString(res);
MyMessage message = new MyMessage(CmdConstant.CMD_EXTRACT,resContent.getBytes().length,resContent.getBytes());
channel.writeAndFlush(message);
}
@Override
public boolean isOnline(String sn) {
return clientMap.isLogin(sn);
}
}

View File

@ -0,0 +1,149 @@
package net.shapelight.modules.nettyapi.service.impl;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import net.shapelight.modules.nettyapi.config.ClientMap;
import net.shapelight.modules.nettyapi.config.CmdConstant;
import net.shapelight.modules.nettyapi.config.MyMessage;
import net.shapelight.modules.nettyapi.service.DeviceApiService;
import net.shapelight.modules.nettyapi.service.MessageService;
import net.shapelight.modules.nettyapi.utils.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;
//import net.sf.ehcache.CacheManager;
@Slf4j
@Service("messageService")
public class MessageServiceImpl implements MessageService {
@Autowired
private DeviceApiService deviceApiService;
@Autowired
private ClientMap clientMap;
@Autowired
private CacheManager cacheManager;
@Override
public void receive(ChannelHandlerContext ctx, MyMessage msg) {
Channel channel = ctx.channel();
String content = new String(msg.content);
switch (msg.cmd) {
//登录
case CmdConstant.CMD_LOGIN: {
// deviceLogin(ctx, msg.content);
deviceApiService.login(channel,content);
log.debug("登录信息:" + msg.cmd);
break;
}
case CmdConstant.CMD_GETALL: {
log.debug("全量获取:" + msg.cmd);
if(!clientMap.hasUser(channel)){
Result res = Result.error(403,"No permission");
String resContent = JSONObject.toJSONString(res);
MyMessage message = new MyMessage(CmdConstant.CMD_GETALL,resContent.length(),resContent.getBytes());
channel.writeAndFlush(message);
return;
}
deviceApiService.getAllMember(channel,content);
break;
}
case CmdConstant.CMD_GETONE: {
log.debug("获取详情:" + msg.cmd);
deviceApiService.getMemberInfo(channel,content);
if(!clientMap.hasUser(channel)){
Result res = Result.error(403,"No permission");
String resContent = JSONObject.toJSONString(res);
MyMessage message = new MyMessage(CmdConstant.CMD_GETONE,resContent.length(),resContent.getBytes());
channel.writeAndFlush(message);
return;
}
break;
}
case CmdConstant.CMD_HART: {
log.debug("收到心跳:" + msg.cmd);
if(!clientMap.hasUser(channel)){
Result res = Result.error(403,"No permission");
String resContent = JSONObject.toJSONString(res);
MyMessage message = new MyMessage(CmdConstant.CMD_HART,resContent.length(),resContent.getBytes());
channel.writeAndFlush(message);
return;
}
deviceApiService.heartbeat(channel,content);
break;
}
case CmdConstant.CMD_UPRECORD: {
log.debug("收到上传记录:" + msg.cmd);
if(!clientMap.hasUser(channel)){
Result res = Result.error(403,"No permission");
String resContent = JSONObject.toJSONString(res);
MyMessage message = new MyMessage(CmdConstant.CMD_UPRECORD,resContent.length(),resContent.getBytes());
channel.writeAndFlush(message);
return;
}
deviceApiService.saveRecord(channel,content);
break;
}
case CmdConstant.CMD_EXTRACT: {
log.debug("提取失败log" + msg.cmd);
if(!clientMap.hasUser(channel)){
Result res = Result.error(403,"No permission");
String resContent = JSONObject.toJSONString(res);
MyMessage message = new MyMessage(CmdConstant.CMD_EXTRACT,resContent.length(),resContent.getBytes());
channel.writeAndFlush(message);
return;
}
deviceApiService.extract(channel,content);
break;
}
case CmdConstant.CMD_CONFIG: {
log.debug("配置成功:" + msg.cmd);
break;
}
case CmdConstant.CMD_CHANGE: {
log.debug("人员变更成功:" + msg.cmd);
break;
}
case CmdConstant.CMD_OPENDOOR: {
log.debug("远程开门:" + msg.cmd);
break;
}
case CmdConstant.CMD_RESTART: {
log.debug("重启设备:" + msg.cmd);
break;
}
case CmdConstant.CMD_APPUPDATE: {
log.debug("app升级" + msg.cmd);
break;
}
case CmdConstant.CMD_CLEANDATA: {
log.debug("清除数据:" + msg.cmd);
break;
}
case CmdConstant.CMD_ENABLE: {
log.debug("停用设备:" + msg.cmd);
break;
}
default:
log.debug("unknown cmd type:" + msg.cmd);
break;
}
}
}

View File

@ -0,0 +1,120 @@
package net.shapelight.modules.nettyapi.service.impl;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import net.shapelight.modules.nettyapi.config.ClientMap;
import net.shapelight.modules.nettyapi.config.CmdConstant;
import net.shapelight.modules.nettyapi.config.MyMessage;
import net.shapelight.modules.nettyapi.service.ServerApiService;
import net.shapelight.modules.ten.entity.TenDeviceEntity;
import net.shapelight.modules.ten.service.TenDeviceService;
import net.shapelight.modules.vo.TenAppVerison;
import net.shapelight.modules.vo.TenDeviceConfig;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service("serverApiService")
public class ServerApiServiceImpl implements ServerApiService {
@Autowired
ClientMap clientMap;
@Autowired
private TenDeviceService tenDeviceService;
@Override
public int devConfig(String sn,TenDeviceConfig dc) {
Channel channel = clientMap.getChannelByUserId(sn);
if(channel == null){
return -1;
}
// Map<String,Object> data = new HashMap<>();
// data.put("data",data);
String content = JSONObject.toJSONString(dc);
MyMessage message = new MyMessage(CmdConstant.CMD_CONFIG,content.length(),content.getBytes());
channel.writeAndFlush(message);
return 0;
}
@Override
public int openDoor(String sn,Long personId) {
Channel channel = clientMap.getChannelByUserId(sn);
if(channel == null){
return -1;
}
Map<String,Object> data = new HashMap<>();
data.put("dev_id",sn);
data.put("uid",personId);
String content = JSONObject.toJSONString(data);
MyMessage message = new MyMessage(CmdConstant.CMD_OPENDOOR,content.length(),content.getBytes());
channel.writeAndFlush(message);
return 0;
}
@Override
public int restart(String sn) {
Channel channel = clientMap.getChannelByUserId(sn);
if(channel == null){
return -1;
}
Map<String,Object> data = new HashMap<>();
data.put("dev_id",sn);
String content = JSONObject.toJSONString(data);
MyMessage message = new MyMessage(CmdConstant.CMD_RESTART,content.length(),content.getBytes());
channel.writeAndFlush(message);
return 0;
}
@Override
public int cleanData(String sn) {
Channel channel = clientMap.getChannelByUserId(sn);
if(channel == null){
return -1;
}
Map<String,Object> data = new HashMap<>();
data.put("dev_id",sn);
String content = JSONObject.toJSONString(data);
MyMessage message = new MyMessage(CmdConstant.CMD_CLEANDATA,content.length(),content.getBytes());
channel.writeAndFlush(message);
return 0;
}
@Override
public int enableDevice(String sn) {
Channel channel = clientMap.getChannelByUserId(sn);
if(channel == null){
return -1;
}
Map<String,Object> data = new HashMap<>();
data.put("dev_id",sn);
String content = JSONObject.toJSONString(data);
MyMessage message = new MyMessage(CmdConstant.CMD_ENABLE,content.length(),content.getBytes());
channel.writeAndFlush(message);
return 0;
}
@Override
public int appUpdate(String sn, TenAppVerison appVerison) {
Channel channel = clientMap.getChannelByUserId(sn);
if(channel == null){
return -1;
}
// Map<String,Object> data = new HashMap<>();
// data.put("data",data);
String content = JSONObject.toJSONString(appVerison);
MyMessage message = new MyMessage(CmdConstant.CMD_APPUPDATE,content.length(),content.getBytes());
channel.writeAndFlush(message);
return 0;
}
}

View File

@ -0,0 +1,67 @@
package net.shapelight.modules.nettyapi.utils;
import java.util.HashMap;
import java.util.Map;
/**
* 返回数据
*
*
*/
public class Result extends HashMap<String, Object> {
private static final long serialVersionUID = 1L;
/*
{
"result": 200,
"desc": "Success",
"data":{}
}
*/
public Result() {
put("code", 200);
put("msg", "success");
put("data", new HashMap<>());
}
public static Result error() {
return error(500, "未知异常,请联系管理员");
}
public static Result error(String msg) {
return error(500, msg);
}
public static Result error(int code, String msg) {
Result r = new Result();
r.put("code", code);
r.put("msg", msg);
r.put("data",new HashMap<>());
return r;
}
public static Result ok(String desc) {
Result r = new Result();
r.put("msg", desc);
return r;
}
public static Result ok(Map<String, Object> map) {
Result r = new Result();
r.putAll(map);
return r;
}
public static Result ok() {
return new Result();
}
@Override
public Result put(String key, Object value) {
super.put(key, value);
return this;
}
}

View File

@ -10,6 +10,7 @@ import io.swagger.annotations.ApiOperation;
import net.shapelight.common.utils.Constant;
import net.shapelight.modules.dev.mqtt.CmdProcess;
import net.shapelight.modules.dev.mqtt.EmqHttpApi;
import net.shapelight.modules.nettyapi.service.ServerApiService;
import net.shapelight.modules.sys.controller.AbstractController;
import net.shapelight.modules.sys.entity.SysDeviceAppEntity;
import net.shapelight.modules.sys.entity.SysDeviceEntity;
@ -22,6 +23,8 @@ import net.shapelight.modules.sys.service.SysUserRoleService;
import net.shapelight.modules.ten.entity.TenUserScopeEntity;
import net.shapelight.modules.ten.service.TenCellService;
import net.shapelight.modules.ten.service.TenUserScopeService;
import net.shapelight.modules.vo.TenAppVerison;
import net.shapelight.modules.vo.TenDeviceConfig;
import net.shapelight.modules.vo.TenDeviceParamVo;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.BeanUtils;
@ -58,6 +61,8 @@ public class TenDeviceController extends AbstractController {
private SysDeviceAppService sysDeviceAppService;
@Autowired
private EmqHttpApi emqHttpApi;
@Autowired
private ServerApiService serverApiService;
/**
* 列表
@ -154,6 +159,21 @@ public class TenDeviceController extends AbstractController {
public R cleanPerson(@RequestBody Map<String, Object> deviceSn){
String sn = (String)deviceSn.get("deviceSn");
CmdProcess.publishCleanPerson(sn);
//清除数据
int r = serverApiService.cleanData(sn);
//配置参数
TenDeviceConfig dc = new TenDeviceConfig();
int s = serverApiService.devConfig(sn,dc);
for(int i =0;i<1000;i++){
}
//升级app
TenAppVerison v = new TenAppVerison();
int a = serverApiService.appUpdate(sn,v);
if(r == -1){
return R.error("设备离线");
}
return R.ok();
}

View File

@ -0,0 +1,83 @@
package net.shapelight.modules.ten.controller;
import java.util.Arrays;
import java.util.Map;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import net.shapelight.modules.ten.entity.TenPersonExtractEntity;
import net.shapelight.modules.ten.service.TenPersonExtractService;
import net.shapelight.common.utils.PageUtils;
import net.shapelight.common.utils.R;
/**
*
*
*/
@RestController
@RequestMapping("ten/personextract")
public class TenPersonExtractController {
@Autowired
private TenPersonExtractService tenPersonExtractService;
/**
* 列表
*/
@GetMapping("/list")
@RequiresPermissions("ten:personextract:list")
public R list(@RequestParam Map<String, Object> params){
PageUtils page = tenPersonExtractService.queryPage(params);
return R.ok().put("data", page);
}
/**
* 信息
*/
@GetMapping("/info/{extractId}")
@RequiresPermissions("ten:personextract:info")
public R info(@PathVariable("extractId") Long extractId){
TenPersonExtractEntity tenPersonExtract = tenPersonExtractService.getById(extractId);
return R.ok().put("data", tenPersonExtract);
}
/**
* 保存
*/
@PostMapping("/save")
@RequiresPermissions("ten:personextract:save")
public R save(@RequestBody TenPersonExtractEntity tenPersonExtract){
tenPersonExtractService.save(tenPersonExtract);
return R.ok();
}
/**
* 修改
*/
@PostMapping("/update")
@RequiresPermissions("ten:personextract:update")
public R update(@RequestBody TenPersonExtractEntity tenPersonExtract){
tenPersonExtractService.updateById(tenPersonExtract);
return R.ok();
}
/**
* 删除
*/
@PostMapping("/delete")
@RequiresPermissions("ten:personextract:delete")
public R delete(@RequestBody Long[] extractIds){
tenPersonExtractService.removeByIds(Arrays.asList(extractIds));
return R.ok();
}
}

View File

@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.shapelight.modules.ten.entity.TenPersonEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import net.shapelight.modules.vo.TenPersonIdUpdateAllVo;
import net.shapelight.modules.vo.TenPersonIdUpdateVo;
import net.shapelight.modules.vo.TenPersonVo;
import org.apache.ibatis.annotations.Mapper;
@ -52,6 +53,11 @@ public interface TenPersonDao {
@Param("roomId")Long roomId
);
List<TenPersonIdUpdateAllVo> findAllPersonIdUpdateAll(@Param("cellId")Long cellId,
@Param("buildId")Long buildId,
@Param("roomId")Long roomId
);
List<TenPersonVo> findByLastUpdatePerson(@Param("cellId")Long cellId,
@Param("buildId")Long buildId,
@Param("roomId")Long roomId,

View File

@ -0,0 +1,14 @@
package net.shapelight.modules.ten.dao;
import net.shapelight.modules.ten.entity.TenPersonExtractEntity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
*
*
*/
@Mapper
public interface TenPersonExtractDao extends BaseMapper<TenPersonExtractEntity> {
}

View File

@ -0,0 +1,56 @@
package net.shapelight.modules.ten.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
/**
*
*
*/
@Data
@TableName("ten_person_extract")
public class TenPersonExtractEntity implements Serializable {
private static final long serialVersionUID = 1L;
/**
* id
*/
@TableId
private Long extractId;
/**
* 提取时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date extractTime;
/**
* ID
*/
private Long personId;
/**
* 类型业主家属物业访客白名单黑名单
*/
private Integer personType;
/**
* id
*/
private String deviceSn;
/**
* 0:成功 1:解析人脸图片失败,2:算法调用失败,3:人脸检测失败,4:人脸质量未通过,5:人脸图片下载失败,6:没有图片
*/
private Integer state;
/**
* 小区ID
*/
private Long cellId;
/**
* 运营商ID
*/
private Long tenantId;
}

View File

@ -0,0 +1,17 @@
package net.shapelight.modules.ten.service;
import com.baomidou.mybatisplus.extension.service.IService;
import net.shapelight.common.utils.PageUtils;
import net.shapelight.modules.ten.entity.TenPersonExtractEntity;
import java.util.Map;
/**
*
*
*/
public interface TenPersonExtractService extends IService<TenPersonExtractEntity> {
PageUtils queryPage(Map<String, Object> params);
}

View File

@ -7,6 +7,7 @@ import net.shapelight.modules.ten.entity.TenBuildEntity;
import net.shapelight.modules.ten.entity.TenCellEntity;
import net.shapelight.modules.ten.entity.TenPersonEntity;
import net.shapelight.modules.ten.entity.TenRoomEntity;
import net.shapelight.modules.vo.TenPersonIdUpdateAllVo;
import net.shapelight.modules.vo.TenPersonIdUpdateVo;
import net.shapelight.modules.vo.TenPersonVo;
import org.apache.ibatis.annotations.Param;
@ -70,6 +71,8 @@ public interface TenPersonService {
Long roomId
);
List<TenPersonIdUpdateAllVo> findAllPersonIdUpdateAll(Long cellId, Long buildId, Long roomId);
List<TenPersonVo> findAllByCellId(Long cellId);

View File

@ -5,6 +5,7 @@ import net.shapelight.common.utils.Constant;
import net.shapelight.common.utils.RedisUtils;
import net.shapelight.modules.dev.mqtt.CmdProcess;
import net.shapelight.modules.dev.mqtt.EmqHttpApi;
import net.shapelight.modules.nettyapi.service.DeviceApiService;
import net.shapelight.modules.ten.entity.*;
import net.shapelight.modules.ten.service.*;
import net.shapelight.modules.vo.TenDeviceVo;
@ -54,6 +55,8 @@ public class TenDeviceServiceImpl extends ServiceImpl<TenDeviceDao, TenDeviceEnt
private EmqHttpApi emqHttpApi;
@Autowired
private TenDeviceAlertService tenDeviceAlertService;
@Autowired
private DeviceApiService deviceApiService;
@Override
public PageUtils queryPage(Map<String, Object> params) {
@ -100,12 +103,22 @@ public class TenDeviceServiceImpl extends ServiceImpl<TenDeviceDao, TenDeviceEnt
}
dev.setScope(scope.toString());
boolean onlineFlag = emqHttpApi.getClient(dev.getSn());
if(onlineFlag){
// boolean onlineFlag = emqHttpApi.getClient(dev.getSn());
// if(onlineFlag){
// dev.setStatus(1);
// }else{
// dev.setStatus(0);
// }
Boolean flag = deviceApiService.isOnline(dev.getSn());
if (flag) {
dev.setStatus(1);
}else{
dev.setStatus(0);
}
}
return new PageUtils(page);
}

View File

@ -0,0 +1,29 @@
package net.shapelight.modules.ten.service.impl;
import org.springframework.stereotype.Service;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.shapelight.common.utils.PageUtils;
import net.shapelight.common.utils.Query;
import net.shapelight.modules.ten.dao.TenPersonExtractDao;
import net.shapelight.modules.ten.entity.TenPersonExtractEntity;
import net.shapelight.modules.ten.service.TenPersonExtractService;
@Service("tenPersonExtractService")
public class TenPersonExtractServiceImpl extends ServiceImpl<TenPersonExtractDao, TenPersonExtractEntity> implements TenPersonExtractService {
@Override
public PageUtils queryPage(Map<String, Object> params) {
IPage<TenPersonExtractEntity> page = this.page(
new Query<TenPersonExtractEntity>().getPage(params),
new QueryWrapper<TenPersonExtractEntity>()
);
return new PageUtils(page);
}
}

View File

@ -21,6 +21,7 @@ import net.shapelight.modules.excel.model.PersonModel;
import net.shapelight.modules.ten.entity.*;
import net.shapelight.modules.ten.service.*;
import net.shapelight.modules.vo.TenDeviceVo;
import net.shapelight.modules.vo.TenPersonIdUpdateAllVo;
import net.shapelight.modules.vo.TenPersonIdUpdateVo;
import net.shapelight.modules.vo.TenPersonVo;
import org.apache.commons.codec.digest.DigestUtils;
@ -1575,6 +1576,14 @@ public class TenPersonServiceImpl implements TenPersonService {
}
@Override
public List<TenPersonIdUpdateAllVo> findAllPersonIdUpdateAll(Long cellId, Long buildId, Long roomId) {
//升序排列
List<TenPersonIdUpdateAllVo> list = tenPersonDao.findAllPersonIdUpdateAll(cellId, buildId, roomId);
return list;
}

View File

@ -0,0 +1,33 @@
package net.shapelight.modules.vo;
import lombok.Data;
@Data
public class TenAppVerison {
/*
{
"dev_id":"3cde32ef123"
"app_name":"GateBox",
"latest_version":10,
"apk_url":"http://ip:port/upgrade/app/GateBox-1.0.2.apk"
apk_file_size:152001212
"desc":"版本描述"
}
*/
private String dev_id;
private String app_name;
private Integer latest_version;
private String apk_url;
private Integer apk_file_size;
private String desc;
public TenAppVerison(){
this.dev_id = "";
this.app_name = "";
this.latest_version = 0;
this.apk_url = "";
this.apk_file_size = 0;
this.desc = "";
}
}

View File

@ -0,0 +1,53 @@
package net.shapelight.modules.vo;
import lombok.Data;
@Data
public class TenDeviceConfig {
/*
{
"work_mode":0,
"recognize_interval":3,
"relay_suck_time":5,
"support_liveness":true,
"liveness_score":60,
"recognize_score":65,
"recognize_distance":2,
"alert_temp_threshold":37.3,
"upload_face_pic":true,
"upload_pic_mode":0,
"upload_http_url":"http://upload.face.com/face/pic/upload",
"support_stranger":false
}
*/
private Integer work_mode;
private Integer recognize_interval;
private Integer relay_suck_time;
private Boolean support_liveness;
private Integer liveness_score;
private Integer recognize_score;
private Integer recognize_distance;
private Float alert_temp_threshold;
private Boolean upload_face_pic;
private Integer upload_pic_mode;
private String upload_http_url;
private Boolean support_stranger;
public TenDeviceConfig(){
this.work_mode = 0;
this.recognize_interval = 3;
this.relay_suck_time = 5;
this.support_liveness = true;
this.liveness_score = 60;
this.recognize_score = 65;
this.recognize_distance = 1;
this.alert_temp_threshold = 37.3f;
this.upload_face_pic = true;
this.upload_pic_mode = 0;
this.upload_http_url = "";
this.support_stranger = true;
}
}

View File

@ -0,0 +1,26 @@
package net.shapelight.modules.vo;
import com.alibaba.fastjson.annotation.JSONField;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class TenPersonIdUpdateAllVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty("人员ID")
private Long uid;
/**
* 更新时间
*/
@ApiModelProperty("更新时间")
// @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
// @JSONField(format="yyyy-MM-dd HH:mm:ss")
private Date last_update_stamp;
}

View File

@ -0,0 +1,30 @@
package net.shapelight.modules.vo;
import lombok.Data;
@Data
public class TenUserVo {
/*
"uid": 10009,
"last_update_stamp":156023023000,
"user_type":0,
"user_name":"张三"
"face_pic_base64":"32423be30xefw",
"face_pic_download_url":"http://example.com/download/face/234234.jpg",
"active_start_time":1559090090,
"active_end_time":156009090,
"card_id":"4ef33423"
*/
private Long uid;
private Long last_update_stamp;
private Integer user_type;
private String user_name;
private String face_pic_base64;
private String face_pic_download_url;
private Integer active_start_time;
private Integer active_end_time;
private String card_id="";
}

View File

@ -3,7 +3,7 @@ spring:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.50.232:3306/cell_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
url: jdbc:mysql://192.168.50.232:3306/cell_db_tcp?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
username: user
password: user@server001
initial-size: 10

View File

@ -100,7 +100,10 @@ global:
appid: wxf59991f23f1f5500
secret: 30b523b2bdd7b0739b7f06e9dc1519f8
tcp_server:
port: 8777
port: 8086
app:
key: 9894480ac52e4
secret: Mjk0ODUzNzA2Mzk3NzEzMjU2OTIwOTk1NzUzMDI5MTQwNDI
shapelight:
cluster: false #集群配置 true集群环境 false单机环境还需打开pom.xml里的spring-session-data-redis注释

View File

@ -92,6 +92,11 @@
<result column="delete_flag" jdbcType="TINYINT" property="deleteFlag"/>
</resultMap>
<resultMap id="idupdateMap" type="net.shapelight.modules.vo.TenPersonIdUpdateAllVo">
<result column="person_id" jdbcType="BIGINT" property="uid"/>
<result column="last_update_time" jdbcType="TIMESTAMP" property="last_update_stamp"/>
</resultMap>
<insert id="insert" parameterType="net.shapelight.modules.ten.entity.TenPersonEntity">
insert into ten_person_${cellId}
@ -664,6 +669,21 @@
</select>
<select id="findAllPersonIdUpdateAll" resultMap="idupdateMap">
select person_id,last_update_time from ten_person_${cellId}
where 1=1
<if test="cellId != null and cellId!=''">
and cell_id = #{cellId}
</if>
<if test="buildId != null and buildId!=''">
and build_id = #{buildId}
</if>
<if test="roomId != null and roomId!=''">
and room_id = #{roomId}
</if>
</select>
<select id="findByLastUpdatePerson" resultMap="updateMap">
select * from ten_person_${cellId}
where 1=1

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.shapelight.modules.ten.dao.TenPersonExtractDao">
<!-- 可根据自己的需求,是否要使用 -->
<!--<resultMap type="net.shapelight.modules.ten.entity.TenPersonExtractEntity" id="tenPersonExtractMap">-->
<!--<result property="extractId" column="extract_id"/>-->
<!--<result property="extractTime" column="extract_time"/>-->
<!--<result property="personId" column="person_id"/>-->
<!--<result property="personType" column="person_type"/>-->
<!--<result property="deviceSn" column="deviceSn"/>-->
<!--<result property="state" column="state"/>-->
<!--<result property="cellId" column="cell_id"/>-->
<!--<result property="tenantId" column="tenant_id"/>-->
<!--</resultMap>-->
</mapper>