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

net.dreamlu.iot.mqtt.client.noear.integration.MqttClientPluginImpl Maven / Gradle / Ivy

There is a newer version: 2.3.7
Show newest version
/* Copyright (c) 2022 Peigen.info. All rights reserved. */

package net.dreamlu.iot.mqtt.client.noear.integration;

import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.iot.mqtt.client.noear.MqttClientCustomizer;
import net.dreamlu.iot.mqtt.client.noear.MqttClientSubscribe;
import net.dreamlu.iot.mqtt.client.noear.MqttClientTemplate;
import net.dreamlu.iot.mqtt.client.noear.config.MqttClientConfiguration;
import net.dreamlu.iot.mqtt.client.noear.config.MqttClientProperties;
import net.dreamlu.iot.mqtt.core.client.IMqttClientConnectListener;
import net.dreamlu.iot.mqtt.core.client.IMqttClientMessageListener;
import net.dreamlu.iot.mqtt.core.client.IMqttClientSession;
import net.dreamlu.iot.mqtt.core.client.MqttClientCreator;
import net.dreamlu.iot.mqtt.core.util.TopicUtil;
import org.noear.solon.Solon;
import org.noear.solon.core.AppContext;
import org.noear.solon.core.BeanWrap;
import org.noear.solon.core.Plugin;
import org.tio.core.ssl.SSLEngineCustomizer;
import org.tio.core.ssl.SslConfig;
import org.tio.utils.mica.ExceptionUtils;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * (MqttClientPluginImpl)
 *
 * @author Lihai
 * @version 1.0.0
 * @since 2023/7/20
 */
@Slf4j
public class MqttClientPluginImpl implements Plugin {
	private final List> subscribeClassTags = new ArrayList<>();
	private final List> subscribeMethodTags = new ArrayList<>();
	private AppContext context;

	@Override
	public void start(AppContext context) throws Throwable {
		this.context = context; //todo: 去掉 Solon.context() 写法,可同时兼容 2.5 之前与之后的版本 by noear,2023-09-15
		// 查找类上的 MqttClientSubscribe 注解
		context.beanBuilderAdd(MqttClientSubscribe.class, (clz, beanWrap, anno) -> {
			subscribeClassTags.add(new ExtractorClassTag<>(clz, beanWrap, anno));
		});
		// 查找方法上的 MqttClientSubscribe 注解
		context.beanExtractorAdd(MqttClientSubscribe.class, (bw, method, anno) -> {
			subscribeMethodTags.add(new ExtractorMethodTag<>(bw, method, anno));
		});
		context.lifecycle(-9, () -> {
			context.beanMake(MqttClientProperties.class);
			context.beanMake(MqttClientConfiguration.class);
			MqttClientProperties properties = context.getBean(MqttClientProperties.class);
			MqttClientCreator clientCreator = context.getBean(MqttClientCreator.class);

			// MqttClientTemplate init
			IMqttClientConnectListener clientConnectListener = context.getBean(IMqttClientConnectListener.class);
			MqttClientCustomizer customizers = context.getBean(MqttClientCustomizer.class);
			MqttClientTemplate clientTemplate = new MqttClientTemplate(clientCreator, clientConnectListener, customizers);
			BeanWrap mqttClientTemplateWrap = context.wrap(MqttClientTemplate.class, clientTemplate);
			context.putWrap(MqttClientTemplate.DEFAULT_CLIENT_TEMPLATE_BEAN, mqttClientTemplateWrap);
			context.putWrap(MqttClientTemplate.class, mqttClientTemplateWrap);

			// ssl 自定义配置
			SslConfig sslConfig = clientCreator.getSslConfig();
			if (sslConfig != null) {
				SSLEngineCustomizer sslCustomizer = context.getBean(SSLEngineCustomizer.class);
				if (sslCustomizer != null) {
					sslConfig.setSslEngineCustomizer(sslCustomizer);
				}
			}

			// 客户端 session
			IMqttClientSession clientSession = context.getBean(IMqttClientSession.class);
			clientCreator.clientSession(clientSession);

			// 添加启动时的临时订阅
			subscribeDetector();

			// connect
			if (properties.isEnabled()) {
				clientTemplate.connect();
			}
		});
	}

	private void subscribeDetector() {
		subscribeClassTags.forEach(each -> {
			MqttClientSubscribe anno = each.getAnno();
			MqttClientTemplate clientTemplate = getMqttClientTemplate(anno);
			String[] topicFilters = getTopicFilters(anno);
			IMqttClientMessageListener iMqttClientMessageListener = each.getBeanWrap().get();
			clientTemplate.addSubscriptionList(topicFilters, anno.qos(), iMqttClientMessageListener);
		});

		subscribeMethodTags.forEach(each -> {
			MqttClientSubscribe anno = each.getAnno();
			MqttClientTemplate clientTemplate = getMqttClientTemplate(anno);
			String[] topicFilters = getTopicFilters(anno);
			clientTemplate.addSubscriptionList(topicFilters, anno.qos(), (ctx, topic, message, payload) -> {
					try {
						each.getMethod().invoke(each.getBw().get(), topic, payload);
					} catch (Throwable e) {
						throw ExceptionUtils.unchecked(e);
					}
				}
			);
		});
	}

	@Override
	public void stop() throws Throwable {
		MqttClientTemplate clientTemplate = context.getBean(MqttClientTemplate.class);
		clientTemplate.destroy();
	}

	private MqttClientTemplate getMqttClientTemplate(MqttClientSubscribe anno) {
		return context.getBean(anno.clientTemplateBean());
	}

	private String[] getTopicFilters(MqttClientSubscribe anno) {
		// 1. 替换 solon cfg 变量
		// 2. 替换订阅中的其他变量
		return Arrays.stream(anno.value())
			.map((x) -> Optional.ofNullable(Solon.cfg().getByTmpl(x)).orElse(x))
			.map(TopicUtil::getTopicFilter)
			.toArray(String[]::new);
	}

	@Data
	@RequiredArgsConstructor
	private static class ExtractorClassTag {
		private final Class clz;
		private final BeanWrap beanWrap;
		private final T anno;
	}

	@Data
	@RequiredArgsConstructor
	private static class ExtractorMethodTag {
		private final BeanWrap bw;
		private final Method method;
		private final T anno;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy