Search in sources :

Example 1 with Series

use of org.knowm.xchart.Series in project smarthome by eclipse.

the class DefaultChartProvider method createChart.

@Override
public BufferedImage createChart(String service, String theme, Date startTime, Date endTime, int height, int width, String items, String groups, Integer dpiValue, Boolean legend) throws ItemNotFoundException, IllegalArgumentException {
    logger.debug("Rendering chart: service: '{}', theme: '{}', startTime: '{}', endTime: '{}', width: '{}', height: '{}', items: '{}', groups: '{}', dpi: '{}', legend: '{}'", service, theme, startTime, endTime, width, height, items, groups, dpiValue, legend);
    QueryablePersistenceService persistenceService;
    int seriesCounter = 0;
    // get theme
    ChartTheme chartTheme = getChartTheme(theme);
    // get DPI
    int dpi;
    if (dpiValue != null && dpiValue > 0) {
        dpi = dpiValue;
    } else {
        dpi = DPI_DEFAULT;
    }
    // Create Chart
    Chart chart = new ChartBuilder().width(width).height(height).build();
    // Define the time axis - the defaults are not very nice
    long period = (endTime.getTime() - startTime.getTime()) / 1000;
    String pattern = "HH:mm";
    if (period <= 600) {
        // 10 minutes
        pattern = "mm:ss";
    } else if (period <= 86400) {
        // 1 day
        pattern = "HH:mm";
    } else if (period <= 604800) {
        // 1 week
        pattern = "EEE d";
    } else {
        pattern = "d MMM";
    }
    chart.getStyleManager().setDatePattern(pattern);
    // axis
    chart.getStyleManager().setAxisTickLabelsFont(chartTheme.getAxisTickLabelsFont(dpi));
    chart.getStyleManager().setAxisTickLabelsColor(chartTheme.getAxisTickLabelsColor());
    chart.getStyleManager().setXAxisMin(startTime.getTime());
    chart.getStyleManager().setXAxisMax(endTime.getTime());
    int yAxisSpacing = Math.max(height / 10, chartTheme.getAxisTickLabelsFont(dpi).getSize());
    chart.getStyleManager().setYAxisTickMarkSpacingHint(yAxisSpacing);
    // chart
    chart.getStyleManager().setChartBackgroundColor(chartTheme.getChartBackgroundColor());
    chart.getStyleManager().setChartFontColor(chartTheme.getChartFontColor());
    chart.getStyleManager().setChartPadding(chartTheme.getChartPadding(dpi));
    chart.getStyleManager().setPlotBackgroundColor(chartTheme.getPlotBackgroundColor());
    float plotGridLinesDash = (float) chartTheme.getPlotGridLinesDash(dpi);
    float[] plotGridLinesDashArray = { plotGridLinesDash, plotGridLinesDash };
    chart.getStyleManager().setPlotGridLinesStroke(new BasicStroke((float) chartTheme.getPlotGridLinesWidth(dpi), 0, 2, 10, plotGridLinesDashArray, 0));
    chart.getStyleManager().setPlotGridLinesColor(chartTheme.getPlotGridLinesColor());
    // legend
    chart.getStyleManager().setLegendBackgroundColor(chartTheme.getLegendBackgroundColor());
    chart.getStyleManager().setLegendFont(chartTheme.getLegendFont(dpi));
    chart.getStyleManager().setLegendSeriesLineLength(chartTheme.getLegendSeriesLineLength(dpi));
    // If a persistence service is specified, find the provider
    persistenceService = null;
    if (service != null) {
        persistenceService = getPersistenceServices().get(service);
    } else {
        // Otherwise, just get the first service, if one exists
        Iterator<Entry<String, QueryablePersistenceService>> it = getPersistenceServices().entrySet().iterator();
        if (it.hasNext()) {
            persistenceService = it.next().getValue();
        } else {
            throw new IllegalArgumentException("No Persistence service found.");
        }
    }
    // Did we find a service?
    if (persistenceService == null) {
        throw new IllegalArgumentException("Persistence service not found '" + service + "'.");
    }
    // Loop through all the items
    if (items != null) {
        String[] itemNames = items.split(",");
        for (String itemName : itemNames) {
            Item item = itemUIRegistry.getItem(itemName);
            if (addItem(chart, persistenceService, startTime, endTime, item, seriesCounter, chartTheme, dpi)) {
                seriesCounter++;
            }
        }
    }
    // Loop through all the groups and add each item from each group
    if (groups != null) {
        String[] groupNames = groups.split(",");
        for (String groupName : groupNames) {
            Item item = itemUIRegistry.getItem(groupName);
            if (item instanceof GroupItem) {
                GroupItem groupItem = (GroupItem) item;
                for (Item member : groupItem.getMembers()) {
                    if (addItem(chart, persistenceService, startTime, endTime, member, seriesCounter, chartTheme, dpi)) {
                        seriesCounter++;
                    }
                }
            } else {
                throw new ItemNotFoundException("Item '" + item.getName() + "' defined in groups is not a group.");
            }
        }
    }
    Boolean showLegend = null;
    // If there are no series, render a blank chart
    if (seriesCounter == 0) {
        // always hide the legend
        showLegend = false;
        List<Date> xData = new ArrayList<Date>();
        List<Number> yData = new ArrayList<Number>();
        xData.add(startTime);
        yData.add(0);
        xData.add(endTime);
        yData.add(0);
        Series series = chart.addSeries("NONE", xData, yData);
        series.setMarker(SeriesMarker.NONE);
        series.setLineStyle(new BasicStroke(0f));
    }
    // if the legend is not already hidden, check if legend parameter is supplied, or calculate a sensible value
    if (showLegend == null) {
        if (legend == null) {
            // more than one series, show the legend. otherwise hide it.
            showLegend = seriesCounter > 1;
        } else {
            // take value from supplied legend parameter
            showLegend = legend;
        }
    }
    // This won't be perfect, but it's a good compromise
    if (showLegend) {
        if (legendPosition < 0) {
            chart.getStyleManager().setLegendPosition(LegendPosition.InsideNW);
        } else {
            chart.getStyleManager().setLegendPosition(LegendPosition.InsideSW);
        }
    } else {
        // hide the whole legend
        chart.getStyleManager().setLegendVisible(false);
    }
    // Write the chart as a PNG image
    BufferedImage lBufferedImage = new BufferedImage(chart.getWidth(), chart.getHeight(), BufferedImage.TYPE_INT_ARGB);
    Graphics2D lGraphics2D = lBufferedImage.createGraphics();
    chart.paint(lGraphics2D);
    return lBufferedImage;
}
Also used : BasicStroke(java.awt.BasicStroke) ChartBuilder(org.knowm.xchart.ChartBuilder) ArrayList(java.util.ArrayList) BufferedImage(java.awt.image.BufferedImage) QueryablePersistenceService(org.eclipse.smarthome.core.persistence.QueryablePersistenceService) GroupItem(org.eclipse.smarthome.core.items.GroupItem) HistoricItem(org.eclipse.smarthome.core.persistence.HistoricItem) Item(org.eclipse.smarthome.core.items.Item) Entry(java.util.Map.Entry) GroupItem(org.eclipse.smarthome.core.items.GroupItem) Chart(org.knowm.xchart.Chart) Date(java.util.Date) Graphics2D(java.awt.Graphics2D) Series(org.knowm.xchart.Series) ItemNotFoundException(org.eclipse.smarthome.core.items.ItemNotFoundException)

