class MoquetteIdleTimeoutHandler extends ChannelDuplexHandler {

    private static final Logger LOG = LoggerFactory.getLogger(MoquetteIdleTimeoutHandler.class);

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {<FILL_FUNCTION_BODY>}
}

        if (evt instanceof IdleStateEvent) {
            IdleState e = ((IdleStateEvent) evt).state();
            if (e == IdleState.READER_IDLE) {
                LOG.warn("Close channel because it's inactive, passed keep alive. MqttClientId = {}.", NettyUtils.clientID(ctx.channel()));
                // fire a close that then fire channelInactive to trigger publish of Will
                ctx.close().addListener(CLOSE_ON_FAILURE);
            }
        } else {
            if (LOG.isTraceEnabled()) {
                LOG.trace("Firing Netty event CId = {}, eventClass = {}", NettyUtils.clientID(ctx.channel()),
                          evt.getClass().getName());
            }
            super.userEventTriggered(ctx, evt);
        }
    
<no_super_class>