飞利浦Hue Bridge无法连接到服务器桌面应用程序

时间:2015-05-11 04:34:19

标签: philips-hue

我正在尝试使用java将桌面连接到PHILIPS Hue灯光服务器。

当代码运行时,它将流入Controller.java。发生这种情况时,Controller.java中的FindBridges方法运行。这是发生错误的地方。在调试中,它在线程“AWT-Event-Queue-0”中显示NullPointerException。

我认为根本无法找到服务器/灯泡,即使它已打开并且我的Android应用程序可以连接到它。 错误如下所述:

  

线程“AWT-EventQueue-0”中的异常java.lang.NullPointerException       在com.philips.lighting.gui.DesktopView $ 1.actionPerformed(DesktopView.java:72)

Controller.java

package com.philips.lighting;

import java.util.List;
import java.util.Random;

import javax.swing.JDialog;

import com.philips.lighting.hue.sdk.upnp.*;
import com.philips.lighting.data.HueProperties;
import com.philips.lighting.gui.AccessPointList;
import com.philips.lighting.gui.DesktopView;
import com.philips.lighting.gui.LightColoursFrame;
import com.philips.lighting.gui.PushLinkFrame;
import com.philips.lighting.hue.sdk.PHAccessPoint;
import com.philips.lighting.hue.sdk.PHBridgeSearchManager;
import com.philips.lighting.hue.sdk.PHHueSDK;
import com.philips.lighting.hue.sdk.PHMessageType;
import com.philips.lighting.hue.sdk.PHSDKListener;
import com.philips.lighting.model.PHBridge;
import com.philips.lighting.model.PHBridgeResourcesCache;
import com.philips.lighting.model.PHHueError;
import com.philips.lighting.model.PHHueParsingError;
import com.philips.lighting.model.PHLight;
import com.philips.lighting.model.PHLightState;

public class Controller {


    private PHHueSDK phHueSDK;
    private DesktopView desktopView;

    private PushLinkFrame pushLinkDialog;
    private LightColoursFrame lightColoursFrame;

    private static final int MAX_HUE=65535;
    private Controller instance;

    public Controller(DesktopView view) {
        this.desktopView = view;
        this.phHueSDK = PHHueSDK.getInstance(); // or phHueSDK = PHHueSDK.getInstance();
        this.instance = this;
    }

    public void findBridges() {
        //To uniquely identify your app in the bridge whitelist we recommend you set your app name, and the device
        phHueSDK.setAppName("SmartShowroomApp");        // e.g. phHueSDK.setAppName("QuickStartApp");
        phHueSDK.setDeviceName("SmartDevice");          // e.g. If you are programming for Android: phHueSDK.setDeviceName(android.os.Build.MODEL);
        phHueSDK = PHHueSDK.getInstance();
        PHBridgeSearchManager sm = (PHBridgeSearchManager) phHueSDK.getSDKService(PHHueSDK.SEARCH_BRIDGE);
        sm.search(true, true);
        //This starts a UPNP/Portal Search and takes around 10 seconds. 
        //The PHSDKListener (onAccessPointsFound) will be notified with the bridges found.
    }



