1f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum/* 2f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * Copyright 2017, The Android Open Source Project 3f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * 4f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * Licensed under the Apache License, Version 2.0 (the "License"); 5f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * you may not use this file except in compliance with the License. 6f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * You may obtain a copy of the License at 7f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * 8f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * http://www.apache.org/licenses/LICENSE-2.0 9f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * 10f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * Unless required by applicable law or agreed to in writing, software 11f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * distributed under the License is distributed on an "AS IS" BASIS, 12f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * See the License for the specific language governing permissions and 14f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * limitations under the License. 15f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum */ 16f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 17f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumpackage com.android.commands.lowpan; 18f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 19f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.ILowpanInterface; 20f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanBeaconInfo; 21f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanCredential; 22f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanEnergyScanResult; 23f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanException; 24f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanIdentity; 25f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanInterface; 26f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanManager; 27f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanProvision; 28f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.net.lowpan.LowpanScanner; 2941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaumimport android.net.LinkAddress; 30f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.os.RemoteException; 31f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.os.ServiceSpecificException; 32f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport android.util.AndroidRuntimeException; 33f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport com.android.internal.os.BaseCommand; 34f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport com.android.internal.util.HexDump; 35f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport java.io.PrintStream; 36f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport java.util.HashMap; 37f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport java.util.Map; 38f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport java.util.concurrent.Semaphore; 39f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumimport java.util.concurrent.TimeUnit; 40f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 41f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaumpublic class LowpanCtl extends BaseCommand { 42f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private LowpanManager mLowpanManager; 43f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private LowpanInterface mLowpanInterface; 44f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private ILowpanInterface mILowpanInterface; 45f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private String mLowpanInterfaceName; 46f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 47f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum /** 48f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * Command-line entry point. 49f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * 50f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum * @param args The command-line arguments 51f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum */ 52f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum public static void main(String[] args) { 53f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum new LowpanCtl().run(args); 54f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 55f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 56f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum @Override 57f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum public void onShowUsage(PrintStream out) { 58f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum out.println( 59f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum "usage: lowpanctl [options] [subcommand] [subcommand-options]\n" 6041641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + "options:\n" 6141641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + " -I / --interface <iface-name> ..... Interface Name\n" 6241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + "subcommands:\n" 63f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum + " lowpanctl status\n" 64f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum + " lowpanctl form\n" 65f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum + " lowpanctl join\n" 6641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + " lowpanctl attach\n" 67f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum + " lowpanctl leave\n" 6841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + " lowpanctl enable\n" 6941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + " lowpanctl disable\n" 7041641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + " lowpanctl show-credential\n" 71f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum + " lowpanctl scan\n" 72f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum + " lowpanctl reset\n" 73f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum + " lowpanctl list\n" 7441641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + "\n" 7541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + "usage: lowpanctl [options] join/form/attach [network-name]\n" 7641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + "subcommand-options:\n" 7741641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + " --name <network-name> ............. Network Name\n" 7841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + " -p / --panid <panid> .............. PANID\n" 7941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + " -c / --channel <channel> .......... Channel Index\n" 8041641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + " -x / --xpanid <xpanid> ............ XPANID\n" 8141641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + " -k / --master-key <master-key> .... Master Key\n" 8241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + " --master-key-index <key-index> .... Key Index\n" 8341641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + "\n" 8441641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + "usage: lowpanctl [options] show-credential\n" 8541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + "subcommand-options:\n" 8641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + " -r / --raw ........................ Print only key contents\n" 87f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum + "\n"); 8841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum 89f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 90f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 91f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private class CommandErrorException extends AndroidRuntimeException { 92f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum public CommandErrorException(String desc) { 93f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum super(desc); 94f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 95f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 96f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 97f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private void throwCommandError(String desc) { 98f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum throw new CommandErrorException(desc); 99f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 100f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 101f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private LowpanInterface getLowpanInterface() { 102f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (mLowpanInterface == null) { 103f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (mLowpanInterfaceName == null) { 104f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum String interfaceArray[] = mLowpanManager.getInterfaceList(); 105f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (interfaceArray.length != 0) { 106f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum mLowpanInterfaceName = interfaceArray[0]; 107f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else { 108f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum throwCommandError("No LoWPAN interfaces are present"); 109f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 110f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 111f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum mLowpanInterface = mLowpanManager.getInterface(mLowpanInterfaceName); 112f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 113f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (mLowpanInterface == null) { 114f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum throwCommandError("Unknown LoWPAN interface \"" + mLowpanInterfaceName + "\""); 115f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 116f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 117f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum return mLowpanInterface; 118f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 119f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 120f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private ILowpanInterface getILowpanInterface() { 121f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (mILowpanInterface == null) { 122f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum mILowpanInterface = getLowpanInterface().getService(); 123f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 124f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum return mILowpanInterface; 125f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 126f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 127f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum @Override 128f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum public void onRun() throws Exception { 129f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum mLowpanManager = LowpanManager.getManager(); 130f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 131f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (mLowpanManager == null) { 132f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum System.err.println(NO_SYSTEM_ERROR_CODE); 133f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum throwCommandError("Can't connect to LoWPAN service; is the service running?"); 134f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 135f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 136f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum try { 137f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum String op; 138f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum while ((op = nextArgRequired()) != null) { 139f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (op.equals("-I") || op.equals("--interface")) { 140f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum mLowpanInterfaceName = nextArgRequired(); 141f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (op.startsWith("-")) { 142f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum throwCommandError("Unrecognized argument \"" + op + "\""); 143f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (op.equals("status") || op.equals("stat")) { 144f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum runStatus(); 145f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum break; 146f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (op.equals("scan") || op.equals("netscan") || op.equals("ns")) { 147f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum runNetScan(); 148f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum break; 14941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum } else if (op.equals("attach")) { 150f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum runAttach(); 151f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum break; 15241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum } else if (op.equals("enable")) { 15341641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum runEnable(); 15441641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum break; 15541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum } else if (op.equals("disable")) { 15641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum runDisable(); 15741641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum break; 15841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum } else if (op.equals("show-credential")) { 15941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum runShowCredential(); 160f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum break; 161f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (op.equals("join")) { 162f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum runJoin(); 163f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum break; 164f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (op.equals("form")) { 165f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum runForm(); 166f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum break; 167f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (op.equals("leave")) { 168f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum runLeave(); 169f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum break; 170f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (op.equals("energyscan") || op.equals("energy") || op.equals("es")) { 171f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum runEnergyScan(); 172f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum break; 173f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (op.equals("list") || op.equals("ls")) { 174f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum runListInterfaces(); 175f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum break; 176f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (op.equals("reset")) { 177f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum runReset(); 178f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum break; 179f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else { 180f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum showError("Error: unknown command '" + op + "'"); 181f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum break; 182f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 183f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 184f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } catch (ServiceSpecificException x) { 185f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum System.out.println( 186f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum "ServiceSpecificException: " + x.errorCode + ": " + x.getLocalizedMessage()); 187f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } catch (CommandErrorException x) { 188f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum System.out.println("error: " + x.getLocalizedMessage()); 189f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 190f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 191f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 192f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private void runReset() throws LowpanException { 193f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum getLowpanInterface().reset(); 194f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 195f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 19641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum private void runEnable() throws LowpanException { 19741641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum getLowpanInterface().setEnabled(true); 19841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum } 19941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum 20041641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum private void runDisable() throws LowpanException { 20141641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum getLowpanInterface().setEnabled(false); 20241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum } 20341641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum 204f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private LowpanProvision getProvisionFromArgs(boolean credentialRequired) { 205f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum LowpanProvision.Builder builder = new LowpanProvision.Builder(); 206f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum Map<String, Object> properties = new HashMap(); 207f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum LowpanIdentity.Builder identityBuilder = new LowpanIdentity.Builder(); 208f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum LowpanCredential credential = null; 209f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum String arg; 210f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum byte[] masterKey = null; 211f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum int masterKeyIndex = 0; 212f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum boolean hasName = false; 213f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 214f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum while ((arg = nextArg()) != null) { 215f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (arg.equals("--name")) { 216f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum identityBuilder.setName(nextArgRequired()); 217f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum hasName = true; 218f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (arg.equals("-p") || arg.equals("--panid")) { 219f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum identityBuilder.setPanid(Integer.decode(nextArgRequired())); 220f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (arg.equals("-c") || arg.equals("--channel")) { 221f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum identityBuilder.setChannel(Integer.decode(nextArgRequired())); 222f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (arg.equals("-x") || arg.equals("--xpanid")) { 223f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum identityBuilder.setXpanid(HexDump.hexStringToByteArray(nextArgRequired())); 224f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (arg.equals("-k") || arg.equals("--master-key")) { 225f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum masterKey = HexDump.hexStringToByteArray(nextArgRequired()); 226f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (arg.equals("--master-key-index")) { 227f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum masterKeyIndex = Integer.decode(nextArgRequired()); 22841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum } else if (arg.equals("--help")) { 22941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum throwCommandError(""); 230f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (arg.startsWith("-") || hasName) { 231f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum throwCommandError("Unrecognized argument \"" + arg + "\""); 232f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else { 233f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum // This is the network name 234f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum identityBuilder.setName(arg); 235f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum hasName = true; 236f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 237f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 238f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 239f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (credential == null && masterKey != null) { 240f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (masterKeyIndex == 0) { 241f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum credential = LowpanCredential.createMasterKey(masterKey); 242f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else { 243f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum credential = LowpanCredential.createMasterKey(masterKey, masterKeyIndex); 244f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 245f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 246f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 247f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (credential != null) { 248f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum builder.setLowpanCredential(credential); 249f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else if (credentialRequired) { 250f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum throwCommandError("No credential (like a master key) was specified!"); 251f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 252f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 253f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum return builder.setLowpanIdentity(identityBuilder.build()).build(); 254f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 255f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 256f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private void runAttach() throws LowpanException { 257f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum LowpanProvision provision = getProvisionFromArgs(true); 258f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 259f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum System.out.println( 260f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum "Attaching to " + provision.getLowpanIdentity() + " with provided credential"); 261f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 262f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum getLowpanInterface().attach(provision); 263f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 264f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum System.out.println("Attached."); 265f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 266f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 267f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private void runLeave() throws LowpanException { 268f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum getLowpanInterface().leave(); 269f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 270f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 271f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private void runJoin() throws LowpanException { 272f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum LowpanProvision provision = getProvisionFromArgs(true); 273f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 274f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum System.out.println( 275f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum "Joining " + provision.getLowpanIdentity() + " with provided credential"); 276f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 277f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum getLowpanInterface().join(provision); 278f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 279f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum System.out.println("Joined."); 280f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 281f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 282f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private void runForm() throws LowpanException { 283f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum LowpanProvision provision = getProvisionFromArgs(false); 284f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 285f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (provision.getLowpanCredential() != null) { 286f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum System.out.println( 287f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum "Forming " 28841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum + provision.getLowpanIdentity() 289f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum + " with provided credential"); 290f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else { 29141641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum System.out.println("Forming " + provision.getLowpanIdentity()); 292f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 293f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 294f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum getLowpanInterface().form(provision); 295f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 296f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum System.out.println("Formed."); 297f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 298f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 29941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum private void runStatus() throws LowpanException, RemoteException { 30041641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum LowpanInterface iface = getLowpanInterface(); 30141641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum StringBuffer sb = new StringBuffer(); 30241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum 30341641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum sb.append(iface.getName()) 30441641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum .append("\t") 30541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum .append(iface.getState() + " (" + iface.getRole() + ")"); 30641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum 30741641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum if (iface.isUp()) { 30841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum sb.append(" UP"); 309f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 310f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 31141641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum if (iface.isConnected()) { 31241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum sb.append(" CONNECTED"); 313f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 314f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 31541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum if (iface.isCommissioned()) { 31641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum sb.append(" COMMISSIONED"); 31741641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum } 31841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum 31941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum sb 32041641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum .append("\n\t") 32141641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum .append(getLowpanInterface().getLowpanIdentity()); 32241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum 32341641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum for (LinkAddress addr : iface.getLinkAddresses()) { 32441641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum sb.append("\n\t").append(addr); 32541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum } 32641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum 32741641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum sb.append("\n"); 32841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum System.out.println(sb.toString()); 329f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 330f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 33141641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum private void runShowCredential() throws LowpanException, RemoteException { 33241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum LowpanInterface iface = getLowpanInterface(); 33341641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum boolean raw = false; 33441641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum String arg; 33541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum while ((arg = nextArg()) != null) { 33641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum if (arg.equals("--raw") || arg.equals("-r")) { 33741641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum raw = true; 33841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum } else { 33941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum throwCommandError("Unrecognized argument \"" + arg + "\""); 340f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 341f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 34241641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum 34341641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum LowpanCredential credential = iface.getLowpanCredential(); 34441641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum if (raw) { 34541641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum System.out.println(HexDump.toHexString(credential.getMasterKey())); 34641641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum } else { 34741641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum System.out.println( 34841641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum iface.getName() + "\t" + credential.toSensitiveString()); 34941641f3e0d7ebccbb18ef1e03898688b50ae3e30Robert Quattlebaum } 350f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 351f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 352f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private void runListInterfaces() { 353f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum for (String name : mLowpanManager.getInterfaceList()) { 354f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum System.out.println(name); 355f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 356f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 357f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 358f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private void runNetScan() throws LowpanException, InterruptedException { 359f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum LowpanScanner scanner = getLowpanInterface().createScanner(); 360f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum String arg; 361f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 362f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum while ((arg = nextArg()) != null) { 363f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (arg.equals("-c") || arg.equals("--channel")) { 364f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum scanner.addChannel(Integer.decode(nextArgRequired())); 365f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else { 366f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum throwCommandError("Unrecognized argument \"" + arg + "\""); 367f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 368f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 369f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 370f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum Semaphore semaphore = new Semaphore(1); 371f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 372f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum scanner.setCallback( 373f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum new LowpanScanner.Callback() { 374f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum @Override 375f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum public void onNetScanBeacon(LowpanBeaconInfo beacon) { 376f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum System.out.println(beacon.toString()); 377f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 378f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 379f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum @Override 380f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum public void onScanFinished() { 381f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum semaphore.release(); 382f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 383f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum }); 384f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 385f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum semaphore.acquire(); 386f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum scanner.startNetScan(); 387f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 388f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum // Wait for our scan to complete. 389f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (semaphore.tryAcquire(1, 60L, TimeUnit.SECONDS)) { 390f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum semaphore.release(); 391f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else { 392f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum throwCommandError("Timeout while waiting for scan to complete."); 393f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 394f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 395f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 396f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum private void runEnergyScan() throws LowpanException, InterruptedException { 397f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum LowpanScanner scanner = getLowpanInterface().createScanner(); 398f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum String arg; 399f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 400f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum while ((arg = nextArg()) != null) { 401f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (arg.equals("-c") || arg.equals("--channel")) { 402f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum scanner.addChannel(Integer.decode(nextArgRequired())); 403f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else { 404f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum throwCommandError("Unrecognized argument \"" + arg + "\""); 405f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 406f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 407f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 408f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum Semaphore semaphore = new Semaphore(1); 409f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 410f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum scanner.setCallback( 411f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum new LowpanScanner.Callback() { 412f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum @Override 413f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum public void onEnergyScanResult(LowpanEnergyScanResult result) { 414f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum System.out.println(result.toString()); 415f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 416f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 417f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum @Override 418f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum public void onScanFinished() { 419f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum semaphore.release(); 420f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 421f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum }); 422f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 423f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum semaphore.acquire(); 424f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum scanner.startEnergyScan(); 425f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum 426f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum // Wait for our scan to complete. 427f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum if (semaphore.tryAcquire(1, 60L, TimeUnit.SECONDS)) { 428f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum semaphore.release(); 429f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } else { 430f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum throwCommandError("Timeout while waiting for scan to complete."); 431f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 432f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum } 433f15236e9c6adc5f69be5152bc61fe19bc975c222Robert Quattlebaum} 434