/* * Dog - Device Driver * * Copyright (c) 2012-2014 Dario Bonino and Luigi De Russis * * 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.echelon.ilon100.singletemperaturesensor; 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.DeviceStatus; import it.polito.elite.dog.core.library.model.devicecategory.SingleTemperatureSensor; import it.polito.elite.dog.core.library.model.notification.TemperatureMeasurementNotification; import it.polito.elite.dog.core.library.model.state.TemperatureState; import it.polito.elite.dog.core.library.model.statevalue.TemperatureStateValue; import it.polito.elite.dog.drivers.echelon.ilon100.network.EchelonIlon100DriverInstance; import it.polito.elite.dog.drivers.echelon.ilon100.network.info.CmdNotificationInfo; import it.polito.elite.dog.drivers.echelon.ilon100.network.info.DataPointInfo; import it.polito.elite.dog.drivers.echelon.ilon100.network.interfaces.EchelonIlon100Network; import java.lang.reflect.Method; import java.util.Set; import javax.measure.DecimalMeasure; import javax.measure.Measure; import javax.measure.unit.SI; import javax.measure.unit.UnitFormat; import org.osgi.framework.BundleContext; import org.osgi.service.log.LogService; /** * @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 EchelonIlon100SingleTemperatureSensorDriverInstance extends EchelonIlon100DriverInstance implements SingleTemperatureSensor { // the class logger private LogHelper logger; /** * The class constructor, initializes all the data structures needed for the * driver to successfully handle TemperatureSensor devices * * @param network * The network driver supporting communication towards the * real-world iLon100 gateway * @param device * The device managed by this meter driver * @param endpointAddress * The endpoint address of the real iLon 100 gateway handling * this device * @param context * The bundle context needed to instantiate the driver logger */ public EchelonIlon100SingleTemperatureSensorDriverInstance(EchelonIlon100Network network, ControllableDevice device, String endpointAddress, BundleContext context) { super(network, device, endpointAddress); // create a logger this.logger = new LogHelper(context); // TODO: get the initial state of the device....(states can be updated // by reading notification group addresses) this.initializeStates(); } @Override public Measure<?, ?> getTemperature() { // direct read on the network... // search the power notification... /* * for (DataPointInfo dp : this.datapoint2Notification.keySet()) { if * (this.datapoint2Notification.get(dp).contains( * TemperatureMeasurementNotification.notificationName)) { * this.network.readDP(dp); return dp.getValueWithUnitOfMeasure(); } } * return null; */ return (Measure<?, ?>) this.currentState.getState(TemperatureState.class.getSimpleName()) .getCurrentStateValue()[0].getValue(); } @Override public void notifyNewTemperatureValue(Measure<?, ?> temperatureValue) { // update the state TemperatureStateValue tValue = new TemperatureStateValue(); tValue.setValue(temperatureValue); this.currentState.setState(TemperatureState.class.getSimpleName(), new TemperatureState(tValue)); // forward the notification to the framework ((SingleTemperatureSensor) this.device).notifyNewTemperatureValue(temperatureValue); // log this.logger.log(LogService.LOG_DEBUG, EchelonIlon100SingleTemperatureSensorDriver.logId + "Dispatched new temperature notification value for " + this.device.getDeviceId() + ": " + temperatureValue.getValue() + ((temperatureValue.getUnit().equals(SI.CELSIUS)) ? " C" : "")); } @Override public DeviceStatus getState() { return this.currentState; } /* * (non-Javadoc) * * @see * it.polito.elite.dog.core.library.model.devicecategory.SingleTemperatureSensor * #updateStatus() */ @Override public void updateStatus() { ((SingleTemperatureSensor) this.device).updateStatus(); } @Override public void newMessageFromHouse(DataPointInfo dataPointInfo) { // check value if ((dataPointInfo.getValue() != Double.NaN) && (dataPointInfo.getValue() != Double.NEGATIVE_INFINITY) && (dataPointInfo.getValue() != Double.POSITIVE_INFINITY)) { // gets the corresponding notification set... Set<CmdNotificationInfo> notificationInfos = this.datapoint2Notification.get(dataPointInfo); // handle the notifications for (CmdNotificationInfo notificationInfo : notificationInfos) { // black magic here... String notificationName = notificationInfo.getName(); // black magic here... // get the hypothetical class method name String notifyMethod = "notify" + Character.toUpperCase(notificationName.charAt(0)) + notificationName.substring(1); // search the method and execute it try { // get the method Method notify = EchelonIlon100SingleTemperatureSensorDriverInstance.class.getDeclaredMethod( notifyMethod, Measure.class); // invoke the method notify.invoke(this, DecimalMeasure.valueOf(dataPointInfo.getValue() + " " + dataPointInfo.getUnitOfMeasure())); } catch (Exception e) { // log the error this.logger.log(LogService.LOG_WARNING, EchelonIlon100SingleTemperatureSensorDriver.logId + "Unable to find a suitable notification method for the datapoint: " + dataPointInfo + ":\n" + e); } // notify the monitor admin this.updateStatus(); } } } @Override protected void specificConfiguration() { // prepare the device state map this.currentState = new DeviceStatus(device.getDeviceId()); } private void initializeStates() { // Since this driver handles the device according to a well // defined interface, we can get the unit of measure from the only // notification handled by this device and fall back to Celsius degrees // if the procedure fails... // add unit of measure aliases (to fix notation problems...) UnitFormat uf = UnitFormat.getInstance(); uf.alias(SI.CELSIUS, "C"); uf.alias(SI.CELSIUS, "Celsius"); String temperatureUOM = SI.CELSIUS.toString(); // search the power notification... for (DataPointInfo dp : this.datapoint2Notification.keySet()) { if (this.datapoint2Notification.get(dp).contains(TemperatureMeasurementNotification.notificationName)) { temperatureUOM = dp.getUnitOfMeasure(); break; // stop the cycle as data has been found } } // create all the states TemperatureStateValue tValue = new TemperatureStateValue(); tValue.setValue(DecimalMeasure.valueOf("0 " + temperatureUOM)); this.currentState.setState(TemperatureState.class.getSimpleName(), new TemperatureState(tValue)); // read the current state (initial) for (DataPointInfo dp : this.datapoint2Notification.keySet()) { this.network.read(dp); } } @Override protected void addToNetworkDriver(DataPointInfo dp) { // add the datapoint to the network driver, no further operation needed this.network.addDriver(dp, this); } @Override public void notifyJoinedGroup(Integer groupNumber) { // intentionally left empty } @Override public void notifyLeftGroup(Integer groupNumber) { // intentionally left empty } @Override public void deleteGroup(Integer groupID) { // TODO Auto-generated method stub } @Override public void storeGroup(Integer groupID) { // TODO Auto-generated method stub } }