blob: 6bfc7b3f43011e00fa6fde15f692ecf791fe7ed5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2016 Orange.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*******************************************************************************/
package org.eclipse.om2m.sdt.home.enocean;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import org.eclipse.om2m.sdt.Domain;
import org.eclipse.om2m.sdt.home.HomeDomain;
import org.eclipse.om2m.sdt.home.devices.GenericDevice;
import org.eclipse.om2m.sdt.home.driver.Logger;
import org.eclipse.om2m.sdt.home.driver.Utils;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.enocean.EnOceanDevice;
import org.osgi.service.enocean.EnOceanEvent;
import org.osgi.service.enocean.EnOceanMessage;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
import org.osgi.service.log.LogService;
import org.osgi.util.tracker.ServiceTracker;
@SuppressWarnings({ "unchecked", "rawtypes" })
public class Activator implements BundleActivator, EventHandler {
static private final String PROTOCOL = "EnOcean";
public interface EnOceanSDTDevice {
public void register();
public void unregister();
public void handleEvent(final EnOceanMessage event);
public Integer getChipId();
}
private Domain domain;
private Map<Integer, EnOceanSDTDevice> sdtDevices;
private boolean activated;
private BundleContext context;
private ServiceTracker enOceanDeviceTracker;
private ServiceRegistration reg;
static Logger logger;
public Activator() {
logger = new Logger(PROTOCOL);
logger.info("ctor");
this.domain = new HomeDomain("EnOcean Domain");
sdtDevices = new HashMap<Integer, EnOceanSDTDevice>();
}
@Override
public void start(BundleContext bc) throws Exception {
logger.info("Activation");
this.context = bc;
activated = true;
ServiceTracker log = new ServiceTracker(context, LogService.class.getName(), null) {
public Object addingService(ServiceReference ref) {
LogService logService = (LogService) context.getService(ref);
logger.setLogService(logService);
logger.info("LogService OK");
return logService;
}
public void removedService(ServiceReference ref, Object service) {
logger.unsetLogService();
}
};
log.open();
initDevicesTracker();
Dictionary<String, String[]> ht = new Hashtable<String, String[]>();
ht.put(org.osgi.service.event.EventConstants.EVENT_TOPIC,
new String[] { EnOceanEvent.TOPIC_MSG_RECEIVED, });
reg = context.registerService(EventHandler.class.getName(), this, ht);
activated = true;
logger.info("Activated " + domain.prettyPrint());
}
@Override
public void stop(BundleContext context) throws Exception {
logger.info("Deactivation " + sdtDevices);
for (EnOceanSDTDevice dev : sdtDevices.values()) {
dev.unregister();
}
sdtDevices.clear();
reg.unregister();
activated = false;
}
private void initDevicesTracker() {
enOceanDeviceTracker = new ServiceTracker(context, EnOceanDevice.class.getName(), null) {
public void removedService(ServiceReference ref, Object service) {
EnOceanDevice device = (EnOceanDevice) service;
logger.info("Removed EnOcean device " + device);
EnOceanSDTDevice dev = sdtDevices.remove(device.getChipId());
if (dev != null) {
dev.unregister();
}
}
public Object addingService(ServiceReference ref) {
if ((! activated) || Boolean.TRUE.equals(ref.getProperty("otb.proxied"))) {
return null;
}
EnOceanSDTDevice dev = createSDTDevice(ref);
if (dev != null) {
logger.info("created device: " + dev);
try {
Utils.setProperties(ref, (GenericDevice) dev);
((GenericDevice) dev).setProtocol(PROTOCOL);
} catch (Exception ignored) {
}
try {
dev.register();
} catch (Exception e) {
logger.error("Error registering device", e);
return null;
}
sdtDevices.put(dev.getChipId(), dev);
}
return dev;
}
};
enOceanDeviceTracker.open(true);
}
@Override
public void handleEvent(final Event event) {
logger.debug("Received EnOcean event: " + event);
int chipId = Integer.parseInt(event.getProperty(EnOceanDevice.CHIP_ID).toString());
logger.debug("EnOcean device: " + chipId);
EnOceanSDTDevice device = sdtDevices.get(chipId);
if (device == null) {
logger.debug("Event for a non-registered device!");
} else {
logger.info("process evt " + event + " on " + chipId + " for device " + device);
device.handleEvent((EnOceanMessage) event
.getProperty(EnOceanEvent.PROPERTY_MESSAGE));
}
}
private EnOceanSDTDevice createSDTDevice(ServiceReference<?> ref) {
logger.info("Added EnOcean ref " + ref);
for (String key : ref.getPropertyKeys()) {
Object prop = ref.getProperty(key);
if (prop instanceof String[]) {
logger.info("prop " + key + " -> " + Arrays.asList((String[]) prop));
} else {
logger.info("prop " + key + " -> " + prop);
}
}
EnOceanDevice device = (EnOceanDevice) this.context.getService(ref);
logger.info("Added EnOcean device " + device);
String serial = (String) ref.getProperty(Utils.DEVICE_SERIAL);
if (serial == null)
serial = "" + device.getChipId();
// eoDevices.put(device.getChipId(), device);
logger.info("process device " + device.getChipId() + " profile: "
+ String.format("0x%02X", device.getRorg()) + "/" + device.getRorg() + " : "
+ String.format("0x%02X", device.getFunc()) + "/" + device.getFunc() + " : "
+ String.format("0x%02X", device.getType()) + "/" + device.getType() + " "
+ device.getManufacturer());
switch (device.getRorg()) {
case 0xF6: // RPS Telegram
switch (device.getFunc()) {
case 0x02: // Rocker Switch, 2 Rocker
return createF602Detector(device, serial);
case 0x03: // Rocker Switch, 4 Rocker
break;
case 0x04: // Position Switch, Home & Office Application
break;
case 0x05: // Detectors
return createF605Detector(device, serial);
case 0x10: // Mechanical Handle
break;
case 0x63:
// ELTAKO smoke detector device
return createSmokeDetector(device, serial);
default:
if (ref.getProperty(Utils.DEVICE_FRIENDLY_NAME).equals("F6-02-01")) {
logger.info(Utils.DEVICE_FRIENDLY_NAME + " = F6-02-01. Try F602");
return createF602Detector(device, serial);
} else {
logger.info("Unprocessed RPS (F6): " + device.getFunc() + ". Try F605 (Detector)");
return createF602Detector(device, serial);
}
}
break;
case 0xD5: // 1BS Telegram
logger.info("Unprocessed 1BS (D5): " + device.getFunc());
break;
case 0xA5: // 4BS Telegram
switch (device.getFunc()) {
case 0x02: // Temperature Sensors
return createTemperatureSensor(device, domain, context);
case 0x04: // Temperature & Humidity Sensors
break;
case 0x05: // Barometric Sensors
break;
case 0x06: // Light Sensors
break;
case 0x07: // Occupancy Sensors
break;
case 0x08: // Light, Temperature & Occupancy Sensors
break;
case 0x09: // Gas Sensors
break;
case 0x10: // Room Operating Panel
break;
case 0x11: // Controller Status
break;
case 0x12: // Automated Meter Reading (AMR)
break;
case 0x13: // Environmental Applications
break;
case 0x14: // Multi-Func Sensors
break;
case 0x20: // HVAC Components
break;
case 0x30: // Digital Input
break;
case 0x37: // Energy Management
break;
case 0x38: // Central Commands
break;
case 0x3F: // Universal
break;
default:
logger.info("Unprocessed 4BS (A5): " + device.getFunc());
break;
}
case 0xD2: // VLD Telegram
switch (device.getFunc()) {
case 0x00: // Room Control Panel (RCP)
break;
case 0x01: // Electronic Switches & Dimmers with Energy Measurement & Local Control
break;
case 0x02: // Sensors for Temperature, Illumination, Occupancy & Smoke
break;
case 0x03: // Light, Switching + Blind Control
break;
case 0x04: // C02, Humidity, Temperature, Day/Night & Autonomy
break;
case 0x05: // Blinds Control for Position & Angle
break;
case 0x10: // Room COntrol Panels with Temperature & Fan Speed Control, Room Status Information
break;
case 0x20: // Fan Control
break;
case 0x30: // Floor Heating Controls & Automated Meter Reading
break;
case 0x31: // Automated Meter Reading Gateway
break;
case 0xA0: // Standard Valve
return createD2AOStandardValve(device, serial);
default:
logger.info("Unprocessed VLD (D2): " + device.getFunc());
break;
}
default:
break;
}
logger.warning("Not implemented!");
return null;
}
private EnOceanSDTDevice createD2AOStandardValve(EnOceanDevice device, String serial) {
if (device.getType() != 0x01) {
logger.error("Non valid EEP");
return null;
}
try {
return new EOWaterValve(device, domain, serial, context);
} catch (Exception e) {
logger.error("Error creating water valve", e);
return null;
}
}
private EnOceanSDTDevice createTemperatureSensor(EnOceanDevice device,
Domain domain, BundleContext context) {
return null;
}
private EnOceanSDTDevice createF605Detector(EnOceanDevice device, String serial) {
try {
return new EOFloodDetector(device, domain, context);
} catch (Exception e) {
logger.error("Error creating flood detector", e);
return null;
}
}
private EnOceanSDTDevice createSmokeDetector(EnOceanDevice device, String serial) {
try {
return new EOSmokeDetector(device, domain, context);
} catch (Exception e) {
logger.error("Error creating F6-02 detector", e);
return null;
}
}
private EnOceanSDTDevice createF602Detector(EnOceanDevice device, String serial) {
// if (device.getType() != 0x01) {
// HLog.error("Non valid EEP");
// return null;
// }
try {
return new EOLightBlindControl(device, domain, context);
} catch (Exception e) {
logger.error("Error creating F6-02 detector", e);
return null;
}
}
}