Commit c7de935e by 杜祥龙

init

Signed-off-by: sdvdxl杜龙少 <sdvdxl@163.com>
parents
# Created by .ignore support plugin (hsz.mobi)
### Vim template
# Swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Session
Session.vim
# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~
### Java template
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Emacs template
# -*- mode: gitignore; -*-
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*
# Org-mode
.org-id-locations
*_archive
# flymake-mode
*_flymake.*
# eshell files
/eshell/history
/eshell/lastdir
# elpa packages
/elpa/
# reftex files
*.rel
# AUCTeX auto folder
/auto/
# cask packages
.cask/
dist/
# Flycheck
flycheck_*.el
# server auth directory
/server/
# projectiles files
.projectile
# directory configuration
.dir-locals.el
# network security
/network-security.data
### Eclipse template
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# PyDev specific (Python IDE for Eclipse)
*.pydevproject
# CDT-specific (C/C++ Development Tooling)
.cproject
# CDT- autotools
.autotools
# Java annotation processor (APT)
.factorypath
# PDT-specific (PHP Development Tools)
.buildpath
# sbteclipse plugin
.target
# Tern plugin
.tern-project
# TeXlipse plugin
.texlipse
# STS (Spring Tool Suite)
.springBeans
# Code Recommenders
.recommenders/
# Annotation Processing
.apt_generated/
# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet
### VisualStudioCode template
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.hekr</groupId>
<artifactId>java-client-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<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>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.51</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package me.hekr.demo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class GatewayDevice {
private static final Executor EXECUTOR = Executors.newSingleThreadExecutor();
// 设备id
private static final String DEV_TID = "";
// 产品密钥
private static final String PROD_KEY = "";
// 设备私钥
private static final String PRIV_KEY = "";
// 网关是否启用2步认证,相关设置在网关产品偏好里面设置
private static final boolean GATEWAY_DEVICE_TWO_FACTOR_AUTHENTICATION = true;
// 最大等待时间 毫秒
private static final int MAX_WAIT_TIME_MILLS = 3000;
public static void main(String[] args)
throws IOException, InterruptedException, ExecutionException, TimeoutException {
TcpClient tcpClient = new TcpClient("hub.hekr.me", 83).connect();
String randomKey = null;
Map<String, Object> message;
Map<String, Object> params;
// 如果启用两步认证,则需要认证设备信息
if (GATEWAY_DEVICE_TWO_FACTOR_AUTHENTICATION) {
// 校验信息
message = new HashMap<>();
message.put("action", "requestVerify");
message.put("msgId", tcpClient.getMsgId());
params = new HashMap<>();
params.put("devTid", DEV_TID);
message.put("params", params);
tcpClient.send(JSON.toJSONString(message) + "\n");
String respMsg = tcpClient.receive(MAX_WAIT_TIME_MILLS);
JSONObject respMap = JSON.parseObject(respMsg);
boolean success = respMap.getIntValue("code") == 200;
if (!success) {
System.out.println("校验失败,resp:" + respMsg);
return;
}
// 获取 randomKey
randomKey = (String) respMap.get("randomKey");
}
// 网关登录
params = new HashMap<>();
params.put("devTid", DEV_TID);
// 如果启用两步认证,需要加上authKey
if (GATEWAY_DEVICE_TWO_FACTOR_AUTHENTICATION) {
String authKey = Util.MD5(randomKey + DEV_TID + PRIV_KEY);
params.put("authKey", authKey);
}
message = new HashMap<>();
message.put("action", "gatewayLogin");
message.put("msgId", tcpClient.getMsgId());
message.put("params", params);
tcpClient.send(JSON.toJSONString(message) + "\n");
String respMsg = tcpClient.receive(MAX_WAIT_TIME_MILLS);
JSONObject resp = JSON.parseObject(respMsg);
if (resp.getIntValue("code") != 200) {
System.out.println("gateway login failed,resp:" + respMsg);
return;
}
// 登录成功,这里订阅消息
subcribeMessage(tcpClient);
// TODO 发送业务数据
// 循环定时发送心跳
loopSendHeartbeat(tcpClient);
}
private static void loopSendHeartbeat(TcpClient tcpClient) {
EXECUTOR.execute(
() -> {
// 如果client 没关闭,则每20s发送过一次心跳
while (tcpClient.isOpen()) {
Map<String, Object> heartbeatMessage = new HashMap<>();
heartbeatMessage.put("action", "heartbeat");
heartbeatMessage.put("msgId", tcpClient.getMsgId());
try {
tcpClient.send(JSON.toJSONString(heartbeatMessage));
} catch (IOException e) {
System.out.println(e.getMessage());
}
try {
TimeUnit.SECONDS.sleep(20);
} catch (InterruptedException ignored) {
}
}
});
}
private static void subcribeMessage(TcpClient tcpClient) {
EXECUTOR.execute(
new ReceiveMessageTask(
tcpClient,
new MessageListener() {
@Override
public void onMessage(String message) {
System.out.println(message);
}
}));
}
}
package me.hekr.demo;
public class HeartbeatTask implements Runnable {
@Override
public void run() {
}
}
package me.hekr.demo;
public interface MessageListener {
void onMessage(String message);
}
package me.hekr.demo;
public class ReceiveMessageTask implements Runnable {
private TcpClient tcpClient;
private MessageListener messageListener;
public ReceiveMessageTask(TcpClient tcpClient, MessageListener messageListener) {
this.tcpClient = tcpClient;
this.messageListener = messageListener;
}
@Override
public void run() {
String message;
try {
while (tcpClient.isOpen() && (message = tcpClient.receive()) != null) {
messageListener.onMessage(message);
}
} catch (Exception e) {
System.out.println(e.getMessage());
tcpClient.close();
}
}
}
package me.hekr.demo;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/** 描述 Created by du on 2017/8/6. */
public class TcpClient {
private static final int TIMEOUT_MILL = 20000;
private Socket client;
private String host;
private int port;
private BufferedReader inFromServer;
private DataOutputStream outToServer;
private int msgId;
public TcpClient(String host, int port) throws SocketException {
this.host = host;
this.port = port;
client = new Socket();
client.setKeepAlive(true);
}
/** 获取msgId,从0-65535 */
public synchronized int getMsgId() {
msgId++;
if (msgId > 65535) {
msgId = 0;
}
return msgId;
}
// 建立链接
public TcpClient connect() throws IOException {
return connect(30000);
}
public TcpClient connect(int timeout) throws IOException {
client.setKeepAlive(true);
client.setSoTimeout(TIMEOUT_MILL);
client.connect(new InetSocketAddress(host, port), timeout);
outToServer = new DataOutputStream(client.getOutputStream());
inFromServer = new BufferedReader(new InputStreamReader(client.getInputStream()));
return this;
}
public TcpClient send(String message) throws IOException {
if (client.isClosed()) {
throw new RuntimeException("TCP client closed");
}
if (client.isOutputShutdown()) {
throw new RuntimeException("output channel closed");
}
outToServer.writeBytes(message);
return this;
}
public void close() {
try {
this.client.close();
} catch (IOException ignored) {
}
try {
if (inFromServer != null) {
inFromServer.close();
}
} catch (IOException ignored) {
}
try {
if (outToServer != null) {
outToServer.close();
}
} catch (IOException ignored) {
}
}
public boolean isOpen() {
return !client.isClosed();
}
/**
* 获取消息,一直阻塞
*
* @return
* @throws IOException
*/
public String receive() throws IOException {
return inFromServer.readLine();
}
/**
* 获取消息
*
* @param timeoutMill 超时时间,毫秒
* @throws IOException
*/
public String receive(int timeoutMill)
throws InterruptedException, ExecutionException, TimeoutException {
return new FutureTask<String>(() -> inFromServer.readLine())
.get(timeoutMill, TimeUnit.MICROSECONDS);
}
}
package me.hekr.demo;
import java.security.MessageDigest;
public class Util {
public static String MD5(String str) {
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
} catch (Exception e) {
return null;
}
md.update(str.getBytes());
byte[] bs = md.digest();
StringBuilder sb = new StringBuilder();
for (byte b : bs) {
int v = b & 0xff;
if (v < 16) {
sb.append(0);
}
sb.append(Integer.toHexString(v));
}
return sb.toString();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment