/* * 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 . */ 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.RecieveColorCallback; 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 org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; 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_ADDSTRIPES = "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 requestWorker; private LinkedBlockingQueue 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) { JSONObject jnson = new JSONObject(); try { jnson.put("action", ACTION_ADDCONTROLLER); jnson.put("channels", c.getChannels()); jnson.put("i2c_dev", c.getI2c_device()); jnson.put("address", c.getAddress()); } catch (JSONException e) { e.printStackTrace(); } addRequestToQueue(jnson, new AnswerTask() { @Override public void onConnectionFailed(String message) { callback.onAddFailed(message, ""); } @Override public void onResponse(JSONObject response) { try { if (response.getBoolean("success")) { c.setId(response.getInt("cid")); callback.onControllerAdded(c); } else { callback.onAddFailed(response.getString("message"), response.getString("message_detail")); } } catch (Exception e) { e.printStackTrace(); } } }); } /** * Get stripes known to daemon */ public void getStripes(final StripesCallback callback) { JSONObject jnson = new JSONObject(); try { jnson.put("action", ACTION_GETALLSTRIPES); } catch (JSONException e) { e.printStackTrace(); } addRequestToQueue(jnson, new AnswerTask() { @Override public void onConnectionFailed(String message) { callback.onGetFailed(message); } @Override public void onResponse(JSONObject response) { try { if (response.getBoolean("success")) { ledDDaemon.getControllers().clear(); List list = new ArrayList<>(); JSONArray jcontrollers = response.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 { if (response.has("message")) callback.onGetFailed(response.getString("message")); else callback.onGetFailed("unknown error"); } } catch (Exception e) { e.printStackTrace(); } } }); } /** * Set color using the stripeid * * @param ledStripe Stripe */ public void setColor(LedStripe ledStripe) { JSONObject jnson = new JSONObject(); JSONObject hsv = new JSONObject(); try { hsv.put("h", ledStripe.getColor().getHue()); hsv.put("s", ledStripe.getColor().getSaturation()); hsv.put("v", ledStripe.getColor().getValue()); jnson.put("action", ACTION_SETCOLOR); jnson.put("sid", ledStripe.getId()); jnson.put("hsv", hsv); } catch (JSONException e) { e.printStackTrace(); } addRequestToQueue(jnson, null); } /** * Get color using the stripeid * * @param ledStripe Stripe */ public void getColor(final LedStripe ledStripe, final RecieveColorCallback callback) { JSONObject jnson = new JSONObject(); try { jnson.put("action", ACTION_GETCOLOR); jnson.put("sid", ledStripe.getId()); } catch (JSONException e) { e.printStackTrace(); } addRequestToQueue(jnson, new AnswerTask() { @Override public void onConnectionFailed(String message) { callback.onRecievFailed(message); } @Override public void onResponse(JSONObject response) { try { if (response.getBoolean("success")) { JSONArray hsv = response.getJSONArray("color"); ledStripe.setColor(new HSV(hsv.getDouble(0), hsv.getDouble(1), hsv.getDouble(2))); callback.onColorRecieved(ledStripe); } else { callback.onRecievFailed(response.getString("message")); } } catch (Exception e) { e.printStackTrace(); } } }); } /** * 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) { JSONObject jnson = new JSONObject(); try { jnson.put("action", ACTION_TESTCHANNEL); jnson.put("cid", c.getId()); jnson.put("channel", channel); jnson.put("value", value); } catch (JSONException e) { e.printStackTrace(); } addRequestToQueue(jnson, new AnswerTask() { @Override public void onConnectionFailed(String message) { } @Override public void onResponse(JSONObject response) { } }); } /** * Get information about an ledd daemon */ public void discover(final DiscoverCallback callback) { JSONObject jnson = new JSONObject(); try { jnson.put("action", ACTION_DISCOVER); } catch (JSONException e) { e.printStackTrace(); } addRequestToQueue(jnson, new AnswerTask() { @Override public void onConnectionFailed(String message) { callback.onConnectionFailed(message); } @Override public void onResponse(JSONObject response) { try { if (response.getBoolean("success")) { callback.onDiscoverSuccessfully(response.getString("version")); } } catch (Exception e) { e.printStackTrace(); } } }); } /** * Get information about an ledd daemon */ public void addStripe(final LedStripe ledStripe, final AddStripeCallback callback) { JSONObject jnson = new JSONObject(); try { jnson.put("action", ACTION_ADDSTRIPES); JSONObject stripe = new JSONObject(); stripe.put("name", ledStripe.getName()); stripe.put("rgb", ledStripe.isRGB()); JSONObject mapping = new JSONObject(); mapping.put("r", ledStripe.getChannelRed()); mapping.put("g", ledStripe.getChannelGreen()); mapping.put("b", ledStripe.getChannelBlue()); stripe.put("map", mapping); stripe.put("cid", ledStripe.getController().getId()); jnson.put("stripe", stripe); } catch (JSONException e) { e.printStackTrace(); } addRequestToQueue(jnson, new AnswerTask() { @Override public void onConnectionFailed(String message) { callback.onConnectionFailed(message); } @Override public void onResponse(JSONObject response) { try { if (response.getBoolean("success")) { ledStripe.setId(response.getInt("sid")); callback.onAddSuccessfully(ledStripe); } } catch (Exception e) { e.printStackTrace(); } } }); } private void addRequestToQueue(JSONObject json, AnswerTask task) { if (json != null && json.length() > 0) dRequests.add(new LedDRequest(json, task)); } public void teardown() { if (mBound) { context.unbindService(mConnection); mBound = false; } requestWorker.stop(); } private static class Worker implements Runnable { private final LinkedBlockingQueue workQueue; private final ColorService.ColorBinder binder; private final LedDDaemon ledDDaemon; public Worker(LinkedBlockingQueue 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(); } } }