    private PHSDKListener listener = new PHSDKListener() {

        @Override
        public void onAccessPointsFound(List<PHAccessPoint> accessPointsList) {
            // Handle your bridge search results here.  
            //Typically if multiple results are returned you will want to display them in a list 
            // and let the user select their bridge.   
            //If one is found you may opt to connect automatically to that bridge. 
            phHueSDK = PHHueSDK.getInstance();
            desktopView.getFindingBridgeProgressBar().setVisible(false);
            if (accessPointsList != null && accessPointsList.size() > 0)
            {
            AccessPointList accessPointList = new AccessPointList(accessPointsList, instance);
            accessPointList.setVisible(true);
            accessPointList.setLocationRelativeTo(null);                // Centre the AccessPointList Frame
            phHueSDK.getAccessPointsFound().clear();                    // Clear all connected access points
            phHueSDK.getAccessPointsFound().addAll(accessPointsList);   // Adds multiple results to the list
            }
            else
            {
                PHBridgeSearchManager sm = (PHBridgeSearchManager) phHueSDK.getSDKService(PHHueSDK.SEARCH_BRIDGE);
                sm.search(false, false, true);
            }
        }

        @Override
        public void onAuthenticationRequired(PHAccessPoint accessPoint) {
            // Start the Pushlink Authentication.
            phHueSDK = PHHueSDK.getInstance();
            desktopView.getFindingBridgeProgressBar().setVisible(false);
            phHueSDK.startPushlinkAuthentication(accessPoint);
            // Arriving here indicates that Pushlinking is required (to prove the User has physical access to the bridge).  
            //Typically here you will display a pushlink image (with a timer) indicating to to the user they need to push the button on their bridge within 30 seconds.
            pushLinkDialog = new PushLinkFrame(instance);
            pushLinkDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            pushLinkDialog.setModal(true);
            pushLinkDialog.setLocationRelativeTo(null); // Center the dialog.
            pushLinkDialog.setVisible(true);

        }

        @Override
        public void onBridgeConnected(PHBridge bridge) {
            phHueSDK = PHHueSDK.getInstance();
            phHueSDK.setSelectedBridge(bridge);
            phHueSDK.enableHeartbeat(bridge, PHHueSDK.HB_INTERVAL);
            // Here it is recommended to set your connected bridge in your sdk object (as above) and start the heartbeat.
            // At this point you are connected to a bridge so you should pass control to your main program/activity.
            // Also it is recommended you store the connected IP Address/ Username in your app here.  
            //This will allow easy automatic connection on subsequent use.

            // Remember to disable the heartbeat when exiting your app
            //phHueSDK.disableAllHeartbeat();

            //If you are only interested in a particular resource (e.g. Lights), you can enable the multi resource heartbeat as follows:
            //PHHeartbeatManager heartbeatManager = PHHeartbeatManager.getInstance();
            //heartbeatManager.enableLightsHeartbeat(bridge, PHHueSDK.HB_INTERVAL);

            // To stop the heartbeat you can use either of the below
            //heartbeatManager.disableLightsHeartbeat(bridge);
            //heartbeatManager.disableAllHeartbeats(bridge);

            desktopView.getFindingBridgeProgressBar().setVisible(false);
            String username = HueProperties.getUsername();
            String lastIpAddress =  bridge.getResourceCache().getBridgeConfiguration().getIpAddress();   
            System.out.println("On connected: IP " + lastIpAddress);
            HueProperties.storeUsername(username);
            HueProperties.storeLastIPAddress(lastIpAddress);
            HueProperties.saveProperties();

            // Update the GUI.
            desktopView.getLastConnectedIP().setText(lastIpAddress);
            desktopView.getLastUserName().setText(username);

            // Close the PushLink dialog (if it is showing).
            if (pushLinkDialog!=null && pushLinkDialog.isShowing()) {
                pushLinkDialog.setVisible(false);
            }

            // Enable the Buttons/Controls to change the hue bulbs.s
            desktopView.getRandomLightsButton().setEnabled(true);
            desktopView.getSetLightsButton().setEnabled(true);

        }

        @Override
        public void onCacheUpdated(List cacheNotificationsList, PHBridge bridge) {
            // Here you receive notifications that the BridgeResource Cache was updated. Use the PHMessageType to   
            // check which cache was updated, e.g.
           if (cacheNotificationsList.contains(PHMessageType.LIGHTS_CACHE_UPDATED)) {
              System.out.println("Lights Cache Updated ");
           }
        }


        @Override
        public void onConnectionLost(PHAccessPoint accessPoint) {
            // Here you would handle the loss of connection to your bridge.
            phHueSDK = PHHueSDK.getInstance();

            if (accessPoint == null)
            {
                System.out.println("Please reconnect to your bridge.");
            }
        }

        @Override
        public void onConnectionResumed(PHBridge bridge) {
            PHHueSDK phHueSDK = PHHueSDK.getInstance();
            for (int i = 0; i < phHueSDK.getDisconnectedAccessPoint().size(); i++) 
            {
                if (phHueSDK.getDisconnectedAccessPoint().get(i).getIpAddress()
                        .equals(bridge.getResourceCache().getBridgeConfiguration().getIpAddress())) {
                    phHueSDK.getDisconnectedAccessPoint().remove(i);
                }
            }

        }

        @Override
        public void onError(int code, final String message) {
            // Here you can handle events such as Bridge Not Responding, Authentication Failed and Bridge Not Found.
            if (code == PHHueError.BRIDGE_NOT_RESPONDING) {
                desktopView.getFindingBridgeProgressBar().setVisible(false);
                desktopView.getFindBridgesButton().setEnabled(true);
                desktopView.getConnectToLastBridgeButton().setEnabled(true);
                desktopView.showDialog(message);
            }
            else if (code == PHMessageType.PUSHLINK_BUTTON_NOT_PRESSED) {
                pushLinkDialog.incrementProgress();
            }
            else if (code == PHMessageType.PUSHLINK_AUTHENTICATION_FAILED) {
                if (pushLinkDialog.isShowing()) {
                    pushLinkDialog.setVisible(false);
                    desktopView.showDialog(message);
                }
                else {
                    desktopView.showDialog(message);
                }
                desktopView.getFindBridgesButton().setEnabled(true);
            }
            else if (code == PHMessageType.BRIDGE_NOT_FOUND) {
                desktopView.getFindingBridgeProgressBar().setVisible(false);
                desktopView.getFindBridgesButton().setEnabled(true);
                desktopView.showDialog(message);
            }
        }

        @Override
        public void onParsingErrors(List<PHHueParsingError> parsingErrorsList) {
            // Any JSON parsing errors are returned here.  
            //Typically your program should never return these.
            for (PHHueParsingError parsingError: parsingErrorsList) {
                System.out.println("ParsingError : " + parsingError.getMessage());
            }
        } 
    };



