All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.envision.energy.eos.sdk.Transport Maven / Gradle / Ivy

There is a newer version: 3.0.3
Show newest version
package com.envision.energy.eos.sdk;

import com.envision.energy.connective.protobuf.*;
import com.envision.energy.connective.protobuf.generated.Sdk;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


import com.envision.energy.connective.common.RegManager;
import com.envision.energy.connective.common.channel.DefaultChannelInitializer;
import com.envision.energy.connective.common.channel.DefaultChannelInitializer.AddChannelHandlerPoint;
import com.envision.energy.connective.common.channel.IChannelHandlerGenerator;
import com.envision.energy.connective.common.protobuf.Decoder;
import com.envision.energy.connective.common.protobuf.generated.Common.KVPairRecord;
import com.envision.energy.connective.protobuf.generated.Sdk.AlertStrReq;
import com.envision.energy.connective.protobuf.generated.Sdk.CmdId;
import com.envision.energy.connective.protobuf.generated.Sdk.IdleRsp;
import com.envision.energy.connective.protobuf.generated.Sdk.PointDetail;
import com.envision.energy.connective.protobuf.generated.Sdk.SDKAuthReq;
import com.envision.energy.connective.protobuf.generated.Sdk.SDKAuthRes;
import com.envision.energy.connective.protobuf.generated.Sdk.SubAllAlarm;
import com.envision.energy.connective.protobuf.generated.Sdk.SubAllData;
import com.envision.energy.connective.protobuf.generated.Sdk.SubDevData;
import com.envision.energy.connective.protobuf.generated.Sdk.SubDomainData;
import com.envision.energy.util.SignUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


class Transport {
	
	private String host;
	private int port;
	private int interval;
	private int curAckId;
	
	private String appKey = null;
	private String appSecrect = null;
	
	private Channel channel = null;
	private Boolean isClosed = false;
	private Boolean isStarted = false;
	private EventLoopGroup workerGroup = null;
	private Bootstrap bootstrap = null;
	private String token = null;
	
	private AuthResMessageProcessor authMsgProcessor = new AuthResMessageProcessor();
	private DoConnect doConnect = null;
	
	private static Logger logger = LoggerFactory.getLogger(Transport.class);
	private static final int DEF_PORT = 80;
	private static final int DEF_INTERVAL = 5;
	
	public static Transport create(String appKey, String appSecrect, String url) {
		return create(appKey, appSecrect, url, DEF_INTERVAL);
	}
	
	public static Transport create(String appKey, String appSecrect, String url, int retryTimeSec) {
		if(appKey == null || appSecrect == null || url == null) {
			return null;
		}
		
		int idx = url.lastIndexOf(":");
		String host = "";
		int port = DEF_PORT;
		if(idx < 0 || idx >= url.length()) {
			host = url;
			port = DEF_PORT;
		}
		host = url.substring(0, idx);
		port = Integer.valueOf(url.substring(idx + 1));
		
		return new Transport(appKey, appSecrect, host, port, retryTimeSec);
	}
	
	//////////////////////////////////
	//////////////////////////////////
	//////////////////////////////////
	
	private void initReg() {
		RegManager.register(CmdId.kv_pair_record_VALUE, KVPairRecord.class, new KVPairRecordProcessor());
		RegManager.register(CmdId.alert_req_VALUE, AlertStrReq.class, new AlertStrReqProcessor());
		RegManager.register(CmdId.event_req_VALUE, Sdk.EventStrReq.class, new EventStrReqProcessor());
		RegManager.register(CmdId.eventv2_req_VALUE, Sdk.EventV2StrReq.class, new EventV2StrReqProcessor());
		RegManager.register(CmdId.asset_change_rsp_VALUE, Sdk.AssetChangeRsp.class, new AssetChangeRspProcessor());
		RegManager.register(CmdId.sub_all_data_req_VALUE, SubAllData.class);
		RegManager.register(CmdId.sub_dev_data_req_VALUE, SubDevData.class);
		RegManager.register(CmdId.sub_domain_data_req_VALUE, SubDomainData.class);
		RegManager.register(CmdId.sub_all_alarm_req_VALUE, SubAllAlarm.class);
		RegManager.register(CmdId.auth_req_VALUE, SDKAuthReq.class);
		RegManager.register(CmdId.idle_rsp_VALUE, IdleRsp.class);
		RegManager.register(CmdId.auth_res_VALUE, SDKAuthRes.class);
		RegManager.register(CmdId.point_detail_VALUE, PointDetail.class, new PointDetailProcessor());
		RegManager.register(CmdId.sub_event_customer_req_VALUE, Sdk.SubEventCustomer.class);
		RegManager.register(CmdId.sub_eventv2_customer_req_VALUE, Sdk.SubEventV2Customer.class);
		RegManager.register(CmdId.sub_asset_change_req_VALUE, Sdk.SubAssetData.class);
	}
	
