Skip to content

feat: Add support for CCS811 sensor#3032

Open
soumyajitnandi0 wants to merge 10 commits intofossasia:flutterfrom
soumyajitnandi0:flutter
Open

feat: Add support for CCS811 sensor#3032
soumyajitnandi0 wants to merge 10 commits intofossasia:flutterfrom
soumyajitnandi0:flutter

Conversation

@soumyajitnandi0
Copy link

@soumyajitnandi0 soumyajitnandi0 commented Jan 25, 2026

Fixes #2990

Changes

  • Implemented CCS811 Air Quality Sensor support:
    • Driver: Added lib/communication/sensors/ccs811.dart implementing I2C communication (init, mode setting, data reading).
    • Providers: Added CCS811Provider for data handling and CCS811ConfigProvider for settings.
    • UI: Created lib/view/ccs811_screen.dart displaying real-time eCO2 (ppm) and TVOC (ppb) values with live charts.
  • Added support for recording sensor data to CSV with optional geolocation.
  • Updated SensorsScreen to include the CCS811 sensor in the list.
  • Addressed I2C concurrency issues by implementing a read guard in the provider.

Checklist:

  • No hard coding: I have used values from constants.dart or localization files instead of hard-coded values (where applicable).
  • No end of file edits: No modifications done at end of resource files.
  • Code reformatted: I have formatted the code using dart format.
  • Code analysis: My code passes checks run in flutter analyze and tests run in flutter test.

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Jan 25, 2026

Reviewer's Guide

Implements CCS811 air quality sensor support by adding a sensor driver, provider layer, configuration model, and a new UI screen with live charts and CSV recording, and wiring it into the existing sensors navigation.

Sequence diagram for CCS811 sensor initialization and periodic data collection

sequenceDiagram
  actor User
  participant SensorsScreen
  participant Navigator
  participant CCS811Screen
  participant _CCS811ScreenState
  participant MultiProvider
  participant CCS811ConfigProvider
  participant CCS811Provider
  participant ScienceLab
  participant I2C
  participant CCS811

  User->>SensorsScreen: tap CCS811 sensor item
  SensorsScreen->>Navigator: push CCS811Screen
  Navigator->>CCS811Screen: create
  CCS811Screen->>_CCS811ScreenState: createState
  _CCS811ScreenState->>_CCS811ScreenState: initState
  _CCS811ScreenState->>_CCS811ScreenState: _initializeScienceLab()
  _CCS811ScreenState->>ScienceLab: getIt.get
  ScienceLab-->>_CCS811ScreenState: ScienceLab instance
  _CCS811ScreenState->>I2C: create with mPacketHandler
  I2C-->>_CCS811ScreenState: I2C instance

  _CCS811ScreenState->>MultiProvider: build
  MultiProvider->>CCS811ConfigProvider: create
  MultiProvider->>CCS811Provider: create(configProvider)

  CCS811Provider->>CCS811ConfigProvider: addListener(_onConfigChanged)

  _CCS811ScreenState->>CCS811Provider: initializeSensors(onError, i2c, scienceLab)
  CCS811Provider->>ScienceLab: isConnected()
  ScienceLab-->>CCS811Provider: true
  CCS811Provider->>CCS811: create(i2c, scienceLab)
  activate CCS811
  CCS811->>ScienceLab: isConnected()
  ScienceLab-->>CCS811: true
  CCS811->>CCS811: _initialize(scienceLab)
  CCS811->>CCS811: _readRegisterByte(hwId)
  CCS811-->>CCS811Provider: CCS811 instance
  deactivate CCS811
  CCS811Provider->>CCS811Provider: _startDataCollection()
  CCS811Provider-->>_CCS811ScreenState: sensorAvailable = true

  loop every updatePeriod ms
    CCS811Provider->>CCS811: getRawData()
    CCS811->>CCS811: _readRegisterByte(status)
    CCS811->>CCS811: readBulk(algResultData)
    CCS811-->>CCS811Provider: {eCO2, TVOC}
    CCS811Provider->>CCS811Provider: _updateCharts()
    CCS811Provider->>CCS811Provider: _recordDataIfEnabled()
    CCS811Provider-->>CCS811Screen: notifyListeners
  end
Loading

Updated class diagram for CCS811 sensor support

