第一次提交
This commit is contained in:
@ -0,0 +1,69 @@
|
||||
package com.fastbee.flowdev.codec;
|
||||
|
||||
import com.fastbee.common.core.mq.message.DeviceData;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.utils.gateway.CRC8Utils;
|
||||
import com.fastbee.flowdev.model.FlowDev;
|
||||
import com.fastbee.protocol.WModelManager;
|
||||
import com.fastbee.protocol.base.model.ActiveModel;
|
||||
import com.fastbee.protocol.util.ArrayMap;
|
||||
import com.fastbee.protocol.util.ExplainUtils;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* @author gsb
|
||||
* @date 2023/5/17 16:37
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@NoArgsConstructor
|
||||
public class FlowDevDecoder {
|
||||
|
||||
@Resource
|
||||
private WModelManager modelManager;
|
||||
private ArrayMap<ActiveModel> headerSchemaMap;
|
||||
|
||||
public FlowDevDecoder(String...basePackages){
|
||||
this.modelManager = new WModelManager(basePackages);
|
||||
this.headerSchemaMap = this.modelManager.getActiveMap(FlowDev.class);
|
||||
}
|
||||
|
||||
public FlowDev decode(DeviceData deviceData, ExplainUtils explain){
|
||||
this.build();
|
||||
ByteBuf in = deviceData.getBuf();
|
||||
verify(in);
|
||||
ActiveModel<FlowDev> activeModel = headerSchemaMap.get(0);
|
||||
FlowDev flowDev = new FlowDev();
|
||||
activeModel.mergeFrom(in,flowDev,explain);
|
||||
log.info("=>流量计数据解析:[{}]",flowDev);
|
||||
return flowDev;
|
||||
}
|
||||
|
||||
/*CRC校验*/
|
||||
private void verify(ByteBuf in){
|
||||
ByteBuf copy = in.duplicate();
|
||||
byte[] source = new byte[in.writerIndex()];
|
||||
copy.readBytes(source);
|
||||
//取倒数第二位校验CRC8
|
||||
byte checkBytes = source[source.length -2];
|
||||
byte[] sourceCheck = ArrayUtils.subarray(source,3,source.length -2);
|
||||
byte crc = CRC8Utils.calcCrc8_E5(sourceCheck);
|
||||
if (crc != checkBytes){
|
||||
log.warn("=>CRC校验异常,报文={}",ByteBufUtil.hexDump(source));
|
||||
throw new ServiceException("CRC校验异常");
|
||||
}
|
||||
}
|
||||
|
||||
private void build(){
|
||||
if (this.headerSchemaMap == null) {
|
||||
this.headerSchemaMap = this.modelManager.getActiveMap(FlowDev.class);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
package com.fastbee.flowdev.codec;
|
||||
|
||||
import com.fastbee.flowdev.model.FlowDev;
|
||||
import com.fastbee.protocol.WModelManager;
|
||||
import com.fastbee.protocol.base.model.ActiveModel;
|
||||
import com.fastbee.protocol.util.ArrayMap;
|
||||
import com.fastbee.protocol.util.ExplainUtils;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufAllocator;
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* @author gsb
|
||||
* @date 2023/5/17 16:45
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@NoArgsConstructor
|
||||
public class FlowDevEncoder {
|
||||
|
||||
private static final ByteBufAllocator ALLOC = PooledByteBufAllocator.DEFAULT;
|
||||
|
||||
@Resource
|
||||
private WModelManager modelManager;
|
||||
private ArrayMap<ActiveModel> headerSchemaMap;
|
||||
|
||||
public FlowDevEncoder(String...basePackages){
|
||||
this.modelManager = new WModelManager(basePackages);
|
||||
this.headerSchemaMap = this.modelManager.getActiveMap(FlowDev.class);
|
||||
}
|
||||
|
||||
public ByteBuf encode(FlowDev message, ExplainUtils explain){
|
||||
this.build();
|
||||
ByteBuf buf = ALLOC.buffer();
|
||||
ActiveModel activeModel = headerSchemaMap.get(1);
|
||||
activeModel.writeTo(buf,message,explain);
|
||||
return buf;
|
||||
}
|
||||
|
||||
private void build() {
|
||||
if (this.headerSchemaMap == null) {
|
||||
this.headerSchemaMap = this.modelManager.getActiveMap(FlowDev.class);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
package com.fastbee.flowdev.codec;
|
||||
|
||||
import com.fastbee.common.annotation.SysProtocol;
|
||||
import com.fastbee.common.constant.FastBeeConstant;
|
||||
import com.fastbee.common.core.mq.DeviceReport;
|
||||
import com.fastbee.common.core.mq.MQSendMessageBo;
|
||||
import com.fastbee.common.core.mq.message.DeviceData;
|
||||
import com.fastbee.common.core.mq.message.FunctionCallBackBo;
|
||||
import com.fastbee.common.core.thingsModel.ThingsModelSimpleItem;
|
||||
import com.fastbee.common.core.thingsModel.ThingsModelValuesInput;
|
||||
import com.fastbee.common.exception.ServiceException;
|
||||
import com.fastbee.common.utils.BeanMapUtilByReflect;
|
||||
import com.fastbee.common.utils.DateUtils;
|
||||
import com.fastbee.common.utils.StringUtils;
|
||||
import com.fastbee.common.utils.gateway.CRC8Utils;
|
||||
import com.fastbee.flowdev.model.FlowDev;
|
||||
import com.fastbee.protocol.base.protocol.IProtocol;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.util.ReferenceCountUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author gsb
|
||||
* @date 2023/5/17 16:56
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@SysProtocol(name = "流量计解析协议",protocolCode = FastBeeConstant.PROTOCOL.FlowMeter,description = "流量计解析协议")
|
||||
public class FlowDevProtocol implements IProtocol {
|
||||
|
||||
@Resource
|
||||
private FlowDevDecoder devDecoder;
|
||||
@Resource
|
||||
private FlowDevEncoder devEncoder;
|
||||
|
||||
|
||||
@Override
|
||||
public DeviceReport decode(DeviceData data, String clientId) {
|
||||
try {
|
||||
DeviceReport report = new DeviceReport();
|
||||
FlowDev flowDev = devDecoder.decode(data,null);
|
||||
this.handlerData(flowDev);
|
||||
List<ThingsModelSimpleItem> items = BeanMapUtilByReflect.beanToItem(flowDev);
|
||||
report.setThingsModelSimpleItem(items);
|
||||
report.setClientId(clientId);
|
||||
report.setMessageId(flowDev.getStart()+"");
|
||||
report.setIsPackage(true);
|
||||
return report;
|
||||
}catch (Exception e){
|
||||
log.error("=>数据解析出错",e);
|
||||
throw new ServiceException("数据解析出错"+e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FunctionCallBackBo encode(MQSendMessageBo message) {
|
||||
FunctionCallBackBo callBack = new FunctionCallBackBo();
|
||||
FlowDev flowDev = new FlowDev();
|
||||
flowDev.setImei(message.getSerialNumber());
|
||||
flowDev.setDire(0x33);
|
||||
flowDev.setLength(0x08);
|
||||
ByteBuf buf = devEncoder.encode(flowDev, null);
|
||||
byte[] source = ByteBufUtil.getBytes(buf, 3, buf.writerIndex() - 5);
|
||||
byte[] result = new byte[ByteBufUtil.getBytes(buf).length];
|
||||
byte b = CRC8Utils.calcCrc8_E5(source);
|
||||
byte[] crc = new byte[]{b,0x16};
|
||||
System.arraycopy(source,0,result,0,source.length);
|
||||
System.arraycopy(crc,0,result,result.length -2,2);
|
||||
System.out.println(ByteBufUtil.hexDump(buf));
|
||||
//删除缓存,防止netty内存溢出
|
||||
ReferenceCountUtil.release(buf);
|
||||
callBack.setSources(ByteBufUtil.hexDump(buf));
|
||||
callBack.setMessage(result);
|
||||
return callBack;
|
||||
}
|
||||
|
||||
private FlowDev handlerData(FlowDev flowDev){
|
||||
//时间处理
|
||||
String ts = flowDev.getTs();
|
||||
if (StringUtils.isNotEmpty(ts)){
|
||||
Date date = DateUtils.dateTime(DateUtils.SS_MM_HH_DD_HH_YY, ts);
|
||||
String s = DateUtils.dateTimeYY(date);
|
||||
flowDev.setTs(s);
|
||||
}
|
||||
String sum = flowDev.getSum();
|
||||
if (StringUtils.isNotEmpty(sum)){
|
||||
String replace = sum.replace("0", "");
|
||||
flowDev.setSum(replace.equals("")? "0":replace);
|
||||
}
|
||||
String instant = flowDev.getInstant();
|
||||
if (StringUtils.isNotEmpty(instant)){
|
||||
String replace = instant.replace("0", "");
|
||||
flowDev.setInstant(replace.equals("")? "0":replace);
|
||||
int val = Integer.parseInt(flowDev.getInstant())/1000;
|
||||
flowDev.setInstant(val+"");
|
||||
}
|
||||
return flowDev;
|
||||
}
|
||||
}
|
@ -0,0 +1,162 @@
|
||||
package com.fastbee.flowdev.model;
|
||||
|
||||
import com.fastbee.common.core.protocol.Message;
|
||||
import com.fastbee.protocol.base.annotation.Column;
|
||||
import com.fastbee.protocol.util.ToStringBuilder;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author gsb
|
||||
* @date 2023/5/17 15:02
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
public class FlowDev extends Message {
|
||||
|
||||
@Column(length = 1,version = {0,1},desc = "起始地址")
|
||||
protected int start = 0x68;
|
||||
@Column(length = 1,version = {0,1},desc = "长度")
|
||||
protected int length;
|
||||
@Column(length = 1,version = {0,1} ,desc = "起始位")
|
||||
protected int start1 =0x68;
|
||||
@Column(length = 1,version = {0,1},desc = "方向")
|
||||
protected int dire;
|
||||
@Column(length = 5,version = {0,1},desc = "设备编号")
|
||||
protected String imei;
|
||||
@Column(length = 1,version = {0,1},desc = "功能码")
|
||||
protected String code = "C1";
|
||||
@Column(length = 5,version = 0,desc = "瞬时流量")
|
||||
protected String instant;
|
||||
@Column(length = 5,version = 0,desc = "累积流量")
|
||||
protected String sum;
|
||||
@Column(length = 4,version = 0,desc = "不解析值")
|
||||
protected int no;
|
||||
@Column(length = 6,version = 0,desc = "数据时间")
|
||||
protected String ts;
|
||||
@Column(length = 1,version = {1},desc = "无意义值")
|
||||
protected int oo = 0;
|
||||
@Column(length = 1,version = {0,1},desc = "CRC")
|
||||
protected int crc;
|
||||
@Column(length = 1,version = {0,1},desc = "结束地址")
|
||||
protected int end = 0x16;
|
||||
|
||||
public int getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(int start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
|
||||
public void setLength(int length) {
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public int getStart1() {
|
||||
return start1;
|
||||
}
|
||||
|
||||
public void setStart1(int start1) {
|
||||
this.start1 = start1;
|
||||
}
|
||||
|
||||
public int getDire() {
|
||||
return dire;
|
||||
}
|
||||
|
||||
public void setDire(int dire) {
|
||||
this.dire = dire;
|
||||
}
|
||||
|
||||
public String getImei() {
|
||||
return imei;
|
||||
}
|
||||
|
||||
public void setImei(String imei) {
|
||||
this.imei = imei;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(String code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getInstant() {
|
||||
return instant;
|
||||
}
|
||||
|
||||
public void setInstant(String instant) {
|
||||
this.instant = instant;
|
||||
}
|
||||
|
||||
public String getSum() {
|
||||
return sum;
|
||||
}
|
||||
|
||||
public void setSum(String sum) {
|
||||
this.sum = sum;
|
||||
}
|
||||
|
||||
public int getNo() {
|
||||
return no;
|
||||
}
|
||||
|
||||
public void setNo(int no) {
|
||||
this.no = no;
|
||||
}
|
||||
|
||||
public String getTs() {
|
||||
return ts;
|
||||
}
|
||||
|
||||
public void setTs(String ts) {
|
||||
this.ts = ts;
|
||||
}
|
||||
|
||||
public int getCrc() {
|
||||
return crc;
|
||||
}
|
||||
|
||||
public void setCrc(int crc) {
|
||||
this.crc = crc;
|
||||
}
|
||||
|
||||
public int getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public void setEnd(int end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public int getOo() {
|
||||
return oo;
|
||||
}
|
||||
|
||||
public void setOo(int oo) {
|
||||
this.oo = oo;
|
||||
}
|
||||
|
||||
protected StringBuilder toStringHead() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
sb.append(";[长度]: ").append(length);
|
||||
sb.append(";[方向]: ").append(dire);
|
||||
sb.append(";[设备编号]: ").append(imei);
|
||||
sb.append(";[功能码]: ").append(code);
|
||||
sb.append(";[瞬时流量]: ").append(instant);
|
||||
sb.append(";[累积流量]: ").append(sum);
|
||||
sb.append(";[数据时间]: ").append(ts);
|
||||
return sb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return ToStringBuilder.toString(toStringHead(), this, true);
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package com.fastbee.flowdev.model;
|
||||
|
||||
import com.fastbee.base.core.annotation.Node;
|
||||
import com.fastbee.base.core.annotation.PakMapping;
|
||||
import com.fastbee.base.session.Session;
|
||||
import com.fastbee.common.core.mq.DeviceReport;
|
||||
import com.fastbee.common.core.protocol.Message;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author gsb
|
||||
* @date 2023/5/19 14:09
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
@Node
|
||||
public class FlowEndPoint {
|
||||
|
||||
@PakMapping(types = 0x68)
|
||||
public Message register(DeviceReport message, Session session){
|
||||
//检测设备是否注册,未注册,进行注册
|
||||
if (!session.isRegistered()){
|
||||
// 注册设备
|
||||
session.register(message);
|
||||
}
|
||||
return message;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.fastbee.flowdev.test;
|
||||
|
||||
import com.fastbee.common.core.mq.message.DeviceData;
|
||||
import com.fastbee.flowdev.codec.FlowDevDecoder;
|
||||
import com.fastbee.flowdev.codec.FlowDevEncoder;
|
||||
import com.fastbee.flowdev.model.FlowDev;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
/**
|
||||
* @author bill
|
||||
*/
|
||||
public class FlowDevCodeTest {
|
||||
|
||||
private static FlowDevDecoder decoder = new FlowDevDecoder("com.fastbee");
|
||||
private static FlowDevEncoder encoder = new FlowDevEncoder("com.fastbee");
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
String flowData = "681B68B33701120008C100000000000000000000022050004341231811215716";
|
||||
ByteBuf in = Unpooled.wrappedBuffer(ByteBufUtil.decodeHexDump(flowData));
|
||||
DeviceData data = DeviceData.builder()
|
||||
.buf(in).build();
|
||||
FlowDev flowDev = decoder.decode(data, null);
|
||||
System.out.println(flowDev);
|
||||
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user