Simple BinaryLight Android Control Point

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Simple BinaryLight Android Control Point

jerry
The documentation on getting an Android Browser is great.  I was able to update that to use Cling 2.0 without trouble and have it working.  The workbench example is very feature rich and a great tool for testing.  Unfortunately, the workbench is too feature rich to quickly extract small functions from.  To learn Cling, I'd like to extend the Android Browser to be a BinaryLight control point and let me simply toggle a light device I create with the workbench.  It seems like this should be achievable in a small amount of code, but trying to extract it from the workbench is a bit challenging while I'm still learning the API (it's highly coupled with the workbench GUI).  Can anyone help me with the least lines of code to enhance the BrowserActivity to toggle a Binary Light on the list?  Sharing a code segment or some pseudo-code would be really appreciated!  Thanks!
Reply | Threaded
Open this post in threaded view
|

Re: Simple BinaryLight Android Control Point

Christian Bauer
Administrator
So, you have tried this without Android? This is actually the first example in the manual...

Reply | Threaded
Open this post in threaded view
|

Re: Simple BinaryLight Android Control Point

jerry
Thanks for the quick reply.  I did build the non-Android samples a few weeks ago when I first starting looking at Cling.  Perhaps I didn't give it enough consideration as a starting point since it isn't android and the ControlPoint only discovers the service and doesn't toggle the light.  I'll take a look at it again.
Reply | Threaded
Open this post in threaded view
|

Re: Simple BinaryLight Android Control Point

jerry
I used the BinaryLightClient example as a starting point and had half success.  I can successfully set, but cannot successfully get. I'd be grateful if someone could point out why my GET operation errors with a null pointer.  I modified createRegistryListener to call my new methods to GET and SET the light value (toggling from on-to-off or off-to-on depending on the initial condition).  Based on the example similarly named items, I created an executeSetAction and SetTargetValueActionInvocation that both take a newTargetValue.  This works.  I then created a matching executeGetAction and GetTargetValueActionInvocation, but I'm doings something wrong because the executeGetAction in createRegistryListener gives the following error:
Exception in thread "cling-26" java.lang.NullPointerException
	at example.binarylight.BinaryLightClient$GetTargetValueActionInvocation.<init>(BinaryLightClient.java:197)
	at example.binarylight.BinaryLightClient.executeGetAction(BinaryLightClient.java:166)
	at example.binarylight.BinaryLightClient$1.remoteDeviceAdded(BinaryLightClient.java:59)
	at org.fourthline.cling.registry.RemoteItems$1.run(RemoteItems.java:111)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Clearly I'm not understanding something about how the Get differs from the Set.  Help would be appreciated.  My code is below.  I know this should be easy and I'm sure my mistake is something stupid.
public class BinaryLightClient implements Runnable {

	public static void main(String[] args) throws Exception {
		// Start a user thread that runs the UPnP stack
		Thread clientThread = new Thread(new BinaryLightClient());
		clientThread.setDaemon(false);
		clientThread.start();

	}

	public void run() {
		try {

			UpnpService upnpService = new UpnpServiceImpl();

			// Add a listener for device registration events
			upnpService.getRegistry().addListener(
					createRegistryListener(upnpService)
					);

			// Broadcast a search message for all devices
			upnpService.getControlPoint().search(
					new STAllHeader()
					);

		} catch (Exception ex) {
			System.err.println("Exception occured: " + ex);
			System.exit(1);
		}
	}
	RegistryListener createRegistryListener(final UpnpService upnpService) {
		return new DefaultRegistryListener() {

			ServiceId serviceId = new UDAServiceId("SwitchPower");

			@Override
			public void remoteDeviceAdded(Registry registry, RemoteDevice device) {

				Service switchPower;
				if ((switchPower = device.findService(serviceId)) != null) {

					System.out.println("Service discovered: " + switchPower);
					//executeAction(upnpService, switchPower);
					
					//Get the current value then set to the opposite (a basic toggle)
			        boolean retTargetValue = false;
			        retTargetValue = executeGetAction(upnpService, switchPower);
			        boolean newTargetValue = ! retTargetValue;
			        executeSetAction(upnpService, switchPower, newTargetValue);


				}

			}

			@Override
			public void remoteDeviceRemoved(Registry registry, RemoteDevice device) {
				Service switchPower;
				if ((switchPower = device.findService(serviceId)) != null) {
					System.out.println("Service disappeared: " + switchPower);
				}
			}

		};
	}
	void executeAction(UpnpService upnpService, Service switchPowerService) {

		ActionInvocation setTargetInvocation =
				new SetTargetActionInvocation(switchPowerService);

		// Executes asynchronous in the background
		upnpService.getControlPoint().execute(
				new ActionCallback(setTargetInvocation) {

					@Override
					public void success(ActionInvocation invocation) {
						assert invocation.getOutput().length == 0;
						System.out.println("Successfully called action!");
					}

					@Override
					public void failure(ActionInvocation invocation,
							UpnpResponse operation,
							String defaultMsg) {
						System.err.println(defaultMsg);
					}
				}
				);

	}

	class SetTargetActionInvocation extends ActionInvocation {

		SetTargetActionInvocation(Service service) {
			super(service.getAction("SetTarget"));
			try {

				// Throws InvalidValueException if the value is of wrong type
				setInput("NewTargetValue", true);

			} catch (InvalidValueException ex) {
				System.err.println(ex.getMessage());
				System.exit(1);
			}
		}
	}
    void executeSetAction(UpnpService upnpService, 
    		Service switchPowerService, boolean newTargetValue) {

    	ActionInvocation setTargetInvocation =
    			new SetTargetValueActionInvocation(switchPowerService, newTargetValue);
    	// Executes asynchronous in the background
    	upnpService.getControlPoint().execute(
    			new ActionCallback(setTargetInvocation) {

    				@Override
    				public void success(ActionInvocation invocation) {
    					assert invocation.getOutput().length == 0;
    					System.out.println("Successfully called action!");
    				}

    				@Override
    				public void failure(ActionInvocation invocation,
    						UpnpResponse operation,
    						String defaultMsg) {
    					System.err.println(defaultMsg);
    				}
    			}
    			);

    }
    class SetTargetValueActionInvocation extends ActionInvocation {

    	SetTargetValueActionInvocation(Service service, boolean newTargetValue) {
    		super(service.getAction("SetTarget"));
    		try {

    			// Throws InvalidValueException if the value is of wrong type
    			// Otherwise sets newTargetValue
    			setInput("NewTargetValue", newTargetValue);

    		} catch (InvalidValueException ex) {
    			System.err.println(ex.getMessage());
    			System.exit(1);
    		}
    	}
    }
    boolean executeGetAction(UpnpService upnpService, 
    		Service switchPowerService) {

    	boolean retTargetValue = false;
    	
    	ActionInvocation getTargetInvocation =
    			new GetTargetValueActionInvocation(switchPowerService, retTargetValue);
    	// Executes asynchronous in the background
    	upnpService.getControlPoint().execute(
    			new ActionCallback(getTargetInvocation) {

    				@Override
    				public void success(ActionInvocation invocation) {
    					assert invocation.getOutput().length == 0;
    					System.out.println("Successfully called action!");
    				}

    				@Override
    				public void failure(ActionInvocation invocation,
    						UpnpResponse operation,
    						String defaultMsg) {
    					System.err.println(defaultMsg);
    				}
    			}
    			);
    	
    	return retTargetValue;

    }
    class GetTargetValueActionInvocation extends ActionInvocation {

    	GetTargetValueActionInvocation(Service service, boolean retTargetValue) {
    		super(service.getAction("GetTarget"));
    		try {

    			// Throws InvalidValueException if the value is of wrong type
    			// Otherwise sets newTargetValue
    			retTargetValue = Boolean.valueOf(getOutput("RetTargetValue").getValue().toString());

    		} catch (InvalidValueException ex) {
    			System.err.println(ex.getMessage());
    			System.exit(1);
    		}
    	}
    }
}
Reply | Threaded
Open this post in threaded view
|

Re: Simple BinaryLight Android Control Point

jerry
I'm still trying to make this work.  So far I've discovered things that tell me I'm missing some fundamental concept on how to correctly use the action callback.  If I change my GetTargetValueActionInvocation to do nothing within the try/catch, I do not crash.  Further, if I print to the screen the value of "invocation.getOutput("RetTargetValue").getValue().toString()" within the success method of ActionCallback(getTargetInvocation) I will see the correct value of the binary light device.  However, I don't see this print until after executeSetAction completes and I don't know how to correctly access the result outside of the success method.

This tells me that I'm not using the callbacks correctly, but unfortunately I don't have much experience with callbacks so my error escapes me.  Help would be appreciated.  I feel confident I can learn from an example, but I continue to struggle to find a simple example anywhere else in the source files.

I've also tried replacing my code with the code in section 3.2.2 of the manual (the "getStatusCallback"), but I still don't see how to access the status from outside the callback.  An example based on that code would equally help me.

Thanks!
Reply | Threaded
Open this post in threaded view
|

Re: Simple BinaryLight Android Control Point

Jean-Claude Dufourd
Le 7/5/14 03:06 , jerry [via Mailinglists] a écrit :
Further, if I print to the screen the value of "invocation.getOutput("RetTargetValue").getValue().toString()" within the success method of ActionCallback(getTargetInvocation) I will see the correct value of the binary light device.  
JCD: If you can access the information you want in the success callback, then place the code using that information in the success callback.
That is what I did.
Best regards
JC
--
Télécom
                  ParisTech Jean-Claude DUFOURD
Directeur d'études
Tél. : +33 1 45 81 77 33
37-39 rue Dareau
75014 Paris, France

Site webTwitterFacebookGoogle+Blog