	private Transport(String appKey, String appSecrect, String host, int port, int retryTimeSec) {
		init(appKey, appSecrect, host, port);
		interval = retryTimeSec;
		curAckId = 0;
		doConnect = new DoConnect();
		start();
	}
	
	private void init(String appKey, String appSecrect, String host, int port) {
		this.appKey = appKey;
		this.appSecrect = appSecrect;
		this.host = host;
		this.port = port;
		
		initReg();
	}

	
	public Boolean isStarted() {
		return isStarted;
	}
	public Boolean isClosed() {
		return isClosed;
	}
	
	public void setToken(String token) {
		this.token = token;
	}
	
	public String getToken() {
		return token;
	}
	
	private void sendAuthReq() {
		if(appKey == null || appSecrect == null) {
			return;
		}
		SDKAuthReq.Builder builder = SDKAuthReq.newBuilder();
		builder.setAppkey(appKey);
		builder.setSignature(SignUtil.sign(appKey, appSecrect, null));
		builder.setAckId(Decoder.getCurHeartbeat(channel));
		if(token != null) {
			builder.setToken(token);
		}
		channel.writeAndFlush(builder.build());
	}
	
	private void start(){
		isClosed = false;
		bootstrap = new Bootstrap();
		workerGroup = new NioEventLoopGroup();
		
		bootstrap.group(workerGroup);
		
		bootstrap.channel(NioSocketChannel.class);
		
		bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
		bootstrap.option(ChannelOption.TCP_NODELAY, true);
		bootstrap.handler(new DefaultChannelInitializer(getGeneratorMap()));
		
		new Thread(doConnect).start();
	}
	
	public void close() {
		
		isClosed = true;
		isStarted = false;
		curAckId = Decoder.getCurHeartbeat(channel);
		channel = null;
		if(workerGroup != null){
			workerGroup.shutdownGracefully();
		}
		
		logger.info("close connection to " + remoteSvrInfo());
	}
	
	public boolean write(Object msg) throws NullPointerException {
		if(channel == null) {
			throw new NullPointerException("channel null");
		}
		if(channel.isWritable()) {
			channel.writeAndFlush(msg);
			return true;
		} 
		
		logger.error("channel can not be written.");
		return false;
	}
	
	public void started() {
		isStarted = true;
        logger.info("connect to " + remoteSvrInfo());
	}
	
	private class DoConnect implements Runnable {
		
		@Override
		public void run() {
			if(isClosed()) {
				return;
			}
			
			ChannelFuture f;
			f = bootstrap.connect(host, port);
			logger.info("do connection...");
			f.addListener(new ChannelFutureListener(){

				@Override
				public void operationComplete(ChannelFuture future)
						throws Exception {
					if (future.isSuccess()) {
						channel = future.channel();
						Decoder.setCurHeartbeat(channel, curAckId);
						
						//auth request
						sendAuthReq();
			            
			        }else{
			        	logger.error("connect " + remoteSvrInfo() + " failed, try again.");
			        	future.channel().eventLoop().schedule( doConnect, interval, TimeUnit.SECONDS);
			        }
				}
				
			});
			
			
		}
		
	}
	
	private Map> getGeneratorMap() {
		Map> retMap = new HashMap<>();
		
		List decoderBeforePointList = new ArrayList<>();
		
		decoderBeforePointList.add(new IChannelHandlerGenerator() {

			@Override
			public ChannelHandler generate() {
				return new ChannelInboundHandlerAdapter() {
					    
					@Override
					public void channelInactive(ChannelHandlerContext ctx)
							throws Exception {
						
						if(channel != null) {
							curAckId = Decoder.getCurHeartbeat(channel);
							channel = null;
						}
						isStarted = false;
						ctx.channel().eventLoop().schedule(doConnect, interval, TimeUnit.SECONDS);
						super.channelInactive(ctx);
					}

				};
			}
			
		});
		
		decoderBeforePointList.add(new IChannelHandlerGenerator()
		{
		    @Override
		    public ChannelHandler generate() {
			return new IdleStateHandler(0, 20, 0, TimeUnit.SECONDS);
		    }
		});
		
		retMap.put(AddChannelHandlerPoint.DecoderBeforePoint, decoderBeforePointList);
		
		List protoHandlerBeforePointList = new ArrayList<>();
		
		protoHandlerBeforePointList.add(new IChannelHandlerGenerator(){
			@Override
			public ChannelHandler generate() {
				return authMsgProcessor;
			}
		});
		
		retMap.put(AddChannelHandlerPoint.ProtoHandlerBeforePoint, protoHandlerBeforePointList);
		
		return retMap;
    }
	
	private String remoteSvrInfo() {
		return "host: " + host + " port: " + port;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy