| | |
| | | import io.netty.buffer.Unpooled; |
| | | import io.netty.channel.Channel; |
| | | import io.netty.channel.ChannelHandlerContext; |
| | | |
| | | import android.os.Handler; |
| | | import android.os.Looper; |
| | | import android.os.Message; |
| | | import android.util.Log; |
| | | |
| | | import com.example.agvcontroller.Item; |
| | | import com.example.agvcontroller.AGVCar; |
| | | import com.example.agvcontroller.MainActivity; |
| | | import com.example.agvcontroller.action.AGV_11_UP; |
| | | import com.example.agvcontroller.action.AckMsgBuilder; |
| | | import com.example.agvcontroller.met.AbstractInboundHandler; |
| | | import com.example.agvcontroller.protocol.AGV_12_UP; |
| | | import com.example.agvcontroller.protocol.AGV_13_UP; |
| | | import com.example.agvcontroller.protocol.AGV_A1_DOWN; |
| | | import com.example.agvcontroller.protocol.AGV_F0_DOWN; |
| | | import com.example.agvcontroller.protocol.AGV_F0_UP; |
| | | import com.example.agvcontroller.protocol.AgvAction; |
| | | import com.example.agvcontroller.protocol.AgvPackage; |
| | | import com.example.agvcontroller.protocol.ProtocolType; |
| | |
| | | |
| | | import org.greenrobot.eventbus.EventBus; |
| | | |
| | | import java.net.InetSocketAddress; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | public class NettyServerHandler extends AbstractInboundHandler<AgvPackage> { |
| | | |
| | | private static final String TAG = "NettyServerHandler"; |
| | | private static ConcurrentHashMap<String, Channel> channelMap = new ConcurrentHashMap<>(); |
| | | private Map<String, Runnable> pendingRemovals = new HashMap<>(); |
| | | private Handler handler = new Handler(Looper.getMainLooper()) { |
| | | @Override |
| | | public void handleMessage(Message msg) { |
| | | super.handleMessage(msg); |
| | | String clientId = (String) msg.obj; |
| | | removeItem(clientId); |
| | | } |
| | | }; |
| | | |
| | | |
| | | @Override |
| | | public void channelActive(ChannelHandlerContext ctx) throws Exception { |
| | | String clientId = ctx.channel().remoteAddress().toString(); |
| | | InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress(); |
| | | String ip = remoteAddress.getAddress().getHostAddress(); |
| | | int port = remoteAddress.getPort(); |
| | | channelMap.put(clientId, ctx.channel()); |
| | | EventBus.getDefault().post(new Item("1",clientId,"3")); |
| | | EventBus.getDefault().post(new AGVCar(clientId,ip,port,"--",0)); |
| | | Log.d(TAG, "Client connected: " + clientId); |
| | | |
| | | // 取消延迟删除操作 |
| | | if (pendingRemovals.containsKey(clientId)) { |
| | | handler.removeCallbacks(pendingRemovals.get(clientId)); |
| | | pendingRemovals.remove(clientId); |
| | | } |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void channelInactive(ChannelHandlerContext ctx) throws Exception { |
| | | String clientId = ctx.channel().remoteAddress().toString(); |
| | | InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress(); |
| | | String ip = remoteAddress.getAddress().getHostAddress(); |
| | | int port = remoteAddress.getPort(); |
| | | channelMap.remove(clientId); |
| | | EventBus.getDefault().post(clientId); |
| | | Log.d(TAG, "Client disconnected: " + clientId); |
| | | |
| | | // 启动延迟删除操作 |
| | | Runnable removalRunnable = new Runnable() { |
| | | @Override |
| | | public void run() { |
| | | removeItem(clientId); |
| | | } |
| | | }; |
| | | pendingRemovals.put(clientId, removalRunnable); |
| | | handler.postDelayed(removalRunnable, 20000); // 20秒后执行删除操作 |
| | | |
| | | } |
| | | |
| | | |
| | | private void removeItem(String clientId) { |
| | | if (channelMap.remove(clientId) != null) { |
| | | Log.d(TAG, "Client removed after 20 seconds: " + clientId); |
| | | EventBus.getDefault().post(clientId); |
| | | } else { |
| | | Log.d(TAG, "Client already reconnected or not found: " + clientId); |
| | | } |
| | | } |
| | | |
| | | // @Override |
| | |
| | | |
| | | @Override |
| | | protected boolean channelRead0(ChannelHandlerContext ctx, AgvPackage pac) throws Exception { |
| | | |
| | | String serialNum = pac.getHeader().getSerialNum(); |
| | | String clientId = ctx.channel().remoteAddress().toString(); |
| | | InetSocketAddress remoteAddress = (InetSocketAddress) ctx.channel().remoteAddress(); |
| | | String ip = remoteAddress.getAddress().getHostAddress(); |
| | | int port = remoteAddress.getPort(); |
| | | Log.i("clientId--->",clientId); |
| | | Log.i("substring",pac.toString()); |
| | | String serialNum = pac.getBody().getMessageBody().getSerialNo(); |
| | | Log.i("substring",serialNum); |
| | | MainActivity.map.put(serialNum, Boolean.TRUE); |
| | | // ack |
| | | ProtocolType ackType = isNeedAck(pac); |
| | | final String uniqueNo = pac.getHeader().getUniqueNo(); |
| | | String agvNo; |
| | | label : switch (pac.getHeader().getProtocolType()){ |
| | | case ACTION_COMPLETE: // 动作完成数据包 |
| | | |
| | | |
| | | AGV_11_UP agv_11_up = (AGV_11_UP) pac.getBody().getMessageBody(); |
| | | // redis.push(RedisConstant.AGV_COMPLETE_FLAG, AgvProtocol.build(uniqueNo).setMessageBody(agv_11_up)); |
| | | |
| | | // 动作完成应答 |
| | | if (null != ackType) { |
| | | AgvPackage ackPac = AckMsgBuilder.ofSuccess(pac, ackType); |
| | | |
| | | AGV_A1_DOWN agv_a1_down = (AGV_A1_DOWN) ackPac.getBody().getMessageBody(); |
| | | agv_a1_down.setAckSign((byte) agv_11_up.getCompleteCode()); |
| | | |
| | | ctx.writeAndFlush(ackPac); |
| | | } |
| | | |
| | | MainActivity.map.put(serialNum, Boolean.TRUE); |
| | | |
| | | break label; |
| | | case DATA_CODE_REPORT: |
| | | AGV_12_UP agv_12_up = (AGV_12_UP) pac.getBody().getMessageBody(); |
| | | agvNo = pac.getHeader().getUniqueNo(); |
| | | channelMap.put(clientId, ctx.channel()); |
| | | EventBus.getDefault().post(new AGVCar(clientId,ip,port,agvNo,1)); |
| | | break label; |
| | | case DATA_WITHOUT_CODE_REPORT: |
| | | AGV_13_UP agv_13_up = (AGV_13_UP) pac.getBody().getMessageBody(); |
| | | agvNo = pac.getHeader().getUniqueNo(); |
| | | channelMap.put(clientId, ctx.channel()); |
| | | EventBus.getDefault().post(new AGVCar(clientId,ip,port,agvNo,1)); |
| | | break label; |
| | | case LOGIN_REPORT: |
| | | AGV_F0_UP agv_f0_up = (AGV_F0_UP) pac.getBody().getMessageBody(); |
| | | if (null != ackType) { |
| | | AgvPackage ackPac = AckMsgBuilder.ofSuccess(pac, ackType); |
| | | AGV_F0_DOWN agv_f0_down = (AGV_F0_DOWN) ackPac.getBody().getMessageBody(); |
| | | ctx.writeAndFlush(ackPac); |
| | | } |
| | | agvNo = pac.getHeader().getUniqueNo(); |
| | | channelMap.put(clientId, ctx.channel()); |
| | | EventBus.getDefault().post(new AGVCar(clientId,ip,port,agvNo,1)); |
| | | break label; |
| | | |
| | | } |
| | | return false; |
| | | } |