/* * Dog - Gateway Driver * * Copyright (c) 2012-2013 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.gateway; 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.KNXNetIPGateway; import it.polito.elite.dog.core.library.util.LogHelper; import it.polito.elite.dog.drivers.knx.network.info.KnxIPInfo; import it.polito.elite.dog.drivers.knx.network.interfaces.KnxIPNetwork; import java.util.Hashtable; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; 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; import org.osgi.service.log.LogService; /** * A class implementing the functionalities of a generic KnxIPNet gateway, as * modeled in DogOnt. It offers ways to trace the number of currently managed * gateways, this permits multiple-gateway operation in Dog. * * Currently no gateway-specific functions are available, however in future * releases functionalities offered by the real devices will be modeled and * implemented here. * * @author <a href="mailto:dario.bonino@polito.it">Dario Bonino</a> * @see <a href="http://elite.polito.it">http://elite.polito.it</a> * */ public class KnxIPGatewayDriver implements Driver { // The OSGi framework context protected BundleContext context; // System logger LogHelper logger; // the log identifier, unique for the class public static String logId = "[KnxIPGatewayDriver]: "; // a reference to the network driver (currently not used by this driver // version, in the future it will be used to implement gateway-specific // functionalities). private AtomicReference<KnxIPNetwork> network; // the registration object needed to handle the life span 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; // the registration object needed to handle the life span 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). // Defines this class as a KnxIPGateway private ServiceRegistration<?> regKnxIPGateway; // the set of currently connected gateways... indexed by their ids private Map<String, KnxIPGatewayDriverInstance> connectedGateways; public KnxIPGatewayDriver() { // initialize atomic references this.network = new AtomicReference<KnxIPNetwork>(); } public void activate(BundleContext bundleContext) { // store the context this.context = bundleContext; // init the logger this.logger = new LogHelper(this.context); // initialize the map of connected gateways this.connectedGateways = new ConcurrentHashMap<String, KnxIPGatewayDriverInstance>(); // if ready, try to register offered services this.registerDriver(); } public void deactivate() { // unregister the driver this.unRegister(); // null the context this.context = null; // null the logger this.logger = null; // clear the map of connected gateways this.connectedGateways.clear(); } public void unRegister() { // un-registers this driver if (this.regDriver != null) { this.regDriver.unregister(); this.regDriver = null; } // un-register the gateway service if (this.regKnxIPGateway != null) { this.regKnxIPGateway.unregister(); this.regKnxIPGateway = null; } } public void addedNetworkService(KnxIPNetwork network) { // store a reference to the network service this.network.set(network); } public void removedNetworkService(KnxIPNetwork network) { // unregisters this driver from the OSGi framework this.unRegister(); // null the network reference this.network.compareAndSet(network, null); } private void registerDriver() { if ((this.network.get() != null) && (this.regDriver == null) && (this.context != null)) { Hashtable<String, Object> propDriver = new Hashtable<String, Object>(); propDriver.put(DeviceCostants.DRIVER_ID, KnxIPGatewayDriver.class.getName()); propDriver.put(DeviceCostants.GATEWAY_COUNT, this.connectedGateways.size()); this.regDriver = this.context.registerService(Driver.class.getName(), this, propDriver); this.regKnxIPGateway = this.context.registerService(KnxIPGatewayDriver.class.getName(), this, null); } } @SuppressWarnings("rawtypes") @Override public synchronized int match(ServiceReference reference) throws Exception { int matchValue = Device.MATCH_NONE; if ((this.regDriver != null) && (this.regKnxIPGateway != null)) { // get the given device category String deviceCategory = (String) reference.getProperty(DeviceCostants.DEVICE_CATEGORY); // get the given device manufacturer String manufacturer = (String) reference.getProperty(DeviceCostants.MANUFACTURER); // compute the matching score between the given device and this // driver if (deviceCategory != null) { if (manufacturer != null && manufacturer.equals(KnxIPInfo.MANUFACTURER) && (deviceCategory.equals(KNXNetIPGateway.class.getName()) )) { matchValue = KNXNetIPGateway.MATCH_MANUFACTURER + KNXNetIPGateway.MATCH_TYPE; } } } return matchValue; } @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public synchronized String attach(ServiceReference reference) throws Exception { if ((this.regDriver != null) && (this.regKnxIPGateway != null)) { //get the referenced device ControllableDevice gatewayDevice = (ControllableDevice) this.context.getService(reference); // get the corresponding end point set Set<String> gatewayAddressSet = gatewayDevice.getDeviceDescriptor().getSimpleConfigurationParams().get(KnxIPInfo.GATEWAY_ADDRESS); String deviceId = gatewayDevice.getDeviceId(); // if not null, it is a singleton if (gatewayAddressSet != null) { // get the endpoint address of the connecting gateway String gatewayAddress = gatewayAddressSet.iterator().next(); // check not null if ((gatewayAddress != null) && (!gatewayAddress.isEmpty())) { if (!this.isGatewayAvailable(deviceId)) { // create a new instance of the gateway driver KnxIPGatewayDriverInstance driver = new KnxIPGatewayDriverInstance(this.network.get(), gatewayDevice, gatewayAddress, this.context); // connect this driver instance with the device gatewayDevice.setDriver(driver); // store a reference to the gateway driver synchronized (this.connectedGateways) { // store a reference to the gateway driver this.connectedGateways.put(deviceId, driver); } // modify the service description causing a forcing the // framework to send a modified service notification final Hashtable<String, Object> propDriver = new Hashtable<String, Object>(); propDriver.put(DeviceCostants.DRIVER_ID, "KnxIP_KnxIPGateway_driver"); propDriver.put(DeviceCostants.GATEWAY_COUNT, this.connectedGateways.size()); this.regDriver.setProperties(propDriver); } } else { // do not attach, log and throw exception this.logger .log(LogService.LOG_WARNING, KnxIPGatewayDriver.logId + "Unable to get the current gateway address (empty set), this prevents the device from being attached!"); throw new Exception( KnxIPGatewayDriver.logId + "Unable to get the current gateway address, this prevents the device from being attached!"); } } else { // do not attach, log and throw exception this.logger .log(LogService.LOG_WARNING, KnxIPGatewayDriver.logId + "Unable to get the current gateway address (missing parameter), this prevents the device from being attached!"); throw new Exception(KnxIPGatewayDriver.logId + "Unable to get the current gateway address, this prevents the device from being attached!"); } } return null; } /** * check if the gateway identified by the given gateway id is currently * registered with this driver * * @param gatewayId * @return true if the gateway corresponding to the given id is already * registered, false otherwise. */ public boolean isGatewayAvailable(String gatewayId) { return this.connectedGateways.containsKey(gatewayId); } /** * Returns a live reference to the specific gateway driver instance * associated with the KnxIP gateway device having the given id. * * @param gatewayId * @return */ public KnxIPGatewayDriverInstance getSpecificGateway(String gatewayId) { return this.connectedGateways.get(gatewayId); } }