@Override
  public void handle(EventContext ctx) throws IOException {
    Channel channel = ctx.getChannel();
    EventType event = ctx.getEvent();

    long timeoutTime = System.currentTimeMillis() + ConfigConst.HEARTBEAT_TIMEOUT * 1000;

    switch (event) {
        /** Start heart beat */
      case SERVER_HEARTBEAT_START:
        xmppServerHeartBeatTimeoutMap.put(channel, timeoutTime);
        startHeartBeat(channel);
        break;
      case PROXY_HEARTBEAT_START:
        proxyHeartBeatTimeoutMap.put(channel, timeoutTime);
        startHeartBeat(channel);
        break;
      case ROBOT_HEARTBEAT_START:
        robotHeartBeatTimeoutMap.put(channel, timeoutTime);
        startHeartBeat(channel);
        break;

        /** Stop heart beat */
      case SERVER_HEARTBEAT_STOP:
        xmppServerHeartBeatTimeoutMap.remove(channel);
        stopHeartBeat(channel);
        break;
      case PROXY_HEARTBEAT_STOP:
        proxyHeartBeatTimeoutMap.remove(channel);
        stopHeartBeat(channel);
        break;
      case ROBOT_HEARTBEAT_STOP:
        robotHeartBeatTimeoutMap.remove(channel);
        stopHeartBeat(channel);
        break;

        /** Normal heart beat */
      case SERVER_HEARTBEAT:
        xmppServerHeartBeatTimeoutMap.put(channel, timeoutTime);
        break;
      case PROXY_HEARTBEAT:
        proxyHeartBeatTimeoutMap.put(channel, timeoutTime);
        break;
      case ROBOT_HEARTBEAT:
        robotHeartBeatTimeoutMap.put(channel, timeoutTime);
        break;
      default:
        throw new UnrecognizedEvent(event.toString());
    }
  }
    @Override
    public void run() {
      while (true) {
        synchronized (timeoutMap) {
          if (timeoutMap.size() > 0) {
            for (Entry<Channel, Long> entry : timeoutMap.entrySet()) {
              if (entry.getValue() <= System.currentTimeMillis()) {
                logger.debug(
                    clientPrefix + "_HEARTBEAT_TIMEOUT: " + entry.getKey().getRemoteAddress());
                eventDispatcher.dispatchEvent(
                    entry.getKey(), null, EventType.valueOf(clientPrefix + "_HEARTBEAT_TIMEOUT"));
              }
            }
          }
        }

        try {
          Thread.sleep(ConfigConst.HEARTBEAT_INTERVAL * 1000);
        } catch (InterruptedException e) {
          // Do nothing
        }
      }
    }