wulianwei 1 year ago
commit
136bb8a334
46 changed files with 2452 additions and 0 deletions
  1. 38 0
      .classpath
  2. 23 0
      .project
  3. 5 0
      .settings/org.eclipse.core.resources.prefs
  4. 8 0
      .settings/org.eclipse.jdt.core.prefs
  5. 4 0
      .settings/org.eclipse.m2e.core.prefs
  6. 58 0
      Californium.properties
  7. 119 0
      pom.xml
  8. 85 0
      src/main/java/regist/AES.java
  9. 96 0
      src/main/java/regist/AliDeviceHttp.java
  10. 76 0
      src/main/java/regist/AliDeviceQuery.java
  11. 223 0
      src/main/java/regist/AliDeviceRegist.java
  12. 381 0
      src/main/java/regist/IotCoapClientWithAes.java
  13. 170 0
      src/main/java/regist/MyServer.java
  14. 36 0
      src/main/java/regist/PropertyConfig.java
  15. 19 0
      src/main/java/regist/Regist.java
  16. 46 0
      src/main/java/regist/aliutil/Config.java
  17. 76 0
      src/main/java/regist/aliutil/MqttSign.java
  18. 146 0
      src/main/java/regist/aliutil/SignatureUtils.java
  19. 54 0
      src/main/java/regist/aliutil/UrlUtil.java
  20. 60 0
      src/main/java/regist/listener/CustomLogContextListener.java
  21. 39 0
      src/main/resources/application.properties
  22. 89 0
      src/main/resources/config/db.setting
  23. 171 0
      src/main/resources/logback.xml
  24. 5 0
      target/classes/META-INF/MANIFEST.MF
  25. 7 0
      target/classes/META-INF/maven/com.agent/ali-device-regist-4g/pom.properties
  26. 119 0
      target/classes/META-INF/maven/com.agent/ali-device-regist-4g/pom.xml
  27. 39 0
      target/classes/application.properties
  28. 89 0
      target/classes/config/db.setting
  29. 171 0
      target/classes/logback.xml
  30. BIN
      target/classes/regist/AES.class
  31. BIN
      target/classes/regist/AliDeviceHttp.class
  32. BIN
      target/classes/regist/AliDeviceQuery.class
  33. BIN
      target/classes/regist/AliDeviceRegist$1.class
  34. BIN
      target/classes/regist/AliDeviceRegist.class
  35. BIN
      target/classes/regist/IotCoapClientWithAes.class
  36. BIN
      target/classes/regist/MyServer.class
  37. BIN
      target/classes/regist/MyServerHandler.class
  38. BIN
      target/classes/regist/MyServerInitializer.class
  39. BIN
      target/classes/regist/PropertyConfig.class
  40. BIN
      target/classes/regist/Regist.class
  41. BIN
      target/classes/regist/aliutil/Config.class
  42. BIN
      target/classes/regist/aliutil/CryptoUtil.class
  43. BIN
      target/classes/regist/aliutil/MqttSign.class
  44. BIN
      target/classes/regist/aliutil/SignatureUtils.class
  45. BIN
      target/classes/regist/aliutil/UrlUtil.class
  46. BIN
      target/classes/regist/listener/CustomLogContextListener.class

+ 38 - 0
.classpath

@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java">
+		<attributes>
+			<attribute name="optional" value="true"/>
+			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="test" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+			<attribute name="test" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="maven.pomderived" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>

+ 23 - 0
.project

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>ali-device-regist-4G</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.m2e.core.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.m2e.core.maven2Nature</nature>
+	</natures>
+</projectDescription>

+ 5 - 0
.settings/org.eclipse.core.resources.prefs

@@ -0,0 +1,5 @@
+eclipse.preferences.version=1
+encoding//src/main/java=UTF-8
+encoding//src/main/resources=UTF-8
+encoding//src/test/java=UTF-8
+encoding//src/test/resources=UTF-8

+ 8 - 0
.settings/org.eclipse.jdt.core.prefs

@@ -0,0 +1,8 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
+org.eclipse.jdt.core.compiler.release=disabled
+org.eclipse.jdt.core.compiler.source=1.8

+ 4 - 0
.settings/org.eclipse.m2e.core.prefs

@@ -0,0 +1,4 @@
+activeProfiles=
+eclipse.preferences.version=1
+resolveWorkspaceProjects=true
+version=1

+ 58 - 0
Californium.properties

@@ -0,0 +1,58 @@
+#Californium CoAP Properties file
+#Sat Jul 23 11:38:37 CST 2022
+HTTP_SERVER_SOCKET_BUFFER_SIZE=8192
+UDP_CONNECTOR_OUT_CAPACITY=2147483647
+CONGESTION_CONTROL_ALGORITHM=Cocoa
+USE_CONGESTION_CONTROL=false
+ACK_TIMEOUT=2000
+MAX_ACTIVE_PEERS=150000
+TCP_CONNECT_TIMEOUT=10000
+NOTIFICATION_CHECK_INTERVAL_COUNT=100
+MAX_MESSAGE_SIZE=1024
+MID_TRACKER_GROUPS=16
+DEDUPLICATOR=DEDUPLICATOR_MARK_AND_SWEEP
+TCP_CONNECTION_IDLE_TIMEOUT=10
+COAP_PORT=5683
+ACK_TIMEOUT_SCALE=2.0
+PREFERRED_BLOCK_SIZE=512
+NETWORK_STAGE_RECEIVER_THREAD_COUNT=6
+DTLS_AUTO_RESUME_TIMEOUT=30000
+MAX_LATENCY=100000
+MAX_SERVER_RESPONSE_DELAY=250000
+DTLS_CONNECTION_ID_LENGTH=
+PROTOCOL_STAGE_THREAD_COUNT=6
+MAX_TRANSMIT_WAIT=93000
+MULTICAST_BASE_MID=65000
+UDP_CONNECTOR_RECEIVE_BUFFER=0
+EXCHANGE_LIFETIME=247000
+HTTP_SERVER_SOCKET_TIMEOUT=100000
+CROP_ROTATION_PERIOD=2000
+UDP_CONNECTOR_DATAGRAM_SIZE=2048
+MAX_RETRANSMIT=4
+MAX_PEER_INACTIVITY_PERIOD=600
+MAX_RESOURCE_BODY_SIZE=8192
+NOTIFICATION_CHECK_INTERVAL=86400000
+LEISURE=5000
+HTTP_CACHE_RESPONSE_MAX_AGE=86400
+BLOCKWISE_STATUS_LIFETIME=300000
+RESPONSE_MATCHING=STRICT
+UDP_CONNECTOR_SEND_BUFFER=0
+MID_TACKER=GROUPED
+TCP_WORKER_THREADS=1
+NETWORK_STAGE_SENDER_THREAD_COUNT=6
+NON_LIFETIME=145000
+TOKEN_SIZE_LIMIT=8
+HTTP_PORT=8080
+MARK_AND_SWEEP_INTERVAL=10000
+HEALTH_STATUS_INTERVAL=0
+ACK_RANDOM_FACTOR=1.5
+SECURE_SESSION_TIMEOUT=86400
+NSTART=1
+USE_RANDOM_MID_START=true
+HTTP_CACHE_SIZE=32
+TLS_HANDSHAKE_TIMEOUT=10000
+DTLS_CONNECTION_ID_NODE_ID=
+PROBING_RATE=1.0
+BLOCKWISE_STRICT_BLOCK2_OPTION=false
+NOTIFICATION_REREGISTRATION_BACKOFF=2000
+COAP_SECURE_PORT=5684

+ 119 - 0
pom.xml

@@ -0,0 +1,119 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.agent</groupId>
+  <artifactId>ali-device-regist-4g</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <name>Archetype - ali-device-regist-4g</name>
+  <url>http://maven.apache.org</url>
+  
+  <properties>
+		<encoding>UTF-8</encoding>
+		<java-version>1.8</java-version>
+		<maven.compiler.source>1.8</maven.compiler.source>
+		<maven.compiler.target>1.8</maven.compiler.target>
+		<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
+  </properties>
+  <dependencies>
+        <dependency>
+            <groupId>org.eclipse.paho</groupId>
+            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
+            <version>1.2.1</version>
+        </dependency>
+        <dependency>
+		  <groupId>org.eclipse.californium</groupId>
+		  <artifactId>californium-core</artifactId>
+		  <version>2.0.0-M17</version>
+		</dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.61</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>27.0.1-jre</version>
+        </dependency>
+        <dependency>
+		    <groupId>io.netty</groupId>
+		    <artifactId>netty-all</artifactId>
+		    <version>4.1.76.Final</version>
+		</dependency>
+		<dependency>
+		    <groupId>cn.hutool</groupId>
+		    <artifactId>hutool-all</artifactId>
+		    <version>5.7.22</version>
+		</dependency>
+		<dependency>
+	    	<groupId>com.zaxxer</groupId>
+		    <artifactId>HikariCP</artifactId>
+		    <version>3.4.2</version>
+		</dependency>
+		
+		<dependency>
+		    <groupId>org.slf4j</groupId>
+		    <artifactId>slf4j-api</artifactId>
+		    <version>1.7.36</version>
+		</dependency>
+		<dependency>
+		    <groupId>ch.qos.logback</groupId>
+		    <artifactId>logback-classic</artifactId>
+		    <version>1.2.11</version>
+		</dependency>
+		<dependency>
+		    <groupId>mysql</groupId>
+		    <artifactId>mysql-connector-java</artifactId>
+		    <version>5.1.33</version>
+		</dependency>
+		<dependency>
+		    <groupId>org.apache.commons</groupId>
+		    <artifactId>commons-lang3</artifactId>
+		    <version>3.9</version>
+		</dependency>
+		<dependency>
+		  <groupId>commons-codec</groupId>
+		  <artifactId>commons-codec</artifactId>
+		  <version>1.13</version>
+		</dependency>
+	</dependencies> 
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.8</source>
+					<target>1.8</target>
+					<encoding>UTF-8</encoding>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<configuration>
+					<appendAssemblyId>false</appendAssemblyId>
+					<descriptorRefs>
+						<descriptorRef>jar-with-dependencies</descriptorRef>
+					</descriptorRefs>
+					<archive>
+						<manifest>
+							<!-- 此处指定main方法入口的class -->
+							<mainClass>regist.Regist</mainClass>
+						</manifest>
+					</archive>
+				</configuration>
+				<executions>
+					<execution>
+						<id>make-assembly</id>
+						<phase>package</phase>
+						<goals>
+							<goal>assembly</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build> 
+</project>

