387 lines
15 KiB
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();
|
|
}
|
|
}
|
|
}
|