Skip to content

Commit 012d5e1

Browse files
committed
Added some tests
1 parent 06ce577 commit 012d5e1

2 files changed

Lines changed: 144 additions & 28 deletions

File tree

lib/communication/science_lab.dart

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1411,12 +1411,25 @@ class ScienceLab {
14111411

14121412
Future<int> getUART2BytesAvailable() async {
14131413
if (!isConnected()) return 0;
1414+
14141415
try {
14151416
mPacketHandler.sendByte(mCommandsProto.uart2);
14161417
mPacketHandler.sendByte(mCommandsProto.readUart2Status);
1417-
return await mPacketHandler.getByte();
1418+
1419+
await Future.delayed(const Duration(milliseconds: 20));
1420+
1421+
Uint8List rawBuffer = Uint8List(4);
1422+
int bytesRead = await mPacketHandler.read(rawBuffer, 4);
1423+
1424+
if (bytesRead > 0) {
1425+
logger.i("DEBUG: Firmware answer with $bytesRead bytes: ${rawBuffer.sublist(0, bytesRead)}");
1426+
1427+
return rawBuffer[0];
1428+
}
1429+
1430+
return 0;
14181431
} catch (e) {
1419-
logger.e("Error reading UART2 status: $e");
1432+
logger.e("DEBUG ERROR: $e");
14201433
return 0;
14211434
}
14221435
}
@@ -1436,4 +1449,28 @@ class ScienceLab {
14361449
return [];
14371450
}
14381451
}
1452+
1453+
Future<void> writeUARTBytes(List<int> bytes) async {
1454+
if (!isConnected()) return;
1455+
1456+
try {
1457+
for (int i = 0; i < bytes.length; i++) {
1458+
mPacketHandler.sendByte(mCommandsProto.uart2);
1459+
1460+
mPacketHandler.sendByte(mCommandsProto.sendByte);
1461+
1462+
mPacketHandler.sendByte(bytes[i]);
1463+
1464+
try {
1465+
await mPacketHandler.getAcknowledgement();
1466+
} catch (e) {
1467+
logger.w("UART2: No ACK for byte index $i, continuing...");
1468+
}
1469+
}
1470+
1471+
logger.i("UART2: Successfully wrote ${bytes.length} bytes to TX2.");
1472+
} catch (e) {
1473+
logger.e("Error writing bytes to UART2: $e");
1474+
}
1475+
}
14391476
}

lib/providers/dust_sensor_state_provider.dart

Lines changed: 105 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ class DustSensorStateProvider extends ChangeNotifier {
1818
double _currentPM25 = 0.0;
1919
double _currentPM10 = 0.0;
2020

21+
final List<int> _uartBuffer = [];
22+
2123
Timer? _timeTimer;
2224
Timer? _dustTimer;
2325

@@ -97,54 +99,131 @@ class DustSensorStateProvider extends ChangeNotifier {
9799
});
98100
}
99101

102+
Future<void> testSingleUARTRead() async {
103+
ScienceLab scienceLab = getIt.get<ScienceLab>();
104+
105+
logger.i("--- STARTING SINGLE UART TEST ---");
106+
107+
if (!scienceLab.isConnected()) {
108+
logger.e("TEST: ScienceLab is not connected!");
109+
return;
110+
}
111+
112+
try {
113+
// 1. Wait 2 seconds. The SDS011 sends data once every 1 second.
114+
// This guarantees that at least one packet should be waiting in the PSLab buffer.
115+
logger.i("TEST: Waiting 2 seconds to let SDS011 send data...");
116+
await Future.delayed(const Duration(seconds: 2));
117+
118+
// 2. Check available bytes
119+
logger.i("TEST: Requesting available byte count...");
120+
int available = await scienceLab.getUART2BytesAvailable();
121+
logger.i("TEST: PSLab reports $available bytes available.");
122+
123+
// 3. Read if available
124+
if (available > 0) {
125+
List<int> rxBytes = await scienceLab.readUARTBytes(available);
126+
logger.i("TEST: Successfully read $available bytes.");
127+
128+
// Convert to HEX string for easy reading in the console
129+
String hexString = rxBytes.map((b) => b.toRadixString(16).padLeft(2, '0').toUpperCase()).join(' ');
130+
logger.i("TEST: RAW DATA (HEX): $hexString");
131+
132+
if (rxBytes.contains(0xAA)) {
133+
logger.i("TEST: SUCCESS! Found SDS011 Start Byte (0xAA) in the stream.");
134+
} else {
135+
logger.w("TEST: Data received, but no 0xAA start byte. Is baud rate correct? Are RX/TX swapped?");
136+
}
137+
} else {
138+
logger.w("TEST: No data available. The sensor might be asleep, or TX/RX are disconnected.");
139+
}
140+
} catch (e) {
141+
logger.e("TEST: Exception during single read: $e");
142+
}
143+
144+
logger.i("--- END SINGLE UART TEST ---");
145+
}
146+
147+
148+
100149
void initializeSensors({Function(String)? onError}) async {
101150
onSensorError = onError;
102151

103152
try {
104153
ScienceLab scienceLab = getIt.get<ScienceLab>();
105154

155+
// 1. Configure the UART port on the PSLab to 9600 baud
106156
await scienceLab.configureUART(baudRate: 9600);
107157
await Future.delayed(const Duration(milliseconds: 500));
108158

159+
// Give the sensor a second to spin up the fan and stabilize [cite: 314]
160+
await Future.delayed(const Duration(seconds: 1));
161+
// ---------------------------------------------------------
162+
109163
_startTime = DateTime.now().millisecondsSinceEpoch / 1000.0;
110164

165+
// 2. Start Time Tracking Timer
111166
_timeTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
112-
_currentTime =
113-
(DateTime.now().millisecondsSinceEpoch / 1000.0) - _startTime;
114-
_updateData();
115-
notifyListeners();
167+
if (!_isPlayingBack) {
168+
_currentTime =
169+
(DateTime.now().millisecondsSinceEpoch / 1000.0) - _startTime;
170+
_updateData();
171+
notifyListeners();
172+
}
116173
});
117174

