Spring集成与gps设备的双向通信

时间:2018-05-02 09:53:18

标签: gps spring-integration two-way

我们正在使用spring集成应用程序从gps设备接收数据。对于当前配置,我们能够从设备接收数据,并通过相同的连接将其发送回设备

当前配置为

@SpringBootApplication
@IntegrationComponentScan
public class SpringIntegrationApplication extends SpringBootServletInitializer{ 

private Integer TIMEOUT=1000*60*10;

    @Value("${TCP_PORT}")
    private Integer TCP_PORT;

    public static void main(String[] args) throws IOException {
        ConfigurableApplicationContext ctx = SpringApplication.run(SpringIntegrationApplication.class, args);       
        System.in.read();
        ctx.close();
    }

    @Bean
    TcpNetServerConnectionFactory cf(){
        TcpNetServerConnectionFactory connectionFactory=new TcpNetServerConnectionFactory(TCP_PORT);

        connectionFactory.setSerializer(new CustomSerializerDeserializer());
        connectionFactory.setDeserializer(new CustomSerializerDeserializer());
        connectionFactory.setSoTimeout(TIMEOUT);
        return connectionFactory;
    }

    @Bean
    TcpInboundGateway tcpGate(){

        TcpInboundGateway gateway=new TcpInboundGateway();
        gateway.setConnectionFactory(cf());
        gateway.setRequestChannel(requestChannel());
        gateway.setRequestTimeout(TIMEOUT);
        return gateway;
    }

    @Bean
    public MessageChannel requestChannel(){

        return new DirectChannel();
    }
}

和消息结束点

@MessageEndpoint 
public class Echo { 

    @ServiceActivator(inputChannel="requestChannel")
    public byte[] echo(byte[] in,@SuppressWarnings("deprecation") @Header("ip_address") String ip){
        //here we receive packet data in bytes from gps device
        return  "".getBytes();//string will contains expected result for device.
    }

以上配置适用于单向通信。但我们希望实现双向沟通。我们想要在服务器和设备之间建立连接之后我们想要明确地发送消息。要通过服务器发送命令我们不知道设备的ip和端口,那么我们如何通过服务器向连接设备发送命令。

我正在尝试以下解决方案

创建了一个oubound channel adapter

@Bean       
    public TcpSendingMessageHandler tcpSendingMessageHandler() {
        System.out.println("Creating outbound adapter");
        TcpSendingMessageHandler outbound = new TcpSendingMessageHandler();
        return outbound;
    }

然后为explicite消息发送创建网关,这将从我们想要明确发送数据的服务中调用

@MessagingGateway(defaultRequestChannel="toTcp")
    public static interface tcpSendService {    
        public byte [] send(String string);
    }

在调用我们设置连接ip和端口的服务激活器之后调用gate方式后,这些ip和ports将从设备接收数据时建立连接

@ServiceActivator(inputChannel="toTcp", outputChannel="fromTcp")    
    public String send(String in){              
        System.out.println(new String(in));     
        TcpNetClientConnectionFactory factory = new TcpNetClientConnectionFactory(ip_extracted_from_inbound_connection, port_extarcted_from_inbound_connection);
        factory.start();        
        tcpSendingMessageHandler.setConnectionFactory(factory);                     
        return in;
    }

//用于ip和端口提取我正在使用以下服务,即入站服务

@ServiceActivator(inputChannel="requestChannel")
    public byte[] echo(byte[] in,@Header("ip_address") String ip){              
        System.out.println(new String(in)+ " ; IP : "+ip);

        for (String connectionId : factory.getOpenConnectionIds()) {
            if(!lastConection.contains(ip))
                lastConection = connectionId;               
        }

        return "hello".getBytes();
    }

对于服务激活器,我每次调用服务时都会设置新的TcpNetClientConnectionFactory。 Ip和端口是从TcpNetServerConnectionFactory中提取的。每当设备连接服务器我保存其连接IP和端口,使用这些IP和端口通过服务器进行数据传输,但我收到连接超时问题。

请帮助我,并建议我解决它。

谢谢。

1 个答案:

答案 0 :(得分:0)

用一对Collaborating Outbound and Inbound Channel Adapters替换网关。

要向连接发送任意消息,您必须设置ip_connectionId标题。

但挑战在于如何将回复指向网关。您需要从请求中捕获replyChannel标头,并在收到ip_connectionId的回复时设置replyChannel标头。

但是,如果您一次只有一个未完成的请求/回复,除非回复中有一些数据可用于将其与请求相关联,否则这只会有效。

另一个挑战是竞争条件,其中设备和服务器同时发起请求。您需要查看入站邮件中的数据,看看它是否是请求或回复。