RRPC capabilities
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.