+ 85 - 0
src/main/java/regist/AES.java

@@ -0,0 +1,85 @@
+package regist;
+import javax.crypto.Cipher; 
+import javax.crypto.spec.SecretKeySpec; 
+ 
+/** 
+ * 
+ * @author Administrator 
+ * 
+ */ 
+public class AES { 
+	 
+    // 加密 
+    public static byte[] encrypt(String sSrc, String sKey) throws Exception { 
+        if (sKey == null) { 
+            System.out.print("Key为空null"); 
+            return null; 
+        } 
+        // 判断Key是否为16位 
+        if (sKey.length() != 16) { 
+            System.out.print("Key长度不是16位"); 
+            return null; 
+        } 
+        byte[] raw = sKey.getBytes("utf-8"); 
+        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES"); 
+        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式" 
+        cipher.init(Cipher.ENCRYPT_MODE, skeySpec); 
+        byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8")); 
+        return encrypted;
+    } 
+ 
+ // 解密
+    public static String decrypt(byte[] encrypted1, String sKey) throws Exception {
+        try {
+            // 判断Key是否正确
+            if (sKey == null) {
+                System.out.print("Key为空null");
+                return null;
+            }
+            // 判断Key是否为16位
+            if (sKey.length() != 16) {
+                System.out.print("Key长度不是16位");
+                return null;
+            }
+            byte[] raw = sKey.getBytes("utf-8");
+            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
+            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
+            try {
+                byte[] original = cipher.doFinal(encrypted1);
+                String originalString = new String(original,"utf-8");
+                return originalString;
+            } catch (Exception e) {
+            	e.printStackTrace();
+                System.out.println(e.toString());
+                return null;
+            }
+        } catch (Exception ex) {
+            System.out.println(ex.toString());
+            return null;
+        }
+    }
+
+    
+ 
+    public static void main(String[] args) throws Exception { 
+        /* 
+         * 此处使用AES-128-ECB加密模式,key需要为16位。 
+         */ 
+        // 需要加密的字串 
+    	String cKey = "tuorenzhinenghua"; 
+        String cSrc = "43186642383902B4&a1xJ4qC587v&89860471162180041210"; 
+        System.out.println(cSrc); 
+        // 加密 
+        byte[] enString = AES.encrypt(cSrc, cKey); 
+        for(byte a:enString)
+		 {
+			 System.out.printf("%02x",a);
+		 }
+       String result = AES.decrypt(enString, cKey);
+       System.out.println("\r\naes decrypt:"+result);
+
+       
+    } 
+} 
+ 

+ 96 - 0
src/main/java/regist/AliDeviceHttp.java

@@ -0,0 +1,96 @@
+package regist;
+
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.alibaba.fastjson.JSONObject;
+
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.http.HttpUtil;
+import regist.aliutil.Config;
+import regist.aliutil.SignatureUtils;
+
+public class AliDeviceHttp {
+	private static Logger logger = LoggerFactory.getLogger(AliDeviceHttp.class);
+
+	public static Map<String, String> getInitParameter() {
+		String timestamp = LocalDateTimeUtil.format(LocalDateTime.now(ZoneOffset.UTC), "yyyy-MM-dd'T'HH:mm:ss'Z'");
+		Map<String, String> map = new HashMap<String, String>();
+		// 公共参数
+		map.put("Format", "JSON");
+		map.put("Version", "2018-01-20");
+		map.put("AccessKeyId", PropertyConfig.getStr("accessKey"));
+		map.put("SignatureMethod", "HMAC-SHA1");
+		map.put("Timestamp", timestamp);
+		map.put("SignatureVersion", "1.0");
+		map.put("SignatureNonce", RandomUtil.randomNumbers(14));
+		map.put("RegionId", PropertyConfig.getStr("regionId"));
+		return map;
+	}
+
+	public static JSONObject deviceQuery(String deviceName) {
+		JSONObject data = new JSONObject();
+		Map<String, String> map = getInitParameter();
+		// 请求参数
+		map.put("Action", "QueryDeviceDetail");
+		if (StringUtils.isNotEmpty(PropertyConfig.getStr("instanceId"))) {
+			map.put("IotInstanceId", PropertyConfig.getStr("instanceId"));
+		}
+		map.put("DeviceName", deviceName);
+		map.put("ProductKey", PropertyConfig.getStr("productKey"));
+
+		try {
+			String signature = SignatureUtils.generate("GET", map, PropertyConfig.getStr("accessKeySecret"));
+			map.put("Signature", signature);
+			Map<String, Object> httpParamMap = new HashMap<String, Object>(map);
+			String result = HttpUtil.get(Config.API_ADDRESS, httpParamMap);
+			System.out.println("result=====" + result);
+			JSONObject queryJson = (JSONObject) JSONObject.parse(result);
+			if (queryJson.getBoolean("Success")) {
+				data = queryJson.getJSONObject("Data");
+			}
+		} catch (Exception e) {
+			logger.error("物联网平台设备查询失败", e);
+		}
+		return data;
+	}
+
+	public static JSONObject deviceRegist(String deviceName) {
+		JSONObject data = new JSONObject();
+		Map<String, String> map = getInitParameter();
+
+		// 请求参数
+		map.put("Action", "RegisterDevice"); // 注册设备
+		if (StringUtils.isNotEmpty(PropertyConfig.getStr("instanceId"))) {
+			map.put("IotInstanceId", PropertyConfig.getStr("instanceId"));
+		}
+		map.put("DeviceName", deviceName);
+		map.put("ProductKey", PropertyConfig.getStr("productKey"));
+
+		try {
+			String signature = SignatureUtils.generate("GET", map, PropertyConfig.getStr("accessKeySecret"));
+			map.put("Signature", signature);
+			Map<String, Object> httpParamMap = new HashMap<String, Object>(map);
+			String result = HttpUtil.get(Config.API_ADDRESS, httpParamMap);
+			System.out.println("result====" + result);
+			JSONObject queryJson = (JSONObject) JSONObject.parse(result);
+			if (queryJson.getBoolean("Success")) {
+				data = queryJson.getJSONObject("Data");
+			}
+		} catch (Exception e) {
+			logger.error("物联网平台设备查询失败", e);
+		}
+		return data;
+	}
+
+	public static void main(String[] args) {
+		deviceRegist("123456789");
+	}
+}

+ 76 - 0
src/main/java/regist/AliDeviceQuery.java

@@ -0,0 +1,76 @@
+package regist;
+
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.alibaba.fastjson.JSONObject;
+
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.http.HttpUtil;
+import regist.aliutil.Config;
+import regist.aliutil.MqttSign;
+import regist.aliutil.SignatureUtils;
+
+public class AliDeviceQuery {
+	private static Logger logger = LoggerFactory.getLogger(AliDeviceQuery.class);
+	public  static JSONObject deviceQuery(String deviceName) {
+		JSONObject conn_info = new JSONObject();
+		String timestamp = LocalDateTimeUtil.format(LocalDateTime.now(ZoneOffset.UTC), "yyyy-MM-dd'T'HH:mm:ss'Z'");
+        Map<String, String> map = new HashMap<String, String>();
+        // 公共参数
+        map.put("Format", "JSON");
+        map.put("Version", "2018-01-20");
+        map.put("AccessKeyId",  PropertyConfig.getStr("accessKey"));
+        map.put("SignatureMethod", "HMAC-SHA1");
+        map.put("Timestamp", timestamp);
+        map.put("SignatureVersion", "1.0");
+        map.put("SignatureNonce", RandomUtil.randomNumbers(14));
+        map.put("RegionId", PropertyConfig.getStr("regionId"));
+        // 请求参数
+        map.put("Action", "QueryDeviceDetail");
+        if(StringUtils.isNotEmpty(PropertyConfig.getStr("instanceId")))
+        {
+        	map.put("IotInstanceId", PropertyConfig.getStr("instanceId"));
+        }
+        map.put("DeviceName", deviceName);
+        map.put("ProductKey", PropertyConfig.getStr("productKey"));
+        
+        try {
+            String signature = SignatureUtils.generate("GET", map, PropertyConfig.getStr("accessKeySecret"));
+            map.put("Signature", signature);
+            Map<String,Object> httpParamMap = new HashMap<String, Object>(map);
+            String result = HttpUtil.get(Config.API_ADDRESS,httpParamMap);
+            System.out.println("result====="+result);
+            JSONObject queryJson = (JSONObject) JSONObject.parse(result);
+            if(queryJson.getBoolean("Success"))
+            {
+            	JSONObject data = queryJson.getJSONObject("Data");
+            	String deviceSecret = data.getString("DeviceSecret");
+            	MqttSign sign = new MqttSign();
+            	sign.calculate(PropertyConfig.getStr("productKey"), deviceName, deviceSecret);
+                conn_info.put("address",PropertyConfig.getStr("productKey")+Config.MQTT_ADDRESS_SUFF);
+                conn_info.put("port",Config.MQTT_PORT);
+                conn_info.put("productKey", PropertyConfig.getStr("productKey"));
+                conn_info.put("clientId",sign.getClientid());
+                conn_info.put("userName", sign.getUsername());
+                conn_info.put("password", sign.getPassword());
+            }            	
+        } catch (Exception e) {
+            e.printStackTrace();
+            logger.error("物联网平台设备查询失败",e);
+            return conn_info;
+        }
+		return conn_info;
+	}
+	
+	public static void main(String[] args) {
+		deviceQuery("43166209363903D1");
+	}
+}

+ 223 - 0
src/main/java/regist/AliDeviceRegist.java

