Как передать данные полученые с апи в график?

Рейтинг: 0Ответов: 0Опубликовано: 28.04.2023

Не получается распарсить json, чтобы создать модели SensorTable и передать их в график. Не могу разобраться, в чем проблема.

import 'package:dio/dio.dart';
import 'dart:convert';
import 'package:untitled35/view/Screens/SensorInfo.dart';
int? id;
class SensorData {
  List<SensorTable> sensorTable;

  SensorData({
    required this.sensorTable,
  });

  factory SensorData.fromJson(Map<String, dynamic> json) => SensorData(
    sensorTable: List<SensorTable>.from(
        json["sensorTable"].map((x) => SensorTable.fromJson(x))),
  );

  Map<String, dynamic> toJson() => {
    "sensorTable": List<dynamic>.from(sensorTable.map((x) => x.toJson())),
  };
}

class SensorTable {
  final availability;
  final avgTemp;
  final day;
  final hour;
  final maxTemp;
  final minTemp;

  SensorTable({
    required this.availability,
    required this.avgTemp,
    required this.day,
    required this.hour,
    required this.maxTemp,
    required this.minTemp,
  });
  DateTime get date {
    List<String> dateSegments = this.day.split('-');
    int year = int.parse(dateSegments[0]);
    int month = int.parse(dateSegments[1]);
    int day = int.parse(dateSegments[2]);
    int hours = int.parse(hour);
    return DateTime(year, month, day, hours);
  }
  factory SensorTable.fromJson(Map<String, dynamic> json) => SensorTable(
    availability: json["availability"],
    avgTemp: json["avgTemp"],
    day: json["day"],
    hour: json["hour"],
    maxTemp: json["maxTemp"],
    minTemp: json["minTemp"],
  );

  Map<String, dynamic> toJson() => {
    "availability": availability,
    "avgTemp": avgTemp,
    "day": day,
    "hour": hour,
    "maxTemp": maxTemp,
    "minTemp": minTemp,
  };
}

 Get() async {
  Dio dio = Dio();
  final response = await dio.get('http://1c.unduty.ru:3014/api/v1/sensorTable?token=c21bf03d52654a66&sensorId=${id.toString()}');
  String jsonStr = await response.data;

  Map<String, dynamic> json = jsonDecode(jsonStr);
  SensorData sensorData = SensorData.fromJson(json);
  list = sensorData.sensorTable;
}

А вот код графика

class SensorDataChart extends StatelessWidget {
  final List<SensorData> sensorData;

  const SensorDataChart({
    required this.sensorData,
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    if (sensorData.isEmpty) {
      return const Center(
        child: Text('Данные с сенсоров не получены'),
      );
    }
    return CustomPaint(
      painter: _SensorDataChartPainter(sensorData),
    );
  }
}

class _SensorDataChartPainter extends CustomPainter {
  static const _celsiusSymbol = '°C';
  static const _textPadding = 10;
  static const _dataPointCircleRadius = 4.0;
  static const _textStyleDeg = TextStyle(
    fontSize: 10,
    color: Colors.black,
  );
  static const _textStyleDate = TextStyle(
    fontSize: 10,
    color: Colors.black,
  );

  final List<SensorData> sensorData;

  _SensorDataChartPainter(this.sensorData);

  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint();
    paint.color = Colors.black.withOpacity(0.1);
    paint.strokeCap = StrokeCap.round;
    paint.strokeWidth = 1.0;
    paint.style = PaintingStyle.fill;

    /// Sort by date
    sensorData.sort((e1, e2) => e1.date.compareTo(e2.date));

    /// Find highest and lowest avgTemp
    final firstSensorData = sensorData.first;
    double highestAvgTemp = firstSensorData.avgTemp;
    double lowestAvgTemp = firstSensorData.avgTemp;
    for (final sensorData in sensorData) {
      if (highestAvgTemp < sensorData.avgTemp) {
        highestAvgTemp = sensorData.avgTemp;
      } else if (lowestAvgTemp > sensorData.avgTemp) {
        lowestAvgTemp = sensorData.avgTemp;
      }
    }

    /// Find temp delimiter height in chart
    int highestTempInChart = highestAvgTemp.ceil();
    int lowestTempInChart = lowestAvgTemp.floor();
    int degreesInChart = highestTempInChart - lowestTempInChart;
    double heightPerDegree = size.height / degreesInChart;

    /// Find day/hour width in chart
    final lastSensorData = sensorData.last;
    final hoursInChart = firstSensorData.date.difference(lastSensorData.date).inHours.abs();
    final daysInChart = (firstSensorData.date.difference(lastSensorData.date).inHours / 24).abs();
    final widthPerHour = size.width / hoursInChart;
    final widthPerDay = size.width / daysInChart;