    public PHSDKListener getListener() {
        return listener;
    }

    public void setListener(PHSDKListener listener) {
        this.listener = listener;
    }

    public void randomLights() {
        PHBridge bridge = phHueSDK.getSelectedBridge();
        PHBridgeResourcesCache cache = bridge.getResourceCache();

        // And now you can get any resource you want, for example:
        List<PHLight> allLights = cache.getAllLights();
        Random rand = new Random();

        for (PHLight light : allLights) {
            PHLightState lightState = new PHLightState();
            lightState.setHue(rand.nextInt(MAX_HUE));
            bridge.updateLightState(light, lightState); // If no bridge response is required then use this simpler form.
        }
    }

    public void showControlLightsWindow() {
        if (lightColoursFrame == null) {
            lightColoursFrame = new LightColoursFrame(); 
        }
        lightColoursFrame.setLocationRelativeTo(null); // Centre window
        lightColoursFrame.setVisible(true);
    }

    /**
     * Connect to the last known access point.
     * This method is triggered by the Connect to Bridge button but it can equally be used to automatically connect to a bridge.
     * 
     */
    public boolean connectToLastKnownAccessPoint() {
        String username = HueProperties.getUsername();
        String lastIpAddress =  HueProperties.getLastConnectedIP();     

        if (username==null || lastIpAddress == null) {
            desktopView.showDialog("Missing Last Username or Last IP.  Last known connection not found.");
            return false;
        }
        //Obviously, every time a user opens up their Android hue app or application you don't want them to have to select their bridge, authenticate pushlink everytime.
        //The recommended way to overcome this issue is to store the connected IP Address/Username (using your preferred method storage) and if set try to connect automatically.
        PHAccessPoint accessPoint = new PHAccessPoint();
        accessPoint.setIpAddress(lastIpAddress);
        accessPoint.setUsername(username);
        phHueSDK.connect(accessPoint);
        return true;
        //Note that the .connect method returns control to your PHSDKListener, so when connected the onBridgeConnected will be called again, and if your users Bridge IP has changed for example, onError will be called and can be handled programatically.
    }

    public void enableFindBridgesButton() {
        desktopView.getFindBridgesButton().setEnabled(true);
    }

    public void showProgressBar() {
        desktopView.getFindingBridgeProgressBar().setVisible(true);
    }
}

DesktopView.java

package com.philips.lighting.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;

import layout.TableLayout;

import com.philips.lighting.Controller;
import com.philips.lighting.data.HueProperties;

/**
 * DesktopView.java
 * 
 * The main GUI showing last connected IP/Username and buttons for Finding Bridges and Changing the Hue Lights, once connected to a bridge.
 *
 */
public class DesktopView extends JFrame {

    private static final long serialVersionUID = -7469471678945429320L;  
    private Controller controller;
    private JButton setLightsButton;
    private JButton randomLightsButton;
    private JButton findBridgesButton;
    private JButton connectToLastBridgeButton;
    private JProgressBar findingBridgeProgressBar;

    private JTextField lastConnectedIP;
    private JTextField lastUserName;

