/* * Dog - Device Driver * * Copyright (c) 2011-2013 Luigi De Russis and Dario Bonino * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package it.polito.elite.dog.drivers.knx.onoffdevice; import it.polito.elite.dog.core.library.util.LogHelper; import it.polito.elite.dog.core.library.model.ControllableDevice; import it.polito.elite.dog.core.library.model.DeviceCostants; import it.polito.elite.dog.core.library.model.devicecategory.Controllable; import it.polito.elite.dog.core.library.model.devicecategory.Lamp; import it.polito.elite.dog.drivers.knx.gateway.KnxIPGatewayDriver; import it.polito.elite.dog.drivers.knx.gateway.KnxIPGatewayDriverInstance; import it.polito.elite.dog.drivers.knx.network.info.KnxIPInfo; import it.polito.elite.dog.drivers.knx.network.interfaces.KnxIPNetwork; import java.util.HashSet; import java.util.Hashtable; import java.util.Set; import java.util.Vector; import java.util.concurrent.atomic.AtomicReference; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.service.device.Device; import org.osgi.service.device.Driver; /** * The (standard) class for creating and handling the registration/removal * process of the driver in the OSGi framework. * * @author <a href="mailto:luigi.derussis@polito.it">Luigi De Russis</a> * @see <a href="http://elite.polito.it">http://elite.polito.it</a> * */ public class KnxIPOnOffDeviceDriver implements Driver { // OSGi framework context BundleContext context; // System logger LogHelper logger; // the log identifier, unique for the class public static String logId = "[KnxIpOnOffDeviceDriver]: "; // a reference to the network driver private AtomicReference<KnxIPNetwork> network; // a reference to the gateway driver private AtomicReference<KnxIPGatewayDriver> gateway; // the registration object needed to handle the lifespan of this bundle in // the OSGi framework (it is a ServiceRegistration object for use by the // bundle registering the service to update the service's properties or to // unregister the service). private ServiceRegistration<?> regDriver; // a vector to store all the connected On/Off device drivers private Vector<KnxIPOnOffDeviceDriverInstance> connectedDriver; // what are the on/off device categories that can match with this driver? private Set<String> OnOffDeviceCategories; /** * The (standard) constructor for the On/Off device driver. I */ public KnxIPOnOffDeviceDriver() { // initialize atomic references this.network = new AtomicReference<KnxIPNetwork>(); this.gateway = new AtomicReference<KnxIPGatewayDriver>(); } public void activate(BundleContext context) { // init the logger this.logger = new LogHelper(context); // store the context this.context = context; // initialize the connected drivers list this.connectedDriver = new Vector<KnxIPOnOffDeviceDriverInstance>(); // initialize the set of implemented device categories this.OnOffDeviceCategories = new HashSet<String>(); // fill the categories this.properFillDeviceCategories(); // try to register the service this.register(); } public void deactivate() { this.unRegister(); this.context = null; this.connectedDriver.clear(); this.connectedDriver = null; this.OnOffDeviceCategories.clear(); this.OnOffDeviceCategories = null; this.logger = null; } /** * Fill a set with all the device categories whose devices can match with * this driver. Automatically retrieve the device categories list by reading * the implemented interfaces of its DeviceDriverInstance class bundle. */ private void properFillDeviceCategories() { for (Class<?> devCat : KnxIPOnOffDeviceDriverInstance.class .getInterfaces()) { this.OnOffDeviceCategories.add(devCat.getName()); } } /** * Try to unregister the service-related part of the driver from the OSGi * framework */ public void unRegister() { // TODO DETACH allocated Drivers if (this.regDriver != null) { this.regDriver.unregister(); this.regDriver = null; } } /** * Handles the "availability" of a KnxIP network driver (store a reference * to the driver and try to start). * * @param netDriver * The available {@link KnxIPNetwork} driver service. */ public void addedNetworkDriver(KnxIPNetwork netDriver) { // store a reference to the network driver this.network.set(netDriver); // try to start service offering // this.register(); } /** * Handles the removal of the connected KnxIP network driver by * unregistering the services provided by this driver */ public void removedNetworkDriver(KnxIPNetwork network) { // un-register this service this.unRegister(); // null the reference to the network driver this.network.compareAndSet(network, null); } /** * Handles the "availability" of a KnxIP gateway driver (store a reference * to the driver and try to start). * * @param gwDriver * The available {@link KnxIPGatewayDriver} service. */ public void addedGatewayDriver(KnxIPGatewayDriver gwDriver) { // store a reference to the gateway driver this.gateway.set(gwDriver); // try to start service offering // this.register(); } /** * Handles the removal of the connected KnxIP gateway driver by * unregistering the services provided by this driver */ public void removedGatewayDriver(KnxIPGatewayDriver gateway) { // un-register this service this.unRegister(); // null the reference to the network driver this.gateway.compareAndSet(gateway, null); } /** * Register the driver in the OSGi framework. */ private void register() { if ((this.network != null) && (this.gateway != null) && (this.context != null) && (this.regDriver == null)) { // create a new property object describing this driver Hashtable<String, Object> propDriver = new Hashtable<String, Object>(); // add the id of this driver to the properties propDriver.put(DeviceCostants.DRIVER_ID, KnxIPOnOffDeviceDriver.class.getName()); // register this driver in the OSGi framework this.regDriver = this.context.registerService( Driver.class.getName(), this, propDriver); } } /* * (non-Javadoc) * * @see * org.osgi.service.device.Driver#match(org.osgi.framework.ServiceReference) */ @SuppressWarnings({ "rawtypes" }) @Override public synchronized int match(ServiceReference reference) throws Exception { int matchValue = Device.MATCH_NONE; if ((this.network != null) && (this.gateway != null) && (this.regDriver != null)) { // the device category for this device String deviceCategory = (String) reference .getProperty(DeviceCostants.DEVICE_CATEGORY); try { //get the device class if (Controllable.class.isAssignableFrom(KnxIPOnOffDeviceDriver.class .getClassLoader().loadClass(deviceCategory))) { // the manufacturer String manufacturer = (String) reference .getProperty(DeviceCostants.MANUFACTURER); // get the gateway to which the device is connected String gateway = (String) reference .getProperty(DeviceCostants.GATEWAY); if (deviceCategory != null) { if ((manufacturer != null) && (gateway != null) && (manufacturer.equals(KnxIPInfo.MANUFACTURER)) && (OnOffDeviceCategories .contains(deviceCategory)) && (this.gateway.get() .isGatewayAvailable(gateway))) { // use Lamp as a generic on/off device, for its // match // values... // TODO: evaluate if it is better to store this // information // in // DogDeviceConstant, to be general... matchValue = Lamp.MATCH_MANUFACTURER + Lamp.MATCH_TYPE; } } } } catch (ClassNotFoundException e) { // skip --> no match } } return matchValue; } /* * (non-Javadoc) * * @see * org.osgi.service.device.Driver#attach(org.osgi.framework.ServiceReference * ) */ @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public synchronized String attach(ServiceReference reference) throws Exception { if ((this.network != null) && (this.gateway != null) && (this.regDriver != null)) { // get the referenced device: from this moment on the driver will be // tracked as using the device ControllableDevice device = (ControllableDevice) this.context .getService(reference); // get the gateway to which the device is connected String gateway = (String) device.getDeviceDescriptor().getGateway(); // get the associated gateway instance KnxIPGatewayDriverInstance gwInstance = this.gateway.get() .getSpecificGateway(gateway); // create a driver instance KnxIPOnOffDeviceDriverInstance driver = new KnxIPOnOffDeviceDriverInstance( this.network.get(), device, gwInstance.getGatewayAddress(), this.context); // attach the driver to the device device.setDriver(driver); // store the driver instance as connected to a device synchronized (this.connectedDriver) { this.connectedDriver.add(driver); } } return null; } }