/*
* 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.modbus.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.ModbusGateway;
import it.polito.elite.dog.core.library.util.LogHelper;
import it.polito.elite.dog.drivers.modbus.network.info.ModbusInfo;
import it.polito.elite.dog.drivers.modbus.network.interfaces.ModbusNetwork;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
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 Modbus gateway, as
* modeled in DogOnt. It offers ways to trace the number of currently managed
* gateways and to access the corresponding slaves and registers, 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 ModbusGatewayDriver implements Driver
{
// The OSGi framework context
protected BundleContext context;
// System logger
LogHelper logger;
// the log identifier, unique for the class
public static String logId = "[ModbusGatewayDriver]: ";
// 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 ModbusNetwork 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;
// register this driver as a gateway used by device-specific drivers
private ServiceRegistration<?> regModbusGateway;
// the set of currently connected gateways... indexed by their ids
private Map<String, ModbusGatewayDriverInstance> connectedGateways;
// the LDAP query used to match the ModbusNetworkDriver
String filterQuery = String.format("(%s=%s)", Constants.OBJECTCLASS, ModbusNetwork.class.getName());
public ModbusGatewayDriver()
{
// initialize the map of connected gateways
this.connectedGateways = new ConcurrentHashMap<String, ModbusGatewayDriverInstance>();
}
/**
* The class constructor, builds a new instance of the ModbusGatewayDriver.
* It tracks the services needed to enable the driver in the OSGi framework.
*
* @param context
* The context for this bundle
*/
public void activate(BundleContext context)
{
// init the logger
this.logger = new LogHelper(context);
// store the context
this.context = context;
if ((this.network != null) && (this.regDriver == null))
this.registerDriver();
}
public void deactivate()
{
// log deactivation
this.logger.log(LogService.LOG_DEBUG, ModbusGatewayDriver.logId + " Deactivation required");
this.unRegister();
// null the inner data structures
this.context = null;
this.logger = null;
this.network = null;
}
public void unRegister()
{
// un-registers this driver
if (this.regDriver != null)
{
this.regDriver.unregister();
this.regDriver = null;
}
// un-register the gateway service
if (this.regModbusGateway != null)
{
this.regModbusGateway.unregister();
this.regModbusGateway = null;
}
}
public void addingService(ModbusNetwork networkDriver)
{
this.network = networkDriver;
if ((this.context != null) && (this.regDriver == null))
this.registerDriver();
}
/**
* Registers this driver in the OSGi framework, making its services
* available to all the other bundles living in the same or in connected
* frameworks.
*/
private void registerDriver()
{
Hashtable<String, Object> propDriver = new Hashtable<String, Object>();
propDriver.put(DeviceCostants.DRIVER_ID, ModbusGatewayDriver.class.getName());
propDriver.put(DeviceCostants.GATEWAY_COUNT, this.connectedGateways.size());
this.regDriver = this.context.registerService(Driver.class.getName(), this, propDriver);
this.regModbusGateway = this.context.registerService(ModbusGatewayDriver.class.getName(), this, null);
}
public void removedService(ModbusNetwork networkDriver)
{
// unregisters this driver from the OSGi framework
this.network = null;
this.unRegister();
}
@SuppressWarnings("rawtypes")
@Override
public int match(ServiceReference reference) throws Exception
{
int matchValue = Device.MATCH_NONE;
if (this.regDriver != 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(ModbusInfo.MANUFACTURER)
&& (deviceCategory.equals(ModbusGateway.class.getName())
))
{
matchValue = ModbusGateway.MATCH_MANUFACTURER + ModbusGateway.MATCH_TYPE;
}
}
}
return matchValue;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public String attach(ServiceReference reference) throws Exception
{
if (this.regDriver != null)
{
// get the corresponding end point set
Set<String> gatewayAddressSet = ((ControllableDevice) this.context.getService(reference))
.getDeviceDescriptor().getSimpleConfigurationParams().get(ModbusInfo.GATEWAY_ADDRESS);
Set<String> gatewayPortSet = ((ControllableDevice) this.context.getService(reference))
.getDeviceDescriptor().getSimpleConfigurationParams().get(ModbusInfo.GATEWAY_PORT);
Set<String> gatewayProtocolSet = ((ControllableDevice) this.context.getService(reference))
.getDeviceDescriptor().getSimpleConfigurationParams().get(ModbusInfo.PROTO_ID);
String deviceId = ((ControllableDevice) this.context.getService(reference)).getDeviceId();
// if not null, it is a singleton
if (gatewayAddressSet != null)
{
// get the endpoint address of the connecting gateway
String gatewayAddress = gatewayAddressSet.iterator().next();
// get the gateway port if exists
String gatewayPort = "";
if ((gatewayPortSet != null) && (!gatewayPortSet.isEmpty()))
gatewayPort = gatewayPortSet.iterator().next();
// get the gateway protocol if exists
String gatewayProtocol = "";
if ((gatewayProtocolSet != null) && (!gatewayProtocolSet.isEmpty()))
gatewayProtocol = gatewayProtocolSet.iterator().next();
// check not null
if ((gatewayAddress != null) && (!gatewayAddress.isEmpty()))
{
if (!this.isGatewayAvailable(deviceId))
{
// create a new instance of the gateway driver
ModbusGatewayDriverInstance driver = new ModbusGatewayDriverInstance(this.network,
(ControllableDevice) this.context.getService(reference), gatewayAddress, gatewayPort,
gatewayProtocol, this.context);
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, "Modbus_ModbusGateway_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,
ModbusGatewayDriver.logId
+ "Unable to get the current gateway address (empty set), this prevents the device from being attached!");
throw new Exception(
ModbusGatewayDriver.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,
ModbusGatewayDriver.logId
+ "Unable to get the current gateway address (missing parameter), this prevents the device from being attached!");
throw new Exception(ModbusGatewayDriver.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 Modbus gateway device having the given id.
*
* @param gatewayId
* @return
*/
public ModbusGatewayDriverInstance getSpecificGateway(String gatewayId)
{
return this.connectedGateways.get(gatewayId);
}
/**
* @return the network
*/
public ModbusNetwork getNetwork()
{
return network;
}
}