118-
_dustTimer = Timer.periodic(const Duration(seconds: 2), (timer) async {
175+
// 3. Start UART Polling Timer (Runs every 1 second)
176+
_dustTimer = Timer.periodic(const Duration(seconds: 1), (timer) async {
177+
if (!scienceLab.isConnected()) return;
178+
119179
int available = await scienceLab.getUART2BytesAvailable();
120-
if (available < 10) {
121-
logger.d("SDS011: only $available bytes available, skipping");
122-
return;
180+
181+
if (available > 0) {
182+
List<int> rxBytes = await scienceLab.readUARTBytes(available);
183+
String hexData = rxBytes.map((b) => b.toRadixString(16).padLeft(2, '0').toUpperCase()).join(' ');
184+
logger.i("📥 RECEIVED DATA: $hexData");
185+
_uartBuffer.addAll(rxBytes);
123186
}
124187

125-
List<int> rxBytes = await scienceLab.readUARTBytes(20);
188+
// 4. Process the continuous buffer
189+
while (_uartBuffer.length >= 10) {
190+
int headerIdx = _uartBuffer.indexOf(0xAA);
126191

127-
int startIdx = -1;
128-
for (int i = 0; i <= rxBytes.length - 10; i++) {
129-
if (rxBytes[i] == 0xAA && rxBytes[i + 9] == 0xAB) {
130-
startIdx = i;
192+
if (headerIdx == -1) {
193+
_uartBuffer.clear();
131194
break;
132195
}
133-
}
134-
if (startIdx == -1) return;
135196

136-
final frame = rxBytes.sublist(startIdx, startIdx + 10);
137-
int checksum = 0;
138-
for (int i = 2; i <= 7; i++) {
139-
checksum += frame[i];
140-
}
197+
if (headerIdx > 0) {
198+
_uartBuffer.removeRange(0, headerIdx);
199+
}
141200

142-
if ((checksum & 0xFF) == frame[8]) {
143-
_currentPM25 = ((frame[3] * 256) + frame[2]) / 10.0;
144-
_currentPM10 = ((frame[5] * 256) + frame[4]) / 10.0;
145-
notifyListeners();
146-
} else {
147-
logger.w("SDS011: Checksum error");
201+
if (_uartBuffer.length >= 10) {
202+
if (_uartBuffer[9] != 0xAB) {
203+
_uartBuffer.removeAt(0);
204+
continue;
205+
}
206+
207+
final frame = _uartBuffer.sublist(0, 10);
208+
_uartBuffer.removeRange(0, 10);
209+
210+
if (frame[1] != 0xC0) continue;
211+
212+
int checksum = 0;
213+
for (int i = 2; i <= 7; i++) {
214+
checksum += frame[i];
215+
}
216+
217+
if ((checksum & 0xFF) == frame[8]) {
218+
_currentPM25 = ((frame[3] * 256) + frame[2]) / 10.0;
219+
_currentPM10 = ((frame[5] * 256) + frame[4]) / 10.0;
220+
221+
logger.d("SDS011 Valid Reading -> PM2.5: $_currentPM25, PM10: $_currentPM10");
222+
notifyListeners();
223+
} else {
224+
logger.w("SDS011: Checksum error on received frame.");
225+
}
226+
}
148227
}
149228
});
150229
} catch (e) {

0 commit comments

Comments
 (0)