package cc.blynk.server.hardware.handlers.hardware.mqtt.logic;
import cc.blynk.server.core.dao.ReportingDao;
import cc.blynk.server.core.dao.SessionDao;
import cc.blynk.server.core.model.DashBoard;
import cc.blynk.server.core.model.auth.Session;
import cc.blynk.server.core.model.enums.PinType;
import cc.blynk.server.core.session.HardwareStateHolder;
import cc.blynk.utils.ParseUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.mqtt.MqttPublishMessage;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.nio.charset.StandardCharsets;
import static cc.blynk.server.core.protocol.enums.Command.HARDWARE;
import static cc.blynk.utils.StringUtils.split3;
/**
* Handler responsible for forwarding messages from hardware to applications.
* Also handler stores all incoming hardware commands to disk in order to export and
* analyze data.
*
* The Blynk Project.
* Created by Dmitriy Dumanskiy.
* Created on 2/1/2015.
*
*/
public class MqttHardwareLogic {
private static final Logger log = LogManager.getLogger(MqttHardwareLogic.class);
private final ReportingDao reportingDao;
private final SessionDao sessionDao;
public MqttHardwareLogic(SessionDao sessionDao, ReportingDao reportingDao) {
this.sessionDao = sessionDao;
this.reportingDao = reportingDao;
}
private static boolean isWriteOperation(String body) {
return body.charAt(1) == 'w';
}
public void messageReceived(ChannelHandlerContext ctx, HardwareStateHolder state, MqttPublishMessage msg) {
Session session = sessionDao.userSession.get(state.userKey);
String body = msg.payload().readSlice(msg.payload().capacity()).toString(StandardCharsets.UTF_8);
//just temp solution to simplify demo
body = body.replace(" ", "\0").replace(" ", "\0");
//minimum command - "aw 1"
if (body.length() < 4) {
//throw new IllegalCommandException("HardwareLogic command body too short.");
return;
}
final int dashId = state.dashId;
final int deviceId = state.deviceId;
DashBoard dash = state.user.profile.getDashByIdOrThrow(dashId);
if (isWriteOperation(body)) {
//" |\0" - to simplify demonstration
String[] splitBody = split3(body);
if (splitBody.length < 3 || splitBody[0].length() == 0) {
//throw new IllegalCommandException("Write command is wrong.");
return;
}
final PinType pinType = PinType.getPinType(splitBody[0].charAt(0));
final byte pin = ParseUtil.parseByte(splitBody[1]);
final String value = splitBody[2];
if (value.length() == 0) {
//throw new IllegalCommandException("Hardware write command doesn't have value for pin.");
return;
}
final long now = System.currentTimeMillis();
reportingDao.process(state.user, dashId, deviceId, pin, pinType, value, now);
dash.update(0, pin, pinType, value, now);
}
//todo do not send if no widget pin
if (dash.isActive) {
session.sendToApps(HARDWARE, msg.variableHeader().messageId(), dashId, deviceId, body);
} else {
log.debug("No active dashboard.");
}
}
}