classDiagram
  class CCS811Screen {
    +CCS811Screen()
  }

  class _CCS811ScreenState {
    +AppLocalizations appLocalizations
    -CsvService _csvService
    -CCS811Provider _provider
    -I2C _i2c
    -ScienceLab _scienceLab
    -CCS811ConfigProvider _configProvider
    +initState()
    -_initializeScienceLab()
    -_showSensorErrorSnackbar(message String)
    -_navigateToLoggedData() Future~void~
    -_toggleRecording() Future~void~
    -_showSaveFileDialog(data List~List~dynamic~~) Future~void~
    +build(context BuildContext) Widget
    -_buildValueCard(title String, value String, unit String) Widget
    -_buildChart(spots List~FlSpot~, title String, color Color) Widget
  }

  class CCS811Provider {
    +AppLocalizations appLocalizations
    -CCS811ConfigProvider _configProvider
    -int _currentECO2
    -int _currentTVOC
    -List~double~ _eCO2Data
    -List~double~ _tvocData
    -List~double~ _timeData
    -List~FlSpot~ eCO2ChartData
    -List~FlSpot~ tvocChartData
    -Timer _dataTimer
    -StreamSubscription _locationStream
    -Position currentPosition
    -double _startTime
    -double _currentTime
    -int _chartMaxLength
    -int _eCO2Min
    -int _eCO2Max
    -int _tvocMin
    -int _tvocMax
    -bool _sensorAvailable
    -bool _isRecording
    -List~List~dynamic~~ _recordedData
    -CCS811 _ccs811
    -I2C _i2c
    -ScienceLab _scienceLab
    -Function(String) onSensorError
    +CCS811Provider(configProvider CCS811ConfigProvider)
    +initializeSensors(onError Function(String), i2c I2C, scienceLab ScienceLab) Future~void~
    +sensorAvailable bool
    +isRecording bool
    +startRecording() Future~void~
    +stopRecording() void
    +getRecordedData() List~List~dynamic~~
    +disposeSensors() void
    +currentECO2 int
    +currentTVOC int
    +getECO2ChartData() List~FlSpot~
    +getTVOCChartData() List~FlSpot~
    +getMinTime() double
    +getMaxTime() double
    +getTimeInterval() double
    +dispose() void
    -_onConfigChanged() void
    -_reinitializeSensors() void
    -_startDataCollection() void
    -_readData() Future~void~
    -_updateCharts() void
    -_recordDataIfEnabled() void
    -_startGeoLocationUpdates() Future~void~
  }

  class CCS811ConfigProvider {
    -CCS811Config _config
    +CCS811ConfigProvider()
    +config CCS811Config
    +updateConfig(newConfig CCS811Config) void
    +updateUpdatePeriod(updatePeriod int) void
    +updateIncludeLocationData(includeLocationData bool) void
    +resetToDefaults() void
    -_loadConfigFromPrefs() Future~void~
    -_saveConfigToPrefs() Future~void~
  }

  class CCS811Config {
    +int updatePeriod
    +bool includeLocationData
    +CCS811Config(updatePeriod int, includeLocationData bool)
    +copyWith(updatePeriod int, includeLocationData bool) CCS811Config
    +fromJson(json Map~String,dynamic~) CCS811Config
    +toJson() Map~String,dynamic~
  }

  class CCS811 {
    +static String tag
    +static int address
    +static int status
    +static int measMode
    +static int algResultData
    +static int rawData
    +static int envData
    +static int ntc
    +static int thresholds
    +static int baseline
    +static int hwId
    +static int hwVersion
    +static int fwBootVersion
    +static int fwAppVersion
    +static int errorId
    +static int appStart
    +static int swReset
    +static int modeIdle
    +static int mode1s
    +static int mode10s
    +static int mode60s
    +static int mode250ms
    +static String name
    +I2C i2c
    -int _eCO2
    -int _tVOC
    +CCS811._(i2c I2C)
    +create(i2c I2C, scienceLab ScienceLab) Future~CCS811~
    +setMode(mode int) Future~void~
    +getRawData() Future~Map~String,int~~
    -_initialize(scienceLab ScienceLab) Future~void~
    -_readRegisterByte(register int) Future~int~
  }

  class ChangeNotifier
  class Equatable
  class I2C
  class ScienceLab
  class FlSpot
  class Position

  CCS811Screen --> _CCS811ScreenState : creates
  _CCS811ScreenState ..> CCS811Provider : uses
  _CCS811ScreenState ..> CCS811ConfigProvider : uses
  _CCS811ScreenState ..> CsvService : uses
  _CCS811ScreenState ..> LoggedDataScreen : navigates

  CCS811Provider --|> ChangeNotifier
  CCS811ConfigProvider --|> ChangeNotifier
  CCS811Config --|> Equatable

  CCS811Provider o--> CCS811ConfigProvider : holds_reference
  CCS811Provider o--> CCS811 : uses_sensor
  CCS811Provider o--> I2C
  CCS811Provider o--> ScienceLab
  CCS811Provider ..> FlSpot
  CCS811Provider ..> Position

  CCS811ConfigProvider o--> CCS811Config
  CCS811 o--> I2C
  CCS811 ..> ScienceLab