    _drawTempDelimiters(
      canvas,
      paint,
      size,
      degreesInChart,
      heightPerDegree,
      lowestTempInChart,
    );

    _drawDayDelimiters(
      canvas,
      paint,
      size,
      firstSensorData,
      daysInChart,
      widthPerDay,
    );

    paint.color = Colors.black;
    _drawChart(
      canvas,
      size,
      paint,
      firstSensorData,
      lowestTempInChart,
      widthPerHour,
      heightPerDegree,
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;

  void _drawTempDelimiters(
    Canvas canvas,
    Paint paint,
    Size size,
    int degreesInChart,
    double heightPerDegree,
    int lowestTempInChart,
  ) {
    for (int nextDeg = 0; nextDeg <= degreesInChart; nextDeg++) {
      final nextDegY = size.height - nextDeg * heightPerDegree;

      TextSpan degreeText = TextSpan(
        style: _textStyleDeg,
        text: '${lowestTempInChart + nextDeg}$_celsiusSymbol',
      );
      TextPainter textPainter = TextPainter(
        text: degreeText,
        textAlign: TextAlign.left,
        textDirection: TextDirection.ltr,
      );
      textPainter.layout();
      textPainter.paint(
        canvas,
        Offset(
          -textPainter.width - _textPadding,
          nextDegY - textPainter.height * 0.5,
        ),
      );

      canvas.drawLine(
        Offset(0, nextDegY),
        Offset(size.width, nextDegY),
        paint,
      );
    }
  }

  void _drawDayDelimiters(
    Canvas canvas,
    Paint paint,
    Size size,
    SensorData firstSensorData,
    double daysInChart,
    double widthPerDay,
  ) {
    for (int nextDay = 0; nextDay <= daysInChart; nextDay++) {
      final nextDayX = nextDay * widthPerDay;
      final delimiterDate = firstSensorData.date.add(Duration(days: nextDay));

      TextSpan dateText = TextSpan(
        style: _textStyleDate,
        text: delimiterDate.toIso8601String().split('T')[0],
      );
      TextPainter textPainter = TextPainter(
        text: dateText,
        textAlign: TextAlign.center,
        textDirection: TextDirection.ltr,
      );
      textPainter.layout(maxWidth: widthPerDay);
      textPainter.paint(
        canvas,
        Offset(
          nextDayX - textPainter.width * 0.5,
          size.height + _textPadding,
        ),
      );

      canvas.drawLine(
        Offset(nextDayX, 0),
        Offset(nextDayX, size.height),
        paint,
      );
    }
  }

  void _drawChart(
    Canvas canvas,
    Size size,
    Paint paint,
    SensorData firstSensorData,
    int lowestTempInChart,
    double widthPerHour,
    double heightPerDegree,
  ) {
    for (int i = 0; i < sensorData.length - 1; i++) {
      SensorData sensorDataCurrent = sensorData[i];
      SensorData sensorDataNext = sensorData[i + 1];

      final chartXInHours = sensorDataCurrent.date.difference(firstSensorData.date).inHours.abs();
      final chartYInDegrees = sensorDataCurrent.avgTemp - lowestTempInChart;
      final chartXInHoursNext = sensorDataNext.date.difference(firstSensorData.date).inHours.abs();
      final chartYInDegreesNext = sensorDataNext.avgTemp - lowestTempInChart;

      final offsetCurrent = Offset(
        chartXInHours * widthPerHour,
        size.height - chartYInDegrees * heightPerDegree,
      );
      final offsetNext = Offset(
        chartXInHoursNext * widthPerHour,
        size.height - chartYInDegreesNext * heightPerDegree,
      );

      canvas.drawCircle(offsetCurrent, _dataPointCircleRadius, paint);
      canvas.drawCircle(offsetNext, _dataPointCircleRadius, paint);
      canvas.drawLine(offsetCurrent, offsetNext, paint);
    }
  }
}


@override
Widget build(BuildContext context) {
  return Center(
    child: SizedBox(
      width: 700,
      height: 400,
      child: SensorDataChart(
        sensorData: [
          SensorData(10, 29.7, "2022-04-12", "00", 45.6, 30.1),
          SensorData(10, 45.1, "2022-04-13", "00", 45.1, 30.1),
          SensorData(10, 33.3, "2022-04-16", "00", 45.1, 30.1),
          SensorData(10, 36.4, "2022-04-17", "23", 45.1, 30.1),
          SensorData(10, 32.1, "2022-04-22", "01", 45.1, 30.1),
        ],
      ),
    ),
  );
}

Ответы

Ответов пока нет.