Java tutorial
/* * 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 android.util.Log; import com.idlegandalf.ledd.ColorApplication; 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; 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) { Log.d(ColorApplication.TAG, "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(); } } }