    public DesktopView(){
        setTitle("Hue Desktop");
        JPanel mainPanel = new JPanel();

        // TODO - Move to another class
        JPanel controls = new JPanel();
        controls.setLayout(new GridLayout(2,3));

        findingBridgeProgressBar = new JProgressBar();
        findingBridgeProgressBar.setBorderPainted(false);
        findingBridgeProgressBar.setIndeterminate(true);
        findingBridgeProgressBar.setVisible(false);

        //Set up components preferred size
        String lastUsername = HueProperties.getUsername(); 
        String lastConnectedIPStr = HueProperties.getLastConnectedIP();

        JLabel labelLastConIP    = new JLabel("Last Connected IP:");
        lastConnectedIP = new JTextField(lastConnectedIPStr);

        lastConnectedIP.setEditable(false);
        JLabel labelLastUsername = new JLabel("Last UserName:");
        lastUserName = new JTextField(lastUsername);
        lastUserName.setEditable(false);
        findBridgesButton = new JButton("Find New Bridges");
        findBridgesButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                findBridgesButton.setEnabled(false);
                connectToLastBridgeButton.setEnabled(false);
                controller.findBridges();
                findingBridgeProgressBar.setBorderPainted(true);
                findingBridgeProgressBar.setVisible(true);
            }
        });

        connectToLastBridgeButton = new JButton("Auto Connect");
        connectToLastBridgeButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                if (controller.connectToLastKnownAccessPoint()) {
                    connectToLastBridgeButton.setEnabled(false);
                    findBridgesButton.setEnabled(false);
                    findingBridgeProgressBar.setBorderPainted(true);
                    findingBridgeProgressBar.setVisible(true);
                }
            }
        });


        setLightsButton = new JButton("Change Light Colours");
        setLightsButton.setEnabled(false);
        setLightsButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                controller.showControlLightsWindow();
            }
        });

        randomLightsButton = new JButton("Randomize Lights");
        randomLightsButton.setEnabled(false);
        randomLightsButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent arg0) {
                controller.randomLights();
            }
        });

        double border = 10;
        double size[][] =
            {{border, 160, 20, 300, 20, 160},                 // Columns
             {border, 26,  10, 26, 26, 26,6,26}}; // Rows

        mainPanel.setLayout (new TableLayout(size));


        mainPanel.add(labelLastConIP,            " 1, 1");
        mainPanel.add(lastConnectedIP,           " 3, 1");

        mainPanel.add(labelLastUsername,         " 1, 3");
        mainPanel.add(lastUserName,              " 3, 3");

        mainPanel.add(findingBridgeProgressBar,  " 3, 5");

        mainPanel.add(connectToLastBridgeButton, " 5, 1");
        mainPanel.add(findBridgesButton,         " 5, 3");

        mainPanel.add(randomLightsButton,        " 5, 5");
        mainPanel.add(setLightsButton,           " 5, 7");

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setPreferredSize(new Dimension(700,270));

        getContentPane().add(new JLabel("   An example Java/Swing Desktop Application to control your Hue Lights."), BorderLayout.NORTH);
        getContentPane().add(mainPanel, BorderLayout.CENTER);


        //4. Size the frame.
        pack();
        setLocationRelativeTo(null); // Centre the window.
        setVisible(true);        

    }

    public void setController(Controller controller) {
        this.controller = controller;
    }

    public JButton getSetLightsButton() {
        return setLightsButton;
    }

    public JButton getRandomLightsButton() {
        return randomLightsButton;
    } 

    public JButton getFindBridgesButton() {
        return findBridgesButton;
    } 

    public JButton getConnectToLastBridgeButton() {
        return connectToLastBridgeButton;
    } 

    public void showDialog(String message) {
        JOptionPane.showMessageDialog(this, message);
    }

    public JProgressBar getFindingBridgeProgressBar() {
        return findingBridgeProgressBar;
    }

    public JTextField getLastConnectedIP() {
        return lastConnectedIP;
    }

    public JTextField getLastUserName() {
        return lastUserName;
    }
}

HueDesktop.java

package com.philips.lighting;

import com.philips.lighting.data.HueProperties;
import com.philips.lighting.gui.DesktopView;
import com.philips.lighting.hue.sdk.PHHueSDK;

/**
 * HueDesktop.java
 * An example Java/Swing Desktop application illustrating how to connect to a bridge and change your Hue lights
 * using a Java Desktop Application.
 * 
 * For more information on programming for Hue see:
 * http://developers.meethue.com
 *
 */
class HueDesktop {

    public static void main(String args[]) {
        new HueDesktop();
    }

    public HueDesktop() {
        PHHueSDK phHueSDK = PHHueSDK.create();

        // Load in HueProperties, if first time use a properties file is created.
        HueProperties.loadProperties();

        //  Set Up the View (A JFrame, MenuBar and Console).
        DesktopView desktopView = new DesktopView();

        // Bind the Model and View
        Controller controller = new Controller(desktopView);
        desktopView.setController(controller);

        // Register the PHSDKListener to receive callbacks from the bridge.
        phHueSDK.getNotificationManager().registerSDKListener(controller.getListener());
    }
}

1 个答案:

答案 0 :(得分:0)

你有没有解决过这个问题?将来最好在GitHub网站上发布hue Java SDK问题。 https://github.com/PhilipsHue/PhilipsHueSDK-Java-MultiPlatform-Android/issues 我会在这里早点看到这个(我写这个代码顺便说一句,所以可能是罪魁祸首)。

我记得以前看过类似的问题,我很确定它与Macs和JDK编译器级别有关(我可能在Mac和JDK 1.6上使用了不兼容的Swing组件)。你能告诉我你的操作系统和JDK编译器级别,我会进一步检查吗?