package com.dataart.android.devicehive.client;
import java.util.LinkedList;
import java.util.List;
import android.content.Context;
import com.dataart.android.devicehive.Command;
import com.dataart.android.devicehive.DeviceData;
import com.dataart.android.devicehive.Notification;
import com.dataart.android.devicehive.client.commands.NotificationsRetrivalCommand;
import com.dataart.android.devicehive.client.commands.PollMultipleDeviceNotificationsCommand;
import com.dataart.android.devicehive.client.commands.PollMultipleDeviceNotificationsCommand.DeviceNotification;
/**
* Represents a device client which provides high-level API for communication
* and receive notifications from several devices. This class is abstract and
* designed to be subclassed in order to handle incoming notifications. Also
* this class provides a number of various callbacks:
* {@link #onStartReceivingNotifications()},
* {@link #onStopReceivingNotifications()},
* {@link #onStartSendingCommand(Command)},
* {@link #onFinishSendingCommand(Command)},
* {@link #onFailSendingCommand(Command)}, etc.
*
*/
public abstract class MultipleDeviceClient extends DeviceClient {
private List<DeviceData> devices;
/**
* Construct client with given {@link Context} and {@link DeviceData}
* objects.
*
* @param context
* {@link Context} object. In most cases this should be
* application context which stays alive during the entire life
* of an application.
* @param deviceData
* {@link DeviceData} object which describes device to
* communicate with.
*/
public MultipleDeviceClient(Context context, final List<DeviceData> devices) {
super(context);
this.devices = devices;
setServiceConnection(new MultipleDeviceClientServiceConnection(context));
}
private class MultipleDeviceClientServiceConnection extends
ClientServiceConnection {
public MultipleDeviceClientServiceConnection(Context context) {
super(context);
}
@Override
protected NotificationsRetrivalCommand getPollNotificationsCommand(
String lastNotificationPollTimestamp, Integer waitTimeout) {
return new PollMultipleDeviceNotificationsCommand(getDeviceGuids(),
lastNotificationPollTimestamp, waitTimeout);
}
@Override
protected void didReceiveNotification(Notification notification) {
DeviceNotification deviceNotification = (DeviceNotification) notification;
onReceiveNotification(deviceNotification.getDeviceGuid(),
notification);
}
private List<String> getDeviceGuids() {
if (devices != null && !devices.isEmpty()) {
final List<String> guids = new LinkedList<String>();
for (DeviceData device : devices) {
guids.add(device.getId());
}
return guids;
} else {
return null;
}
}
}
/**
* Send command to the given device.
*
* @param device
* Target device.
* @param command
* {@link Command} to be sent.
*/
public void sendCommand(DeviceData device, final Command command) {
this.sendCommand(device, command);
}
/**
* Reload device data. Current device data is updated with instance of
* {@link DeviceData} retrieved from the server.
*
* @see #onFinishReloadingDeviceData(DeviceData)
* @see #onFailReloadingDeviceData()
*/
public void reloadDeviceData(DeviceData device) {
serviceConnection.reloadDeviceData(device);
}
/* package */void onReloadDeviceDataFinishedInternal(DeviceData deviceData) {
final DeviceData device = getDeviceDataWithId(deviceData.getId());
devices.remove(device);
devices.add(deviceData);
onFinishReloadingDeviceData(deviceData);
}
private DeviceData getDeviceDataWithId(String deviceId) {
for (DeviceData device : devices) {
if (device.getId().equals(deviceId)) {
return device;
}
}
return null;
}
/**
* Handle received notification. Can be called either on main (UI) thread or
* some background thread depending on
* {@link #shouldReceiveNotificationAsynchronously(Notification)} method
* return value.
*
* @param notification
* {@link Notification} instance to handle by the client.
*/
protected abstract void onReceiveNotification(String deviceId,
final Notification notification);
}