@@ -0,0 +1,223 @@
+package regist;
+import java.nio.charset.StandardCharsets;
+import java.util.Random;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
+import org.eclipse.paho.client.mqttv3.MqttCallback;
+import org.eclipse.paho.client.mqttv3.MqttClient;
+import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
+import org.eclipse.paho.client.mqttv3.MqttException;
+import org.eclipse.paho.client.mqttv3.MqttMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.alibaba.fastjson.JSONObject;
+
+import cn.hutool.cache.CacheUtil;
+import cn.hutool.cache.impl.FIFOCache;
+import regist.aliutil.Config;
+
+
+public class AliDeviceRegist {
+		
+	private static Logger logger = LoggerFactory.getLogger(AliDeviceRegist.class);
+	public static FIFOCache<String, Object> cacheDevice = CacheUtil.newFIFOCache(1000, 3600 * 1000);
+	
+	 
+    /**
+     * 动态注册。
+     *
+     * @param deviceName 设备名称
+     * @throws Exception
+     */
+    public boolean register(String deviceName) throws Exception {
+        // 表示客户端ID,建议使用设备的MAC地址或SN码,64字符内。
+    	String productKey = PropertyConfig.getStr("productKey");
+    	String broker  = "ssl://" + productKey + ".iot-as-mqtt." + PropertyConfig.getStr("regionId") + ".aliyuncs.com:443";;
+    	String productSecret = PropertyConfig.getStr("productSecret");
+        String clientId = productKey + "." + deviceName;
+
+        // 获取随机值。
+        Random r = new Random();
+        int random = r.nextInt(1000);
+        // securemode只能为2表示只能使用TLS;signmethod指定签名算法。
+        String clientOpts = "|securemode=2,authType=regnwl,signmethod=" + Config.HMAC_ALGORITHM + ",random=" 
+        		+ random +"|";
+        if(StringUtils.isNotEmpty(PropertyConfig.getStr("instanceId"))){
+        	clientOpts = "|securemode=2,authType=regnwl,signmethod=" + Config.HMAC_ALGORITHM + ",random=" 
+            		+ random + ",instanceId="+PropertyConfig.getStr("instanceId")+"|";
+        }
+
+        // MQTT接入客户端ID。
+        String mqttClientId = clientId + clientOpts;
+
+        // MQTT接入用户名。
+        String mqttUsername = deviceName + "&" + productKey;
+
+        // MQTT接入密码,即签名。
+        JSONObject params = new JSONObject();
+        params.put("productKey", productKey);
+        params.put("deviceName", deviceName);
+        params.put("random", random);
+        String mqttPassword = sign(params, productSecret);
+        // 通过MQTT connect报文进行动态注册。
+        return connect(broker, mqttClientId, mqttUsername, mqttPassword);
+    }
+
+    /**
+     * 通过MQTT connect报文发送动态注册信息。
+     *
+     * @param serverURL 动态注册域名地址
+     * @param clientId 客户端ID
+     * @param username MQTT用户名
+     * @param password MQTT密码
+     */
+    @SuppressWarnings("resource")
+    private boolean connect(String serverURL, String clientId, final String username, String password) {
+    	MqttConnectOptions connOpts = new MqttConnectOptions();
+        connOpts.setCleanSession(false);
+        connOpts.setKeepAliveInterval(60*4);
+        connOpts.setMqttVersion(4);// MQTT 3.1.1
+        connOpts.setUserName(username);// 用户名
+        connOpts.setPassword(password.toCharArray());// 密码
+        connOpts.setAutomaticReconnect(false); // MQTT动态注册协议规定必须关闭自动重连。
+        System.out.println("----- register params -----");
+        System.out.print("server=" + serverURL + ",clientId=" + clientId);
+        System.out.println(",username=" + username + ",password=" + password);
+    	try {
+           // MemoryPersistence persistence = new MemoryPersistence();
+            final MqttClient sampleClient = new MqttClient(serverURL, clientId);
+            sampleClient.setCallback(new MqttCallback() {
+                public void messageArrived(String topic, MqttMessage message) throws Exception {
+                    // 仅处理动态注册返回消息。
+                    if (Config.REGISTER_TOPIC.equals(topic)) {
+                        String payload = new String(message.getPayload(), StandardCharsets.UTF_8);
+                        System.out.println("----- register result -----");
+                        System.out.println(payload);
+                        JSONObject regist_info = JSONObject.parseObject(payload);
+                        JSONObject conn_info = new JSONObject();
+                        conn_info.put("address",PropertyConfig.getStr("productKey")+Config.MQTT_ADDRESS_SUFF);
+                        conn_info.put("port",Config.MQTT_PORT);
+                        conn_info.put("productKey", PropertyConfig.getStr("productKey"));
+                        conn_info.put("clientId",regist_info.getString("clientId")+Config.MQTT_CLIENT_NWL_SUFF);
+                        conn_info.put("userName", username);
+                        conn_info.put("password", regist_info.getString("deviceToken"));
+                        cacheDevice.put(regist_info.getString("deviceName"), conn_info.toString());
+                    }
+                    sampleClient.disconnect();
+                    sampleClient.close();
+                }
+
+                public void deliveryComplete(IMqttDeliveryToken token) {
+                }
+
+                public void connectionLost(Throwable cause) {
+                }
+            });
+            sampleClient.connect(connOpts);
+            return true;
+        } catch (MqttException e) {
+            System.out.println("excep " + e);
+            logger.error("物联网平台mqtt注册失败",e);
+            return false;
+        }
+    }
+
+    /**
+     * 动态注册签名。
+     *
+     * @param params 签名参数
+     * @param productSecret 产品密钥
+     * @return 签名十六进制字符串
+     */
+    private String sign(JSONObject params, String productSecret) {
+
+        // 请求参数按字典顺序排序。
+        Set<String> keys = getSortedKeys(params);
+
+        // sign、signMethod除外。
+        keys.remove("sign");
+        keys.remove("signMethod");
+
+        // 组装签名明文。
+        StringBuffer content = new StringBuffer();
+        for (String key : keys) {
+            content.append(key);
+            content.append(params.getString(key));
+        }
+
+        // 计算签名。
+        String sign = encrypt(content.toString(), productSecret);
+        System.out.println("sign content=" + content);
+        System.out.println("sign result=" + sign);
+
+        return sign;
+    }
+
+    /**
+     * 获取JSON对象排序后的key集合。
+     *
+     * @param json 需要排序的JSON对象
+     * @return 排序后的key集合
+     */
+    private Set<String> getSortedKeys(JSONObject json) {
+        SortedMap<String, String> map = new TreeMap<String, String>();
+        for (String key : json.keySet()) {
+            String vlaue = json.getString(key);
+            map.put(key, vlaue);
+        }
+        return map.keySet();
+    }
+
+    /**
+     * 使用HMAC_ALGORITHM加密。
+     *
+     * @param content 明文
+     * @param secret 密钥
+     * @return 密文
+     */
+    private String encrypt(String content, String secret) {
+        try {
+            byte[] text = content.getBytes(StandardCharsets.UTF_8);
+            byte[] key = secret.getBytes(StandardCharsets.UTF_8);
+            SecretKeySpec secretKey = new SecretKeySpec(key, Config.HMAC_ALGORITHM);
+            Mac mac = Mac.getInstance(secretKey.getAlgorithm());
+            mac.init(secretKey);
+            return byte2hex(mac.doFinal(text));
+        } catch (Exception e) {
+            e.printStackTrace();
+            logger.error("注册签名失败",e);
+            return null;
+        }
+    }
+
+    /**
+     * 二进制转十六进制字符串。
+     *
+     * @param b 二进制数组
+     * @return 十六进制字符串
+     */
+    private String byte2hex(byte[] b) {
+        StringBuffer sb = new StringBuffer();
+        for (int n = 0; b != null && n < b.length; n++) {
+            String stmp = Integer.toHexString(b[n] & 0XFF);
+            if (stmp.length() == 1) {
+                sb.append('0');
+            }
+            sb.append(stmp);
+        }
+        return sb.toString().toUpperCase();
+    }
+
+    public static void main(String[] args) throws Exception {
+    	AliDeviceRegist regist = new AliDeviceRegist();
+    	regist.register("12357");
+	}
+}

+ 381 - 0
src/main/java/regist/IotCoapClientWithAes.java

