package com.programyourhome.hue;_x000D_
_x000D_
import java.util.List;_x000D_
import java.util.Map;_x000D_
_x000D_
import org.springframework.stereotype.Component;_x000D_
_x000D_
import com.philips.lighting.hue.listener.PHLightListener;_x000D_
import com.philips.lighting.hue.sdk.PHAccessPoint;_x000D_
import com.philips.lighting.hue.sdk.PHHueSDK;_x000D_
import com.philips.lighting.hue.sdk.PHSDKListener;_x000D_
import com.philips.lighting.hue.sdk.heartbeat.PHHeartbeatManager;_x000D_
import com.philips.lighting.model.PHBridge;_x000D_
import com.philips.lighting.model.PHBridgeResource;_x000D_
import com.philips.lighting.model.PHHueError;_x000D_
import com.philips.lighting.model.PHHueParsingError;_x000D_
import com.philips.lighting.model.PHLight;_x000D_
_x000D_
@Component_x000D_
public class SDKListener implements PHSDKListener, PHLightListener {_x000D_
_x000D_
    // TODO: More deep diving into event stuff in SDK?_x000D_
    // Conclusions / ideas / thoughts:_x000D_
    // - OnCachechanged event only if actual changes in lights / state -> no, also on local changes, but only if no errors occured!_x000D_
    // - Should only happen when other actor is acting on lights -> no!_x000D_
    // - Own modifications are directly saved in the state -> yes, but also events happen._x000D_
    // - Maybe a race condition in updating the state and doing a heartbeat will result in a onCacheUpdate -> maybe_x000D_
    // - Or the get of the API actually returns the old state, while the cache is already updated with the new state -> hmm, that would be a big conflict / bug_x000D_
    // --> This actually indeed happens, but only for values not set in the last command, they will be updated later on. For on/off it even seems to be a little_x000D_
    // more unreliable_x000D_
    // - So: still use oncacheupdate to send update events to the PYH server, but not useful 'locally' so far -> indeed, but also a bit useful for_x000D_
    // local changes, because it actually confirms the success of the local command_x000D_
    // - Open question: why do we get a lot of onCacheUpdate events when we set a scene, even after a few seconds: -> slowly dropping in the changes,_x000D_
    // bridge/lamp hardware related?_x000D_
    // transition time? or maybe color values 'syncing'? -> the last indeed, and even on/off 'settling'_x000D_
    // - TODO test: Print the entire lights+state cache list state upon receiving a cache update event and find the changes manually to see why these event_x000D_
    // occur_x000D_
    // - TODO test: Print on state 20 times a second (like existing Thread in comment) and change state with Android app to see when it is picked up_x000D_
_x000D_
    // Test result: event should always be fired from local change, but 1 param error will prevent that. In this case, it was the reachable param_x000D_
    // that cannot be set from the outside that prevented the onCacheUpdate, because the notifyBridgeAPIError code path stops further processing._x000D_
    // TODO: this really is more of a bug than a feature. Try to find a way to contact the Philips Java API developers and file some bug reports._x000D_
_x000D_
    // Correction by lamp done on setting a value, setting the correction value gives another correction, but always the same values_x000D_
    // example: set Color.RED = x: 0,674 y: 0,322 -> correction to x: 0.6736, y: 0,3221 setting those gives correction to: x: 0.6725, y: 0,3223_x000D_
    // Setting those last corrected values gives the same values back, so no correction._x000D_
    // Second example: Color.BLUE = x: 0.168, y: 0.041 -> correction to x: 0,1684, y: 0,0416 setting those gives correction to x: 0.1684, y: 0.0417_x000D_
    // Setting those gives another correction to: x: 0.1692, y: 0.0429, followed by another correction: x: 0.1693, y: 0.043 -> x: 0.1701, y: 0.0443_x000D_
    // After that finally stays the same (but hue is corrected from 47127 to 47126 :)_x000D_
    // Setting hue/sat directly does not result in a hue/sat correction, only updated values for other color params (if needed)_x000D_
    // Color temp settings are corrected, e.g. READ = 343 is corrected to 340 -> corrected to 337 -> 334 -> 331 -> 328_x000D_
    // Another example 499 -> 497 -> 492 -> 488 (always the same)_x000D_
    // Seems to be the same for every lamp for all params (a few 'steekproeven': for 2 lamps exacty the same resuls!)_x000D_
_x000D_
    private final PHHueSDK sdk;_x000D_
_x000D_
    public SDKListener() {_x000D_
        this.sdk = PHHueSDK.getInstance();_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onAccessPointsFound(final List<PHAccessPoint> accessPoints) {_x000D_
        // Handle your bridge search results here. Typically if multiple results are returned you will want to display_x000D_
        // them in a list and let the user select their bridge. If one is found you may opt to connect automatically to_x000D_
        // that bridge._x000D_
        System.out.println("onAccessPointsFound: " + accessPoints);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onAuthenticationRequired(final PHAccessPoint accessPoint) {_x000D_
        // Arriving here indicates that Pushlinking is required (to prove the User has physical access to the bridge)._x000D_
        // Typically here you will display a pushlink image (with a timer) indicating to to the user they need to push_x000D_
        // the button on their bridge within 30 seconds._x000D_
        System.out.println("onAuthenticationRequired: " + accessPoint);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onBridgeConnected(final PHBridge bridge) {_x000D_
        System.out.println("onBridgeConnected: " + bridge);_x000D_
        this.sdk.setSelectedBridge(bridge);_x000D_
        // TODO: Add other heartbeats when / if necessary_x000D_
        // TODO: check everyhue.com forum for replies on javadoc and error message bug report_x000D_
        // TODO: Pick nice value for lights heartbeat (250 seems ok, 4 timer per second updae should be enough)_x000D_
        final PHHeartbeatManager heartbeatManager = PHHeartbeatManager.getInstance();_x000D_
        heartbeatManager.enableLightsHeartbeat(bridge, 1000);_x000D_
        // this.sdk.enableHeartbeat(bridge, PHHueSDK.HB_INTERVAL);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onCacheUpdated(final List<Integer> cacheNotificationsList, final PHBridge bridge) {_x000D_
        // Here you receive notifications that the BridgeResource Cache was updated. Use the PHMessageType to_x000D_
        // check which cache was updated, e.g._x000D_
        // if (cacheNotificationsList.contains(PHMessageType.LIGHTS_CACHE_UPDATED)) {_x000D_
        // System.out.println("Lights Cache Updated ");_x000D_
        // }_x000D_
        System.out.println("onCacheUpdated: " + cacheNotificationsList + ", " + bridge);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onReceivingLightDetails(final PHLight paramPHLight) {_x000D_
        System.out.println("onReceivingLightDetails: " + paramPHLight);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onReceivingLights(final List<PHBridgeResource> paramList) {_x000D_
        System.out.println("onReceivingLights: " + paramList);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onSearchComplete() {_x000D_
        System.out.println("onSearchComplete");_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onStateUpdate(final Map<String, String> paramMap, final List<PHHueError> paramList) {_x000D_
        System.out.println("onStateUpdate: " + paramMap + ", " + paramList);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onSuccess() {_x000D_
        System.out.println("onSuccess");_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onConnectionLost(final PHAccessPoint accessPoint) {_x000D_
        // Bridge disconnected_x000D_
        System.out.println("onConnectionLost: " + accessPoint);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onConnectionResumed(final PHBridge bridge) {_x000D_
        // This method will be called on every 'tick' of the heartbeat. Not sure this is a bug or a feature._x000D_
        // No implementation necessary._x000D_
        // System.out.println("onConnectionResumed aka heartbeat");_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onError(final int code, final String message) {_x000D_
        System.out.println("onError: " + code + ", " + message);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onParsingErrors(final List<PHHueParsingError> parsingErrorsList) {_x000D_
        // Any JSON parsing errors are returned here. Typically your program should never return these._x000D_
        System.out.println("onParsingErrors: " + parsingErrorsList);_x000D_
    }_x000D_
_x000D_
}_x000D_

// TODO: More deep diving into event stuff in SDK?_x000D_
package com.programyourhome.hue;_x000D_
_x000D_
import java.util.List;_x000D_
import java.util.Map;_x000D_
_x000D_
import org.springframework.stereotype.Component;_x000D_
_x000D_
import com.philips.lighting.hue.listener.PHLightListener;_x000D_
import com.philips.lighting.hue.sdk.PHAccessPoint;_x000D_
import com.philips.lighting.hue.sdk.PHHueSDK;_x000D_
import com.philips.lighting.hue.sdk.PHSDKListener;_x000D_
import com.philips.lighting.hue.sdk.heartbeat.PHHeartbeatManager;_x000D_
import com.philips.lighting.model.PHBridge;_x000D_
import com.philips.lighting.model.PHBridgeResource;_x000D_
import com.philips.lighting.model.PHHueError;_x000D_
import com.philips.lighting.model.PHHueParsingError;_x000D_
import com.philips.lighting.model.PHLight;_x000D_
_x000D_
@Component_x000D_
public class SDKListener implements PHSDKListener, PHLightListener {_x000D_
_x000D_
    // TODO: More<SUF>
    // Conclusions / ideas / thoughts:_x000D_
    // - OnCachechanged event only if actual changes in lights / state -> no, also on local changes, but only if no errors occured!_x000D_
    // - Should only happen when other actor is acting on lights -> no!_x000D_
    // - Own modifications are directly saved in the state -> yes, but also events happen._x000D_
    // - Maybe a race condition in updating the state and doing a heartbeat will result in a onCacheUpdate -> maybe_x000D_
    // - Or the get of the API actually returns the old state, while the cache is already updated with the new state -> hmm, that would be a big conflict / bug_x000D_
    // --> This actually indeed happens, but only for values not set in the last command, they will be updated later on. For on/off it even seems to be a little_x000D_
    // more unreliable_x000D_
    // - So: still use oncacheupdate to send update events to the PYH server, but not useful 'locally' so far -> indeed, but also a bit useful for_x000D_
    // local changes, because it actually confirms the success of the local command_x000D_
    // - Open question: why do we get a lot of onCacheUpdate events when we set a scene, even after a few seconds: -> slowly dropping in the changes,_x000D_
    // bridge/lamp hardware related?_x000D_
    // transition time? or maybe color values 'syncing'? -> the last indeed, and even on/off 'settling'_x000D_
    // - TODO test: Print the entire lights+state cache list state upon receiving a cache update event and find the changes manually to see why these event_x000D_
    // occur_x000D_
    // - TODO test: Print on state 20 times a second (like existing Thread in comment) and change state with Android app to see when it is picked up_x000D_
_x000D_
    // Test result: event should always be fired from local change, but 1 param error will prevent that. In this case, it was the reachable param_x000D_
    // that cannot be set from the outside that prevented the onCacheUpdate, because the notifyBridgeAPIError code path stops further processing._x000D_
    // TODO: this really is more of a bug than a feature. Try to find a way to contact the Philips Java API developers and file some bug reports._x000D_
_x000D_
    // Correction by lamp done on setting a value, setting the correction value gives another correction, but always the same values_x000D_
    // example: set Color.RED = x: 0,674 y: 0,322 -> correction to x: 0.6736, y: 0,3221 setting those gives correction to: x: 0.6725, y: 0,3223_x000D_
    // Setting those last corrected values gives the same values back, so no correction._x000D_
    // Second example: Color.BLUE = x: 0.168, y: 0.041 -> correction to x: 0,1684, y: 0,0416 setting those gives correction to x: 0.1684, y: 0.0417_x000D_
    // Setting those gives another correction to: x: 0.1692, y: 0.0429, followed by another correction: x: 0.1693, y: 0.043 -> x: 0.1701, y: 0.0443_x000D_
    // After that finally stays the same (but hue is corrected from 47127 to 47126 :)_x000D_
    // Setting hue/sat directly does not result in a hue/sat correction, only updated values for other color params (if needed)_x000D_
    // Color temp settings are corrected, e.g. READ = 343 is corrected to 340 -> corrected to 337 -> 334 -> 331 -> 328_x000D_
    // Another example 499 -> 497 -> 492 -> 488 (always the same)_x000D_
    // Seems to be the same for every lamp for all params (a few 'steekproeven': for 2 lamps exacty the same resuls!)_x000D_
_x000D_
    private final PHHueSDK sdk;_x000D_
_x000D_
    public SDKListener() {_x000D_
        this.sdk = PHHueSDK.getInstance();_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onAccessPointsFound(final List<PHAccessPoint> accessPoints) {_x000D_
        // Handle your bridge search results here. Typically if multiple results are returned you will want to display_x000D_
        // them in a list and let the user select their bridge. If one is found you may opt to connect automatically to_x000D_
        // that bridge._x000D_
        System.out.println("onAccessPointsFound: " + accessPoints);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onAuthenticationRequired(final PHAccessPoint accessPoint) {_x000D_
        // Arriving here indicates that Pushlinking is required (to prove the User has physical access to the bridge)._x000D_
        // Typically here you will display a pushlink image (with a timer) indicating to to the user they need to push_x000D_
        // the button on their bridge within 30 seconds._x000D_
        System.out.println("onAuthenticationRequired: " + accessPoint);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onBridgeConnected(final PHBridge bridge) {_x000D_
        System.out.println("onBridgeConnected: " + bridge);_x000D_
        this.sdk.setSelectedBridge(bridge);_x000D_
        // TODO: Add other heartbeats when / if necessary_x000D_
        // TODO: check everyhue.com forum for replies on javadoc and error message bug report_x000D_
        // TODO: Pick nice value for lights heartbeat (250 seems ok, 4 timer per second updae should be enough)_x000D_
        final PHHeartbeatManager heartbeatManager = PHHeartbeatManager.getInstance();_x000D_
        heartbeatManager.enableLightsHeartbeat(bridge, 1000);_x000D_
        // this.sdk.enableHeartbeat(bridge, PHHueSDK.HB_INTERVAL);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onCacheUpdated(final List<Integer> cacheNotificationsList, final PHBridge bridge) {_x000D_
        // Here you receive notifications that the BridgeResource Cache was updated. Use the PHMessageType to_x000D_
        // check which cache was updated, e.g._x000D_
        // if (cacheNotificationsList.contains(PHMessageType.LIGHTS_CACHE_UPDATED)) {_x000D_
        // System.out.println("Lights Cache Updated ");_x000D_
        // }_x000D_
        System.out.println("onCacheUpdated: " + cacheNotificationsList + ", " + bridge);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onReceivingLightDetails(final PHLight paramPHLight) {_x000D_
        System.out.println("onReceivingLightDetails: " + paramPHLight);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onReceivingLights(final List<PHBridgeResource> paramList) {_x000D_
        System.out.println("onReceivingLights: " + paramList);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onSearchComplete() {_x000D_
        System.out.println("onSearchComplete");_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onStateUpdate(final Map<String, String> paramMap, final List<PHHueError> paramList) {_x000D_
        System.out.println("onStateUpdate: " + paramMap + ", " + paramList);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onSuccess() {_x000D_
        System.out.println("onSuccess");_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onConnectionLost(final PHAccessPoint accessPoint) {_x000D_
        // Bridge disconnected_x000D_
        System.out.println("onConnectionLost: " + accessPoint);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onConnectionResumed(final PHBridge bridge) {_x000D_
        // This method will be called on every 'tick' of the heartbeat. Not sure this is a bug or a feature._x000D_
        // No implementation necessary._x000D_
        // System.out.println("onConnectionResumed aka heartbeat");_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onError(final int code, final String message) {_x000D_
        System.out.println("onError: " + code + ", " + message);_x000D_
    }_x000D_
_x000D_
    @Override_x000D_
    public void onParsingErrors(final List<PHHueParsingError> parsingErrorsList) {_x000D_
        // Any JSON parsing errors are returned here. Typically your program should never return these._x000D_
        System.out.println("onParsingErrors: " + parsingErrorsList);_x000D_
    }_x000D_
_x000D_
}_x000D_
