Files
LedD-Android/app/src/main/java/com/idlegandalf/ledd/helper/LedDHelper.java

387 lines
15 KiB
Java

/*
* LEDD Project
* Copyright (C) 2015 LEDD Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.idlegandalf.ledd.helper;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import com.idlegandalf.ledd.callbacks.AddControllerCallback;
import com.idlegandalf.ledd.callbacks.AddStripeCallback;
import com.idlegandalf.ledd.callbacks.DiscoverCallback;
import com.idlegandalf.ledd.callbacks.ReceiveColorCallback;
import com.idlegandalf.ledd.callbacks.StripesCallback;
import com.idlegandalf.ledd.components.AnswerTask;
import com.idlegandalf.ledd.components.Controller;
import com.idlegandalf.ledd.components.HSV;
import com.idlegandalf.ledd.components.LedDDaemon;
import com.idlegandalf.ledd.components.LedDRequest;
import com.idlegandalf.ledd.components.LedStripe;
import com.idlegandalf.ledd.services.ColorService;
import com.thetransactioncompany.jsonrpc2.JSONRPC2Error;
import com.thetransactioncompany.jsonrpc2.JSONRPC2Request;
import com.thetransactioncompany.jsonrpc2.JSONRPC2Response;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.LinkedBlockingQueue;
import timber.log.Timber;
public class LedDHelper {
final String ACTION_SETCOLOR = "set_color";
final String ACTION_GETCOLOR = "get_color";
final String ACTION_ADDCONTROLLER = "add_controller";
final String ACTION_GETALLSTRIPES = "get_stripes";
final String ACTION_ADDSTRIPE = "add_stripe";
final String ACTION_TESTCHANNEL = "test_channel";
final String ACTION_DISCOVER = "discover";
private Context context;
private boolean mBound = false;
private LedDDaemon ledDDaemon;
private Worker<LedDRequest> requestWorker;
private LinkedBlockingQueue<LedDRequest> dRequests;
ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
Timber.d("ColorService bound!");
requestWorker = new Worker<>(dRequests, (ColorService.ColorBinder) service, ledDDaemon);
mBound = true;
new Thread(requestWorker).start();
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
requestWorker.stop();
mBound = false;
}
};
public LedDHelper(LedDDaemon ledDDaemon, Context appl) {
this.context = appl;
this.dRequests = new LinkedBlockingQueue<>();
this.ledDDaemon = ledDDaemon;
Intent intent = new Intent(appl, ColorService.class);
appl.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
/**
* Add controller to ledd daemon
*
* @param c controller object
*/
public void addController(final Controller c, final AddControllerCallback callback) {
Map<String, Object> params = new HashMap<>();
params.put("channels", c.getChannels());
params.put("i2c_dev", c.getI2c_device());
params.put("address", c.getAddress());
JSONRPC2Request request = new JSONRPC2Request(ACTION_ADDCONTROLLER, params, UUID.randomUUID().toString());
addRequestToQueue(request, new AnswerTask() {
@Override
public void onConnectionFailed(String message) {
callback.onConnectionFailed(message);
}
@Override
public void onResponse(JSONRPC2Response response) {
if (response.indicatesSuccess()) {
try {
JSONObject json = new JSONObject(response.getResult().toString());
c.setId(json.getInt("cid"));
callback.onControllerAdded(c);
} catch (JSONException e) {
e.printStackTrace();
}
} else {
@SuppressWarnings("ThrowableResultOfMethodCallIgnored") JSONRPC2Error error = response.getError();
callback.onAddFailed(error.getCode(), error.getMessage());
}
}
});
}
/**
* Get stripes known to daemon
*/
public void getStripes(final StripesCallback callback) {
addRequestToQueue(new JSONRPC2Request(ACTION_GETALLSTRIPES, UUID.randomUUID().toString()), new AnswerTask() {
@Override
public void onConnectionFailed(String message) {
callback.onConnectionFailed(message);
}
@Override
public void onResponse(JSONRPC2Response response) {
try {
if (response.indicatesSuccess()) {
ledDDaemon.getControllers().clear();
List<LedStripe> list = new ArrayList<>();
JSONObject json = new JSONObject(response.getResult().toString());
JSONArray jcontrollers = json.getJSONArray("controller");
for (int i = 0; i < jcontrollers.length(); i++) {
JSONObject row = jcontrollers.getJSONObject(i);
Controller nController = new Controller();
nController.setAddress(row.getString("address"));
nController.setChannels(row.getInt("channel"));
nController.setI2c_device(row.getInt("i2c_device"));
nController.setId(row.getInt("id"));
JSONArray jstripes = row.getJSONArray("stripes");
for (int o = 0; o < jstripes.length(); o++) {
JSONObject srow = jstripes.getJSONObject(o);
LedStripe nStripe = new LedStripe();
nStripe.setId(srow.getInt("id"));
nStripe.setRGB(srow.getBoolean("rgb"));
nStripe.setChannelRed(srow.getJSONArray("channel").getInt(0));
nStripe.setChannelGreen(srow.getJSONArray("channel").getInt(1));
nStripe.setChannelBlue(srow.getJSONArray("channel").getInt(2));
nStripe.setName(srow.getString("name"));
nStripe.setController(nController);
nStripe.setLedDDaemon(ledDDaemon);
list.add(nStripe);
}
ledDDaemon.getControllers().add(nController);
}
callback.onSuccess(list);
} else {
@SuppressWarnings("ThrowableResultOfMethodCallIgnored") JSONRPC2Error error = response.getError();
callback.onGetFailed(error.getCode(), error.getMessage());
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Set color using the stripeid
*
* @param ledStripe Stripe
*/
public void setColor(LedStripe ledStripe) {
Map<String, Object> hsv = new HashMap<>();
hsv.put("h", ledStripe.getColor().getHue());
hsv.put("s", ledStripe.getColor().getSaturation());
hsv.put("v", ledStripe.getColor().getValue());
Map<String, Object> params = new HashMap<>();
params.put("sid", ledStripe.getId());
params.put("hsv", hsv);
JSONRPC2Request request = new JSONRPC2Request(ACTION_SETCOLOR, params, UUID.randomUUID().toString());
addRequestToQueue(request, null);
}
/**
* Get color using the stripeid
*
* @param ledStripe Stripe
*/
public void getColor(final LedStripe ledStripe, final ReceiveColorCallback callback) {
HashMap<String, Object> params = new HashMap<>();
params.put("sid", ledStripe.getId());
addRequestToQueue(new JSONRPC2Request(ACTION_GETCOLOR, params, UUID.randomUUID().toString()), new AnswerTask() {
@Override
public void onConnectionFailed(String message) {
callback.onConnectionFailed(message);
}
@Override
public void onResponse(JSONRPC2Response response) {
if (response.indicatesSuccess()) {
try {
JSONObject json = new JSONObject(response.getResult().toString());
JSONArray hsv = json.getJSONArray("color");
if (hsv.length() == 3) {
ledStripe.setColor(new HSV(hsv.getDouble(0), hsv.getDouble(1), hsv.getDouble(2)));
callback.onColorReceived(ledStripe);
} else {
callback.onReceiveFailed(-1, "HSV was empty");
}
} catch (JSONException e) {
e.printStackTrace();
callback.onReceiveFailed(-1, "Unhandeled JSON Exception");
}
} else {
@SuppressWarnings("ThrowableResultOfMethodCallIgnored") JSONRPC2Error error = response.getError();
callback.onReceiveFailed(error.getCode(), error.getMessage());
}
}
});
}
/**
* Test a channel on the controller
*
* @param c controller
* @param channel channel number
* @param value value (1= on, 0 = off)
*/
public void testChannel(Controller c, int channel, int value) {
HashMap<String, Object> params = new HashMap<>();
params.put("cid", c.getId());
params.put("channel", channel);
params.put("value", value);
addRequestToQueue(new JSONRPC2Request(ACTION_TESTCHANNEL, params, UUID.randomUUID().toString()), new AnswerTask() {
@Override
public void onConnectionFailed(String message) {
}
@Override
public void onResponse(JSONRPC2Response response) {
}
});
}
/**
* Get information about an ledd daemon
*/
public void discover(final DiscoverCallback callback) {
addRequestToQueue(new JSONRPC2Request(ACTION_DISCOVER, UUID.randomUUID().toString()), new AnswerTask() {
@Override
public void onConnectionFailed(String message) {
callback.onConnectionFailed(message);
}
@Override
public void onResponse(JSONRPC2Response response) {
try {
if (response.indicatesSuccess()) {
JSONObject json = new JSONObject(response.getResult().toString());
callback.onDiscoverSuccessfully(json.getString("version"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Get information about an ledd daemon
*/
public void addStripe(final LedStripe ledStripe, final AddStripeCallback callback) {
HashMap<String, Object> params = new HashMap<>();
HashMap<String, Object> mapping = new HashMap<>();
params.put("name", ledStripe.getName());
params.put("rgb", ledStripe.isRGB());
mapping.put("r", ledStripe.getChannelRed());
mapping.put("g", ledStripe.getChannelGreen());
mapping.put("b", ledStripe.getChannelBlue());
params.put("map", mapping);
params.put("cid", ledStripe.getController().getId());
addRequestToQueue(new JSONRPC2Request(ACTION_ADDSTRIPE, params, UUID.randomUUID().toString()), new AnswerTask() {
@Override
public void onConnectionFailed(String message) {
callback.onConnectionFailed(message);
}
@Override
public void onResponse(JSONRPC2Response response) {
try {
if (response.indicatesSuccess()) {
JSONObject json = new JSONObject(response.getResult().toString());
ledStripe.setId(json.getInt("sid"));
callback.onAddSuccessfully(ledStripe);
} else {
@SuppressWarnings("ThrowableResultOfMethodCallIgnored") JSONRPC2Error error = response.getError();
callback.onAddFailed(error.getCode(), error.getMessage());
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
private void addRequestToQueue(JSONRPC2Request request, AnswerTask task) {
if (request != null) dRequests.add(new LedDRequest(request, task));
}
public void teardown() {
if (mBound) {
context.unbindService(mConnection);
mBound = false;
}
requestWorker.stop();
}
private static class Worker<T> implements Runnable {
private final LinkedBlockingQueue<T> workQueue;
private final ColorService.ColorBinder binder;
private final LedDDaemon ledDDaemon;
public Worker(LinkedBlockingQueue<T> workQueue, ColorService.ColorBinder colorBinder, LedDDaemon dDaemon) {
this.workQueue = workQueue;
this.binder = colorBinder;
this.ledDDaemon = dDaemon;
}
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
final T item = workQueue.take();
if (item instanceof LedDRequest) {
binder.queueSend(ledDDaemon, ((LedDRequest) item).getRequest(), ((LedDRequest) item).getTask());
}
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
break;
}
}
}
public void stop() {
Thread.currentThread().interrupt();
}
}
}