package cc.blynk.server.hardware.handlers.hardware.logic; import cc.blynk.server.core.model.DashBoard; import cc.blynk.server.core.model.HardwareInfo; import cc.blynk.server.core.model.widgets.others.rtc.RTC; import cc.blynk.server.core.protocol.enums.Response; import cc.blynk.server.core.protocol.model.messages.StringMessage; import cc.blynk.server.core.session.HardwareStateHolder; import cc.blynk.utils.StringUtils; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.timeout.ReadTimeoutHandler; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import static cc.blynk.server.core.protocol.enums.Command.BLYNK_INTERNAL; import static cc.blynk.utils.BlynkByteBufUtil.*; import static cc.blynk.utils.StringUtils.BODY_SEPARATOR; /** * * Simple handler that accepts info command from hardware. * At the moment only 1 param is used "h-beat". * * The Blynk Project. * Created by Dmitriy Dumanskiy. * Created on 2/1/2015. * */ @ChannelHandler.Sharable public class BlynkInternalLogic { private static final Logger log = LogManager.getLogger(BlynkInternalLogic.class); private final int hardwareIdleTimeout; public BlynkInternalLogic(int hardwareIdleTimeout) { this.hardwareIdleTimeout = hardwareIdleTimeout; } public void messageReceived(ChannelHandlerContext ctx, HardwareStateHolder state, StringMessage message) { String[] messageParts = message.body.split(StringUtils.BODY_SEPARATOR_STRING); if (messageParts.length == 0 || messageParts[0].length() == 0) { ctx.writeAndFlush(makeResponse(message.id, Response.ILLEGAL_COMMAND), ctx.voidPromise()); return; } final String cmd = messageParts[0]; switch (cmd.charAt(0)) { case 'v' : parseHardwareInfo(ctx, messageParts, state, message.id); break; case 'a' : break; case 'r' : sendRTC(ctx, state, message.id); break; case 'o' : break; } } private void sendRTC(ChannelHandlerContext ctx, HardwareStateHolder state, int msgId) { DashBoard dashBoard = state.user.profile.getDashByIdOrThrow(state.dashId); RTC rtc = dashBoard.getWidgetByType(RTC.class); if (rtc != null) { ctx.writeAndFlush(makeASCIIStringMessage(BLYNK_INTERNAL, msgId, "rtc" + BODY_SEPARATOR + rtc.getTime()), ctx.voidPromise()); } } private void parseHardwareInfo(ChannelHandlerContext ctx, String[] messageParts, HardwareStateHolder state, int msgId) { HardwareInfo hardwareInfo = new HardwareInfo(messageParts); int newHardwareInterval = hardwareInfo.heartbeatInterval; log.trace("Info command. heartbeat interval {}", newHardwareInterval); if (hardwareIdleTimeout != 0 && newHardwareInterval > 0) { final int newReadTimeout = (int) Math.ceil(newHardwareInterval * 2.3D); log.debug("Changing read timeout interval to {}", newReadTimeout); ctx.pipeline().remove(ReadTimeoutHandler.class); ctx.pipeline().addFirst(new ReadTimeoutHandler(newReadTimeout)); } DashBoard dashBoard = state.user.profile.getDashByIdOrThrow(state.dashId); //this info is not important, so we don't mark dash as updated. //this update will be stored only in case hardware sends real data to pins dashBoard.hardwareInfo = hardwareInfo; ctx.writeAndFlush(ok(msgId), ctx.voidPromise()); } }