我有一个 Greengrass 核心 (Jetson TX2) 广播一个隔离的接入点,因此不同的物联网设备可以相互通信。接入点工作,因为我能够让一个设备通过 OSC 协议与核心通信。
现在我正试图让我的智能手表(运行 WearOS)与 AWS Greengrass MQTT 通信。这需要 SSL 连接以及核心提供的组证书。当核心和智能手表都连接到具有活动互联网连接的网络时,我的实现工作。但是,当我尝试通过隔离接入点与它们通信时,智能手表无法与核心通信
我正在通过paho.mqtt.android
asocketFactory
来实现通信以存储我的密钥和证书。我不确定是什么导致我的应用无法与我的核心处理器通信
我试图找出问题所在,智能手表似乎确实连接到了接入点并检索了 IP 地址。但是,该paho.mqtt.android
库不使用该 IP 地址来启动 MQTT 连接
这就是我从手表实现客户端的方式
AWSMQTTService.kt
// ... other code
socketFactory = AWSIotSslUtility.getSocketFactory(
applicationContext.resources.openRawResource(R.raw.groupca),
applicationContext.resources.openRawResource(R.raw.fc7334298c_certificate),
applicationContext.resources.openRawResource(R.raw.fc7334298c_private)
)
mqttClient = MqttAndroidClient(this, "ssl://${getEdgeEndpoint()}:8883", getDeviceName())
val mqttOptions = MqttConnectOptions()
mqttOptions.connectionTimeout = 5
mqttOptions.isAutomaticReconnect = true
mqttOptions.socketFactory = socketFactory
mqttClient.connect(mqttOptions, null, object : IMqttActionListener {
override fun onSuccess(asyncActionToken: IMqttToken?) {
debugLog("success")
}
override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable) {
debugLog("failure")
Log.e("Jarvis/err", "Failure", exception)
}
})
AWSIotSslUtility.kt
/*
* Copyright 2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.shelltechworks.jarviswear.lib.utils
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.openssl.PEMKeyPair
import org.bouncycastle.openssl.PEMParser
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter
import java.io.*
import java.security.cert.CertificateFactory
import java.security.cert.Certificate as Certificate
import java.security.*
import java.security.Security
import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.TrustManagerFactory
/**
* This is a helper class to facilitate reading of the configurations and
* certificate from the resource files.
*/
object AWSIotSslUtility {
@Throws(Exception::class)
fun getSocketFactory(
caCrtFile: InputStream,
crtFile: InputStream, keyFile: InputStream
): SSLSocketFactory {
Security.addProvider(BouncyCastleProvider())
val cf = CertificateFactory.getInstance("X.509")
val caCert = cf.generateCertificate(caCrtFile)
val cert = cf.generateCertificate(crtFile)
// load client private key
val pemParser = PEMParser(InputStreamReader(keyFile))
val pemRawValue = pemParser.readObject()
val converter = JcaPEMKeyConverter()
.setProvider("BC")
val key: KeyPair
key = converter.getKeyPair(pemRawValue as PEMKeyPair)
pemParser.close()
// CA certificate is used to authenticate server
val caKs = KeyStore.getInstance(KeyStore.getDefaultType())
caKs.load(null, null)
caKs.setCertificateEntry("ca-certificate", caCert)
val tmf = TrustManagerFactory.getInstance("X509")
tmf.init(caKs)
// client key and certificates are sent to server so it can authenticate
// us
val ks = KeyStore.getInstance(KeyStore.getDefaultType())
ks.load(null, null)
ks.setCertificateEntry("certificate", cert)
ks.setKeyEntry(
"private-key", key.private, "".toCharArray(),
arrayOf(cert)
)
val kmf = KeyManagerFactory.getInstance(
KeyManagerFactory.getDefaultAlgorithm()
)
kmf.init(ks, "".toCharArray())
// finally, create SSL socket factory
val context = SSLContext.getInstance("TLSv1.2")
context.init(kmf.keyManagers, tmf.trustManagers, null)
return context.socketFactory
}
}
我希望这能够连接并打印success
到调试日志。但是,我收到了这个错误
2019-05-29 16:18:31.259 13475-13475/com.shelltechworks.jarviswear D/Jarvis/AWSMQTTService: failure
2019-05-29 16:18:31.270 13475-13475/com.shelltechworks.jarviswear E/Jarvis/err: Failure
MqttException (0) - java.net.SocketTimeoutException: failed to connect to /192.168.12.1 (port 8883) from /192.168.167.239 (port 41415) after 5000ms
at org.eclipse.paho.client.mqttv3.internal.ExceptionHelper.createMqttException(ExceptionHelper.java:38)
at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:715)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.net.SocketTimeoutException: failed to connect to /192.168.12.1 (port 8883) from /192.168.167.239 (port 41415) after 5000ms
at libcore.io.IoBridge.connectErrno(IoBridge.java:185)
at libcore.io.IoBridge.connect(IoBridge.java:130)
at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:129)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:356)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:356)
at java.net.Socket.connect(Socket.java:616)
at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:80)
at org.eclipse.paho.client.mqttv3.internal.SSLNetworkModule.start(SSLNetworkModule.java:103)
at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:701)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)