Loading

File-Level Changes

Change Details Files
Wire CCS811 sensor screen into existing sensors navigation flow.
  • Import the CCS811 screen into the sensors screen module
  • Extend the sensor selection switch to route CCS811 identifiers to the new screen
  • Fall back to existing snackbar error handling for unknown sensors
lib/view/sensors_screen.dart
Add a CCS811 air quality measurement screen with live readings, charts, and CSV recording/export.
  • Create a stateful CCS811Screen that initializes I2C/ScienceLab and shows error snackbars on failures
  • Wrap the screen in providers for CCS811 configuration and runtime sensor data using ChangeNotifierProvider and ChangeNotifierProxyProvider
  • Render current eCO2/TVOC values in cards and historical data using fl_chart line charts
  • Support starting/stopping recordings from CommonScaffold, persisting CSV via CsvService, and navigating to LoggedDataScreen for past runs
lib/view/ccs811_screen.dart
Introduce a CCS811Provider to manage sensor lifecycle, polling, chart data, and optional geolocation-aware recording.
  • Initialize CCS811 via the new sensor driver using injected I2C and ScienceLab instances, with error propagation through a callback
  • Poll the sensor at a configurable interval, maintain sliding-window time series for eCO2 and TVOC, and expose FlSpot lists for charting
  • Track min/max values internally (currently not surfaced) and manage sensor availability state
  • Implement CSV recording with timestamped rows and optional latitude/longitude, and hook into Geolocator for live location updates
  • React to configuration changes from CCS811ConfigProvider by reinitializing sensors and cleaning up timers/streams in dispose
lib/providers/ccs811_provider.dart
Implement a CCS811 sensor driver over I2C for the ScienceLab platform.
  • Define CCS811 I2C address, register, and mode constants, plus a static name for the device
  • Add a factory constructor that validates ScienceLab connection, checks HW_ID, starts the CCS811 application, and configures a measurement mode
  • Provide helpers to set measurement mode, read single registers, and fetch algorithm result data when new data is available
  • Parse raw I2C bytes into eCO2 and TVOC integer readings with basic error logging and exception propagation
lib/communication/sensors/ccs811.dart
Add persistent configuration model and provider for CCS811 sampling and location options.
  • Define an Equatable CCS811Config model with updatePeriod and includeLocationData fields plus copyWith/toJson/fromJson helpers
  • Create CCS811ConfigProvider that loads/saves configuration with SharedPreferences under the 'ccs811_config' key
  • Expose convenience methods to update individual fields or reset to defaults while notifying listeners
lib/providers/ccs811_config_provider.dart
lib/models/ccs811_config.dart

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • There’s a potential race between _initializeScienceLab() (async) and the CCS811Provider.initializeSensors call in the post-frame callback – if _i2c/_scienceLab aren’t ready yet you’ll hit the 'ScienceLab not connected' path; consider awaiting initialization before wiring up the provider or deferring initializeSensors until the lab is confirmed connected.
  • Several user-facing strings are hard-coded in the new code (e.g. snack bar messages, 'ScienceLab not connected', 'Failed to initialize CCS811...', 'CCS811 Air Quality'); these should be sourced from AppLocalizations or existing constants to follow the project’s no hard-coding/localization pattern.
  • There are a few unused or effectively dead elements (e.g. AppLocalizations appLocalizations in CCS811 and _navigateToLoggedData in CCS811Screen) that can be removed or wired up to avoid carrying unused code.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- There’s a potential race between `_initializeScienceLab()` (async) and the `CCS811Provider.initializeSensors` call in the post-frame callback – if `_i2c`/`_scienceLab` aren’t ready yet you’ll hit the 'ScienceLab not connected' path; consider awaiting initialization before wiring up the provider or deferring `initializeSensors` until the lab is confirmed connected.
- Several user-facing strings are hard-coded in the new code (e.g. snack bar messages, 'ScienceLab not connected', 'Failed to initialize CCS811...', 'CCS811 Air Quality'); these should be sourced from `AppLocalizations` or existing constants to follow the project’s no hard-coding/localization pattern.
- There are a few unused or effectively dead elements (e.g. `AppLocalizations appLocalizations` in `CCS811` and `_navigateToLoggedData` in `CCS811Screen`) that can be removed or wired up to avoid carrying unused code.

## Individual Comments

