package cgl.iotcloud.core.sensorsite;
import cgl.iotcloud.core.*;
import cgl.iotcloud.core.sensorsite.events.SensorEvent;
import cgl.iotcloud.core.transport.Channel;
import cgl.iotcloud.core.transport.ChannelName;
import cgl.iotcloud.core.transport.Transport;
import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
public class SiteSensorDeployer {
private Logger LOG = LoggerFactory.getLogger(SiteSensorDeployer.class);
private SiteContext siteContext;
private Map conf;
private EventBus siteEventBus;
public SiteSensorDeployer(Map conf, SiteContext siteContext, EventBus eventBus) {
this.conf = conf;
this.siteContext = siteContext;
this.siteEventBus = eventBus;
}
@Subscribe
public void handlerSensorEvent(SensorEvent event) {
try {
if (event.getState() == SensorState.DEPLOY) {
SensorDeployDescriptor deployDescriptor = event.getDeployDescriptor();
deploySensor(deployDescriptor);
} else if (event.getState() == SensorState.ACTIVATE) {
SensorInstance descriptor = siteContext.getSensorDescriptor(event.getSensorId());
if (descriptor != null) {
ISensor sensor = descriptor.getSensor();
sensor.activate();
} else {
LOG.error("Trying to activate non-existing sensor: " + event.getSensorId());
}
} else if (event.getState() == SensorState.DEACTIVATE) {
SensorInstance descriptor = siteContext.getSensorDescriptor(event.getSensorId());
if (descriptor != null) {
ISensor sensor = descriptor.getSensor();
sensor.deactivate();
} else {
LOG.error("Trying to de-activate non-existing sensor: " + event.getSensorId());
}
} else if (event.getState() == SensorState.UN_DEPLOY) {
unDeploySensor(event);
}
} catch (Exception e) {
LOG.error("Exception occurred in the worker listening for consumer changes", e);
}
}
public void unDeploySensor(SensorEvent event) {
SensorInstance descriptor = siteContext.getSensor(event.getSensorId());
if (descriptor == null) {
LOG.error("Trying to un-deploy non existing sensor {}", event.getSensorId());
return;
}
LOG.info("Un-Deploying sensor {}", descriptor.getSensorContext().getName());
ISensor sensor = descriptor.getSensor();
sensor.close();
Map<String, List<Channel>> channels = descriptor.getSensorContext().getChannels();
for (Map.Entry<String, List<Channel>> entry : channels.entrySet()) {
Transport t = siteContext.getTransport(entry.getKey());
if (t != null) {
for (Channel c : entry.getValue()) {
// register with the transport
c.close();
t.unRegisterChannel(new ChannelName(descriptor.getSensorContext().getName(), c.getName()), c);
}
}
}
SensorEvent sensorEvent = new SensorEvent(event.getSensorId(), SensorState.UN_DEPLOY);
siteEventBus.post(sensorEvent);
}
public void deploySensor(SensorDeployDescriptor deployDescriptor) {
try {
LOG.info("Deploying sensor with jar: {} and class: {}", deployDescriptor.getJarName(), deployDescriptor.getClassName());
String url = "file://";
File file = new File(deployDescriptor.getJarName());
if (!file.isAbsolute()) {
String iotHome = Configuration.getIoTHome(conf);
String repo = Configuration.getSensorRepositoryPath(conf);
url += iotHome + "/" + repo + "/" + deployDescriptor.getJarName();
} else {
url += deployDescriptor.getJarName();
}
LOG.info("The sensor jar URL is {}", url);
ISensor sensor = Utils.loadSensor(new URL(url),
deployDescriptor.getClassName(), this.getClass().getClassLoader());
// generate a unique id for the sensor
final String sensorID = UUID.randomUUID().toString().replaceAll("-", "");
// get the sensor specific configurations
Configurator configurator = sensor.getConfigurator(conf);
Map<String, String> config = new HashMap<String, String>(deployDescriptor.getProperties());
SensorContext sensorContext = configurator.configure(siteContext, config);
// set the sensor id
sensorContext.setSensorID(sensorID);
// get the channels registered for this sensor
Map<String, List<Channel>> channels = sensorContext.getChannels();
for (Map.Entry<String, List<Channel>> entry : channels.entrySet()) {
Transport t = siteContext.getTransport(entry.getKey());
if (t != null) {
for (Channel c : entry.getValue()) {
// set the sensor id to channels
c.setSensorID(sensorID);
// register with the transport
t.registerChannel(new ChannelName(sensorContext.getName(), c.getName()), c);
c.open();
}
}
}
LOG.info("Deployed sensor with name: {} with: id {}", sensorContext.getName(), sensorContext.getSensorID());
// open the sensor
sensor.open(sensorContext);
LOG.info("Open sensor with name: {} with: id {}", sensorContext.getName(), sensorContext.getSensorID());
// add the sensor to the site
siteContext.addSensor(sensorContext, sensor);
// notify the master about the sensor
SensorEvent event = new SensorEvent(sensorContext.getSensorID(), SensorState.DEPLOY);
siteEventBus.post(event);
} catch (MalformedURLException e) {
String msg = "The jar name is not a correct url";
LOG.error(msg);
throw new RuntimeException(msg, e);
}
}
}