package com.zy.iot.config; import com.zy.iot.entity.IotTopicConfig; import lombok.AccessLevel; import lombok.Data; import lombok.Getter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; import java.util.concurrent.ThreadLocalRandom; @Data @Component @ConfigurationProperties(prefix = "iot") public class IotProperties { private boolean enabled; private String endpoint; private Integer port = 8883; private String thingName; private String clientId; private boolean cleanSession; private boolean automaticReconnect = true; private Integer keepAliveSeconds = 60; private Integer connectionTimeoutSeconds = 10; private String persistenceDir; private String caCertPath; private String clientCertPath; private String privateKeyPath; private IotTopicConfig topics = new IotTopicConfig(); private Map pickStationMappings = new LinkedHashMap<>(); @Getter(AccessLevel.NONE) private volatile String resolvedClientIdCache; public String getResolvedClientId() { if (resolvedClientIdCache != null) { return resolvedClientIdCache; } synchronized (this) { if (resolvedClientIdCache != null) { return resolvedClientIdCache; } String base = null; if (clientId != null && clientId.trim().length() > 0) { base = clientId.trim(); } else if (thingName != null && thingName.trim().length() > 0) { base = thingName.trim(); } if (base == null) { return null; } resolvedClientIdCache = base + "-" + newClientIdSuffix(); return resolvedClientIdCache; } } private static String newClientIdSuffix() { long n = ThreadLocalRandom.current().nextLong() & 0xFFFFFFFFL; return Long.toHexString(n); } public boolean isTlsEnabled() { return isTlsMqttScheme(getServerUri()); } /** 与 Paho 建连 URI:完整前缀 mqtts/mqtt/wss/ws/ssl/tcp 原样;仅主机名时默认 mqtts 或 mqtt。 */ public String getServerUri() { if (endpoint == null || endpoint.trim().length() == 0) { return null; } String trimmed = endpoint.trim(); if (hasExplicitBrokerScheme(trimmed)) { return trimmed; } int resolvedPort = port == null ? 8883 : port; String scheme = resolvedPort == 1883 ? "mqtt://" : "mqtts://"; return scheme + trimmed + ":" + resolvedPort; } private static boolean hasExplicitBrokerScheme(String s) { String lower = s.toLowerCase(Locale.ROOT); return lower.startsWith("mqtts://") || lower.startsWith("mqtt://") || lower.startsWith("ssl://") || lower.startsWith("tcp://") || lower.startsWith("wss://") || lower.startsWith("ws://"); } private static boolean isTlsMqttScheme(String serverUri) { if (serverUri == null || serverUri.isEmpty()) { return false; } int p = serverUri.indexOf("://"); if (p <= 0) { return false; } String scheme = serverUri.substring(0, p).toLowerCase(Locale.ROOT); return "mqtts".equals(scheme) || "ssl".equals(scheme) || "wss".equals(scheme); } }