package com.kuxhausen.huemore.net; import com.kuxhausen.huemore.state.BulbState; import java.util.List; public class BrightnessManager { private BrightnessPolicy mPolicy; /** * 1 - 100 */ private Integer mVolumeBri; private List<NetworkBulb> mBulbs; public BrightnessManager(List<NetworkBulb> bulbs) { if (bulbs == null) { throw new IllegalArgumentException(); } mBulbs = bulbs; mPolicy = BrightnessPolicy.DIRECT_BRI; } public void setPolicy(BrightnessPolicy policy) { if (policy == null) { throw new IllegalArgumentException(); } mPolicy = policy; if (mPolicy == BrightnessPolicy.DIRECT_BRI) { mVolumeBri = null; } } public BrightnessPolicy getPolicy() { return mPolicy; } public BulbState getState(NetworkBulb netBulb, NetworkBulb.GetStateConfidence confidence) { if (netBulb == null || !mBulbs.contains(netBulb) || confidence == null) { throw new IllegalArgumentException(); } BulbState adjusted = netBulb.getState(confidence).clone(); if (mPolicy == BrightnessPolicy.VOLUME_BRI && adjusted.get255Bri() != null) { Integer volume = mVolumeBri; if (volume == null) { volume = getAveragePercentBrightness(mBulbs, NetworkBulb.GetStateConfidence.KNOWN); } adjusted.set255Bri(((int) Math.round(adjusted.get255Bri() * 100.0) / volume)); } return adjusted; } public void setState(NetworkBulb netBulb, BulbState targetState) { if (netBulb == null || targetState == null || !mBulbs.contains(netBulb)) { throw new IllegalArgumentException( (netBulb == null) + "," + (targetState == null) + "," + (!mBulbs.contains(netBulb))); } BulbState adjusted = targetState.clone(); //in volume bri mode, new color with unspecified bri is assumed to at 100% of current volume if (mPolicy == BrightnessPolicy.VOLUME_BRI && adjusted.get255Bri() == null && ( adjusted.getMiredCT() != null || adjusted.hasXY())) { adjusted.set255Bri(255); } if (mPolicy == BrightnessPolicy.VOLUME_BRI && adjusted.get255Bri() != null) { if (mVolumeBri == null) { //calculate existing volume bri as average bri mVolumeBri = getAveragePercentBrightness(mBulbs, NetworkBulb.GetStateConfidence.KNOWN); } adjusted.set255Bri((int) Math.round((mVolumeBri * adjusted.get255Bri()) / 100.0)); } netBulb.setState(adjusted); } /** * Does not update lights, only valid in volume mode * @param newVolume ranges from 1 to 100 */ public void setVolumeWithoutUpdate(int newVolume) { if (mPolicy != BrightnessPolicy.VOLUME_BRI) { throw new IllegalStateException(); } mVolumeBri = newVolume; } /** * @param brightness ranges from 1 to 100 */ public void setBrightness(int brightness) { int newBrightness = Math.max(1, Math.min(100, brightness)); if (mPolicy == BrightnessPolicy.VOLUME_BRI) { if (mVolumeBri == null) { //calculate existing volume bri as average brightness mVolumeBri = getAveragePercentBrightness(mBulbs, NetworkBulb.GetStateConfidence.KNOWN); } int oldVolume = mVolumeBri; int newVolume = newBrightness; for (NetworkBulb bulb : mBulbs) { Integer oldPhysicalBri = bulb.getState(NetworkBulb.GetStateConfidence.KNOWN).getPercentBri(); if (oldPhysicalBri == null) { oldPhysicalBri = oldVolume; } oldPhysicalBri = Math.min(oldPhysicalBri, oldVolume); int newPhysicalBri = (oldPhysicalBri * newVolume) / oldVolume; BulbState bs = new BulbState(); bs.setPercentBri(newPhysicalBri); bs.setTransitionTime(BulbState.TRANSITION_TIME_BRIGHTNESS_BAR); bulb.setState(bs); } mVolumeBri = newVolume; } else { BulbState bs = new BulbState(); bs.setPercentBri(newBrightness); bs.setTransitionTime(BulbState.TRANSITION_TIME_BRIGHTNESS_BAR); for (NetworkBulb bulb : mBulbs) { bulb.setState(bs); } } } /** * @return brightness ranging from 1 to 100 */ public int getBrightness() { if (mPolicy == BrightnessPolicy.VOLUME_BRI) { if (mVolumeBri == null) { //calculate existing volume bri as average brightness return getAveragePercentBrightness(mBulbs, NetworkBulb.GetStateConfidence.KNOWN); } else { return mVolumeBri; } } else { return getAveragePercentBrightness(mBulbs, NetworkBulb.GetStateConfidence.GUESS); } } //calculate the largest brightness among the group, returning 1 if no bulbs are sufficiently confident of brightness private static int getLargestPercentBrightness(List<NetworkBulb> list) { if (list == null) { throw new IllegalArgumentException(); } int briMax = 1; for (NetworkBulb bulb : list) { Integer physicalBri = bulb.getState(NetworkBulb.GetStateConfidence.KNOWN).getPercentBri(); if (physicalBri != null && physicalBri > briMax) { briMax = physicalBri; } } return briMax; } //calculate the average brightness among the group, returning 1 if no bulbs are sufficiently confident of brightness private static int getAveragePercentBrightness(List<NetworkBulb> list, NetworkBulb.GetStateConfidence confidence) { if (list == null) { throw new IllegalArgumentException(); } int briSum = 0; int briNum = 0; for (NetworkBulb bulb : list) { Integer physicalBri = bulb.getState(confidence).getPercentBri(); if (physicalBri != null) { briSum += physicalBri; briNum++; } } if (briNum == 0) { return 1; } return briSum / briNum; } public enum BrightnessPolicy { DIRECT_BRI, VOLUME_BRI } }