code: @Override
      protected void checkIfHeartbeatSkipped(String name, EventChannelStruct channelStruct) {
              // Check if heartbeat have been skipped, can happen if
              // 1- the server is dead
              // 2- The network was down;
              // 3- The server has been restarted on another host.
  
          if (KeepAliveThread.heartbeatHasBeenSkipped(channelStruct)) {
              DevError    dev_error = null;
              try{
                  String  admDeviceName = channelStruct.adm_device_proxy.fullName();  //.toLowerCase();
                  //  Since Tango 8.1, heartbeat is sent in lower case.
                  if (channelStruct.getTangoRelease()>=810)
                      admDeviceName = admDeviceName.toLowerCase();
                  channelStruct.adm_device_proxy = new DeviceProxy(admDeviceName);
                  channelStruct.adm_device_proxy.set_timeout_millis(300);
                  channelStruct.adm_device_proxy.ping();
                  reconnectToChannel(name);
              }
              catch (DevFailed e) {
                  dev_error = e.errors[0];
              }
  
              Enumeration callbackStructs = EventConsumer.getEventCallbackMap().elements();
              while (callbackStructs.hasMoreElements()) {
                  EventCallBackStruct callbackStruct = (EventCallBackStruct) callbackStructs.nextElement();
                  if (callbackStruct.channel_name.equals(name)) {
                      //	Push exception
                      if (dev_error != null)
                          pushReceivedException(channelStruct, callbackStruct, dev_error);
                      else {
                          //  ToDo Re connect without error means heartbeat missing
                          dev_error = new DevError("API_NoHeartbeat",
                                  ErrSeverity.ERR, "No heartbeat from " +
                                      channelStruct.adm_device_proxy.get_name(),
                                  "ZmqEventConsumer.checkIfHeartbeatSkipped()");
                          pushReceivedException(channelStruct, callbackStruct, dev_error);
                      }
  
                      //	If reconnection done, try to re subscribe
                      //		and read attribute in synchronous mode
                      if (reconnectToEvent(channelStruct, callbackStruct)) {
                          if (!callbackStruct.event_name.equals(eventNames[DATA_READY_EVENT])) {
                              readAttributeAndPush(channelStruct, callbackStruct);
                          }
                      }
                  }
              }
          }
      }
docs: ===============================================================