private String getBinaryData(SensorVariable sensorVariable, AGGREGATION_TYPE aggrType) {
    Long fromTime = null;
    switch (aggrType) {
      case RAW:
        fromTime = System.currentTimeMillis() - TIME_REF.ONE_HOUR;
        break;
      case ONE_MINUTE:
        fromTime = System.currentTimeMillis() - TIME_REF.ONE_HOUR * 6;
        break;
      case FIVE_MINUTES:
        fromTime = System.currentTimeMillis() - TIME_REF.ONE_DAY;
        break;
      case ONE_HOUR:
        fromTime = System.currentTimeMillis() - TIME_REF.ONE_DAY * 30;
        break;
      default:
        break;
    }
    List<MetricsBinaryTypeDevice> metrics =
        MetricsAggregationBase.getMetricsBinaryData(sensorVariable, fromTime);

    StringBuilder builder = new StringBuilder();
    // Headers
    builder.append("Timestamp").append(",");
    builder.append("Time").append(",");
    builder.append("Status");

    // Update data
    for (MetricsBinaryTypeDevice metric : metrics) {
      builder.append("\n");
      builder.append(metric.getTimestamp());
      builder.append(",").append(timeFormat.format(new Date(metric.getTimestamp())));
      builder.append(",").append(metric.getState());
    }
    return builder.toString();
  }
  private ArrayList<MetricsChartDataGroupNVD3> getMetricsDataJsonNVD3(
      List<Integer> variableIds,
      Integer sensorId,
      Long timestampFrom,
      Long timestampTo,
      Boolean withMinMax,
      String chartType) {

    // if chartType not null, call this
    if (chartType != null) {
      return getMetricsDataJsonNVD3WithChartType(
          variableIds, timestampFrom, timestampTo, chartType);
    }

    // Get sensor variables
    List<SensorVariable> sensorVariables = null;
    if (!variableIds.isEmpty()) {
      sensorVariables = DaoUtils.getSensorVariableDao().getAll(variableIds);
    } else {
      sensorVariables = DaoUtils.getSensorVariableDao().getAllBySensorId(sensorId);
    }
    // Return if no data available
    if (sensorVariables == null) {
      return new ArrayList<MetricsChartDataGroupNVD3>();
    }

    MetricsGraphSettings metricsGraphSettings =
        ObjectFactory.getAppProperties().getMetricsGraphSettings();
    ArrayList<MetricsChartDataGroupNVD3> finalData = new ArrayList<MetricsChartDataGroupNVD3>();

    for (SensorVariable sensorVariable : sensorVariables) {
      MetricsGraph metrics =
          metricsGraphSettings.getMetric(sensorVariable.getVariableType().getText());
      switch (sensorVariable.getMetricType()) {
        case DOUBLE:
          ArrayList<MetricsChartDataNVD3> preDoubleData = new ArrayList<MetricsChartDataNVD3>();

          MetricsDoubleTypeDevice metricQueryDouble =
              MetricsDoubleTypeDevice.builder()
                  .timestampFrom(timestampFrom)
                  .timestampTo(timestampTo)
                  .sensorVariable(sensorVariable)
                  .build();
          List<MetricsDoubleTypeDevice> doubleMetrics =
              DaoUtils.getMetricsDoubleTypeDeviceDao().getAll(metricQueryDouble);
          ArrayList<Object> avgMetricDoubleValues = new ArrayList<Object>();
          ArrayList<Object> minMetricDoubleValues = new ArrayList<Object>();
          ArrayList<Object> maxMetricDoubleValues = new ArrayList<Object>();
          for (MetricsDoubleTypeDevice metric : doubleMetrics) {
            avgMetricDoubleValues.add(new Object[] {metric.getTimestamp(), metric.getAvg()});
            if (withMinMax) {
              minMetricDoubleValues.add(new Object[] {metric.getTimestamp(), metric.getMin()});
              maxMetricDoubleValues.add(new Object[] {metric.getTimestamp(), metric.getMax()});
            }
          }
          preDoubleData.add(
              MetricsChartDataNVD3.builder()
                  .key(ObjectFactory.getMcLocale().getString(MC_LOCALE.AVERAGE))
                  .values(avgMetricDoubleValues)
                  .color(metrics.getColor())
                  .type(metrics.getSubType())
                  .build()
                  .updateSubType(metrics.getType()));
          if (withMinMax) {
            preDoubleData.add(
                MetricsChartDataNVD3.builder()
                    .key(ObjectFactory.getMcLocale().getString(MC_LOCALE.MINUMUM))
                    .values(minMetricDoubleValues)
                    .color(COLOR_MINIMUM)
                    .type(metrics.getSubType())
                    .build()
                    .updateSubType(metrics.getType()));
            preDoubleData.add(
                MetricsChartDataNVD3.builder()
                    .key(ObjectFactory.getMcLocale().getString(MC_LOCALE.MAXIMUM))
                    .values(maxMetricDoubleValues)
                    .color(COLOR_MAXIMUM)
                    .type(metrics.getSubType())
                    .build()
                    .updateSubType(metrics.getType()));
          }
          finalData.add(
              MetricsChartDataGroupNVD3.builder()
                  .metricsChartDataNVD3(preDoubleData)
                  .id(sensorVariable.getId())
                  .unit(sensorVariable.getUnit())
                  .timeFormat(getTimeFormat(timestampFrom))
                  .variableType(
                      ObjectFactory.getMcLocale()
                          .getString(sensorVariable.getVariableType().name()))
                  .dataType(sensorVariable.getMetricType().getText())
                  .resourceName(
                      new ResourceModel(RESOURCE_TYPE.SENSOR_VARIABLE, sensorVariable)
                          .getResourceLessDetails())
                  .chartType(metrics.getType())
                  .chartInterpolate(metrics.getInterpolate())
                  .build());

          break;
        case BINARY:
          ArrayList<MetricsChartDataNVD3> preBinaryData = new ArrayList<MetricsChartDataNVD3>();
          MetricsBinaryTypeDevice metricQueryBinary =
              MetricsBinaryTypeDevice.builder()
                  .timestampFrom(timestampFrom)
                  .timestampTo(timestampTo)
                  .sensorVariable(sensorVariable)
                  .build();
          List<MetricsBinaryTypeDevice> binaryMetrics =
              DaoUtils.getMetricsBinaryTypeDeviceDao().getAll(metricQueryBinary);
          ArrayList<Object> metricBinaryValues = new ArrayList<Object>();
          for (MetricsBinaryTypeDevice metric : binaryMetrics) {
            metricBinaryValues.add(new Object[] {metric.getTimestamp(), metric.getState() ? 1 : 0});
          }
          preBinaryData.add(
              MetricsChartDataNVD3.builder()
                  .key(sensorVariable.getVariableType().getText())
                  .values(metricBinaryValues)
                  .color(metrics.getColor())
                  .type(metrics.getSubType())
                  .build()
                  .updateSubType(metrics.getType()));
          finalData.add(
              MetricsChartDataGroupNVD3.builder()
                  .metricsChartDataNVD3(preBinaryData)
                  .id(sensorVariable.getId())
                  .unit(sensorVariable.getUnit())
                  .timeFormat(getTimeFormat(timestampFrom))
                  .variableType(
                      ObjectFactory.getMcLocale()
                          .getString(sensorVariable.getVariableType().name()))
                  .dataType(sensorVariable.getMetricType().getText())
                  .resourceName(
                      new ResourceModel(RESOURCE_TYPE.SENSOR_VARIABLE, sensorVariable)
                          .getResourceLessDetails())
                  .chartType(metrics.getType())
                  .chartInterpolate(metrics.getInterpolate())
                  .build());
          break;
        default:
          // no need to do anything here
          break;
      }
    }

    return finalData;
  }
  private ArrayList<MetricsChartDataGroupNVD3> getMetricsDataJsonNVD3WithChartType(
      List<Integer> variableIds, Long timestampFrom, Long timestampTo, String chartType) {

    // Get sensor variables
    List<SensorVariable> sensorVariables = null;
    if (!variableIds.isEmpty()) {
      sensorVariables = DaoUtils.getSensorVariableDao().getAll(variableIds);
    }

    // Return if no data available
    if (sensorVariables == null) {
      return new ArrayList<MetricsChartDataGroupNVD3>();
    }

    MetricsGraphSettings metricsGraphSettings =
        ObjectFactory.getAppProperties().getMetricsGraphSettings();
    ArrayList<MetricsChartDataGroupNVD3> finalData = new ArrayList<MetricsChartDataGroupNVD3>();

    SensorVariable yaxis1Variable = null;
    boolean initialLoadDone = false;
    String chartTypeInternal = null;

    ArrayList<MetricsChartDataNVD3> metricDataValues = new ArrayList<MetricsChartDataNVD3>();

    String unit = null;
    String unit2 = null;
    String chartInterpolate = null;
    boolean isMultiChart = false;

    for (SensorVariable sensorVariable : sensorVariables) {
      MetricsGraph metrics =
          metricsGraphSettings.getMetric(sensorVariable.getVariableType().getText());
      // Load initial settings
      if (!initialLoadDone) {
        if (CHART_TYPE.MULTI_CHART == CHART_TYPE.fromString(chartType)) {
          isMultiChart = true;
          yaxis1Variable = sensorVariable;
          chartTypeInternal = chartType;
        } else if (CHART_TYPE.LINE_CHART == CHART_TYPE.fromString(chartType)) {
          chartTypeInternal = chartType;
          chartInterpolate = metrics.getInterpolate();
        }
        initialLoadDone = true;
      }

      Integer yAxis = null;
      if (yaxis1Variable != null) {
        if (yaxis1Variable.getVariableType() == sensorVariable.getVariableType()) {
          yAxis = 1;
          unit = sensorVariable.getUnit();
        } else {
          yAxis = 2;
          unit2 = sensorVariable.getUnit();
        }
      } else {
        unit = sensorVariable.getUnit();
      }

      if (chartTypeInternal == null) {
        chartTypeInternal = metrics.getType();
      }

      String seriesName = null;
      if (isMultiChart) {
        seriesName =
            sensorVariable.getSensor().getName() + "-" + sensorVariable.getVariableType().getText();
      } else {
        seriesName = sensorVariable.getSensor().getName();
      }
      switch (sensorVariable.getMetricType()) {
        case DOUBLE:
          MetricsDoubleTypeDevice metricQueryDouble =
              MetricsDoubleTypeDevice.builder()
                  .timestampFrom(timestampFrom)
                  .timestampTo(timestampTo)
                  .sensorVariable(sensorVariable)
                  .build();
          List<MetricsDoubleTypeDevice> doubleMetrics =
              DaoUtils.getMetricsDoubleTypeDeviceDao().getAll(metricQueryDouble);
          ArrayList<Object> avgMetricDoubleValues = new ArrayList<Object>();
          for (MetricsDoubleTypeDevice metric : doubleMetrics) {
            if (isMultiChart) {
              avgMetricDoubleValues.add(
                  MetricsChartDataXY.builder().x(metric.getTimestamp()).y(metric.getAvg()).build());
            } else {
              avgMetricDoubleValues.add(new Object[] {metric.getTimestamp(), metric.getAvg()});
            }
          }
          if (!doubleMetrics.isEmpty()) {
            metricDataValues.add(
                MetricsChartDataNVD3.builder()
                    .key(seriesName)
                    .values(avgMetricDoubleValues)
                    .type(metrics.getSubType())
                    // .interpolate(metrics.getInterpolate())
                    .yAxis(yAxis)
                    .build()
                    .updateSubType(chartTypeInternal));
          }

          break;
        case BINARY:
          MetricsBinaryTypeDevice metricQueryBinary =
              MetricsBinaryTypeDevice.builder()
                  .timestampFrom(timestampFrom)
                  .timestampTo(timestampTo)
                  .sensorVariable(sensorVariable)
                  .build();
          List<MetricsBinaryTypeDevice> binaryMetrics =
              DaoUtils.getMetricsBinaryTypeDeviceDao().getAll(metricQueryBinary);
          ArrayList<Object> metricBinaryValues = new ArrayList<Object>();
          for (MetricsBinaryTypeDevice metric : binaryMetrics) {
            if (isMultiChart) {
              metricBinaryValues.add(
                  MetricsChartDataXY.builder()
                      .x(metric.getTimestamp())
                      .y(metric.getState() ? 1 : 0)
                      .build());
            } else {
              metricBinaryValues.add(
                  new Object[] {metric.getTimestamp(), metric.getState() ? 1 : 0});
            }
          }
          if (!binaryMetrics.isEmpty()) {
            metricDataValues.add(
                MetricsChartDataNVD3.builder()
                    .key(seriesName)
                    .values(metricBinaryValues)
                    .type(metrics.getSubType())
                    // .interpolate(metrics.getInterpolate())
                    .yAxis(yAxis)
                    .id(sensorVariable.getId())
                    .resourceName(
                        new ResourceModel(RESOURCE_TYPE.SENSOR_VARIABLE, sensorVariable)
                            .getResourceLessDetails())
                    .build()
                    .updateSubType(chartTypeInternal));
          }

          break;
        default:
          // no need to do anything here
          break;
      }
    }

    finalData.add(
        MetricsChartDataGroupNVD3.builder()
            .metricsChartDataNVD3(metricDataValues)
            .unit(unit)
            .unit2(unit2)
            .timeFormat(getTimeFormat(timestampFrom))
            .chartType(chartType)
            .chartInterpolate(chartInterpolate)
            .build());

    return finalData;
  }