All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feingto.iot.server.handler.mqtt.PublishHandler Maven / Gradle / Ivy

There is a newer version: 1.2.5.RELEASE
Show newest version
package com.feingto.iot.server.handler.mqtt;

import com.feingto.iot.common.model.mqtt.ImSpan;
import com.feingto.iot.common.model.mqtt.SendMessage;
import com.feingto.iot.common.service.mqtt.MessageRequest;
import com.feingto.iot.common.service.mqtt.MessageResponse;
import com.feingto.iot.common.util.MessageId;
import com.feingto.iot.server.cache.MessageCache;
import com.feingto.iot.server.cache.RetainedCache;
import com.feingto.iot.server.cache.SessionCache;
import com.feingto.iot.server.cache.SubscribeCache;
import com.feingto.iot.server.handler.BaseMessageHandler;
import com.feingto.iot.server.serialize.JSON;
import com.feingto.iot.server.service.PushService;
import com.feingto.iot.server.util.Constants;
import io.netty.channel.Channel;
import io.netty.handler.codec.mqtt.*;
import lombok.extern.slf4j.Slf4j;

import java.util.Optional;
import java.util.UUID;

/**
 * 消息发布处理器
 *
 * @author longfei
 */
@Slf4j
public class PublishHandler extends BaseMessageHandler {
    private final PushService pushService;

    public PublishHandler(PushService pushService) {
        super(MqttMessageType.PUBLISH);
        this.pushService = pushService;
    }

    @Override
    public void handle(Channel channel, Object object) {
        MqttPublishMessage msg = (MqttPublishMessage) object;
        MqttFixedHeader fixedHeader = msg.fixedHeader();
        MqttPublishVariableHeader variableHeader = msg.variableHeader();
        SendMessage sendMessage = SendMessage.newInstance(msg);

        // 存储每个Topic的最后一条保留消息及其Qos
        if (sendMessage.retain()) {
            log.debug(">>> save retain message on {}", sendMessage.topic());
            RetainedCache.getInstance(igniteRetained).put(sendMessage.topic(), sendMessage);
        }

        sendMessage.retain(false);
        // 推送到云端
        this.storeOnCloud(channel, sendMessage);

        switch (fixedHeader.qosLevel()) {
            case AT_MOST_ONCE:
                // 发布消息到所有订阅者
                pushService.internalSend(sendMessage);
                break;
            case AT_LEAST_ONCE:
                // 持久化消息
                this.storeMessage(sendMessage, MqttMessageType.PUBLISH);

                // 发布消息到所有订阅者
                pushService.internalSend(sendMessage);

                // 返回puback消息
                MessageResponse.puback(channel, MqttMessageType.PUBACK, MqttQoS.AT_MOST_ONCE, variableHeader.packetId());
                break;
            case EXACTLY_ONCE:
                // 持久化消息
                this.storeMessage(sendMessage, MqttMessageType.PUBREC);

                // 返回pubrec消息
                MessageResponse.puback(channel, MqttMessageType.PUBREC, MqttQoS.AT_LEAST_ONCE, variableHeader.packetId());
                break;
            case FAILURE:
                break;
        }
    }

    /**
     * 推送到云端
     */
    private void storeOnCloud(Channel channel, SendMessage message) {
        SubscribeCache.getInstance((igniteSubscribe)).findByTopic(Constants.TOPIC_STORE_ES)
                .forEach(subscribe -> Optional.ofNullable(SessionCache.getInstance().get(subscribe.clientId()))
                        .ifPresent(sess -> MessageRequest.publish(sess.channel(), Constants.TOPIC_STORE_ES,
                                JSON.getInstance().obj2json(new ImSpan()
                                        .id(UUID.randomUUID().toString() + "-" + MessageId.messageId())
                                        .from(channel.attr(com.feingto.iot.common.Constants.KEY_CLIENT_ID).get())
                                        .to(subscribe.clientId())
                                        .topic(message.topic())
                                        .payload(message.payload())
                                        .timestamp(System.currentTimeMillis())), false, 0)));
    }

    /**
     * 持久化消息
     */
    private void storeMessage(SendMessage message, MqttMessageType type) {
        SubscribeCache.getInstance((igniteSubscribe)).findByTopic(message.topic())
                .forEach(subscribe -> MessageCache.getInstance(igniteMessage)
                        .put(subscribe.clientId(), message.type(type)));
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy