/* * This file is part of OpenMUC. * For more information visit http://www.openmuc.org * * You are free to use code of this sample file in any * way you like and without any restrictions. * */ package org.openmuc.framework.app.simpledemo; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Locale; import org.openmuc.framework.data.DoubleValue; import org.openmuc.framework.data.Flag; import org.openmuc.framework.data.Record; import org.openmuc.framework.data.StringValue; import org.openmuc.framework.data.Value; import org.openmuc.framework.dataaccess.Channel; import org.openmuc.framework.dataaccess.DataAccessService; import org.openmuc.framework.dataaccess.RecordListener; import org.osgi.service.component.ComponentContext; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Deactivate; import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component(service = {}) public final class SimpleDemoApp extends Thread { private static final Logger logger = LoggerFactory.getLogger(SimpleDemoApp.class); private static final DecimalFormatSymbols DFS = DecimalFormatSymbols.getInstance(Locale.US); private static final DecimalFormat DF = new DecimalFormat("#0.000", DFS); // ChannelIDs, see conf/channel.xml private static final String ID_POWER_ELECTIC_VEHICLE = "power_electic_vehicle"; private static final String ID_POWER_GRID = "power_grid"; private static final String ID_STATUS_ELECTRIC_VEHICLE = "status_electric_vehicle"; private static final String ID_ENERGY_EXPORTED = "enery_exported"; private static final String ID_ENERGY_IMPORTED = "enery_imported"; private static final double STANDBY_POWER_CHARGING_STATION = 0.020; // for conversion from power (kW) to energy (kWh) private static final double SECONDS_PER_HOUR = 3600.0; private static final double SECONDS_PER_INTERVAL = 5.0; private static final double HOUR_BASED_INTERVAL_TIME = SECONDS_PER_INTERVAL / SECONDS_PER_HOUR; private volatile boolean deactivatedSignal; // With the dataAccessService you can access to your measured and control data of your devices. private DataAccessService dataAccessService; // Channel for accessing data of a channel. private Channel chPowerElecticVehicle; private Channel chPowerGrid; private Channel chEvStatus; private Channel chEnergyExported; private Channel chEnergyImported; private double energyExportedKWh = 0; private double energyImportedKWh = 0; int printCounter; // for slowing down the output of the console /** * Every app needs one activate method. Is is called at begin. Here you can configure all you need at start of your * app. The Activate method can block the start of your OpenMUC, f.e. if you use Thread.sleep(). * * @param context */ @Activate protected void activate(ComponentContext context) { logger.info("Activating Demo App"); setName("OpenMUC Simple Demo App"); start(); } /** * Every app needs one deactivate method. It handles the shutdown of your app e.g. closing open streams. * * @param context */ @Deactivate protected void deactivate(ComponentContext context) { logger.info("Deactivating Demo App"); deactivatedSignal = true; interrupt(); try { this.join(); } catch (InterruptedException e) { } } /** * To set the DataAccessService dataAccessService for your app. */ @Reference protected void bindDataAccessService(DataAccessService dataAccessService) { this.dataAccessService = dataAccessService; } /** * To unset the DataAccessService dataAccessService for your app. */ protected void unbindDataAccessService(DataAccessService dataAccessService) { this.dataAccessService = null; } /** * application logic */ @Override public void run() { logger.info("Demo App started running..."); if (deactivatedSignal) { logger.info("DemoApp thread interrupted: will stop"); return; } initializeChannels(); applyListener(); while (!deactivatedSignal) { updateEvStatusChannel(); sleepMs(5000); } } /** * Initialize channel objects */ private void initializeChannels() { chPowerElecticVehicle = dataAccessService.getChannel(ID_POWER_ELECTIC_VEHICLE); chPowerGrid = dataAccessService.getChannel(ID_POWER_GRID); chEvStatus = dataAccessService.getChannel(ID_STATUS_ELECTRIC_VEHICLE); chEnergyExported = dataAccessService.getChannel(ID_ENERGY_EXPORTED); chEnergyImported = dataAccessService.getChannel(ID_ENERGY_IMPORTED); } /** * Apply a RecordListener to get notified if a new value is available for a channel */ private void applyListener() { chPowerGrid.addListener(new RecordListener() { @Override public void newRecord(Record record) { if (record.getValue() != null) { updateEnergyChannels(record); } } }); } /** * Calculate energy imported and exported from current grid power. (Demonstrates how to access the latest record of * a channel and how to set it.) * * @param gridPowerRecord */ private void updateEnergyChannels(Record gridPowerRecord) { double gridPower = gridPowerRecord.getValue().asDouble(); logger.info("home1: current grid power = " + gridPower + " kW"); double energyOfInterval = Math.abs(gridPower) * HOUR_BASED_INTERVAL_TIME; long now = System.currentTimeMillis(); if (gridPower >= 0) { energyImportedKWh += energyOfInterval; } else { energyExportedKWh += energyOfInterval; } DoubleValue exportDouble = new DoubleValue(Double.parseDouble(DF.format(energyExportedKWh))); Record exportRecord = new Record(exportDouble, now, Flag.VALID); chEnergyExported.setLatestRecord(exportRecord); DoubleValue importDouble = new DoubleValue(Double.parseDouble(DF.format(energyImportedKWh))); Record importRecord = new Record(importDouble, now, Flag.VALID); chEnergyImported.setLatestRecord(importRecord); } /** * Checks if the electric vehicle is charging (Demonstrates how to access a value from a channel and how to set a * value/record) */ private void updateEvStatusChannel() { double evPower; String status = "idle"; // get current value of the electric vehicle power channel Record lastRecord = chPowerElecticVehicle.getLatestRecord(); if (lastRecord != null) { Value value = lastRecord.getValue(); if (value != null) { evPower = chPowerElecticVehicle.getLatestRecord().getValue().asDouble(); if (evPower > STANDBY_POWER_CHARGING_STATION) { status = "charging"; } // set value for virtual channel Record newRecord = new Record(new StringValue(status), System.currentTimeMillis(), Flag.VALID); chEvStatus.setLatestRecord(newRecord); } } } private void sleepMs(long timeInMs) { try { Thread.sleep(timeInMs); } catch (InterruptedException e) { } } }