Skip to content

Commit 29adcd8

Browse files
committed
Working with new transformer
1 parent 8a3ca3b commit 29adcd8

File tree

6 files changed

+115
-42
lines changed

6 files changed

+115
-42
lines changed

libraries/Camera/examples/CameraCaptureRawBytes/CameraCaptureRawBytes.ino

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ void sendCameraConfig(){
9696

9797
void loop() {
9898
if(!Serial) {
99-
Serial.begin(115200, SERIAL_8E2);
99+
Serial.begin(115200);
100100
while(!Serial);
101101
}
102102

libraries/Camera/extras/WebSerialCamera/app.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* @fileoverview This file contains the main application logic.
3+
* @author Sebastian Romero
4+
*/
5+
16
const connectButton = document.getElementById('connect');
27
const refreshButton = document.getElementById('refresh');
38
const startButton = document.getElementById('start');
@@ -10,7 +15,8 @@ const ctx = canvas.getContext('2d');
1015
// https://wicg.github.io/serial/
1116

1217

13-
const imageDataProcessor = new ImageDataProcessor(ctx);
18+
const imageDataProcessor = new ImageDataProcessor();
19+
let imageDataTransfomer = new ImageDataTransformer();
1420
const connectionHandler = new SerialConnectionHandler();
1521

1622
connectionHandler.onConnect = async () => {
@@ -28,6 +34,9 @@ connectionHandler.onConnect = async () => {
2834
}
2935
imageDataProcessor.setMode(imageMode);
3036
imageDataProcessor.setResolution(imageResolution.width, imageResolution.height);
37+
imageDataTransfomer.setImageMode(imageMode);
38+
imageDataTransfomer.setResolution(imageResolution.width, imageResolution.height);
39+
connectionHandler.setTransformer(imageDataTransfomer);
3140
renderStream();
3241
};
3342

@@ -54,7 +63,10 @@ async function renderFrame(){
5463
const bytes = await connectionHandler.getFrame(imageDataProcessor.getTotalBytes());
5564
if(!bytes || bytes.length == 0) return false; // Nothing to render
5665
// console.log(`Reading done ✅. Rendering image...`);
57-
const imageData = imageDataProcessor.getImageData(bytes);
66+
const imageData = ctx.createImageData(320, 240);
67+
const data = imageDataProcessor.getImageData(bytes);
68+
imageData.data.set(data);
69+
5870
renderBitmap(imageDataProcessor.width, imageDataProcessor.height, imageData);
5971
return true;
6072
}

libraries/Camera/extras/WebSerialCamera/cameraConfig.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/**
22
* @fileoverview This file contains the configuration for the camera.
3+
* @author Sebastian Romero
34
*/
45

56
/**

libraries/Camera/extras/WebSerialCamera/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<button id="start">Start</button>
1717
</div>
1818
</div>
19+
<script src="transformers.js"></script>
1920
<script src="imageDataProcessor.js"></script>
2021
<script src="serialConnectionHandler.js"></script>
2122
<script src="cameraConfig.js"></script>

libraries/Camera/extras/WebSerialCamera/serialConnectionHandler.js

Lines changed: 14 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,6 @@
11
const ArduinoUSBVendorId = 0x2341;
22
const UserActionAbortError = 8;
33

4-
class BytesWaitTransformer {
5-
constructor(waitBytes) {
6-
this.waitBytes = waitBytes;
7-
this.buffer = new Uint8Array(0);
8-
this.controller = undefined;
9-
}
10-
11-
async transform(chunk, controller) {
12-
this.controller = controller;
13-
14-
// Concatenate incoming chunk with existing buffer
15-
this.buffer = new Uint8Array([...this.buffer, ...chunk]);
16-
17-
while (this.buffer.length >= this.waitBytes) {
18-
// Extract the required number of bytes
19-
const bytesToProcess = this.buffer.slice(0, this.waitBytes);
20-
21-
// Remove processed bytes from the buffer
22-
this.buffer = this.buffer.slice(this.waitBytes);
23-
24-
// Notify the controller that bytes have been processed
25-
controller.enqueue(bytesToProcess);
26-
}
27-
}
28-
29-
flush(controller) {
30-
if (this.buffer.length > 0) {
31-
// Handle remaining bytes (if any) when the stream is closed
32-
const remainingBytes = this.buffer.slice();
33-
console.log("Remaining bytes:", remainingBytes);
34-
35-
// Notify the controller that remaining bytes have been processed
36-
controller.enqueue(remainingBytes);
37-
}
38-
}
39-
}
40-
414
/**
425
* Handles the connection between the browser and the Arduino board via Web Serial.
436
*/
@@ -54,6 +17,7 @@ class SerialConnectionHandler {
5417
this.currentPort = null;
5518
this.currentReader = null;
5619
this.readableStreamClosed = null;
20+
this.transformer = new BytesWaitTransformer();
5721
this.registerEvents();
5822
}
5923

@@ -74,6 +38,14 @@ class SerialConnectionHandler {
7438
}
7539
}
7640

41+
/**
42+
* Sets the transformer that is used to convert bytes into higher-level data types.
43+
* @param {*} transformer
44+
*/
45+
setTransformer(transformer) {
46+
this.transformer = transformer;
47+
}
48+
7749
/**
7850
* Checks if the browser is connected to a serial port.
7951
* @returns {boolean} True if the browser is connected, false otherwise.
@@ -121,6 +93,7 @@ class SerialConnectionHandler {
12193
this.currentPort = null;
12294
await this.currentReader?.cancel();
12395
await this.readableStreamClosed.catch(() => { }); // Ignores the error
96+
this.transformer.flush();
12497
await port.close();
12598
console.log('🔌 Disconnected from serial port.');
12699
if(this.onDisconnect) this.onDisconnect();
@@ -165,8 +138,9 @@ class SerialConnectionHandler {
165138
console.log('🔒 Stream is already locked. Ignoring request...');
166139
return null;
167140
}
168-
169-
const transformStream = new TransformStream(new BytesWaitTransformer(numBytes));
141+
142+
this.transformer.setBytesToWait(numBytes);
143+
const transformStream = new TransformStream(this.transformer);
170144
// pipeThrough() cannot be used because we need a promise that resolves when the stream is closed
171145
// to be able to close the port. pipeTo() returns such a promise.
172146
// SEE: https://stackoverflow.com/questions/71262432/how-can-i-close-a-web-serial-port-that-ive-piped-through-a-transformstream
@@ -180,6 +154,7 @@ class SerialConnectionHandler {
180154
timeoutID = setTimeout(() => {
181155
console.log('⌛️ Timeout occurred while reading.');
182156
if (this.currentPort?.readable) reader?.cancel();
157+
this.transformer.flush();
183158
}, timeout);
184159
}
185160
const { value, done } = await reader.read();
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
class BytesWaitTransformer {
2+
constructor(waitBytes = 1) {
3+
this.waitBytes = waitBytes;
4+
this.buffer = new Uint8Array(0);
5+
this.controller = undefined;
6+
}
7+
8+
setBytesToWait(waitBytes) {
9+
this.waitBytes = waitBytes;
10+
}
11+
12+
/**
13+
* Converts bytes into higher-level data types.
14+
* This method is meant to be overridden by subclasses.
15+
* @param {Uint8Array} bytes
16+
* @returns
17+
*/
18+
convertBytes(bytes) {
19+
return bytes;
20+
}
21+
22+
23+
async transform(chunk, controller) {
24+
this.controller = controller;
25+
26+
// Concatenate incoming chunk with existing buffer
27+
this.buffer = new Uint8Array([...this.buffer, ...chunk]);
28+
29+
while (this.buffer.length >= this.waitBytes) {
30+
// Extract the required number of bytes
31+
const bytesToProcess = this.buffer.slice(0, this.waitBytes);
32+
33+
// Remove processed bytes from the buffer
34+
this.buffer = this.buffer.slice(this.waitBytes);
35+
36+
// Notify the controller that bytes have been processed
37+
controller.enqueue(this.convertBytes(bytesToProcess));
38+
}
39+
}
40+
41+
flush(controller) {
42+
if (this.buffer.length > 0) {
43+
// Handle remaining bytes (if any) when the stream is closed
44+
const remainingBytes = this.buffer.slice();
45+
console.log("Remaining bytes:", remainingBytes);
46+
47+
// Notify the controller that remaining bytes have been processed
48+
controller.enqueue(remainingBytes);
49+
}
50+
}
51+
}
52+
53+
class ImageDataTransformer extends BytesWaitTransformer {
54+
constructor(context, width, height, imageMode) {
55+
super(1);
56+
this.width = width;
57+
this.height = height;
58+
}
59+
60+
setResolution(width, height) {
61+
this.width = width;
62+
this.height = height;
63+
}
64+
65+
setImageMode(imageMode) {
66+
this.imageMode = imageMode;
67+
}
68+
69+
convertBytes(bytes) {
70+
console.log("Converting bytes");
71+
let a = new Uint8Array(bytes);
72+
// Iterate over UInt8Array
73+
for (let i = 0; i < a.length; i++) {
74+
a[i] = a[i] * 2;
75+
}
76+
77+
// const imageData = new ImageData(this.width, this.height);
78+
// for (let i = 0; i < bytes.length; i++) {
79+
// imageData.data[i] = bytes[i];
80+
// }
81+
// return imageData;
82+
return bytes;
83+
}
84+
}

0 commit comments

Comments
 (0)