Search in sources :

Example 1 with None

use of org.knowm.xchart.style.markers.None in project openhab-core by openhab.

the class DefaultChartProvider method createChart.

@Override
public BufferedImage createChart(@Nullable String serviceId, @Nullable String theme, ZonedDateTime startTime, ZonedDateTime endTime, int height, int width, @Nullable String items, @Nullable String groups, @Nullable Integer dpiValue, @Nullable String yAxisDecimalPattern, @Nullable Boolean legend) throws ItemNotFoundException, IllegalArgumentException {
    logger.debug("Rendering chart: service: '{}', theme: '{}', startTime: '{}', endTime: '{}', width: '{}', height: '{}', items: '{}', groups: '{}', dpi: '{}', yAxisDecimalPattern: '{}', legend: '{}'", serviceId, theme, startTime, endTime, width, height, items, groups, dpiValue, yAxisDecimalPattern, legend);
    // If a persistence service is specified, find the provider, or use the default provider
    PersistenceService service = (serviceId == null) ? persistenceServiceRegistry.getDefault() : persistenceServiceRegistry.get(serviceId);
    // Did we find a service?
    QueryablePersistenceService persistenceService = (service instanceof QueryablePersistenceService) ? (QueryablePersistenceService) service : (QueryablePersistenceService) // 
    persistenceServiceRegistry.getAll().stream().filter(// 
    it -> it instanceof QueryablePersistenceService).findFirst().orElseThrow(() -> new IllegalArgumentException("No Persistence service found."));
    int seriesCounter = 0;
    // get theme
    ChartTheme chartTheme = theme == null ? CHART_THEME_DEFAULT : CHART_THEMES.getOrDefault(theme, CHART_THEME_DEFAULT);
    // get DPI
    int dpi = dpiValue != null && dpiValue > 0 ? dpiValue : DPI_DEFAULT;
    // Create Chart
    XYChart chart = new XYChartBuilder().width(width).height(height).build();
    // Define the time axis - the defaults are not very nice
    Duration period = Duration.between(startTime, endTime);
    String pattern;
    if (period.compareTo(TEN_MINUTES) <= 0) {
        pattern = "mm:ss";
    } else if (period.compareTo(ONE_DAY) <= 0) {
        pattern = "HH:mm";
    } else if (period.compareTo(ONE_WEEK) <= 0) {
        pattern = "EEE d";
    } else {
        pattern = "d MMM";
    }
    XYStyler styler = chart.getStyler();
    styler.setDatePattern(pattern);
    // axis
    styler.setAxisTickLabelsFont(chartTheme.getAxisTickLabelsFont(dpi));
    styler.setAxisTickLabelsColor(chartTheme.getAxisTickLabelsColor());
    styler.setXAxisMin((double) startTime.toInstant().toEpochMilli());
    styler.setXAxisMax((double) endTime.toInstant().toEpochMilli());
    int yAxisSpacing = Math.max(height / 10, chartTheme.getAxisTickLabelsFont(dpi).getSize());
    if (yAxisDecimalPattern != null) {
        styler.setYAxisDecimalPattern(yAxisDecimalPattern);
    }
    styler.setYAxisTickMarkSpacingHint(yAxisSpacing);
    styler.setYAxisLabelAlignment(Styler.TextAlignment.Right);
    // chart
    styler.setChartBackgroundColor(chartTheme.getChartBackgroundColor());
    styler.setChartFontColor(chartTheme.getChartFontColor());
    styler.setChartPadding(chartTheme.getChartPadding(dpi));
    styler.setPlotBackgroundColor(chartTheme.getPlotBackgroundColor());
    float plotGridLinesDash = (float) chartTheme.getPlotGridLinesDash(dpi);
    float[] plotGridLinesDashArray = { plotGridLinesDash, plotGridLinesDash };
    styler.setPlotGridLinesStroke(new BasicStroke((float) chartTheme.getPlotGridLinesWidth(dpi), BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 10, plotGridLinesDashArray, 0));
    styler.setPlotGridLinesColor(chartTheme.getPlotGridLinesColor());
    // legend
    styler.setLegendBackgroundColor(chartTheme.getLegendBackgroundColor());
    styler.setLegendFont(chartTheme.getLegendFont(dpi));
    styler.setLegendSeriesLineLength(chartTheme.getLegendSeriesLineLength(dpi));
    LegendPositionDecider legendPositionDecider = new LegendPositionDecider();
    // 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, legendPositionDecider)) {
                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, legendPositionDecider)) {
                        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<>();
        List<Number> yData = new ArrayList<>();
        xData.add(Date.from(startTime.toInstant()));
        yData.add(0);
        xData.add(Date.from(endTime.toInstant()));
        yData.add(0);
        XYSeries series = chart.addSeries("NONE", xData, yData);
        series.setMarker(new 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) {
        styler.setLegendPosition(legendPositionDecider.getLegendPosition());
    } else {
        // hide the whole legend
        styler.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, chart.getWidth(), chart.getHeight());
    return lBufferedImage;
}
Also used : BasicStroke(java.awt.BasicStroke) XYSeries(org.knowm.xchart.XYSeries) ArrayList(java.util.ArrayList) BufferedImage(java.awt.image.BufferedImage) QueryablePersistenceService(org.openhab.core.persistence.QueryablePersistenceService) HistoricItem(org.openhab.core.persistence.HistoricItem) GroupItem(org.openhab.core.items.GroupItem) Item(org.openhab.core.items.Item) GroupItem(org.openhab.core.items.GroupItem) Duration(java.time.Duration) XYStyler(org.knowm.xchart.style.XYStyler) Date(java.util.Date) Graphics2D(java.awt.Graphics2D) QueryablePersistenceService(org.openhab.core.persistence.QueryablePersistenceService) PersistenceService(org.openhab.core.persistence.PersistenceService) XYChart(org.knowm.xchart.XYChart) XYChartBuilder(org.knowm.xchart.XYChartBuilder) None(org.knowm.xchart.style.markers.None) ItemNotFoundException(org.openhab.core.items.ItemNotFoundException)

