Android中使用CoAP协议

什么是CoAP协议

CoAP(Constrained Application Protocol)协议是一种物联网协议。与传统的PC、智能手机相比,物联网设备大多是资源限制型的,有限的CPU、RAM、Flash、网络带宽等。对于这些设备来说,直接使用TCP和HTTP协议是不太现实的。

CoAP协议主要有以下特征

  • 受限制的小型设备的Web传输协议(类似于HTTP)
  • 异步信息交换
  • 低开销,非常易于解析
  • 支持URI和内容类型
  • 代理和缓存功能

从抽象协议层,CoAP可以表示为
Android中使用CoAP协议_第1张图片
如上所示,CoAP协议分为Request/Response和Messages层,其中,Messages层处理UDP和异步消息。Request/Response基于请求/响应消息来管理请求/响应交互

CoAP支持始终不同的消息类型

  • CON Confirmable 可确认的
  • NON Non-Confirmable 无法确认
  • Acknowledge 确认
  • Reset 重置

这里我们重点介绍下可确认消息与不可确认消息。

可确认消息是可靠消息,在两个端点之间交换信息时,这些消息可能是可靠的。在CoAP中,使用确认消息(CON)获得可靠的消息。使用这些消息,客户端可以确保消息将达到服务器。反复发送确认消息,知道另一方发送确认回复消息(ACK)。ACK消息包含与确认消息(CON)相同的ID。

整个过程如下图所示
Android中使用CoAP协议_第2张图片
不可确认消息(NON)是指不需要服务端来确认的消息。它们是不可靠消息,或者换句话说,这些消息不包含必须传递给服务器的关键信息。包含从传感器读取的值的消息属于此类别。

即使这些消息不可靠,它们也具有唯一的ID。

Android中使用CoAP协议_第3张图片
值的注意的是,与HTTP协议类似,CoAP协议的Request方法包含以下四种。

  • GET方法 用于获取某资源
  • POST方法 用于创建某资源
  • PUT方法 用于更新某资源
  • DELETE方法 用于删除某资源

当然,以上的Request方法都是官方的定义,具体的功能由代码来决定。POST也可以用来获取信息

下面来重点介绍下Android端如何集成使用CoAP服务。

集成

这里我们使用org.eclipse.californium:californium-core开源框架来实现CoAP功能
GitHub地址

https://github.com/eclipse/californium

项目的build.gradle文件集成如下代码

dependencies {
    def californiumVersion = '3.2.0'
    implementation 'org.eclipse.californium:californium-core:'+californiumVersion
}

服务端实现

服务端开启CoAP服务时,需要开启一个Service,如下

class DemoServerService : Service() {
    private lateinit var mCoapService: CoapServer
    private lateinit var mBinder: Binder

    override fun onCreate() {
        this.mCoapService = CoapServer(6723) //这里需要定义端口号
        val coapResource = CoapResource("base")
        coapResource.add(AResource())
        this.mCoapService.add(coapResource)
    }
    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        kotlin.runCatching {
            this.mCoapService.start()
            myLogger.d("onStartCommand")
        }
        return super.onStartCommand(intent, flags, startId)
    }
}

这里AResource的定义如下

class SearchResource : BaseCoapResource("a") {
    private val myLogger: MyLogger by lazy { MyLogger.get(SearchResource::class.java.simpleName) }
    override fun handleGET(exchange: CoapExchange?) {
        super.handleGET(exchange)
        exchange?.respond("this is get")
    }

    override fun handlePOST(exchange: CoapExchange?) {
        if (exchange == null) return
        myLogger.d("requestString:${exchange.requestText}")
    }
}

这样,当我们启动DemoServerService服务时,服务端就开启了一个CoAP服务,如下

val intent = Intent(context, DemoServerService::class.java)
context.startService(intent)

客户端实现

客户端如何发起一个CoAP请求呢?示例代码如下,我们对服务端发起一个POST请求

   internal fun request() {

        val url = "coap://192.168.3.12:6723)}/base/a"
        val map = ArrayMap<String, Any>()
        map["deviceId"] = "1234"

        val handler = object : CoapHandler {
            override fun onLoad(response: CoapResponse?) {
                if (response == null) return
                myLogger.d(Utils.prettyPrint(response))
            }

            override fun onError() {
                myLogger.d("connect error")
                callback?.invoke(false)
            }
        }
        val coapClient = CoapClient(url).useNONs().setTimeout(UAMClientManager.DEFAULT_TIMEOUT)
        coapClient.post(handler, Gson().toJson(map), MediaTypeRegistry.APPLICATION_JSON)
    }

实现广播

如何向局域网内发起一个广播呢?我们都知道只需要向网关发送CoAP请求即可。但是实践中,我们发现一个CoAP request只能收到一个response,那怎么能保证一个Request收到多个Response呢?

如下实现,我们将发起网络请求的时候,不使用默认的CoapClient,而是使用我们定义的MulticastCoapClient

class MulticastCoapClient(url: String) : CoapClient(url) {
    companion object {
        private val TAG = MulticastCoapClient::class.java.simpleName
    }
    private val logger by lazy { MyLogger.get(TAG) }

    override fun send(request: Request?): Request {
        if (request != null) {
            val address = request.localAddress
            request.setLocalAddress(address, true)
        }
        return super.send(request)
    }
}

如此,我们就可以实现局域网内广播CoAP请求了!

你可能感兴趣的:(Android,android)