Json RPC: Object.Set methods have the updated object in the response

This commit is contained in:
BadAix 2016-12-30 14:24:10 +01:00
parent c1eca56e38
commit 9e96b3e13b
5 changed files with 248 additions and 167 deletions

View file

@ -20,7 +20,6 @@ package de.badaix.snapcast;
import android.content.Context;
import android.support.v7.widget.PopupMenu;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@ -64,7 +63,7 @@ public class ClientItem extends LinearLayout implements SeekBar.OnSeekBarChangeL
}
private void update() {
Log.d(TAG, "update: " + client.getVisibleName() + ", connected: " + client.isConnected());
//Log.d(TAG, "update: " + client.getVisibleName() + ", connected: " + client.isConnected());
title.setText(client.getVisibleName());
title.setEnabled(client.isConnected());
volumeSeekBar.setProgress(client.getConfig().getVolume().getPercent());

View file

@ -55,6 +55,7 @@ import java.util.ArrayList;
import de.badaix.snapcast.control.RemoteControl;
import de.badaix.snapcast.control.json.Client;
import de.badaix.snapcast.control.json.Group;
import de.badaix.snapcast.control.json.ServerStatus;
import de.badaix.snapcast.control.json.Stream;
import de.badaix.snapcast.utils.NsdHelper;
@ -431,8 +432,9 @@ public class MainActivity extends AppCompatActivity implements GroupItem.GroupIt
remoteControl.setStream(groupId, streamId);
changed = true;
}
if (changed)
remoteControl.getServerStatus();
//TODO
// if (changed)
// remoteControl.getServerStatus();
}
}
@ -467,7 +469,7 @@ public class MainActivity extends AppCompatActivity implements GroupItem.GroupIt
@Override
public void onClientEvent(RemoteControl remoteControl, Client client, RemoteControl.ClientEvent event) {
Log.d(TAG, "onClientEvent: " + event.toString());
remoteControl.getServerStatus();
// remoteControl.getServerStatus();
/* TODO: group
if (event == RemoteControl.ClientEvent.deleted)
serverStatus.removeClient(client);
@ -475,6 +477,9 @@ public class MainActivity extends AppCompatActivity implements GroupItem.GroupIt
serverStatus.updateClient(client);
sectionsPagerAdapter.updateServer(serverStatus);
*/
if (event != RemoteControl.ClientEvent.deleted)
serverStatus.updateClient(client);
groupListFragment.updateServer(serverStatus);
}
@Override
@ -489,6 +494,12 @@ public class MainActivity extends AppCompatActivity implements GroupItem.GroupIt
// TODO: group sectionsPagerAdapter.updateServer(serverStatus);
}
@Override
public void onGroupUpdate(RemoteControl remoteControl, Group group) {
// TODO
Log.d(TAG, "onGroupUpdate: " + group.toString());
}
private void setActionbarSubtitle(final String subtitle) {
MainActivity.this.runOnUiThread(new Runnable() {

View file

@ -44,14 +44,12 @@ public class RemoteControl implements TcpClient.TcpClientListener {
private TcpClient tcpClient;
private long msgId;
private RemoteControlListener listener;
private ServerStatus serverStatus;
private String host;
private int port;
private HashMap<Long, String> pendingRequests;
public RemoteControl(RemoteControlListener listener) {
this.listener = listener;
serverStatus = new ServerStatus();
msgId = 0;
pendingRequests = new HashMap<>();
}
@ -96,7 +94,9 @@ public class RemoteControl implements TcpClient.TcpClientListener {
// Log.d(TAG, "Msg received: " + message);
try {
JSONObject json = new JSONObject(message);
if (json.has("id")) {
/// Response
// Log.d(TAG, "ID: " + json.getString("id"));
long id = json.getLong("id");
String request = "";
@ -107,38 +107,53 @@ public class RemoteControl implements TcpClient.TcpClientListener {
pendingRequests.remove(id);
}
}
if (listener == null)
return;
if (json.has("error")) {
JSONObject error = json.getJSONObject("error");
Log.e(TAG, "error " + error.getInt("code") + ": " + error.getString("message"));
} else if (!TextUtils.isEmpty(request)) {
if (request.equals("Server.GetStatus")) {
serverStatus.fromJson(json.getJSONObject("result"));
if (listener != null)
listener.onServerStatus(this, serverStatus);
}
if (TextUtils.isEmpty(request)) {
Log.e(TAG, "request for id " + id + " not found");
return;
}
/// Response to a "Object.GetStatus" message
if (request.equals("Client.GetStatus")) {
listener.onClientEvent(this, new Client(json.getJSONObject("result")), ClientEvent.updated);
} else if (request.equals("Group.GetStatus")) {
listener.onGroupUpdate(this, new Group(json.getJSONObject("result")));
} else if (request.equals("Server.GetStatus")) {
listener.onServerStatus(this, new ServerStatus(json.getJSONObject("result")));
} else if (json.getJSONObject("result").has("method") && json.getJSONObject("result").has("params")) {
/// Response to a "Object.Set" message
JSONObject result = json.getJSONObject("result");
String method = result.getString("method");
if ("Client.OnUpdate".equals(method)) {
// listener.onClientEvent(this, new Client(result.getJSONObject("params")), ClientEvent.updated);
} else if ("Group.OnUpdate".equals(method)) {
listener.onGroupUpdate(this, new Group(result.getJSONObject("params")));
} else if ("Server.OnUpdate".equals(method)) {
listener.onServerStatus(this, new ServerStatus(result.getJSONObject("params")));
}
}
} else {
/// Notification
if (listener == null)
return;
String method = json.getString("method");
// Log.d(TAG, "Notification: " + method);
if (method.contains("Client.On")) {
final Client client = new Client(json.getJSONObject("params").getJSONObject("data"));
// serverStatus.addClient(client);
if (listener != null) {
ClientEvent event;
if (method.equals("Client.OnUpdate"))
listener.onClientEvent(this, client, ClientEvent.updated);
else if (method.equals("Client.OnConnect"))
listener.onClientEvent(this, client, ClientEvent.connected);
else if (method.equals("Client.OnDisconnect"))
listener.onClientEvent(this, client, ClientEvent.disconnected);
else if (method.equals("Client.OnDelete")) {
listener.onClientEvent(this, client, ClientEvent.deleted);
}
}
final Client client = new Client(json.getJSONObject("params"));
listener.onClientEvent(this, client, ClientEvent.fromString(method));
} else if (method.equals("Stream.OnUpdate")) {
Stream stream = new Stream(json.getJSONObject("params").getJSONObject("data"));
listener.onStreamUpdate(this, stream);
Log.d(TAG, stream.toString());
listener.onStreamUpdate(this, new Stream(json.getJSONObject("params")));
} else if (method.equals("Group.OnUpdate")) {
listener.onGroupUpdate(this, new Group(json.getJSONObject("params")));
} else if (method.equals("Server.OnUpdate")) {
listener.onServerStatus(this, new ServerStatus(json.getJSONObject("params")));
}
}
@ -157,7 +172,6 @@ public class RemoteControl implements TcpClient.TcpClientListener {
@Override
public void onConnected(TcpClient tcpClient) {
Log.d(TAG, "onConnected");
serverStatus = new ServerStatus();
if (listener != null)
listener.onConnected(this);
}
@ -165,7 +179,6 @@ public class RemoteControl implements TcpClient.TcpClientListener {
@Override
public void onDisconnected(TcpClient tcpClient, Exception e) {
Log.d(TAG, "onDisconnected");
serverStatus = null;
if (listener != null)
listener.onDisconnected(this, e);
}
@ -262,10 +275,30 @@ public class RemoteControl implements TcpClient.TcpClientListener {
}
public enum ClientEvent {
connected,
disconnected,
updated,
deleted
connected("Client.OnConnect"),
disconnected("Client.OnDisconnect"),
updated("Client.OnUpdate"),
deleted("Client.OnDelete");
private String text;
ClientEvent(String text) {
this.text = text;
}
public static ClientEvent fromString(String text) {
if (text != null) {
for (ClientEvent b : ClientEvent.values()) {
if (text.equalsIgnoreCase(b.text)) {
return b;
}
}
}
throw new IllegalArgumentException("No ClientEvent with text " + text + " found");
}
public String getText() {
return this.text;
}
}
public interface RemoteControlListener {
@ -280,5 +313,7 @@ public class RemoteControl implements TcpClient.TcpClientListener {
void onServerStatus(RemoteControl remoteControl, ServerStatus serverStatus);
void onStreamUpdate(RemoteControl remoteControl, Stream stream);
void onGroupUpdate(RemoteControl remoteControl, Group group);
}
}

View file

@ -150,9 +150,7 @@ Json JsonNotification::getJson(const std::string& method, Json data)
Json notification = {
{"jsonrpc", "2.0"},
{"method", method},
{"params", {
{"data", data}
}}
{"params", data}
};
return notification;

View file

@ -112,51 +112,68 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
try
{
request.parse(message);
logD << "method: " << request.method << ", " << "id: " << request.id << "\n";
logO << "method: " << request.method << ", " << "id: " << request.id << "\n";
json response;
ClientInfoPtr clientInfo = nullptr;
GroupPtr group = nullptr;
msg::ServerSettings serverSettings;
serverSettings.setBufferMs(settings_.bufferMs);
json result;
if (request.method.find("Group.Set") == 0)
if (request.method.find("Client.") == 0)
{
group = Config::instance().getGroup(request.getParam("group").get<string>());
if (group == nullptr)
throw JsonInternalErrorException("Group not found", request.id);
}
if (request.method.find("Client.Set") == 0)
{
clientInfo = Config::instance().getClientInfo(request.getParam("client").get<string>());
ClientInfoPtr clientInfo = Config::instance().getClientInfo(request.getParam("client").get<string>());
if (clientInfo == nullptr)
throw JsonInternalErrorException("Client not found", request.id);
}
if (request.method == "Server.GetStatus")
if (request.method == "Client.GetStatus")
{
/// TODO: rpc
string clientId = request.hasParam("client") ? request.getParam("client").get<string>() : "";
response = Config::instance().getServerStatus(/*clientId,*/ streamManager_->toJson());
// logO << response.dump(4);
}
else if (request.method == "Server.DeleteClient")
{
clientInfo = Config::instance().getClientInfo(request.getParam("client").get<string>());
if (clientInfo == nullptr)
throw JsonInternalErrorException("Client not found", request.id);
response = clientInfo->host.mac;
Config::instance().remove(clientInfo);
Config::instance().save();
json notification = JsonNotification::getJson("Client.OnDelete", clientInfo->toJson());
controlServer_->send(notification.dump(), controlSession);
clientInfo = nullptr;
result = clientInfo->toJson();
}
else if (request.method == "Client.SetVolume")
{
clientInfo->config.volume.fromJson(request.getParam("volume"));
response = clientInfo->config.volume.toJson();
}
else if (request.method == "Client.SetLatency")
{
clientInfo->config.latency = request.getParam<int>("latency", -10000, settings_.bufferMs);
}
else if (request.method == "Client.SetName")
{
clientInfo->config.name = request.getParam("name").get<string>();
}
else
throw JsonMethodNotFoundException(request.id);
if (request.method.find("Client.Set") == 0)
{
/// Response: updated client
result = {{"method", "Client.OnUpdate"}, {"params", clientInfo->toJson()}};
/// Update client
session_ptr session = getStreamSession(request.getParam("client").get<string>());
if (session != nullptr)
{
msg::ServerSettings serverSettings;
serverSettings.setBufferMs(settings_.bufferMs);
serverSettings.setVolume(clientInfo->config.volume.percent);
serverSettings.setMuted(clientInfo->config.volume.muted);
serverSettings.setLatency(clientInfo->config.latency);
session->send(&serverSettings);
}
/// Notify others
json notification = JsonNotification::getJson("Client.OnUpdate", clientInfo->toJson());
logO << "Notification: " << notification.dump() << "\n";
controlServer_->send(notification.dump(), controlSession);
}
}
else if (request.method.find("Group.") == 0)
{
GroupPtr group = Config::instance().getGroup(request.getParam("group").get<string>());
if (group == nullptr)
throw JsonInternalErrorException("Group not found", request.id);
if (request.method == "Group.GetStatus")
{
result = group->toJson();
}
else if (request.method == "Group.SetStream")
{
@ -166,8 +183,11 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
throw JsonInternalErrorException("Stream not found", request.id);
group->streamId = streamId;
response = group->streamId;
/// Response: updated group
result = {{"method", "Group.OnUpdate"}, {"params", group->toJson()}};
/// Update clients
for (auto client: group->clients)
{
session_ptr session = getStreamSession(client->id);
@ -177,6 +197,11 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
session->setPcmStream(stream);
}
}
/// Notify others
json notification = JsonNotification::getJson("Group.OnUpdate", group->toJson());
logO << "Notification: " << notification.dump() << "\n";
controlServer_->send(notification.dump(), controlSession);
}
else if (request.method == "Group.SetClients")
{
@ -228,37 +253,50 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
if (group->empty())
Config::instance().remove(group);
// response = Config::instance().getServerStatus(/*clientId,*/ streamManager_->toJson());
json serverJson = Config::instance().getServerStatus(streamManager_->toJson());
result = {{"method", "Server.OnUpdate"}, {"params", serverJson}};
/// Notify others: since at least two groups are affected, send a complete server update
json notification = JsonNotification::getJson("Server.OnUpdate", serverJson);
logO << "Notification: " << notification.dump() << "\n";
controlServer_->send(notification.dump(), controlSession);
}
else if (request.method == "Client.SetLatency")
{
clientInfo->config.latency = request.getParam<int>("latency", -10000, settings_.bufferMs);
response = clientInfo->config.latency;
else
throw JsonMethodNotFoundException(request.id);
}
else if (request.method == "Client.SetName")
else if (request.method.find("Server.") == 0)
{
clientInfo->config.name = request.getParam("name").get<string>();
response = clientInfo->config.name;
if (request.method == "Server.GetStatus")
{
result = Config::instance().getServerStatus(streamManager_->toJson());
}
else if (request.method == "Server.DeleteClient")
{
ClientInfoPtr clientInfo = Config::instance().getClientInfo(request.getParam("client").get<string>());
if (clientInfo == nullptr)
throw JsonInternalErrorException("Client not found", request.id);
Config::instance().remove(clientInfo);
json serverJson = Config::instance().getServerStatus(streamManager_->toJson());
result = {{"method", "Server.OnUpdate"}, {"params", serverJson}};
/// Notify others
json notification = JsonNotification::getJson("Server.OnUpdate", serverJson);
logO << "Notification: " << notification.dump() << "\n";
controlServer_->send(notification.dump(), controlSession);
}
else
throw JsonMethodNotFoundException(request.id);
}
else
throw JsonMethodNotFoundException(request.id);
if (clientInfo != nullptr)
{
serverSettings.setVolume(clientInfo->config.volume.percent);
serverSettings.setMuted(clientInfo->config.volume.muted);
serverSettings.setLatency(clientInfo->config.latency);
session_ptr session = getStreamSession(request.getParam("client").get<string>());
if (session != nullptr)
session->send(&serverSettings);
Config::instance().save();
json notification = JsonNotification::getJson("Client.OnUpdate", clientInfo->toJson());
controlServer_->send(notification.dump(), controlSession);
}
controlSession->send(request.getResponse(response).dump());
string responseJson = request.getResponse(result).dump();
logO << "Response: " << responseJson << "\n";
controlSession->send(responseJson);
}
catch (const JsonRequestException& e)
{