### Comment 1
<location> `lib/providers/ccs811_provider.dart:96-97` </location>
<code_context>
+  void _startDataCollection() {
+    int interval = _configProvider.config.updatePeriod;
+    _dataTimer?.cancel();
+    _dataTimer = Timer.periodic(Duration(milliseconds: interval), (timer) async {
+       await _readData();
+    });
+  }
</code_context>

<issue_to_address>
**issue (bug_risk):** Avoid using an async callback directly in Timer.periodic to prevent overlapping sensor reads.

Because `Timer.periodic` doesn’t wait for the `async` callback, slow I2C operations or a short `updatePeriod` can cause `_readData` calls to overlap, leading to concurrent access to `_ccs811` and the internal data arrays. Guard `_readData` with a `_isReading` flag, or refactor so each read schedules the next timer only after it completes.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@soumyajitnandi0 soumyajitnandi0 changed the title Fixes #2990 Add support for CCS811 sensor feat: Fixes #2990 Add support for CCS811 sensor Jan 25, 2026
@soumyajitnandi0 soumyajitnandi0 force-pushed the flutter branch 4 times, most recently from 28ca6df to c3b803b Compare January 25, 2026 21:21
@github-actions
Copy link
Contributor

github-actions bot commented Jan 25, 2026

Build Status

Build successful. APKs to test: https://github.com/fossasia/pslab-app/actions/runs/22302288793/artifacts/5615170216.

Screenshots

Android Screenshots
iPhone Screenshots
iPad Screenshots

@soumyajitnandi0
Copy link
Author

@marcnause
Hi! I’ve implemented support for the CCS811 sensor and all CI checks are passing.
Could you please review this PR when you get a chance?

@marcnause marcnause changed the title feat: Fixes #2990 Add support for CCS811 sensor feat: Add support for CCS811 sensor Jan 29, 2026
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds CCS811 air quality sensor support to the PSLab Flutter app, including the I2C driver, provider/state handling, and a dedicated UI screen with charting and CSV recording (optionally with geolocation).

Changes:

  • Added CCS811 I2C driver and a config model/provider for sampling & recording options.
  • Implemented CCS811 data provider with periodic reads, chart series generation, and CSV logging (with optional location).
  • Added a CCS811 UI screen and wired it into the sensor selection flow.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
pubspec.yaml Adds equatable (and includes existing geolocator/wakelock deps) to support new config model.
pubspec.lock Updates resolved package set and SDK constraints after dependency changes.
macos/Flutter/GeneratedPluginRegistrant.swift Registers additional plugins (geolocator, wakelock) for macOS.
lib/view/sensors_screen.dart Adds CCS811 to the sensor list and routes to the new screen.
lib/view/ccs811_screen.dart New CCS811 UI showing live values, charts, and CSV recording controls.
lib/providers/ccs811_provider.dart New provider for CCS811 polling, chart data, recording, and geolocation stream hookup.
lib/providers/ccs811_config_provider.dart Persists CCS811 settings via SharedPreferences.
lib/models/ccs811_config.dart New equatable config model (update period + include location).
lib/communication/sensors/ccs811.dart New CCS811 I2C driver (init/app start, mode, data reads).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

targetScreen = const VL53L0XScreen();
break;
case 'CCS811':
targetScreen = const CCS811Screen();
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing break after the CCS811 case causes fall-through into the SHT21 case, so tapping CCS811 will navigate to the SHT21 screen instead. Add a break (or return) after setting targetScreen for CCS811.

Suggested change
targetScreen = const CCS811Screen();
targetScreen = const CCS811Screen();
break;

Copilot uses AI. Check for mistakes.
Comment on lines 21 to +23
environment:
sdk: ^3.5.4
flutter: '3.38.7'
flutter: "3.38.7"
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pubspec.lock resolves with dart: ">=3.9.0 <4.0.0", but pubspec.yaml still allows sdk: ^3.5.4. This mismatch can cause dependency resolution/build failures for anyone on Dart 3.5.x. Update the environment.sdk constraint to the actual minimum Dart required by the resolved dependencies (likely aligned with Flutter 3.38.7’s bundled Dart).

Copilot uses AI. Check for mistakes.
Comment on lines +45 to +55

bool get sensorAvailable => _sensorAvailable;
bool get isRecording => _isRecording;

CCS811Provider(this._configProvider) {
_configProvider.addListener(_onConfigChanged);
}