Example 2 with Series

use of org.knowm.xchart.Series in project smarthome by eclipse.

the class DefaultChartProvider method addItem.

boolean addItem(Chart chart, QueryablePersistenceService service, Date timeBegin, Date timeEnd, Item item, int seriesCounter, ChartTheme chartTheme, int dpi) {
    Color color = chartTheme.getLineColor(seriesCounter);
    // Get the item label
    String label = null;
    if (itemUIRegistry != null) {
        // Get the item label
        label = itemUIRegistry.getLabel(item.getName());
        if (label != null && label.contains("[") && label.contains("]")) {
            label = label.substring(0, label.indexOf('['));
        }
    }
    if (label == null) {
        label = item.getName();
    }
    Iterable<HistoricItem> result;
    FilterCriteria filter;
    // Generate data collections
    List<Date> xData = new ArrayList<Date>();
    List<Number> yData = new ArrayList<Number>();
    // Declare state here so it will hold the last value at the end of the process
    State state = null;
    // First, get the value at the start time.
    // This is necessary for values that don't change often otherwise data will start
    // after the start of the graph (or not at all if there's no change during the graph period)
    filter = new FilterCriteria();
    filter.setEndDate(ZonedDateTime.ofInstant(timeBegin.toInstant(), timeZoneProvider.getTimeZone()));
    filter.setItemName(item.getName());
    filter.setPageSize(1);
    filter.setOrdering(Ordering.DESCENDING);
    result = service.query(filter);
    if (result.iterator().hasNext()) {
        HistoricItem historicItem = result.iterator().next();
        state = historicItem.getState();
        xData.add(timeBegin);
        yData.add(convertData(state));
    }
    // Now, get all the data between the start and end time
    filter.setBeginDate(ZonedDateTime.ofInstant(timeBegin.toInstant(), timeZoneProvider.getTimeZone()));
    filter.setEndDate(ZonedDateTime.ofInstant(timeEnd.toInstant(), timeZoneProvider.getTimeZone()));
    filter.setPageSize(Integer.MAX_VALUE);
    filter.setOrdering(Ordering.ASCENDING);
    // Get the data from the persistence store
    result = service.query(filter);
    Iterator<HistoricItem> it = result.iterator();
    // Iterate through the data
    while (it.hasNext()) {
        HistoricItem historicItem = it.next();
        // to avoid diagonal lines
        if (state instanceof OnOffType || state instanceof OpenClosedType) {
            Calendar cal = Calendar.getInstance();
            cal.setTime(historicItem.getTimestamp());
            cal.add(Calendar.MILLISECOND, -1);
            xData.add(cal.getTime());
            yData.add(convertData(state));
        }
        state = historicItem.getState();
        xData.add(historicItem.getTimestamp());
        yData.add(convertData(state));
    }
    // Lastly, add the final state at the endtime
    if (state != null) {
        xData.add(timeEnd);
        yData.add(convertData(state));
    }
    // The chart engine will throw an exception if there's no data
    if (xData.size() == 0) {
        return false;
    }
    // If there's only 1 data point, plot it again!
    if (xData.size() == 1) {
        xData.add(xData.iterator().next());
        yData.add(yData.iterator().next());
    }
    Series series = chart.addSeries(label, xData, yData);
    float lineWidth = (float) chartTheme.getLineWidth(dpi);
    series.setLineStyle(new BasicStroke(lineWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_MITER));
    series.setMarker(SeriesMarker.NONE);
    series.setLineColor(color);
    // We use this to decide whether to put the legend in the top or bottom corner.
    if (yData.iterator().next().floatValue() > ((series.getYMax() - series.getYMin()) / 2 + series.getYMin())) {
        legendPosition++;
    } else {
        legendPosition--;
    }
    return true;
}
Also used : BasicStroke(java.awt.BasicStroke) Color(java.awt.Color) Calendar(java.util.Calendar) ArrayList(java.util.ArrayList) FilterCriteria(org.eclipse.smarthome.core.persistence.FilterCriteria) Date(java.util.Date) Series(org.knowm.xchart.Series) OnOffType(org.eclipse.smarthome.core.library.types.OnOffType) State(org.eclipse.smarthome.core.types.State) OpenClosedType(org.eclipse.smarthome.core.library.types.OpenClosedType) HistoricItem(org.eclipse.smarthome.core.persistence.HistoricItem)

Aggregations

BasicStroke (java.awt.BasicStroke)2 ArrayList (java.util.ArrayList)2 Date (java.util.Date)2 HistoricItem (org.eclipse.smarthome.core.persistence.HistoricItem)2 Series (org.knowm.xchart.Series)2 Color (java.awt.Color)1 Graphics2D (java.awt.Graphics2D)1 BufferedImage (java.awt.image.BufferedImage)1 Calendar (java.util.Calendar)1 Entry (java.util.Map.Entry)1 GroupItem (org.eclipse.smarthome.core.items.GroupItem)1 Item (org.eclipse.smarthome.core.items.Item)1 ItemNotFoundException (org.eclipse.smarthome.core.items.ItemNotFoundException)1 OnOffType (org.eclipse.smarthome.core.library.types.OnOffType)1 OpenClosedType (org.eclipse.smarthome.core.library.types.OpenClosedType)1 FilterCriteria (org.eclipse.smarthome.core.persistence.FilterCriteria)1 QueryablePersistenceService (org.eclipse.smarthome.core.persistence.QueryablePersistenceService)1 State (org.eclipse.smarthome.core.types.State)1 Chart (org.knowm.xchart.Chart)1 ChartBuilder (org.knowm.xchart.ChartBuilder)1