Example 2 with None

use of org.knowm.xchart.style.markers.None in project openhab-core by openhab.

the class DefaultChartProvider method addItem.

private boolean addItem(XYChart chart, QueryablePersistenceService service, ZonedDateTime timeBegin, ZonedDateTime timeEnd, Item item, int seriesCounter, ChartTheme chartTheme, int dpi, LegendPositionDecider legendPositionDecider) {
    Color color = chartTheme.getLineColor(seriesCounter);
    // Get the item label
    String label = itemUIRegistry.getLabel(item.getName());
    if (label == null) {
        label = item.getName();
    } else if (label.contains("[") && label.contains("]")) {
        label = label.substring(0, label.indexOf('['));
    }
    Iterable<HistoricItem> result;
    FilterCriteria filter;
    // Generate data collections
    List<Date> xData = new ArrayList<>();
    List<Number> yData = new ArrayList<>();
    // 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(timeBegin);
    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(Date.from(timeBegin.toInstant()));
        yData.add(convertData(state));
    }
    // Now, get all the data between the start and end time
    filter.setBeginDate(timeBegin);
    filter.setEndDate(timeEnd);
    filter.setPageSize(Integer.MAX_VALUE);
    filter.setOrdering(Ordering.ASCENDING);
    // Get the data from the persistence store
    result = service.query(filter);
    // Iterate through the data
    for (HistoricItem historicItem : result) {
        // to avoid diagonal lines
        if (state instanceof OnOffType || state instanceof OpenClosedType) {
            xData.add(Date.from(historicItem.getTimestamp().toInstant().minus(1, ChronoUnit.MILLIS)));
            yData.add(convertData(state));
        }
        state = historicItem.getState();
        xData.add(Date.from(historicItem.getTimestamp().toInstant()));
        yData.add(convertData(state));
    }
    // Lastly, add the final state at the endtime
    if (state != null) {
        xData.add(Date.from(timeEnd.toInstant()));
        yData.add(convertData(state));
    }
    // The chart engine will throw an exception if there's no data
    if (xData.isEmpty()) {
        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());
    }
    XYSeries 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(new None());
    series.setLineColor(color);
    legendPositionDecider.addData(series, yData);
    return true;
}
Also used : XYSeries(org.knowm.xchart.XYSeries) BasicStroke(java.awt.BasicStroke) Color(java.awt.Color) ArrayList(java.util.ArrayList) FilterCriteria(org.openhab.core.persistence.FilterCriteria) Date(java.util.Date) OnOffType(org.openhab.core.library.types.OnOffType) State(org.openhab.core.types.State) OpenClosedType(org.openhab.core.library.types.OpenClosedType) HistoricItem(org.openhab.core.persistence.HistoricItem) None(org.knowm.xchart.style.markers.None)

Aggregations

BasicStroke (java.awt.BasicStroke)2 ArrayList (java.util.ArrayList)2 Date (java.util.Date)2 XYSeries (org.knowm.xchart.XYSeries)2 None (org.knowm.xchart.style.markers.None)2 HistoricItem (org.openhab.core.persistence.HistoricItem)2 Color (java.awt.Color)1 Graphics2D (java.awt.Graphics2D)1 BufferedImage (java.awt.image.BufferedImage)1 Duration (java.time.Duration)1 XYChart (org.knowm.xchart.XYChart)1 XYChartBuilder (org.knowm.xchart.XYChartBuilder)1 XYStyler (org.knowm.xchart.style.XYStyler)1 GroupItem (org.openhab.core.items.GroupItem)1 Item (org.openhab.core.items.Item)1 ItemNotFoundException (org.openhab.core.items.ItemNotFoundException)1 OnOffType (org.openhab.core.library.types.OnOffType)1 OpenClosedType (org.openhab.core.library.types.OpenClosedType)1 FilterCriteria (org.openhab.core.persistence.FilterCriteria)1 PersistenceService (org.openhab.core.persistence.PersistenceService)1