RRPC capabilities

Updated at:

RRPC (revert-RPC) allows you to send synchronous requests from the cloud to a device and receive responses.

Background information

RRPC (revert-RPC) is a synchronous call initiated from the cloud by using a cloud API. The call returns a response directly from the device.

The device receives a synchronous request on a topic, such as /ext/rrpc/{messageId}/{rrpc_topic} or /sys/{pk}/{dn}/rrpc/request/${msgId}. After the device processes the message, it publishes the result to /ext/rrpc/{messageId}/{rrpc_topic} or /ext/rrpc/${msgId}/${topic}.

Message communication API

Call the cloud RRPC API to send a synchronous request to a device.

Device management API

To send a synchronous RRPC request to a device, call the synchronous service API on the cloud. You can also define a device service as synchronous in IoT Platform and then trigger the service invocation.

API calls

Before making an RRPC call, make sure the device-side SDK is initialized. A successful initialization indicates that the MQTT connection is established.

RRPC listener and reply

Cloud RRPC requests are received by the downstream listener on the topic specified by the caller.

// This is the global interface for setting the downstream listener.
LinkKit.getInstance().registerOnPushListener(notifyListener);
        /**
     * Downstream listener. All downstream MQTT data from the cloud is returned through this callback.
     */
private static IConnectNotifyListener notifyListener = new IConnectNotifyListener() {
    /**
         * onNotify is triggered only if shouldHandle does not block this topic.
         * @param connectId The connection type. Check if it is a persistent connection: connectId == ConnectSDK.getInstance().getPersistentConnectId()
         * @param topic The downstream topic.
         * @param aMessage The content of the downstream data.
         */
    @Override
    public void onNotify(String connectId, String topic, AMessage aMessage) {
        String data = new String((byte[]) aMessage.data);
        // Example of data returned from the server-side: data = {"method":"thing.service.test_service","id":"123374967","params":{"vv":60},"version":"1.0.0"}
    }
    /**
         * @param connectId The connection type. Check if it is a persistent connection: connectId == ConnectSDK.getInstance().getPersistentConnectId()
         * @param topic The downstream topic.
         * @return Specifies whether to process this topic. If true, the data is passed to the onNotify callback. If false, onNotify does not receive data for this topic. The recommended value is true.
         */
    @Override
    public boolean shouldHandle(String connectId, String topic) {
        return true;
    }
    /**
         * @param connectId The connection type. Check if it is a persistent connection: connectId == ConnectSDK.getInstance().getPersistentConnectId()
         * @param connectState {@link ConnectState}
         *     CONNECTED, Connection successful
         *     DISCONNECTED, Disconnected
         *     CONNECTING, Connecting
         *     CONNECTFAIL; Connection failed
         */
    @Override
    public void onConnectStateChange(String connectId, ConnectState connectState) {
        Log.d(TAG, "onConnectStateChange() called with: connectId = [" + connectId + "], connectState = [" + connectState + "]");
    }
};

Usage example

Device-side

The RRPC response contains data based on the caller's request. By default, the following example returns an empty data object.

// Use the global downstream listener.
LinkKit.getInstance().registerOnPushListener(notifyListener);
private IConnectNotifyListener notifyListener = new IConnectNotifyListener() {
    @Override
    public void onNotify(String connectId, String topic, AMessage aMessage) {
            if (CONNECT_ID.equals(connectId) && !TextUtils.isEmpty(topic) &&
                    topic.startsWith("/ext/rrpc/")) {
            // Example: topic=/ext/rrpc/1138654706478941696//a1ExY4afKY1/testDevice/user/get
            //ALog.d(TAG, "receive Message=" + new String((byte[]) aMessage.data));
            // Example of data returned from the server-side: {"method":"thing.service.test_service","id":"123374967","params":{"vv":60},"version":"1.0.0"}
            MqttPublishRequest request = new MqttPublishRequest();
            request.isRPC = false;
            request.topic = topic;
            String[] array = topic.split("/");
            String resId = array[3];
            request.msgId = resId;
            // TODO: Fill this in as needed. This is for reference only.
            request.payloadObj = "{\"id\":\"" + resId + "\", \"code\":\"200\"" + ",\"data\":{} }";
            LinkKit.getInstance().publish(request, new IConnectSendListener() {
                @Override
                public void onResponse(ARequest aRequest, AResponse aResponse) {
                                        // The response is successful.
                }
                @Override
                public void onFailure(ARequest aRequest, AError aError) {
                                        // The response failed.
                }
                    });
        }
    }
    @Override
    public boolean shouldHandle(String connectId, String topic) {
        return true;
    }
    @Override
    public void onConnectStateChange(String connectId, ConnectState connectState) {
        Log.d(TAG, "onConnectStateChange() called with: connectId = [" + connectId + "], connectState = [" + connectState + "]");
    }
};

Cloud

For sample code to trigger a cloud-side RRPC call, see Invoke an RRPC call on a custom topic.