@@ -0,0 +1,381 @@
+package regist;
+/*   
+ * Copyright © 2019 Alibaba. All rights reserved.
+ */
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.lang3.RandomUtils;
+import org.eclipse.californium.core.CoapClient;
+import org.eclipse.californium.core.CoapResponse;
+import org.eclipse.californium.core.Utils;
+import org.eclipse.californium.core.coap.CoAP;
+import org.eclipse.californium.core.coap.CoAP.Code;
+import org.eclipse.californium.core.coap.CoAP.Type;
+import org.eclipse.californium.core.coap.MediaTypeRegistry;
+import org.eclipse.californium.core.coap.Option;
+import org.eclipse.californium.core.coap.OptionNumberRegistry;
+import org.eclipse.californium.core.coap.OptionSet;
+import org.eclipse.californium.core.coap.Request;
+import org.eclipse.californium.elements.exception.ConnectorException;
+
+import com.alibaba.fastjson.JSONObject;
+
+/**
+ * CoAP客户端连接阿里云物联网平台,基于eclipse californium开发。
+ * 自主接入开发流程及参数填写,请参见《CoAP连接通信》的使用对称加密自主接入章节。
+ */
+public class IotCoapClientWithAes {
+
+    // ===================需要用户填写的参数,开始。===========================
+    // 地域ID,以华东2(上海)为例。
+   // private static String regionId = "cn-shanghai";
+    // 产品productKey。
+    private static String productKey = "he1f6YdSWHW";
+    // 设备名成deviceName。
+    private static String deviceName = "43186642383902B4";
+    // 设备密钥deviceSecret。
+    private static String deviceSecret = "e7a246378fa3c25fbb1e88264053074e";
+    // ===================需要用户填写的参数,结束。===========================
+
+    // 定义加密方式,MAC算法可选以下算法:HmacMD5、HmacSHA1,需与signmethod一致。
+    private static final String HMAC_ALGORITHM = "hmacsha1";
+
+    // CoAP接入地址,对称加密端口号是5682。
+   // private static String serverURI = "coap://" + productKey + ".coap." + regionId + ".link.aliyuncs.com:5682";
+    private static String serverURI = "iot-060a0bgd.coap.iothub.aliyuncs.com:5682";
+
+    // 发送消息用的Topic。需要在控制台自定义Topic,设备操作权限需选择为“发布”。
+    private static String updateTopic = "/sys/" + productKey + "/" + deviceName + "/thing/model/up_raw";
+    
+    private static String getShadowTopic = "/shadow/get/" + productKey + "/" + deviceName ;
+
+    // token option
+    private static final int COAP2_OPTION_TOKEN = 2088;
+    // seq option
+    private static final int COAP2_OPTION_SEQ = 2089;
+
+    // 加密算法sha256。
+    private static final String SHA_256 = "SHA-256";
+
+    private static final int DIGITAL_16 = 16;
+    private static final int DIGITAL_48 = 48;
+
+    // CoAP客户端。
+    private CoapClient coapClient = new CoapClient();
+
+    // token有效期7天,失效后需要重新获取。
+    private String token = "OQJgYw8EsouO2VG1zyDmhe1f00.4004";
+    private String random = "a8d3632236fc245e";
+    @SuppressWarnings("unused")
+    private long seqOffset = 3;
+
+    /**
+     * 初始化CoAP客户端。
+     * 
+     * @param productKey,产品key。
+     * @param deviceName,设备名称。
+     * @param deviceSecret ,设备密钥。
+     */
+    public void connect(String productKey, String deviceName, String deviceSecret) {
+        try {
+        	System.out.println("in---------------");
+            // 认证uri,/auth。
+            String uri = serverURI + "/auth";
+
+            // 只支持POST方法。
+            Request request = new Request(Code.POST, Type.CON);
+
+            // 设置option。
+            OptionSet optionSet = new OptionSet();
+            optionSet.addOption(new Option(OptionNumberRegistry.CONTENT_FORMAT, MediaTypeRegistry.APPLICATION_JSON));
+            optionSet.addOption(new Option(OptionNumberRegistry.ACCEPT, MediaTypeRegistry.APPLICATION_JSON));
+            request.setOptions(optionSet);
+
+            // 设置认证uri。
+            request.setURI(uri);
+            request.setMID(1);
+
+            // 设置认证请求payload。
+            request.setPayload(authBody(productKey, deviceName, deviceSecret));
+            
+
+            // 发送认证请求。
+            CoapResponse response = coapClient.advanced(request);
+            System.out.println("out---------------");
+            System.out.println(Utils.prettyPrint(response));
+            System.out.println();
+
+            // 解析请求响应。
+            JSONObject json = JSONObject.parseObject(response.getResponseText());
+            token = json.getString("token");
+            random = json.getString("random");
+            seqOffset = json.getLongValue("seqOffset");
+        } catch (ConnectorException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 发送消息。
+     * 
+     * @param topic,发送消息的Topic。
+     * @param payload,消息内容。
+     */
+    public void publish(String topic, byte[] payload) {
+        try {
+            // 消息发布uri,/topic/${topic}。
+            String uri = serverURI + "/topic" + topic;
+
+            // AES加密seq,seq=RandomUtils.nextInt()。
+            String shaKey = encod(deviceSecret + "," + random);
+            System.out.println("shaKey:"+shaKey);
+            byte[] keys = Hex.decodeHex(shaKey.substring(DIGITAL_16, DIGITAL_48));
+            System.out.println();
+            for(byte b: keys) {
+            	System.out.printf("%02x",b);
+            }
+            byte[] seqBytes = encrypt(String.valueOf(7).getBytes(StandardCharsets.UTF_8), keys);
+            System.out.println();
+            for(byte b: seqBytes) {
+            	System.out.printf("%02x",b);
+            }
+            
+            // 只支持POST方法。
+            Request request = new Request(CoAP.Code.POST, CoAP.Type.CON);
+
+            // 设置option。
+            OptionSet optionSet = new OptionSet();
+            optionSet.addOption(new Option(OptionNumberRegistry.CONTENT_FORMAT, MediaTypeRegistry.APPLICATION_JSON));
+            optionSet.addOption(new Option(OptionNumberRegistry.ACCEPT, MediaTypeRegistry.APPLICATION_JSON));
+            optionSet.addOption(new Option(COAP2_OPTION_TOKEN, token));
+            optionSet.addOption(new Option(COAP2_OPTION_SEQ, seqBytes));
+            request.setOptions(optionSet);
+
+            // 设置消息发布uri。
+            request.setURI(uri);
+            request.setMID(9);
+
+            // 设置消息payload。
+            byte[] paybyte = encrypt(payload, keys);
+            System.out.println("paybyte:");
+            for(byte b: paybyte) {
+            	System.out.printf("%02x",b);
+            }
+            request.setPayload(paybyte);
+            
+
+            // 发送消息。
+            CoapResponse response = coapClient.advanced(request);
+            System.out.println(Utils.prettyPrint(response));
+            
+            // 解析消息发送结果。
+			
+			  String result = null; if (response.getPayload() != null) { result = new
+			  String(decrypt(response.getPayload(), keys)); }
+			  System.out.println("payload: " + result);
+			 
+            System.out.println();
+        } catch (ConnectorException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (DecoderException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 生成认证请求内容。
+     * 
+     * @param productKey,产品key。
+     * @param deviceName,设备名字。
+     * @param deviceSecret,设备密钥。
+     * @return 认证请求。
+     */
+    private String authBody(String productKey, String deviceName, String deviceSecret) {
+
+        // 构建认证请求。
+        JSONObject body = new JSONObject();
+        body.put("productKey", productKey);
+        body.put("deviceName", deviceName);
+        body.put("clientId", productKey + "." + deviceName);
+//        body.put("timestamp", String.valueOf(System.currentTimeMillis()));
+        body.put("signmethod", HMAC_ALGORITHM);
+        body.put("seq", 2);
+        body.put("sign", sign(body, deviceSecret));
+
+        System.out.println("----- auth body -----");
+        System.out.println(body.toJSONString());
+
+        return body.toJSONString();
+    }
+
+    /**
+     * 设备端签名。
+     * 
+     * @param params,签名参数。
+     * @param deviceSecret,设备密钥。
+     * @return 签名十六进制字符串。
+     */
+    private String sign(JSONObject params, String deviceSecret) {
+
+        // 请求参数按字典顺序排序。
+        Set<String> keys = getSortedKeys(params);
+
+        // sign、signmethod、version、resources除外。
+        keys.remove("sign");
+        keys.remove("signmethod");
+        keys.remove("version");
+        keys.remove("resources");
+
+        // 组装签名明文。
+        StringBuffer content = new StringBuffer();
+        for (String key : keys) {
+            content.append(key);
+            content.append(params.getString(key));
+        }
+        System.out.println("content:"+content.toString());
+        // 计算签名。
+        String sign = encrypt(content.toString(), deviceSecret);
+        System.out.println("sign content=" + content);
+        System.out.println("sign result=" + sign);
+
+        return sign;
+    }
+
+    /**
+     * 获取JSON对象排序后的key集合。
+     * 
+     * @param json,需要排序的JSON对象。
+     * @return 排序后的key集合。
+     */
+    private Set<String> getSortedKeys(JSONObject json) {
+        SortedMap<String, String> map = new TreeMap<String, String>();
+        for (String key : json.keySet()) {
+            String vlaue = json.getString(key);
+            map.put(key, vlaue);
+        }
+        return map.keySet();
+    }
+
+    /**
+     * 使用HMAC_ALGORITHM加密。
+     * 
+     * @param content,明文。
+     * @param secret,密钥。
+     * @return 密文。
+     */
+    private String encrypt(String content, String secret) {
+        try {
+            byte[] text = content.getBytes(StandardCharsets.UTF_8);
+            byte[] key = secret.getBytes(StandardCharsets.UTF_8);
+            SecretKeySpec secretKey = new SecretKeySpec(key, HMAC_ALGORITHM);
+            Mac mac = Mac.getInstance(secretKey.getAlgorithm());
+            mac.init(secretKey);
+            return Hex.encodeHexString(mac.doFinal(text));
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * SHA-256
+     * 
+     * @param str,待加密的报文。
+     */
+    private String encod(String str) {
+        MessageDigest messageDigest;
+        String encdeStr = "";
+        try {
+            messageDigest = MessageDigest.getInstance(SHA_256);
+            byte[] hash = messageDigest.digest(str.getBytes(StandardCharsets.UTF_8));
+            encdeStr = Hex.encodeHexString(hash);
+        } catch (NoSuchAlgorithmException e) {
+            System.out.println(String.format("Exception@encod: str=%s;", str));
+            e.printStackTrace();
+            return null;
+        }
+        return encdeStr;
+    }
+
+    // AES加解密算法。
+    private static final String IV = "543yhjy97ae7fyfg";
+    private static final String TRANSFORM = "AES/CBC/PKCS5Padding";
+    private static final String ALGORITHM = "AES";
+
+    /**
+     * key length = 16 bits
+     */
+    private byte[] encrypt(byte[] content, byte[] key) {
+    	System.out.println();
+        return encrypt(content, key, IV);
+    }
+
+    /**
+     * key length = 16 bits
+     */
+    private byte[] decrypt(byte[] content, byte[] key) {
+        return decrypt(content, key, IV);
+    }
+
+    /**
+     * aes 128 cbc key length = 16 bits
+     */
+    private byte[] encrypt(byte[] content, byte[] key, String ivContent) {
+        try {
+            SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);
+            Cipher cipher = Cipher.getInstance(TRANSFORM);
+            IvParameterSpec iv = new IvParameterSpec(ivContent.getBytes(StandardCharsets.UTF_8));
+            cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
+            return cipher.doFinal(content);
+        } catch (Exception ex) {
+            System.out.println(
+                    String.format("AES encrypt error, %s, %s, %s", content, Hex.encodeHex(key), ex.getMessage()));
+            return null;
+        }
+    }
+
+    /**
+     * aes 128 cbc key length = 16 bits
+     */
+    private byte[] decrypt(byte[] content, byte[] key, String ivContent) {
+        try {
+            SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM);
+            Cipher cipher = Cipher.getInstance(TRANSFORM);
+            IvParameterSpec iv = new IvParameterSpec(ivContent.getBytes(StandardCharsets.UTF_8));
+            cipher.init(Cipher.DECRYPT_MODE, keySpec, iv);
+            return cipher.doFinal(content);
+        } catch (Exception ex) {
+            System.out.println(String.format("AES decrypt error, %s, %s, %s", Hex.encodeHex(content),
+                    Hex.encodeHex(key), ex.getMessage()));
+            return null;
+        }
+    }
+
+    public static void main(String[] args) throws InterruptedException {
+    	JSONObject json = new JSONObject();
+    	json.put("method", "get");
+    	System.out.println("json:"+json.toJSONString());
+        IotCoapClientWithAes client = new IotCoapClientWithAes();
+        //client.connect(productKey, deviceName, deviceSecret);
+       client.publish(getShadowTopic, json.toJSONString().getBytes(StandardCharsets.UTF_8));
+       // client.publish(updateTopic, new byte[] { 0x01, 0x02, 0x03, 0x05 });
+    }
+}
+

+ 170 - 0
src/main/java/regist/MyServer.java

@@ -0,0 +1,170 @@
+package regist;
+
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.util.Date;
+
+import javax.sql.DataSource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.alibaba.fastjson.JSONObject;
+
+import cn.hutool.core.util.IdUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.db.sql.SqlExecutor;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
+import regist.aliutil.Config;
+
+public class MyServer {
+	
+			
+	static EventLoopGroup bossGroup = new NioEventLoopGroup();
+	static EventLoopGroup workerGroup = new NioEventLoopGroup();
+	
+	public static void nettyServer() throws InterruptedException {
+		try {
+			ServerBootstrap serverBootstrap = new ServerBootstrap();
+			serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
+			.childHandler(new MyServerInitializer());
+			ChannelFuture channelFuture = serverBootstrap.bind(Integer.parseInt(PropertyConfig.getStr("port"))).sync();
+			channelFuture.channel().closeFuture().sync();
+		}finally {
+			bossGroup.shutdownGracefully();
+			workerGroup.shutdownGracefully();
+		}
+	}
+}
+
+class MyServerInitializer extends ChannelInitializer<SocketChannel>{
+
+	@Override
+	protected void initChannel(SocketChannel ch) throws Exception {
+		// TODO Auto-generated method stub
+	ChannelPipeline pipeline = ch.pipeline();
+	pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 2,0,2));
+	//pipeline.addLast(new LengthFieldPrepender(2));
+	//pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
+	//pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
+	pipeline.addLast(new  MyServerHandler());
+	}
+}
+
+class MyServerHandler extends ChannelInboundHandlerAdapter{
+	
+	private static Logger logger = LoggerFactory.getLogger(MyServerHandler.class);
+	String key ="tuorenzhinenghua";
+	AliDeviceRegist regist = new AliDeviceRegist();
+	DataSource ds = PropertyConfig.getDs();
+	@Override
+	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
+		// TODO Auto-generated method stub
+		//打印出客户端地址
+		ByteBuf result = (ByteBuf)msg;
+		byte[] resultByte = new byte[result.readableBytes()];
+		result.readBytes(resultByte);
+		result.release();
+		String msgStr = AES.decrypt(resultByte,key);
+        System.out.println("aes decrypt:"+msgStr);
+        logger.info("aes decrypt:"+msgStr);
+        String jsonString = "{\"code\":\"1\"}";
+        String ip = ctx.channel().remoteAddress().toString();
+        logger.info("regist ip :"+ip);
+        
+        try {
+        	jsonString = handleRegist(msgStr);
+        }catch (Exception e) {
+			// TODO: handle exception
+        	logger.error("regist error:"+e);
+		}
+        
+        byte[] resultRegist = AES.encrypt(jsonString,key);
+        ByteBuf encoded = ctx.alloc().buffer(2 * resultRegist.length);  
+       
+        encoded.writeBytes(resultRegist);
+        ctx.channel().writeAndFlush(encoded);
+        ctx.flush();
+	}
+	
+	private String handleRegist(String msgStr) throws Exception{
+		JSONObject json = new JSONObject();
+        json.put("code", 1);
+        
+        if(StrUtil.isBlank(msgStr)) {
+        	return json.toString();
+        }
+   
+        String[] prodata = msgStr.split("&");
+        boolean deviceExist = false;
+        if(prodata.length <= 2){
+        	return json.toString();
+        }
+        String deviceName = prodata[0];
+        String simIccid = prodata[1];
+        String version = "";
+        if(prodata.length > 2) {
+        	version = prodata[2];
+        }
+        
+        Connection conn = ds.getConnection();
+        ResultSet resultSet =  SqlExecutor.callQuery(conn, "select mqtt_conn_info,is_delete from bus_device where device_id = ? limit 1", deviceName);
+        if(resultSet.next()){
+        	SqlExecutor.execute(conn, "update bus_device set sim_iccid = ?,version = ?,create_time = ? where  device_id = ? ", simIccid,version,new Date(),deviceName);
+        	String jsonString = resultSet.getString(1);
+        	int isDelete = resultSet.getInt(2);
+        	if(isDelete == 0){
+        		deviceExist = true;
+        	}
+        	if(deviceExist && StrUtil.isNotBlank(jsonString)){
+        		if(!conn.getAutoCommit()){              	
+              		conn.commit();
+              	}
+        		conn.close();
+        		return jsonString;
+        	}
+        }else{
+        	SqlExecutor.execute(conn, "insert into bus_device(id,device_id,tenant_id,sim_iccid,version,create_time,create_by)values(?,?,?,?,?,?,?) "
+        			,IdUtil.getSnowflakeNextIdStr(),deviceName,"1",simIccid,version,new Date(),"1" );
+        	 if(!conn.getAutoCommit()){
+         		conn.commit();
+         	 }
+        }
+        
+        
+        JSONObject registData = AliDeviceHttp.deviceRegist(deviceName);
+        if(registData.isEmpty()) {
+        	registData = AliDeviceHttp.deviceQuery(deviceName); 
+        }
+        if(!registData.isEmpty()) {
+        	json.put("code", 0);
+        	json.put("type", 0x15);
+        	json.put("address",Config.COAP_ADDRESS);
+        	json.put("port",Config.COAP_PORT);
+        	json.put("deviceName", deviceName);
+        	json.put("deviceSecret", registData.getString("DeviceSecret"));
+        	json.put("productKey", registData.getString("ProductKey"));
+			SqlExecutor.execute(conn, "update bus_device set mqtt_conn_info = ? where  device_id = ? ", json.toString(),deviceName);
+        }
+        
+        
+        if(!conn.getAutoCommit())
+    	{
+    		conn.commit();
+    	}
+        conn.close();
+        
+        return json.toString();
+	}
+}

+ 36 - 0
src/main/java/regist/PropertyConfig.java

@@ -0,0 +1,36 @@
+package regist;
+import javax.sql.DataSource;
+
+import cn.hutool.db.ds.DSFactory;
+import cn.hutool.setting.Setting;
+
+public class PropertyConfig {
+	
+	private static Setting allConfig = new Setting("application.properties");
+	private static Setting config = null;
+	private static DataSource ds = null;
+	
+	static {
+		String active = allConfig.getStr("active");
+		config = allConfig.getSetting(active);
+		ds = DSFactory.get(active); //配置数据库
+	}
+	
+	public static void init() {
+		String active = allConfig.getStr("active");
+		config = allConfig.getSetting(active);
+		ds = DSFactory.get(active); //配置数据库
+	}
+	
+	public static DataSource getDs() {
+		if(ds == null) {
+			String active = allConfig.getStr("active");
+			ds = DSFactory.get(active); //配置数据库
+		}
+		return ds;
+	}
+	public static String getStr(String key) {
+		return config.getStr(key);
+	}
+	
+}

+ 19 - 0
src/main/java/regist/Regist.java

@@ -0,0 +1,19 @@
+package regist;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Regist {
+	private static Logger logger = LoggerFactory.getLogger(Regist.class);
+	public static void main(String[] args) {
+		try {
+			logger.info("===========代理服务器启动=========");
+			MyServer.nettyServer();
+		} catch (InterruptedException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+			logger.error("代理服务启动失败",e);
+		}
+		
+	}
+}

+ 46 - 0
src/main/java/regist/aliutil/Config.java

@@ -0,0 +1,46 @@
+package regist.aliutil;
+
+import regist.PropertyConfig;
+
+/**
+ * 服务端API签名配置文件
+ * 
+ * @author: ali
+ * @version: 0.1 2018-08-08 08:23:54
+ */
+public class Config {
+
+	// AccessKey信息
+//    public final static String ACCESSKEY = "LTAI5t6P3oZtXeer23AVgj1k";
+//    public final static String ACCESSKEYSECRET = "Bss56yy0JFNGvmsEmZdxYqCnwhzDX2";
+//    public static final String PRODUCT_KEY = "a1xJ4qC587v";
+//    public static final String PRODUCT_SECRET = "S45tKq7fofGMElcN";
+//    
+//    public static final String REGIONID = "cn-shanghai";
+    
+    public final static String CHARSET_UTF8 = "utf8";
+    
+    // 定义加密方式。可选MAC算法:HmacMD5、HmacSHA1、HmacSHA256,需和signmethod取值一致。
+    public static final String HMAC_ALGORITHM = "hmacsha256";
+
+    // 接收物联网平台下发设备证书的Topic。无需创建,无需订阅,直接使用。
+    public static final String REGISTER_TOPIC = "/ext/regnwl";
+    
+    public static final String API_ADDRESS = "https://iot."+PropertyConfig.getStr("regionId")+".aliyuncs.com";
+    public static final String MQTT_ADDRESS_SUFF = ".iot-as-mqtt."+PropertyConfig.getStr("regionId")+".aliyuncs.com";
+    public static final String MQTT_PORT = "1883";
+    public static final String  MQTT_CLIENT_NWL_SUFF= "|securemode=-2,authType=connwl|";  //动态非预注册MQTT连接clientId后缀
+    
+    public static final String COAP_ADDRESS = "iot-060a0bgd.coap.iothub.aliyuncs.com";
+    public static final String COAP_PORT = "5682";
+    
+
+	/*
+	 * public final static Map<String,String> PRODUCT_MAP = new HashMap<String,
+	 * String>(); //Map<productKey,productSecret>
+	 * 
+	 * static { PRODUCT_MAP.put("a1xJ4qC587v", "S45tKq7fofGMElcN");
+	 * PRODUCT_MAP.put("a1ALlsBa2ZK", "zePsybCgZSSF4CQ4"); }
+	 */  
+    
+}

+ 76 - 0
src/main/java/regist/aliutil/MqttSign.java

@@ -0,0 +1,76 @@
+package regist.aliutil;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import java.math.BigInteger;
+
+class CryptoUtil {
+    private static String hmac(String plainText, String key, String algorithm, String format) throws Exception {
+        if (plainText == null || key == null) {
+            return null;
+        }
+
+        byte[] hmacResult = null;
+
+        Mac mac = Mac.getInstance(algorithm);
+        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), algorithm);
+        mac.init(secretKeySpec);
+        hmacResult = mac.doFinal(plainText.getBytes());
+        return String.format(format, new BigInteger(1, hmacResult));
+    }
+
+//    public static String hmacMd5(String plainText, String key) throws Exception {
+//        return hmac(plainText,key,"HmacMD5","%032x");
+//    }
+//
+//    public static String hmacSha1(String plainText, String key) throws Exception {
+//        return hmac(plainText,key,"HmacSHA1","%040x");
+//    }
+
+    public static String hmacSha256(String plainText, String key) throws Exception {
+        return hmac(plainText,key,"HmacSHA256","%064x");
+    }
+}
+
+public class MqttSign {
+    private String username = "";
+
+    private String password = "";
+
+    private String clientid = "";
+
+    public String getUsername() { return this.username;}
+
+    public String getPassword() { return this.password;}
+
+    public String getClientid() { return this.clientid;}
+
+    public void calculate(String productKey, String deviceName, String deviceSecret) {
+        if (productKey == null || deviceName == null || deviceSecret == null) {
+            return;
+        }
+
+        try {
+            //MQTT鐢ㄦ埛鍚�
+            this.username = deviceName + "&" + productKey;
+
+            //MQTT瀵嗙爜
+            String timestamp = Long.toString(System.currentTimeMillis());
+            String plainPasswd = "clientId" + productKey + "." + deviceName + "deviceName" +
+                    deviceName + "productKey" + productKey + "timestamp" + timestamp;
+            this.password = CryptoUtil.hmacSha256(plainPasswd, deviceSecret);
+
+            //MQTT ClientId
+            this.clientid = productKey + "." + deviceName + "|" + "timestamp=" + timestamp +
+                    ",securemode=2,signmethod=hmacsha256|";
+        }catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+    
+    public static void main(String[] args) {
+    	MqttSign sign = new MqttSign();
+    	sign.calculate("a1xJ4qC587v","43186642383902B4","a3f3fc46eebcf01439395cfd8b8fa7ee");
+    	System.out.println("clinetId:"+sign.getClientid()+" username:"+sign.getUsername()+" password:"+sign.getPassword());
+	}
+}

+ 146 - 0
src/main/java/regist/aliutil/SignatureUtils.java

@@ -0,0 +1,146 @@
+package regist.aliutil;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang3.StringUtils;
+
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.http.HttpUtil;
+import regist.PropertyConfig;
+
+/**
+ * 服务端API签名
+ * 
+ * @author: ali
+ * @version: 0.1 2018-06-21 20:47:05
+ */
+public class SignatureUtils {
+
+    private final static String CHARSET_UTF8 = "utf8";
+    private final static String ALGORITHM = "HmacSHA1";
+    private final static String SEPARATOR = "&";
+
+    public static Map<String, String> splitQueryString(String url)
+            throws URISyntaxException, UnsupportedEncodingException {
+        URI uri = new URI(url);
+        String query = uri.getQuery();
+        final String[] pairs = query.split("&");
+        TreeMap<String, String> queryMap = new TreeMap<String, String>();
+        for (String pair : pairs) {
+            final int idx = pair.indexOf("=");
+            final String key = idx > 0 ? pair.substring(0, idx) : pair;
+            if (!queryMap.containsKey(key)) {
+                queryMap.put(key, URLDecoder.decode(pair.substring(idx + 1), CHARSET_UTF8));
+            }
+        }
+        return queryMap;
+    }
+
+    public static String generate(String method, Map<String, String> parameter, String accessKeySecret)
+            throws Exception {
+        String signString = generateSignString(method, parameter);
+        System.out.println("signString---" + signString);
+        byte[] signBytes = hmacSHA1Signature(accessKeySecret + "&", signString);
+        String signature = newStringByBase64(signBytes);
+        System.out.println("signature----" + signature);
+        if ("POST".equals(method))
+            return signature;
+        return URLEncoder.encode(signature, "UTF-8");
+    }
+
+    public static String generateSignString(String httpMethod, Map<String, String> parameter) throws IOException {
+        TreeMap<String, String> sortParameter = new TreeMap<String, String>();
+        sortParameter.putAll(parameter);
+        String canonicalizedQueryString = UrlUtil.generateQueryString(sortParameter, true);
+        if (null == httpMethod) {
+            throw new RuntimeException("httpMethod can not be empty");
+        }
+        StringBuilder stringToSign = new StringBuilder();
+        stringToSign.append(httpMethod).append(SEPARATOR);
+        stringToSign.append(percentEncode("/")).append(SEPARATOR);
+        stringToSign.append(percentEncode(canonicalizedQueryString));
+        return stringToSign.toString();
+    }
+
+    public static String percentEncode(String value) {
+        try {
+            return value == null ? null
+                    : URLEncoder.encode(value, CHARSET_UTF8).replace("+", "%20").replace("*", "%2A").replace("%7E",
+                            "~");
+        } catch (Exception e) {
+        }
+        return "";
+    }
+
+    public static byte[] hmacSHA1Signature(String secret, String baseString) throws Exception {
+        if (StringUtils.isEmpty(secret)) {
+            throw new IOException("secret can not be empty");
+        }
+        if (StringUtils.isEmpty(baseString)) {
+            return null;
+        }
+        Mac mac = Mac.getInstance("HmacSHA1");
+        SecretKeySpec keySpec = new SecretKeySpec(secret.getBytes(CHARSET_UTF8), ALGORITHM);
+        mac.init(keySpec);
+        return mac.doFinal(baseString.getBytes(CHARSET_UTF8));
+    }
+
+    public static String newStringByBase64(byte[] bytes) throws UnsupportedEncodingException {
+        if (bytes == null || bytes.length == 0) {
+            return null;
+        }
+        return new String(Base64.encodeBase64(bytes, false), CHARSET_UTF8);
+    }
+    
+    
+    
+    public static void main(String[] args) throws UnsupportedEncodingException {
+
+       
+
+    	String timestamp = LocalDateTimeUtil.format(LocalDateTime.now(ZoneOffset.UTC), "yyyy-MM-dd'T'HH:mm:ss'Z'");
+        Map<String, String> map = new HashMap<String, String>();
+        // 公共参数
+        map.put("Format", "JSON");
+        map.put("Version", "2018-01-20");
+        map.put("AccessKeyId", PropertyConfig.getStr("accessKey"));
+        map.put("SignatureMethod", "HMAC-SHA1");
+        map.put("Timestamp", timestamp);
+        map.put("SignatureVersion", "1.0");
+        map.put("SignatureNonce", RandomUtil.randomNumbers(14));
+        map.put("RegionId", "cn-shanghai");
+        // 请求参数
+        map.put("Action", "QueryDeviceDetail");
+        map.put("DeviceName", "43186642383902B4");
+        map.put("ProductKey", "a1xJ4qC587v");
+        
+        
+        System.out.println("timestamp:"+timestamp);
+        try {
+            String signature = SignatureUtils.generate("GET", map, PropertyConfig.getStr("accessKeySecret"));
+            map.put("Signature", signature);
+            Map<String,Object> httpParamMap = new HashMap<String, Object>(map);
+            String result = HttpUtil.get("https://iot.cn-shanghai.aliyuncs.com",httpParamMap);
+            System.out.println("最终signature: " + signature);
+            System.out.println("最终result: " + result);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        System.out.println();
+    }
+}

+ 54 - 0
src/main/java/regist/aliutil/UrlUtil.java

@@ -0,0 +1,54 @@
+package regist.aliutil;
+
+import java.net.URLEncoder;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+/**
+ * URL处理类
+ * 
+ * @author: ali
+ * @version: 0.1 2018-06-21 20:40:52
+ */
+public class UrlUtil {
+
+    private final static String CHARSET_UTF8 = "utf8";
+
+    public static String urlEncode(String url) {
+        if (!StringUtils.isEmpty(url)) {
+            try {
+                url = URLEncoder.encode(url, "UTF-8");
+            } catch (Exception e) {
+                System.out.println("Url encode error:" + e.getMessage());
+            }
+        }
+        return url;
+    }
+
+    public static String generateQueryString(Map<String, String> params, boolean isEncodeKV) {
+        StringBuilder canonicalizedQueryString = new StringBuilder();
+        for (Map.Entry<String, String> entry : params.entrySet()) {
+            if (isEncodeKV)
+                canonicalizedQueryString.append(percentEncode(entry.getKey())).append("=")
+                        .append(percentEncode(entry.getValue())).append("&");
+            else
+                canonicalizedQueryString.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
+        }
+        if (canonicalizedQueryString.length() > 1) {
+            canonicalizedQueryString.setLength(canonicalizedQueryString.length() - 1);
+        }
+        return canonicalizedQueryString.toString();
+    }
+
+    public static String percentEncode(String value) {
+        try {
+            // 使用URLEncoder.encode编码后,将"+","*","%7E"做替换即满足API规定的编码规范。
+            return value == null ? null
+                    : URLEncoder.encode(value, CHARSET_UTF8).replace("+", "%20").replace("*", "%2A").replace("%7E",
+                            "~");
+        } catch (Exception e) {
+
+        }
+        return "";
+    }
+}

+ 60 - 0
src/main/java/regist/listener/CustomLogContextListener.java

@@ -0,0 +1,60 @@
+package regist.listener;
+
+import ch.qos.logback.classic.Level;
+import ch.qos.logback.classic.Logger;
+import ch.qos.logback.classic.LoggerContext;
+import ch.qos.logback.classic.spi.LoggerContextListener;
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.spi.ContextAwareBase;
+import ch.qos.logback.core.spi.LifeCycle;
+import regist.PropertyConfig;
+
+public class CustomLogContextListener extends ContextAwareBase implements LoggerContextListener, LifeCycle {
+ 
+    /** 存储日志路径标识 */
+    public static final String LOG_PAHT_KEY = "LOG_PATH";
+ 
+    public boolean isResetResistant() {
+        return false;
+    }
+ 
+
+ 
+ 
+ 
+    public void start() {
+        // "user.dir"是指用户当前工作目录
+        String s = PropertyConfig.getStr("logPath");
+        Context context = getContext();
+        context.putProperty(LOG_PAHT_KEY,  s);
+    }
+ 
+    public void stop() {
+ 
+    }
+ 
+    public boolean isStarted() {
+        return false;
+    }
+
+	public void onStart(LoggerContext context) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void onReset(LoggerContext context) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void onStop(LoggerContext context) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void onLevelChange(Logger logger, Level level) {
+		// TODO Auto-generated method stub
+		
+	}
+
+}

+ 39 - 0
src/main/resources/application.properties

@@ -0,0 +1,39 @@
+active=dev
+
+[dev]
+port=8888
+#aliyun
+accessKey=LTAI4G7FA9ytMc76oNkJ45YJ
+accessKeySecret=R7hOvMfiHb0PYroDqUDXAYgB9htQss
+#productKey=he1f6YdSWHW
+#productSecret=AdL6qKEf8xeI0ToJ
+productKey=he1f9vgI5pt
+productSecret=0zZFoRqVVM7ILjyA
+instanceId=iot-060a0bgd
+regionId=cn-shanghai
+#logback
+logPath=D://log/ali-regist-service
+
+[test]
+port=8888
+#aliyun
+accessKey=LTAI4FhB19MgQuviGxwA3aod
+accessKeySecret=cQQVkATR0yv2G9CEtfjAhEGBepPDRs
+productKey=a1ALlsBa2ZK
+productSecret=zePsybCgZSSF4CQ4
+instanceId=iot-060a0bgd
+regionId=cn-shanghai
+#logback
+logPath=/home/logs/ali-regist-service
+
+[prod]
+port=8888
+#aliyun
+accessKey=LTAI4G7FA9ytMc76oNkJ45YJ
+accessKeySecret=R7hOvMfiHb0PYroDqUDXAYgB9htQss
+productKey=he1f6YdSWHW
+productSecret=AdL6qKEf8xeI0ToJ
+instanceId=iot-060a0bgd
+regionId=cn-shanghai
+#logback
+logPath=/home/logs/ali-regist-service

+ 89 - 0
src/main/resources/config/db.setting

@@ -0,0 +1,89 @@
+[dev]
+url = jdbc:mysql://47.101.214.91:7001/nbnetpump?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
+username = root
+password = Tuoren123.
+## 可选配置
+# 是否在日志中显示执行的SQL
+showSql = true
+# 是否格式化显示的SQL
+formatSql = false
+# 是否显示SQL参数
+showParams = true
+# 打印SQL的日志等级,默认debug,可以是info、warn、error
+sqlLevel = debug
+# 自动提交
+autoCommit = true
+# 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
+connectionTimeout = 30000
+# 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟
+idleTimeout = 600000
+# 一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒,参考MySQL wait_timeout参数(show variables like '%timeout%';)
+maxLifetime = 1800000
+# 获取连接前的测试SQL
+connectionTestQuery = SELECT 1
+# 最小闲置连接数
+minimumIdle = 10
+# 连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count)
+maximumPoolSize = 10
+# 连接只读数据库时配置为true, 保证安全
+readOnly = false
+
+[test]
+url = jdbc:mysql://192.168.100.32:3306/nbnetpump?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
+username = root
+password = 123456
+## 可选配置
+# 是否在日志中显示执行的SQL
+showSql = true
+# 是否格式化显示的SQL
+formatSql = false
+# 是否显示SQL参数
+showParams = true
+# 打印SQL的日志等级,默认debug,可以是info、warn、error
+sqlLevel = debug
+# 自动提交
+autoCommit = true
+# 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
+connectionTimeout = 30000
+# 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟
+idleTimeout = 600000
+# 一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒,参考MySQL wait_timeout参数(show variables like '%timeout%';)
+maxLifetime = 1800000
+# 获取连接前的测试SQL
+connectionTestQuery = SELECT 1
+# 最小闲置连接数
+minimumIdle = 10
+# 连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count)
+maximumPoolSize = 10
+# 连接只读数据库时配置为true, 保证安全
+readOnly = false
+
+[prod]
+url = jdbc:mysql://172.23.67.71:7001/nbnetpump?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
+username = root
+password = Tuoren123.
+## 可选配置
+# 是否在日志中显示执行的SQL
+showSql = true
+# 是否格式化显示的SQL
+formatSql = false
+# 是否显示SQL参数
+showParams = true
+# 打印SQL的日志等级,默认debug,可以是info、warn、error
+sqlLevel = debug
+# 自动提交
+autoCommit = true
+# 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
+connectionTimeout = 30000
+# 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟
+idleTimeout = 600000
+# 一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒,参考MySQL wait_timeout参数(show variables like '%timeout%';)
+maxLifetime = 1800000
+# 获取连接前的测试SQL
+connectionTestQuery = SELECT 1
+# 最小闲置连接数
+minimumIdle = 10
+# 连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count)
+maximumPoolSize = 10
+# 连接只读数据库时配置为true, 保证安全
+readOnly = false

+ 171 - 0
src/main/resources/logback.xml

@@ -0,0 +1,171 @@
+<!-- Logback configuration. See http://logback.qos.ch/manual/index.html -->
+<configuration scan="true" scanPeriod="10 seconds">
+
+	<!-- 监听器,指定日志文件存放目录 -->
+    <contextListener class="regist.listener.CustomLogContextListener" /> 
+    <!--设置系统日志目录-->
+    <!-- <property name="LOG_PATH"  value="D://logs/ali-regist-service" />  -->
+
+    <!-- 彩色日志 -->
+        <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
+
+    <!-- 控制台输出 -->
+    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+    	<file>${LOG_PATH}/log_info.log</file>
+        <encoder>
+            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>info</level>
+        </filter>
+    </appender>
+
+
+    <!-- 时间滚动输出 level为 DEBUG 日志 -->
+    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_debug.log</file>
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--
+                归档的日志文件的路径,例如今天是2017-04-26日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
+                而2017-04-26的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引
+            -->
+            <fileNamePattern>${LOG_PATH}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--
+                除按日志记录之外,还配置了日志文件不能超过500M,若超过500M,日志文件会以索引0开始,
+                命名日志文件,例如log-error-2017-04-26.0.log
+            -->
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>500MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <maxHistory>7</maxHistory>
+        </rollingPolicy>
+        <!-- 此日志文件只记录debug级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>debug</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 时间滚动输出 level为 INFO 日志 -->
+    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_info.log</file>
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--
+                归档的日志文件的路径,例如今天是2017-04-26日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
+                而2017-04-26的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引
+            -->
+            <fileNamePattern>${LOG_PATH}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--
+                除按日志记录之外,还配置了日志文件不能超过500M,若超过500M,日志文件会以索引0开始,
+                命名日志文件,例如log-error-2017-04-26.0.log
+            -->
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>500MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <maxHistory>7</maxHistory>
+        </rollingPolicy>
+        <!-- 此日志文件只记录info级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>info</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 时间滚动输出 level为 WARN 日志 -->
+    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_warn.log</file>
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--
+                归档的日志文件的路径,例如今天是2017-04-26日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
+                而2017-04-26的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引
+            -->
+            <fileNamePattern>${LOG_PATH}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--
+                除按日志记录之外,还配置了日志文件不能超过500M,若超过500M,日志文件会以索引0开始,
+                命名日志文件,例如log-error-2017-04-26.0.log
+            -->
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>500MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <maxHistory>7</maxHistory>
+        </rollingPolicy>
+        <!-- 此日志文件只记录warn级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>warn</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 时间滚动输出 level为 ERROR 日志 -->
+    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_error.log</file>
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--
+                归档的日志文件的路径,例如今天是2017-04-26日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
+                而2017-04-26的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引
+            -->
+            <fileNamePattern>${LOG_PATH}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--
+                除按日志记录之外,还配置了日志文件不能超过500M,若超过500M,日志文件会以索引0开始,
+                命名日志文件,例如log-error-2017-04-26.0.log
+            -->
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>500MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <maxHistory>7</maxHistory>
+        </rollingPolicy>
+        <!-- 此日志文件只记录ERROR级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>error</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+    <root level="debug">
+            <appender-ref ref="CONSOLE" />
+            <appender-ref ref="DEBUG_FILE" />
+            <appender-ref ref="INFO_FILE" />
+            <appender-ref ref="WARN_FILE" />
+            <appender-ref ref="ERROR_FILE" />
+      </root>
+</configuration>

+ 5 - 0
target/classes/META-INF/MANIFEST.MF

@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+Built-By: wulianwei
+Build-Jdk: 15.0.1
+Created-By: Maven Integration for Eclipse
+

+ 7 - 0
target/classes/META-INF/maven/com.agent/ali-device-regist-4g/pom.properties

@@ -0,0 +1,7 @@
+#Generated by Maven Integration for Eclipse
+#Fri May 17 10:14:31 CST 2024
+m2e.projectLocation=D\:\\workspace\\ali-device-regist-4G
+m2e.projectName=ali-device-regist-4G
+groupId=com.agent
+artifactId=ali-device-regist-4g
+version=0.0.1-SNAPSHOT

+ 119 - 0
target/classes/META-INF/maven/com.agent/ali-device-regist-4g/pom.xml

@@ -0,0 +1,119 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>com.agent</groupId>
+  <artifactId>ali-device-regist-4g</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <name>Archetype - ali-device-regist-4g</name>
+  <url>http://maven.apache.org</url>
+  
+  <properties>
+		<encoding>UTF-8</encoding>
+		<java-version>1.8</java-version>
+		<maven.compiler.source>1.8</maven.compiler.source>
+		<maven.compiler.target>1.8</maven.compiler.target>
+		<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
+  </properties>
+  <dependencies>
+        <dependency>
+            <groupId>org.eclipse.paho</groupId>
+            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
+            <version>1.2.1</version>
+        </dependency>
+        <dependency>
+		  <groupId>org.eclipse.californium</groupId>
+		  <artifactId>californium-core</artifactId>
+		  <version>2.0.0-M17</version>
+		</dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.61</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>27.0.1-jre</version>
+        </dependency>
+        <dependency>
+		    <groupId>io.netty</groupId>
+		    <artifactId>netty-all</artifactId>
+		    <version>4.1.76.Final</version>
+		</dependency>
+		<dependency>
+		    <groupId>cn.hutool</groupId>
+		    <artifactId>hutool-all</artifactId>
+		    <version>5.7.22</version>
+		</dependency>
+		<dependency>
+	    	<groupId>com.zaxxer</groupId>
+		    <artifactId>HikariCP</artifactId>
+		    <version>3.4.2</version>
+		</dependency>
+		
+		<dependency>
+		    <groupId>org.slf4j</groupId>
+		    <artifactId>slf4j-api</artifactId>
+		    <version>1.7.36</version>
+		</dependency>
+		<dependency>
+		    <groupId>ch.qos.logback</groupId>
+		    <artifactId>logback-classic</artifactId>
+		    <version>1.2.11</version>
+		</dependency>
+		<dependency>
+		    <groupId>mysql</groupId>
+		    <artifactId>mysql-connector-java</artifactId>
+		    <version>5.1.33</version>
+		</dependency>
+		<dependency>
+		    <groupId>org.apache.commons</groupId>
+		    <artifactId>commons-lang3</artifactId>
+		    <version>3.9</version>
+		</dependency>
+		<dependency>
+		  <groupId>commons-codec</groupId>
+		  <artifactId>commons-codec</artifactId>
+		  <version>1.13</version>
+		</dependency>
+	</dependencies> 
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.8</source>
+					<target>1.8</target>
+					<encoding>UTF-8</encoding>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<configuration>
+					<appendAssemblyId>false</appendAssemblyId>
+					<descriptorRefs>
+						<descriptorRef>jar-with-dependencies</descriptorRef>
+					</descriptorRefs>
+					<archive>
+						<manifest>
+							<!-- 此处指定main方法入口的class -->
+							<mainClass>regist.Regist</mainClass>
+						</manifest>
+					</archive>
+				</configuration>
+				<executions>
+					<execution>
+						<id>make-assembly</id>
+						<phase>package</phase>
+						<goals>
+							<goal>assembly</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+		</plugins>
+	</build> 
+</project>

+ 39 - 0
target/classes/application.properties

@@ -0,0 +1,39 @@
+active=dev
+
+[dev]
+port=8888
+#aliyun
+accessKey=LTAI4G7FA9ytMc76oNkJ45YJ
+accessKeySecret=R7hOvMfiHb0PYroDqUDXAYgB9htQss
+#productKey=he1f6YdSWHW
+#productSecret=AdL6qKEf8xeI0ToJ
+productKey=he1f9vgI5pt
+productSecret=0zZFoRqVVM7ILjyA
+instanceId=iot-060a0bgd
+regionId=cn-shanghai
+#logback
+logPath=D://log/ali-regist-service
+
+[test]
+port=8888
+#aliyun
+accessKey=LTAI4FhB19MgQuviGxwA3aod
+accessKeySecret=cQQVkATR0yv2G9CEtfjAhEGBepPDRs
+productKey=a1ALlsBa2ZK
+productSecret=zePsybCgZSSF4CQ4
+instanceId=iot-060a0bgd
+regionId=cn-shanghai
+#logback
+logPath=/home/logs/ali-regist-service
+
+[prod]
+port=8888
+#aliyun
+accessKey=LTAI4G7FA9ytMc76oNkJ45YJ
+accessKeySecret=R7hOvMfiHb0PYroDqUDXAYgB9htQss
+productKey=he1f6YdSWHW
+productSecret=AdL6qKEf8xeI0ToJ
+instanceId=iot-060a0bgd
+regionId=cn-shanghai
+#logback
+logPath=/home/logs/ali-regist-service

+ 89 - 0
target/classes/config/db.setting

@@ -0,0 +1,89 @@
+[dev]
+url = jdbc:mysql://47.101.214.91:7001/nbnetpump?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
+username = root
+password = Tuoren123.
+## 可选配置
+# 是否在日志中显示执行的SQL
+showSql = true
+# 是否格式化显示的SQL
+formatSql = false
+# 是否显示SQL参数
+showParams = true
+# 打印SQL的日志等级,默认debug,可以是info、warn、error
+sqlLevel = debug
+# 自动提交
+autoCommit = true
+# 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
+connectionTimeout = 30000
+# 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟
+idleTimeout = 600000
+# 一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒,参考MySQL wait_timeout参数(show variables like '%timeout%';)
+maxLifetime = 1800000
+# 获取连接前的测试SQL
+connectionTestQuery = SELECT 1
+# 最小闲置连接数
+minimumIdle = 10
+# 连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count)
+maximumPoolSize = 10
+# 连接只读数据库时配置为true, 保证安全
+readOnly = false
+
+[test]
+url = jdbc:mysql://192.168.100.32:3306/nbnetpump?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
+username = root
+password = 123456
+## 可选配置
+# 是否在日志中显示执行的SQL
+showSql = true
+# 是否格式化显示的SQL
+formatSql = false
+# 是否显示SQL参数
+showParams = true
+# 打印SQL的日志等级,默认debug,可以是info、warn、error
+sqlLevel = debug
+# 自动提交
+autoCommit = true
+# 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
+connectionTimeout = 30000
+# 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟
+idleTimeout = 600000
+# 一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒,参考MySQL wait_timeout参数(show variables like '%timeout%';)
+maxLifetime = 1800000
+# 获取连接前的测试SQL
+connectionTestQuery = SELECT 1
+# 最小闲置连接数
+minimumIdle = 10
+# 连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count)
+maximumPoolSize = 10
+# 连接只读数据库时配置为true, 保证安全
+readOnly = false
+
+[prod]
+url = jdbc:mysql://172.23.67.71:7001/nbnetpump?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
+username = root
+password = Tuoren123.
+## 可选配置
+# 是否在日志中显示执行的SQL
+showSql = true
+# 是否格式化显示的SQL
+formatSql = false
+# 是否显示SQL参数
+showParams = true
+# 打印SQL的日志等级,默认debug,可以是info、warn、error
+sqlLevel = debug
+# 自动提交
+autoCommit = true
+# 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 缺省:30秒
+connectionTimeout = 30000
+# 一个连接idle状态的最大时长(毫秒),超时则被释放(retired),缺省:10分钟
+idleTimeout = 600000
+# 一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒,参考MySQL wait_timeout参数(show variables like '%timeout%';)
+maxLifetime = 1800000
+# 获取连接前的测试SQL
+connectionTestQuery = SELECT 1
+# 最小闲置连接数
+minimumIdle = 10
+# 连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count)
+maximumPoolSize = 10
+# 连接只读数据库时配置为true, 保证安全
+readOnly = false

+ 171 - 0
target/classes/logback.xml

@@ -0,0 +1,171 @@
+<!-- Logback configuration. See http://logback.qos.ch/manual/index.html -->
+<configuration scan="true" scanPeriod="10 seconds">
+
+	<!-- 监听器,指定日志文件存放目录 -->
+    <contextListener class="regist.listener.CustomLogContextListener" /> 
+    <!--设置系统日志目录-->
+    <!-- <property name="LOG_PATH"  value="D://logs/ali-regist-service" />  -->
+
+    <!-- 彩色日志 -->
+        <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
+
+    <!-- 控制台输出 -->
+    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+    	<file>${LOG_PATH}/log_info.log</file>
+        <encoder>
+            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>info</level>
+        </filter>
+    </appender>
+
+
+    <!-- 时间滚动输出 level为 DEBUG 日志 -->
+    <appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_debug.log</file>
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--
+                归档的日志文件的路径,例如今天是2017-04-26日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
+                而2017-04-26的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引
+            -->
+            <fileNamePattern>${LOG_PATH}/debug/log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--
+                除按日志记录之外,还配置了日志文件不能超过500M,若超过500M,日志文件会以索引0开始,
+                命名日志文件,例如log-error-2017-04-26.0.log
+            -->
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>500MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <maxHistory>7</maxHistory>
+        </rollingPolicy>
+        <!-- 此日志文件只记录debug级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>debug</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 时间滚动输出 level为 INFO 日志 -->
+    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_info.log</file>
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--
+                归档的日志文件的路径,例如今天是2017-04-26日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
+                而2017-04-26的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引
+            -->
+            <fileNamePattern>${LOG_PATH}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--
+                除按日志记录之外,还配置了日志文件不能超过500M,若超过500M,日志文件会以索引0开始,
+                命名日志文件,例如log-error-2017-04-26.0.log
+            -->
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>500MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <maxHistory>7</maxHistory>
+        </rollingPolicy>
+        <!-- 此日志文件只记录info级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>info</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 时间滚动输出 level为 WARN 日志 -->
+    <appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_warn.log</file>
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--
+                归档的日志文件的路径,例如今天是2017-04-26日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
+                而2017-04-26的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引
+            -->
+            <fileNamePattern>${LOG_PATH}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--
+                除按日志记录之外,还配置了日志文件不能超过500M,若超过500M,日志文件会以索引0开始,
+                命名日志文件,例如log-error-2017-04-26.0.log
+            -->
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>500MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <maxHistory>7</maxHistory>
+        </rollingPolicy>
+        <!-- 此日志文件只记录warn级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>warn</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+
+
+    <!-- 时间滚动输出 level为 ERROR 日志 -->
+    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <!-- 正在记录的日志文件的路径及文件名 -->
+        <file>${LOG_PATH}/log_error.log</file>
+        <!--日志文件输出格式-->
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
+            <charset>UTF-8</charset> <!-- 此处设置字符集 -->
+        </encoder>
+        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <!--
+                归档的日志文件的路径,例如今天是2017-04-26日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
+                而2017-04-26的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引
+            -->
+            <fileNamePattern>${LOG_PATH}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <!--
+                除按日志记录之外,还配置了日志文件不能超过500M,若超过500M,日志文件会以索引0开始,
+                命名日志文件,例如log-error-2017-04-26.0.log
+            -->
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <maxFileSize>500MB</maxFileSize>
+            </timeBasedFileNamingAndTriggeringPolicy>
+            <!--日志文件保留天数-->
+            <maxHistory>7</maxHistory>
+        </rollingPolicy>
+        <!-- 此日志文件只记录ERROR级别的 -->
+        <filter class="ch.qos.logback.classic.filter.LevelFilter">
+            <level>error</level>
+            <onMatch>ACCEPT</onMatch>
+            <onMismatch>DENY</onMismatch>
+        </filter>
+    </appender>
+    <root level="debug">
+            <appender-ref ref="CONSOLE" />
+            <appender-ref ref="DEBUG_FILE" />
+            <appender-ref ref="INFO_FILE" />
+            <appender-ref ref="WARN_FILE" />
+            <appender-ref ref="ERROR_FILE" />
+      </root>
+</configuration>

BIN
target/classes/regist/AES.class


BIN
target/classes/regist/AliDeviceHttp.class


BIN
target/classes/regist/AliDeviceQuery.class


BIN
target/classes/regist/AliDeviceRegist$1.class


BIN
target/classes/regist/AliDeviceRegist.class


BIN
target/classes/regist/IotCoapClientWithAes.class


BIN
target/classes/regist/MyServer.class


BIN
target/classes/regist/MyServerHandler.class


BIN
target/classes/regist/MyServerInitializer.class


BIN
target/classes/regist/PropertyConfig.class


BIN
target/classes/regist/Regist.class


BIN
target/classes/regist/aliutil/Config.class


BIN
target/classes/regist/aliutil/CryptoUtil.class


BIN
target/classes/regist/aliutil/MqttSign.class


BIN
target/classes/regist/aliutil/SignatureUtils.class


BIN
target/classes/regist/aliutil/UrlUtil.class


BIN
target/classes/regist/listener/CustomLogContextListener.class