void _onConfigChanged() {
if (_sensorAvailable) {
_reinitializeSensors();
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_onConfigChanged reinitializes the CCS811 hardware for any config change, but the only config fields are updatePeriod and includeLocationData—changing location logging shouldn’t require tearing down and re-creating the sensor. Track the previous config and only restart the timer / sensor when the sampling interval changes.

Suggested change
bool get sensorAvailable => _sensorAvailable;
bool get isRecording => _isRecording;
CCS811Provider(this._configProvider) {
_configProvider.addListener(_onConfigChanged);
}
void _onConfigChanged() {
if (_sensorAvailable) {
_reinitializeSensors();
Object? _lastUpdatePeriod;
bool get sensorAvailable => _sensorAvailable;
bool get isRecording => _isRecording;
CCS811Provider(this._configProvider) {
_lastUpdatePeriod = _configProvider.updatePeriod;
_configProvider.addListener(_onConfigChanged);
}
void _onConfigChanged() {
if (_sensorAvailable) {
final currentPeriod = _configProvider.updatePeriod;
if (currentPeriod != _lastUpdatePeriod) {
_lastUpdatePeriod = currentPeriod;
_reinitializeSensors();
}

Copilot uses AI. Check for mistakes.
Comment on lines +180 to +189
Future<void> _startGeoLocationUpdates() async {
bool serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) return;

_locationStream = Geolocator.getPositionStream(
locationSettings: const LocationSettings(accuracy: LocationAccuracy.high),
).listen((Position position) {
currentPosition = position;
});
}
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_startGeoLocationUpdates starts a position stream without checking/requesting permissions. In this codebase, other providers (e.g. BarometerStateProvider) call Geolocator.checkPermission() / requestPermission() and handle deniedForever; without that, this can throw and break recording when location is enabled. Add the same permission flow here before subscribing.

Copilot uses AI. Check for mistakes.
Comment on lines +190 to +192
return CommonScaffold(
title: "CCS811 Air Quality",
onRecordPressed: _toggleRecording,
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This screen introduces several user-facing strings as hardcoded text (e.g., the scaffold title). Since the app is localized, these should be moved into the ARB files and accessed via AppLocalizations (and regenerated app_localizations*.dart) so they translate correctly.

Copilot uses AI. Check for mistakes.
_scienceLab = scienceLab;

if (_i2c == null || _scienceLab == null || !_scienceLab!.isConnected()) {
onSensorError?.call('ScienceLab not connected');
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initializeSensors reports connection failures using a hardcoded string ('ScienceLab not connected') even though appLocalizations.pslabNotConnected exists and is used elsewhere. Consider using the localized string here for consistent UX across screens.

Suggested change
onSensorError?.call('ScienceLab not connected');
onSensorError?.call(appLocalizations.pslabNotConnected);

Copilot uses AI. Check for mistakes.
@marcnause marcnause self-requested a review February 22, 2026 16:32
@mariobehling
Copy link
Member

Thank you for adding support for the CCS811 air quality sensor and for your work on this feature. The implementation of the sensor driver, provider, UI screen with live charts, and CSV recording is a valuable addition.

Before this can be merged, a few issues need to be addressed:

1. Resolve merge conflicts and update to the current codebase
There are conflicts with the main branch that must be resolved so the PR can be cleanly merged. Please rebase or merge main into your branch and fix any resulting issues.

2. Address outstanding review feedback
The automated review left the following actionable comments that still need to be resolved:

  • Race condition during initialization:
    There is a potential race between _initializeScienceLab() and the CCS811Provider.initializeSensors call. The provider may attempt to initialize before I2C and ScienceLab are ready. Please ensure the initialization sequence waits appropriately before sensor interaction.

  • Localization of user-facing strings:
    Several UI strings are hard-coded (for example snack bar messages and labels like “ScienceLab not connected” and “CCS811 Air Quality”). These should be sourced from AppLocalizations or existing constants to follow project conventions.

  • Remove or use unused elements:
    There are unused variables and methods (e.g., AppLocalizations appLocalizations in the driver class, and _navigateToLoggedData in the screen). Either remove these or implement them as intended.

  • Timer callback safety:
    The periodic timer in the provider uses an async callback directly. This can lead to overlapping sensor reads. Protect against concurrent access by guarding with a flag or using a scheduling approach that waits for each read to complete.

Please resolve these points and push an update. Once the branch is up to date with main, conflicts are resolved, and all review comments are addressed, we can proceed with the review and merging.

Thank you again for your contribution and for improving PSLab’s sensor support.

Copy link
Member

@mariobehling mariobehling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address AI comments.

Also a process note.

We have automatic Copilot PR reviews enabled on this repository. These reviews are only triggered if the contributor has GitHub Copilot enabled and an active license on their own account.

Please enable Copilot in your GitHub settings if you have access. In many regions, free licenses are available through educational institutions or developer programs. Enabling Copilot helps us speed up the auto review process and reduces manual review overhead for the core team.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for sensor CCS811

3 participants