/** * Starts the session with the remote controllable device * * @param eventsListener */ public void startSession(DeviceEventsListener eventsListener) throws ControlPanelException { if (eventsListener == null) { throw new ControlPanelException("Events listener can't be NULL"); } deviceEventsListener = eventsListener; if (sessionId != null) { String msg = "The device is already in session: '" + deviceId + "', sessionId: '" + sessionId + "'"; Log.d(TAG, msg); deviceEventsListener.sessionEstablished(this, getControlPanelCollections()); return; } connMgr.registerEventListener(ConnManagerEventType.SESSION_JOINED, this); connMgr.registerEventListener(ConnManagerEventType.SESSION_LOST, this); connMgr.registerEventListener(ConnManagerEventType.SESSION_JOIN_FAIL, this); Log.d(TAG, "Device: '" + deviceId + "' starting session with sender: '" + sender + "'"); Status status = connMgr.joinSession(sender, deviceId); if (status != Status.OK) { String statusName = status.name(); Log.e(TAG, "Failed to join session: '" + statusName + "'"); deviceEventsListener.errorOccurred(this, statusName); return; } } // startSession
/** * Handle session join failed * * @param args */ private void handleSessionJoinFailed(Map<String, Object> args) { String deviceId = (String) args.get("DEVICE_ID"); Object statusObj = args.get("STATUS"); if (statusObj == null || !(statusObj instanceof Status)) { return; } String status = ((Status) statusObj).name(); Log.w( TAG, "Received SESSION_JOIN_FAIL event for deviceId: '" + deviceId + "', this deviceId is: '" + this.deviceId + "', Status: '" + status + "'"); if (deviceId == null || !deviceId.equals(this.deviceId)) { return; } this.sessionId = null; connMgr.unregisterEventListener(ConnManagerEventType.SESSION_JOINED, this); connMgr.unregisterEventListener(ConnManagerEventType.SESSION_LOST, this); connMgr.unregisterEventListener(ConnManagerEventType.SESSION_JOIN_FAIL, this); deviceEventsListener.errorOccurred(this, status); } // handleSessionJoinedFailed
/** * Stops all the device activities <br> * close session <br> * stop find adv name <br> * stop scheduled service <br> * Set is reachable to false */ void stopDeviceActivities() { isReachable.set(false); try { connMgr.cancelFindAdvertisedName(sender); } catch (ControlPanelException cpe) { Log.e(TAG, "Failed to call cancelFindAdvertisedName(), Error: '" + cpe.getMessage() + "'"); } connMgr.unregisterEventListener(ConnManagerEventType.FOUND_DEVICE, this); connMgr.unregisterEventListener(ConnManagerEventType.LOST_DEVICE, this); Status status = endSession(); if (status != Status.OK) { Log.e(TAG, "Failed to end the session, Status: '" + status + "'"); } stopDeviceFoundVerificationService(); for (Unit unit : unitMap.values()) { unit.release(); } unitMap.clear(); } // stopDeviceActivities
/** * Starts {@link ControlPanelService} which discovers controllable devices in its proximity. <br> * The ControlPanelService user is informed about the devices in proximity via the {@link * DeviceRegistry} interface. <br> * The discovery mechanism is implemented by receiving Announcement signals. <br> * * @param bus BusAttachment that the service should use * @param deviceRegistry Holds the information about the devices in proximity<br> * {@link DefaultDeviceRegistry} may be passed in to receive information about the devices * @throws ControlPanelException if failed to initialize the control panel service */ public void init(BusAttachment bus, DeviceRegistry deviceRegistry) throws ControlPanelException { if (deviceRegistry == null) { throw new ControlPanelException("deviceRegistry can't be NULL"); } AboutService aboutService = AboutServiceImpl.getInstance(); if (!aboutService.isClientRunning()) { throw new ControlPanelException( "The AboutService is not running, impossible to receive Announcement signals"); } // Perform the basic service initialization init(bus); this.deviceRegistry = deviceRegistry; Log.d(TAG, "Start listening for Announcement signals"); connMgr.registerEventListener(ConnManagerEventType.ANNOUNCEMENT_RECEIVED, this); // Add an announcement handler announcementReceiver = new AnnouncementReceiver(); for (String iface : ANNOUNCEMENT_IFACES) { aboutService.addAnnouncementHandler(announcementReceiver, new String[] {iface}); } } // init
/** Shutdown the {@link ControlPanelService} */ public void shutdown() { Log.d(TAG, "Shutdown ControlPanelService"); if (announcementReceiver != null) { AboutService aboutService = AboutServiceImpl.getInstance(); for (String iface : ANNOUNCEMENT_IFACES) { aboutService.removeAnnouncementHandler(announcementReceiver, new String[] {iface}); } } if (deviceRegistry != null) { Log.d(TAG, "Clear devices registry"); for (ControllableDevice device : deviceRegistry.getDevices().values()) { stopControllableDevice(device); } deviceRegistry = null; } TaskManager taskManager = TaskManager.getInstance(); if (taskManager.isRunning()) { taskManager.shutdown(); } connMgr.shutdown(); } // shutdown
/** * Constructor * * @param deviceId The device unique identifier * @param sender The unique identifier of the remote device */ public ControllableDevice(String deviceId, String sender) { this.deviceId = deviceId; this.sender = sender; this.isReachable = new AtomicBoolean(false); this.unitMap = new HashMap<String, Unit>(); this.sessionId = null; this.deviceRegistry = ControlPanelService.getInstance().getDeviceRegistry(); this.connMgr = ConnectionManager.getInstance(); } // Constructor
/** * Handle session lost * * @param args */ private void handleSessionLost(Map<String, Object> args) { Integer sessionId = (Integer) args.get("SESSION_ID"); Log.w( TAG, "Received SESSION_LOST event for sessionId: '" + sessionId + "', this device sessionId is: '" + this.sessionId + "'"); if (sessionId == null || !sessionId.equals(this.sessionId)) { return; } this.sessionId = null; connMgr.unregisterEventListener(ConnManagerEventType.SESSION_JOINED, this); connMgr.unregisterEventListener(ConnManagerEventType.SESSION_LOST, this); connMgr.unregisterEventListener(ConnManagerEventType.SESSION_JOIN_FAIL, this); deviceEventsListener.sessionLost(this); } // handleSessionLost
/** * End the session with the remote controllable device * * @return {@link Status} of endSession execution */ public Status endSession() { Log.i(TAG, "endSession has been called, leaving the session"); if (sessionId == null) { Log.w(TAG, "Fail to execute endSession, sessionId is NULL, returning Status of FAIL"); return Status.FAIL; } Status status; try { status = connMgr.leaveSession(sessionId); } catch (ControlPanelException cpe) { Log.e( TAG, "Failed to call leaveSession, Error: '" + cpe.getMessage() + "', returning status of FAIL"); return Status.FAIL; } String logMsg = "endSession return Status is: '" + status + "'"; if (status == Status.OK) { sessionId = null; Log.i(TAG, logMsg); // Unregister the session relevant events connMgr.unregisterEventListener(ConnManagerEventType.SESSION_JOINED, this); connMgr.unregisterEventListener(ConnManagerEventType.SESSION_LOST, this); connMgr.unregisterEventListener(ConnManagerEventType.SESSION_JOIN_FAIL, this); } else { Log.w(TAG, logMsg); } return status; } // endSession
/** Subscribe to receive foundAdvName and lostAdvName events of ConnectionManager */ void subscribeOnFoundLostEvents() { Log.d(TAG, "Register on ConnManager to receive events of found and lost advertised name"); connMgr.registerEventListener(ConnManagerEventType.FOUND_DEVICE, this); connMgr.registerEventListener(ConnManagerEventType.LOST_DEVICE, this); } // subscribeOnFoundLostEvents
/** Constructor */ private ControlPanelService() { connMgr = ConnectionManager.getInstance(); }
/** * Checks whether the received announcement has ControlPanel interface <br> * If has creates ControllableObject and save it in the registry * * @param args */ private void handleAnnouncement(Map<String, Object> args) { String deviceId = (String) args.get("DEVICE_ID"); String appId = (String) args.get("APP_ID"); String sender = (String) args.get("SENDER"); BusObjectDescription[] objDescList = (BusObjectDescription[]) args.get("OBJ_DESC"); if (deviceId == null || deviceId.length() == 0) { Log.e(TAG, "Received a bad Announcement signal, deviceId can't be NULL or empty"); return; } if (sender == null || sender.length() == 0) { Log.e(TAG, "Received a bad Announcement signal, sender can't be NULL or empty"); return; } if (objDescList == null || objDescList.length == 0) { Log.e(TAG, "Received a bad Announcement signal, BusObjectDescription array is empty"); return; } // The controllable device id should be constructed from the deviceId and the appId deviceId = deviceId + "_" + appId; boolean newDevice = false; // TRUE if it's a not registered new device boolean handledDevice = false; // TRUE if for at least one received control panel object path we handled the device ControllableDevice device = deviceRegistry.getDevices().get(deviceId); // Iterate over the BusObjectDescription objects received from an Announcement signal for (BusObjectDescription busObjDesc : objDescList) { Log.v(TAG, "Found objPath: '" + busObjDesc.getPath() + "'"); String[] interfaces = busObjDesc.getInterfaces(); int ifaceMask = CommunicationUtil.getInterfaceMask(interfaces); // Check if found a ControlPanel or HTTPControl interfaces if (!CommunicationUtil.maskIncludes(ifaceMask, ControlPanel.ID_MASK) && !CommunicationUtil.maskIncludes(ifaceMask, HTTPControl.ID_MASK)) { continue; } String objPath = busObjDesc.getPath(); Log.d(TAG, "Found ControlPanel object, path: '" + objPath + "'"); if (!handledDevice) { if (device == null) { Log.d( TAG, "Discovered new device, deviceId: '" + deviceId + "', sender: '" + sender + "'"); device = new ControllableDevice(deviceId, sender); device.subscribeOnFoundLostEvents(); // Listen to events of found | lost adv. name newDevice = true; } // device == null else { Log.d( TAG, "Device with deviceId: '" + deviceId + "' already exists, updating sender to be: '" + sender + "'"); device.setSender(sender); try { connMgr.cancelFindAdvertisedName(sender); } catch (ControlPanelException cpe) { Log.e( TAG, "Failed to call cancelFindAdvertisedName(), Error: '" + cpe.getMessage() + "'"); return; } } // else :: device == null device.setReachable(true); device.startDeviceFoundVerificationService(); // Start scheduled service before call // findAdvName Log.d(TAG, "Start findAdvertisedName for sender: '" + sender + "'"); Status res; try { res = connMgr.findAdvertisedName(sender); } catch (ControlPanelException cpe) { Log.e(TAG, "Failed to call findAdvertisedName(), Error: '" + cpe.getMessage() + "'"); return; } if (res != Status.OK) { Log.d( TAG, "Failed to start findAdvertisedName for sender: '" + sender + "', Error: '" + res + "'"); device.stopDeviceActivities(); return; } // We handled the discovered device for at least one of the received ControlPanel object // paths handledDevice = true; } // if :: not handledDevice try { device.addControlPanel(objPath, ifaceMask); } catch (ControlPanelException cpe) { Log.w( TAG, "Received a broken object path: '" + objPath + "', Error: '" + cpe.getMessage() + "'"); } } // for :: BusObjectDescription if (handledDevice) { if (newDevice) { deviceRegistry.foundNewDevice(device); } else { deviceRegistry.reachabilityChanged(device, true); } } } // handleAnnouncement
/** * Starts {@link ControlPanelService} without discovering new devices in proximity * * @param bus */ public void init(BusAttachment bus) throws ControlPanelException { connMgr.setBusAttachment(bus); TaskManager.getInstance().initPool(); } // init