Skip to content

Commit

Permalink
feat(AttachmentServer): 苏标附件服务器
Browse files Browse the repository at this point in the history
  • Loading branch information
hylexus committed Jan 14, 2024
1 parent 24fadad commit ed608e1
Show file tree
Hide file tree
Showing 37 changed files with 1,214 additions and 12 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
## 2.1.4-beta1(2024-01-14)

### ⭐ New Features

- 支持苏标附件服务器

## 2.1.3(2023-10-03)

### 🐞 Bug Fixes

`BuiltinCommonHandler.processTerminalHeartBeatMsg` 应该回复 `0x8001` 消息,而不是不回复消息

## 2.1.2(2023-09-01)

### ⭐ New Features

- [#78](https://github.com/hylexus/jt-framework/issues/78)

## 2.1.1

### ⭐ New Features
Expand Down
4 changes: 2 additions & 2 deletions build-script/script/common-maven-config.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,6 @@ def isSnapshot() {
}

def static publishToMavenCentralRepo() {
// gradle clean build publish -Dpublish2MavenCentralRepo=true
System.getProperty("publish2MavenCentralRepo") ?: "false" == "true"
// ./gradlew clean build publish -DpublishToMavenCentralRepo=true
System.getProperty("publishToMavenCentralRepo") ?: "false" == "true"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package io.github.hylexus.jt.demos.jt808.handler;

import io.github.hylexus.jt.jt808.Jt808ProtocolVersion;
import io.github.hylexus.jt.jt808.spec.Jt808CommandSender;
import io.github.hylexus.jt.jt808.spec.Jt808MsgBuilder;
import io.github.hylexus.jt.jt808.spec.Jt808Request;
import io.github.hylexus.jt.jt808.spec.builtin.msg.req.BuiltinMsg1210Alias;
import io.github.hylexus.jt.jt808.spec.builtin.msg.req.BuiltinMsg1211Alias;
import io.github.hylexus.jt.jt808.spec.builtin.msg.req.BuiltinMsg1212Alias;
import io.github.hylexus.jt.jt808.spec.builtin.msg.req.BuiltinMsg30316364Alias;
import io.github.hylexus.jt.jt808.spec.builtin.msg.resp.BuiltinMsg9208Alias;
import io.github.hylexus.jt.jt808.spec.builtin.msg.resp.BuiltinMsg9212Alias;
import io.github.hylexus.jt.jt808.spec.builtin.msg.resp.BuiltinServerCommonReplyMsg;
import io.github.hylexus.jt.jt808.spec.session.Jt808Session;
import io.github.hylexus.jt.jt808.spec.session.Jt808SessionManager;
import io.github.hylexus.jt.jt808.support.annotation.handler.Jt808RequestHandler;
import io.github.hylexus.jt.jt808.support.annotation.handler.Jt808RequestHandlerMapping;
import io.netty.buffer.ByteBuf;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@Component
@Jt808RequestHandler
public class AttachmentFileHandler {
private final Jt808SessionManager sessionManager;

public AttachmentFileHandler(Jt808SessionManager sessionManager) {
this.sessionManager = sessionManager;
}

@Jt808RequestHandlerMapping(msgType = 0x1210, versions = Jt808ProtocolVersion.AUTO_DETECTION)
public BuiltinServerCommonReplyMsg processMsg0x1210(Jt808Request request, BuiltinMsg1210Alias body) {
log.info("0x1210 ==> {}", body);
return BuiltinServerCommonReplyMsg.success(request.header().msgId(), request.flowId());
}

@Jt808RequestHandlerMapping(msgType = 0x1211, versions = Jt808ProtocolVersion.AUTO_DETECTION)
public BuiltinServerCommonReplyMsg processMsg0x1211(Jt808Request request, BuiltinMsg1211Alias body) {
log.info("0x1211 ==> {}", body);
return BuiltinServerCommonReplyMsg.success(request.header().msgId(), request.flowId());
}

@Jt808RequestHandlerMapping(msgType = 0x1212, versions = Jt808ProtocolVersion.AUTO_DETECTION)
public BuiltinServerCommonReplyMsg processMsg0x1212(Jt808Request request, BuiltinMsg1212Alias reqBody) {
log.info("0x1211 ==> {}", reqBody);
// final BuiltinMsg9212Alias respBody = new BuiltinMsg9212Alias();
// respBody.setFileNameLength(reqBody.getFileNameLength());
// respBody.setFileName(reqBody.getFileName());
// respBody.setFileType(reqBody.getFileType());
// respBody.setUploadResult((byte) 0x00);
// respBody.setPackageCountToReTransmit((short) 0);

// this.sendMsg9212(request.terminalId(), respBody);
return BuiltinServerCommonReplyMsg.success(request.header().msgId(), request.flowId());
}

@Jt808RequestHandlerMapping(msgType = 0x30316364)
public void processMsg30316364(Jt808Request request, BuiltinMsg30316364Alias body, @Nullable Jt808Session session) {
log.info("0x30316364 ==> session:{}, msg:{}", session, body);
}

public void sendMsg9212(String terminalId, BuiltinMsg9212Alias body) {
final Jt808Session session = this.sessionManager.findByTerminalId(terminalId).orElseThrow();

final ByteBuf byteBuf = Jt808MsgBuilder.newEntityBuilder(session)
.version(session.protocolVersion())
.terminalId(terminalId)
.body(body)
.build();
session.sendMsgToClient(byteBuf);
}
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
projectGroup=io.github.hylexus.jt
projectVersion=2.2.0-beta2
projectVersion=2.1.4-beta1
# scm
projectScmUrl=https://github.com/hylexus/jt-framework
projectScmConnection=scm:git:git@github.com:hylexus/jt-framework.git
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package io.github.hylexus.jt.jt808.boot.config.configuration;

import io.github.hylexus.jt.core.OrderedComponent;
import io.github.hylexus.jt.jt808.boot.props.Jt808ServerProps;
import io.github.hylexus.jt.jt808.boot.props.attachment.AttachmentServerProps;
import io.github.hylexus.jt.jt808.boot.props.msg.processor.MsgProcessorExecutorGroupProps;
import io.github.hylexus.jt.jt808.spec.session.Jt808FlowIdGeneratorFactory;
import io.github.hylexus.jt.jt808.spec.session.Jt808SessionEventListener;
import io.github.hylexus.jt.jt808.support.codec.Jt808MsgDecoder;
import io.github.hylexus.jt.jt808.support.codec.Jt808RequestRouteExceptionHandler;
import io.github.hylexus.jt.jt808.support.dispatcher.Jt808DispatcherHandler;
import io.github.hylexus.jt.jt808.support.extension.attachment.*;
import io.github.hylexus.jt.jt808.support.extension.attachment.impl.DefaultAttachmentJt808SessionManager;
import io.github.hylexus.jt.jt808.support.extension.attachment.impl.SimpleAttachmentJt808RequestProcessor;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.EventExecutorGroup;
import io.netty.util.concurrent.RejectedExecutionHandlers;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;

import java.util.Comparator;

import static io.github.hylexus.jt.jt808.JtProtocolConstant.BEAN_NAME_JT808_ATTACHMENT_MSG_PROCESSOR_EVENT_EXECUTOR_GROUP;

@Slf4j
@ConditionalOnProperty(prefix = "jt808.attachment-server", name = "enabled", havingValue = "true", matchIfMissing = false)
public class Jt808AttachmentServerAutoConfiguration {
private final Jt808ServerProps instructionServerProps;

public Jt808AttachmentServerAutoConfiguration(Jt808ServerProps instructionServerProps) {
this.instructionServerProps = instructionServerProps;
}

@Bean
@ConditionalOnMissingBean
public AttachmentJt808SessionManager attachmentJt808SessionManager(ObjectProvider<Jt808SessionEventListener> listeners, Jt808FlowIdGeneratorFactory factory) {
final AttachmentJt808SessionManager manager = new DefaultAttachmentJt808SessionManager(factory);
listeners.stream().sorted(Comparator.comparing(OrderedComponent::getOrder)).forEach(manager::addListener);
return manager;
}

@Bean
@ConditionalOnMissingBean(SimpleAttachmentJt808RequestProcessor.class)
public SimpleAttachmentJt808RequestProcessor simpleAttachmentJt808RequestProcessor(
Jt808MsgDecoder jt808MsgDecoder,
AttachmentJt808SessionManager sessionManager,
Jt808RequestRouteExceptionHandler routeExceptionHandler,
Jt808DispatcherHandler dispatcherHandler) {
return new SimpleAttachmentJt808RequestProcessor(jt808MsgDecoder, sessionManager, routeExceptionHandler, dispatcherHandler);
}

@Bean(name = BEAN_NAME_JT808_ATTACHMENT_MSG_PROCESSOR_EVENT_EXECUTOR_GROUP)
@ConditionalOnMissingBean(name = BEAN_NAME_JT808_ATTACHMENT_MSG_PROCESSOR_EVENT_EXECUTOR_GROUP)
public EventExecutorGroup eventExecutorGroup() {

final MsgProcessorExecutorGroupProps poolProps = instructionServerProps.getAttachmentServer().getMsgProcessor().getExecutorGroup();
final DefaultThreadFactory threadFactory = new DefaultThreadFactory(poolProps.getPoolName());

log.info("MsgProcessorConfig = {}", poolProps);
return new DefaultEventExecutorGroup(
poolProps.getThreadCount(),
threadFactory,
poolProps.getMaxPendingTasks(),
RejectedExecutionHandlers.reject()
);
}

@Bean
@ConditionalOnMissingBean
public AttachmentJt808DispatchChannelHandlerAdapter attachmentJt808DispatchChannelHandlerAdapter(
AttachmentJt808RequestProcessor requestProcessor,
AttachmentJt808SessionManager sessionManager) {

return new AttachmentJt808DispatchChannelHandlerAdapter(requestProcessor, sessionManager);
}

@Bean
@ConditionalOnMissingBean
public Jt808AttachmentServerNettyConfigure jt808AttachmentServerNettyConfigure(
AttachmentJt808DispatchChannelHandlerAdapter attachmentJt808DispatchChannelHandlerAdapter,
@Qualifier(BEAN_NAME_JT808_ATTACHMENT_MSG_PROCESSOR_EVENT_EXECUTOR_GROUP) EventExecutorGroup executors) {

final AttachmentServerProps attachmentServerProps = instructionServerProps.getAttachmentServer();
return new Jt808AttachmentServerNettyConfigure.DefaultJt808AttachmentServerNettyConfigure(
new Jt808AttachmentServerNettyConfigure.DefaultJt808AttachmentServerNettyConfigure.BuiltInServerBootstrapProps(
instructionServerProps.getProtocol().getMaxFrameLength(),
attachmentServerProps.getMaxFrameLength()
),
attachmentJt808DispatchChannelHandlerAdapter,
executors
);
}

@Bean(initMethod = "doStart", destroyMethod = "doStop")
@ConditionalOnMissingBean
public Jt808NettyTcpAttachmentServer jt808NettyTcpAttachmentServer(Jt808AttachmentServerNettyConfigure configure) {
final Jt808NettyTcpAttachmentServer server = new Jt808NettyTcpAttachmentServer(
"808-tcp-attachment-server",
configure
);

final AttachmentServerProps nettyProps = instructionServerProps.getAttachmentServer();
server.setPort(nettyProps.getPort());
server.setBossThreadCount(nettyProps.getBossThreadCount());
server.setWorkThreadCount(nettyProps.getWorkerThreadCount());
return server;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
*/
@Slf4j
@Import({
Jt808NettyServerAutoConfiguration.Jt808ServerParamPrinterConfig.class
Jt808NettyServerAutoConfiguration.Jt808ServerParamPrinterConfig.class,
Jt808AttachmentServerAutoConfiguration.class,
})
public class Jt808NettyServerAutoConfiguration {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package io.github.hylexus.jt.jt808.boot.props;

import io.github.hylexus.jt.jt808.boot.props.attachment.AttachmentServerProps;
import io.github.hylexus.jt.jt808.boot.props.builtin.BuiltComponentsProps;
import io.github.hylexus.jt.jt808.boot.props.builtin.RequestSubPackageStorageProps;
import io.github.hylexus.jt.jt808.boot.props.builtin.ResponseSubPackageStorageProps;
import io.github.hylexus.jt.jt808.boot.props.msg.processor.MsgProcessorProps;
import io.github.hylexus.jt.jt808.boot.props.feature.Jt808FeatureProps;
import io.github.hylexus.jt.jt808.boot.props.msg.processor.MsgProcessorProps;
import io.github.hylexus.jt.jt808.boot.props.protocol.ProtocolConfig;
import io.github.hylexus.jt.jt808.boot.props.server.Jt808NettyTcpServerProps;
import lombok.Getter;
Expand Down Expand Up @@ -56,4 +57,7 @@ public class Jt808ServerProps {

@NestedConfigurationProperty
private Jt808FeatureProps features = new Jt808FeatureProps();

@NestedConfigurationProperty
private AttachmentServerProps attachmentServer = new AttachmentServerProps();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.github.hylexus.jt.jt808.boot.props.attachment;

import io.github.hylexus.jt.jt808.boot.props.msg.processor.MsgProcessorProps;
import lombok.Data;
import lombok.ToString;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

import javax.validation.constraints.Min;

@Data
@ToString
public class AttachmentServerProps {
private boolean enabled = false;
private int port = 6809;

@Min(value = 0, message = "bossThreadCount >= 0, 0 means that Netty's default logical")
private int bossThreadCount = 0;

@Min(value = 0, message = "workerThreadCount >= 0, 0 means that Netty's default logical")
private int workerThreadCount = 0;

private int maxFrameLength = 1024 * 65;

@NestedConfigurationProperty
private MsgProcessorProps msgProcessor = new MsgProcessorProps();
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
public class MsgProcessorExecutorGroupProps {

@NotEmpty(message = "poolName is null or empty. defaultValue = '808-msg-processor' ")
private String poolName = "808-msg-processor";
private String poolName = "808-attachment-processor";

/**
* 默认: 128。
*/
@Min(value = 1, message = "threadCount >= 1, defaultValue = 128")
private int threadCount = 128;
private int threadCount = 32;

@Min(value = 16, message = "maxPendingTasks >= 16, defaultValue = 128")
private int maxPendingTasks = 128;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public interface JtProtocolConstant {

String BEAN_NAME_JT808_INTERCEPTORS = "jt808Interceptors";
String BEAN_NAME_JT808_MSG_PROCESSOR_EVENT_EXECUTOR_GROUP = "jt808MsgProcessorEventExecutorGroup";
String BEAN_NAME_JT808_ATTACHMENT_MSG_PROCESSOR_EVENT_EXECUTOR_GROUP = "jt808AttachmentMsgProcessorEventExecutorGroup";
String BEAN_NAME_NETTY_HANDLER_NAME_808_HEART_BEAT = "Jt808NettyHeartBeatHandler";

String NETTY_HANDLER_NAME_808_IDLE_STATE = "Jt808NettyIdleStateHandler";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ default Jt808Request copy() {
// <== Shortcut Methods End
// ++++++++++++++++++++++++++++++++++++++++++++

static Jt808RequestBuilder newBuilder(MsgType msgType) {
return new DefaultJt808Request.DefaultJt808RequestBuilder(msgType);
}

interface Jt808RequestBuilder {

Jt808RequestBuilder header(Jt808RequestHeader header);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ default int msgBodyLength() {

String toString();

static Jt808MsgHeaderBuilder newBuilder() {
return new DefaultJt808RequestHeader.DefaultJt808MsgHeaderBuilder();
}

default Jt808MsgHeaderBuilder mutate() {
return new DefaultJt808RequestHeader.DefaultJt808MsgHeaderBuilder(this);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package io.github.hylexus.jt.jt808.spec.builtin.msg.req;

import io.github.hylexus.jt.annotation.BuiltinComponent;
import io.github.hylexus.jt.jt808.support.annotation.msg.req.Jt808RequestBody;
import io.github.hylexus.jt.jt808.support.annotation.msg.req.RequestField;
import io.github.hylexus.jt.jt808.support.annotation.msg.req.RequestFieldAlias;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.util.List;

import static io.github.hylexus.jt.jt808.support.data.MsgDataType.LIST;

/**
* @author hylexus
*/
@Data
@Accessors(chain = true)
@Jt808RequestBody
@BuiltinComponent
public class BuiltinMsg1210Alias {

// byte[0,7)
@RequestFieldAlias.Bytes(order = 10, length = 7)
private String terminalId;

// byte[7,23)
@RequestFieldAlias.Bytes(order = 20, length = 16)
private String alarmIdentifier;

// byte[23,55)
@RequestFieldAlias.Bytes(order = 30, length = 32)
private String alarmNo;

// byte[55]
@RequestFieldAlias.Byte(order = 40)
private short messageType;

// byte[56]
@RequestFieldAlias.Byte(order = 50)
private short attachmentCount;

// byte[57,...)
@RequestField(order = 60, dataType = LIST, lengthExpression = "#ctx.msgBodyLength() - 57")
private List<AttachmentItem> attachmentItemList;

@Data
@NoArgsConstructor
public static class AttachmentItem {
@RequestFieldAlias.Byte(order = 10)
private int length;

@RequestFieldAlias.String(order = 20, lengthExpression = "#this.length")
private String fileName;

@RequestFieldAlias.Dword(order = 30)
private long fileSize;
}
}
Loading

0 comments on commit ed608e1

Please sign in to comment.