- Hue now thread safe - Added the auto-brightness * probably realistic enough * probably a bit buggy - Added test for it - Rearranged imports
248 lines
8.3 KiB
Java
248 lines
8.3 KiB
Java
package device;
|
|
|
|
import ai.api.GsonFactory;
|
|
import com.google.common.util.concurrent.AtomicDouble;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import support.Rest;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* Classe che permette di controllare le luci Philips Hue
|
|
*/
|
|
public class Hue {
|
|
|
|
/**
|
|
* Log che serve per debug
|
|
*/
|
|
private static final Logger LOG = LoggerFactory.getLogger("Hue");
|
|
|
|
/**
|
|
* La luminopsita' massima a cui si puo' arrivare
|
|
*/
|
|
private static final int MAX_BRIGHTNESS = 254;
|
|
|
|
/**
|
|
* Una mappa che ad ogni colore (in lingua ita) assegna il proprio valore in hue
|
|
*/
|
|
private static final Map<String, Double[]> COLORS = new HashMap<>();
|
|
|
|
/**
|
|
* L'url in cui si possono trovare le luci
|
|
*/
|
|
private final String lightsURL;
|
|
|
|
/**
|
|
* Tutte le luci che sono state registrate dall'url
|
|
*/
|
|
private final Map<String, Map<String, Object>> allLights;
|
|
|
|
/**
|
|
* L'ultima luminosita' impostata
|
|
*/
|
|
private final AtomicDouble brightness = new AtomicDouble(0);
|
|
|
|
// Riempimento della mappa con i vari colori
|
|
static {
|
|
COLORS.put("giall[oae]", new Double[]{0.45, 0.45});
|
|
COLORS.put("ross[oae]", new Double[]{0.7, 0.25});
|
|
COLORS.put("verd[ei]", new Double[]{0.1, 0.55});
|
|
COLORS.put("blu", new Double[]{0.12, 0.125});
|
|
COLORS.put("rosa", new Double[]{0.45, 0.275});
|
|
COLORS.put("viola", new Double[]{0.25, 0.1});
|
|
COLORS.put("azzurr[oae]", new Double[]{0.15, 0.25});
|
|
COLORS.put("arancio(ne|ni)?", new Double[]{0.55, 0.4});
|
|
//COLORS.put("nero", new Double[]{1.0, 1.0});
|
|
COLORS.put("bianc(o|a|he)", new Double[]{0.275, 0.3});
|
|
}
|
|
|
|
/**
|
|
* Cerca le luci Philips Hue a ll'indirizzo <a href="http://172.30.1.138/api/C0vPwqjJZo5Jt9Oe5HgO6sBFFMxgoR532IxFoGmx/lights/">http://172.30.1.138/api/C0vPwqjJZo5Jt9Oe5HgO6sBFFMxgoR532IxFoGmx/lights/</a>
|
|
* @throws NullPointerException se non trova nessun bridge
|
|
*/
|
|
public Hue () throws NullPointerException { this("172.30.1.138", "C0vPwqjJZo5Jt9Oe5HgO6sBFFMxgoR532IxFoGmx"); }
|
|
|
|
/**
|
|
* Cerca le luci Philips Hue nell'indirizzo specificato e con l'utente specificato.<br>
|
|
* Una volta trovate le luci le setta tutte alla stessa luminosita' e allo stesso colore<br>
|
|
* (per ora fa una media e poi assegna il valore risultante a tutte)
|
|
* @param ip l'indirizzo IP (seguito dalla porta se e' diversa dalla solita 8000)
|
|
* @param user l'utente
|
|
* @throws NullPointerException se non trova nessun bridge
|
|
*/
|
|
public Hue(String ip, String user) throws NullPointerException {
|
|
lightsURL = "http://" + ip + "/api/" + user + "/lights/";
|
|
allLights = (Map<String, Map<String, Object>>)Rest.get(lightsURL);
|
|
|
|
if(allLights.isEmpty())
|
|
throw new NullPointerException("Non e' stato possibile connettersi alle luci");
|
|
|
|
double bri = 0;
|
|
double hue = 0;
|
|
for (String name: allLights.keySet()) {
|
|
Map<String, Object> state = (Map<String, Object>)allLights.get(name).get("state");
|
|
bri += (Double) state.get("bri");
|
|
hue += (Double) state.get("hue");
|
|
}
|
|
bri = bri/allLights.size();
|
|
hue = hue/allLights.size();
|
|
|
|
Map<String, Object> map = new HashMap<>();
|
|
map.put("bri", (int)bri);
|
|
map.put("hue", (int)hue);
|
|
setState(map);
|
|
|
|
brightness.set((bri*MAX_BRIGHTNESS)/100);
|
|
}
|
|
|
|
/**
|
|
* Ritorna un insieme contenente tutti i nomi delle luci che si sono trovate
|
|
*
|
|
* @return l'insieme dei nomi delle luci
|
|
*/
|
|
public Set<String> getNameLights() { return allLights.keySet(); }
|
|
|
|
/**
|
|
* Rimuove dal controllo tutte le luci che hanno il nome uguale ad uno contenuto nell'insieme passato
|
|
*
|
|
* @param toRemove le luci da rimuovere
|
|
*/
|
|
public void removeLights(Set<String> toRemove) {
|
|
for(String string : toRemove)
|
|
allLights.remove(string);
|
|
}
|
|
|
|
/**
|
|
* Accende o spegne le luci controllate
|
|
* @param on vero se si vuole le luci accese, false per spegnerle
|
|
*/
|
|
public void on(boolean on) { setState("on", on, false); }
|
|
|
|
/**
|
|
* Accende tutte le luci controllate
|
|
*/
|
|
public void turnOn() { on(true); }
|
|
|
|
/**
|
|
* Spegne tutte le luci controllate
|
|
*/
|
|
public void turnOff() { on(false); }
|
|
|
|
/**
|
|
* Ritorna la liminosita' attuale delle luci controllate
|
|
* @return il valore e' compreso tra 0 e 100
|
|
*/
|
|
public double getCurrentBrightness() { return brightness.doubleValue(); }
|
|
|
|
/**
|
|
* Modifica la luminosita' delle luci a seconda del valore inserito
|
|
* @param num la luminosita' che si vuole da (0 a 100)
|
|
*/
|
|
public void setBrightness(double num) {
|
|
if (num<0)
|
|
num=0;
|
|
else if (num>100)
|
|
num=100;
|
|
|
|
setState("bri", (int) (num*MAX_BRIGHTNESS)/100 );
|
|
brightness.set(num);
|
|
}
|
|
|
|
/**
|
|
* Aggiunge il valore delta alla luminosita' corrente delle luci.
|
|
* @param delta un qualsiasi numero che va da -100 a 100
|
|
*/
|
|
public void addBrightness(double delta) {
|
|
setBrightness(brightness.doubleValue() + delta);
|
|
}
|
|
|
|
/**
|
|
* Aumenta la luminosita' delle luci controllate della percentuale che viene passata
|
|
* @param percentage la percentuale di aumento della luminosita'
|
|
*/
|
|
public void increaseBrightness(double percentage) {
|
|
if (percentage<0)
|
|
percentage = 0;
|
|
else if (percentage>100)
|
|
percentage = 100;
|
|
setBrightness(brightness.doubleValue() + percentage);
|
|
}
|
|
|
|
/**
|
|
* Aumenta la luminosita' delle luci controllate del 25%
|
|
*/
|
|
public void increaseBrightness() { increaseBrightness(25); }
|
|
|
|
/**
|
|
* Dinuisce la luminosita' delle luci controllate della percentuale che viene passata
|
|
* @param percentage la percentuale di diminuzione della luminosita'
|
|
*/
|
|
public void decreaseBrightness(int percentage) {
|
|
if (percentage<0)
|
|
percentage = 0;
|
|
else if (percentage>100)
|
|
percentage = 100;
|
|
setBrightness(brightness.doubleValue() - percentage);
|
|
}
|
|
|
|
/**
|
|
* Dinuisce la luminosita' delle luci controllate del 25%
|
|
*/
|
|
public void decreaseBrightness() { decreaseBrightness(25); }
|
|
|
|
public void changeColor(String colorName) {
|
|
for (String regex: COLORS.keySet())
|
|
if(colorName.matches("(?i)" + regex))
|
|
setState("xy", COLORS.get(regex));
|
|
}
|
|
|
|
/**
|
|
* Modifica il colore delle luci in modo da fare un bel effetto arcobaleno continuo
|
|
*/
|
|
public void colorLoop() { setState("effect", "colorloop"); }
|
|
|
|
/**
|
|
* Invia una richiesta a tutte le luci hue con l'attributo selezionato ed il suo valore<br>
|
|
* Con esso invia anche una transition:20 in modo che sia piu fluido il cambiamento
|
|
* @param attribute l'attributo che si vuole cambiare
|
|
* @param value il valore da inserire
|
|
*/
|
|
public void setState(String attribute, Object value){
|
|
setState(attribute, value, true);
|
|
}
|
|
|
|
/**
|
|
* Invia una richiesta a tutte le luci hue con l'attributo selezionato ed il suo valore<br>
|
|
* Con esso invia anche una transition:20 in modo che sia piu fluido il cambiamento se si mette true al terzo parametro
|
|
* @param attribute l'attributo da modificare
|
|
* @param value il valore da inserire
|
|
* @param transition se includere la transizione o meno
|
|
*/
|
|
public void setState(String attribute, Object value, boolean transition){
|
|
Map<String, Object> map = new HashMap<>();
|
|
map.put(attribute, value);
|
|
if(transition)
|
|
map.put("transition", 200);
|
|
setState(map);
|
|
}
|
|
|
|
/**
|
|
* Invia una richiesta a tutte le luci hue con gli attributi selezionati ed il loro valore
|
|
* @param attributes una mappa di attributi -> valori
|
|
*/
|
|
public synchronized void setState(Map<String, Object> attributes) {
|
|
String body = GsonFactory.getDefaultFactory().getGson().toJson(attributes);
|
|
LOG.info("Setting: " + body);
|
|
for (String light : allLights.keySet()) {
|
|
Rest.put(lightsURL + light + "/state", body,"application/json");
|
|
|
|
Map<String, Object> state = (Map<String, Object>)allLights.get(light).get("state");
|
|
for (String attr : attributes.keySet())
|
|
state.put(attr, attributes.get(attr));
|
|
}
|
|
}
|
|
}
|