this week i want to explore as many messaging protocols. .
individual assignment
The Web Serial API is one of a set of APIs that allow websites to communicate with peripherals connected to a user's computer. It provides the ability to connect to devices that are required by the operating system to communicate via the serial API, rather than USB which can be accessed via the WebUSB API
, or input devices that can be accessed via WebHID API
.
from icircuit
<!-- Heading -->
<h2 id="heading">WebSerial API for Week 14</h2>
<!-- Toggle switch for controlling LED -->
<label class="toggle-switch">
<input type="checkbox" onchange="toggleColor()">
<span class="slider"></span>
</label>
<!-- Connect button -->
<button class="connect-button" onclick="connectDevice()">Connect</button>
<input type="checkbox">
) wrapped in a <label>
element. This switch is intended to control an LED.<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>web serial</title>
<style>
/* Styling for the toggle switch */
.toggle-switch {
position: relative;
display: inline-block;
width: 50px;
height: 26px;
}
.toggle-switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
border-radius: 26px; /* Round shape */
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 22px;
width: 22px;
left: 2px;
bottom: 2px;
background-color: white;
border-radius: 50%; /* Round shape */
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #e3dd1f; /* Red color when toggle is on */
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(22px);
-ms-transform: translateX(22px);
transform: translateX(22px);
}
/* Styling for the connect button */
.connect-button {
padding: 10px 20px;
background-color: #4CAF50;
border: none;
color: white;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin-left: 20px;
border-radius: 5px;
cursor: pointer;
}
</style>
</head>
<body>
<h2 id="heading">WebSerial API for Week 14</h2>
<label class="toggle-switch">
<input type="checkbox" onchange="toggleColor()">
<span class="slider"></span>
</label>
<button class="connect-button" onclick="connectDevice()">Connect</button>
<script>
let port;
let isToggled = false;
// Function to handle the connect button click event
async function connectDevice() {
try {
// Request access to the serial port
port = await navigator.serial.requestPort();
// Set the baud rate to 9600
await port.open({ baudRate: 9600 });
// Log a success message
console.log('Port opened successfully with baud rate 9600.');
// Change the text of the connect button to "Connected"
document.querySelector('.connect-button').innerText = "Connected";
// Add a disconnect event listener
port.addEventListener('disconnect', handleDisconnect);
} catch (error) {
// Log any errors
console.error('Error:', error);
// Change the text of the connect button back to "Connect"
document.querySelector('.connect-button').innerText = "Connect";
}
}
// Function to handle disconnect event
function handleDisconnect() {
console.log('Device disconnected.');
// Change the text of the connect button back to "Connect"
document.querySelector('.connect-button').innerText = "Connect";
}
// Function to handle toggle switch state change
function toggleColor() {
// If the toggle switch is turned on
if (document.querySelector('.toggle-switch input').checked) {
// Send command to keep LED on
sendToSerial();
} else {
// Send command to turn off LED
sendToSerial();
}
}
// Function to send data to the serial port
async function sendToSerial() {
// Obtain a writable stream writer for the serial port
const writer = port.writable.getWriter();
const encoder = new TextEncoder()
// Define the data to send based on the toggle state
const dataToSend = isToggled ? '0' : '1';
// Toggle the state for the next iteration
isToggled = !isToggled;
// Write the data to the serial port
writer.write(encoder.encode(dataToSend)).then(() => {
// Log a message when the data is successfully sent
console.log("Sent: " + dataToSend);
});
// Release the lock on the writer after writing data
writer.releaseLock();
}
</script>
</body>
</html>
<!-- <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Serial</title>
<style>
.navbar {
display: flex;
position: absolute;
padding: 1.5rem 1.5rem;
font-size: 2rem;
font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
}
.navbar span {
font-weight: 700;
}
.container {
width: 100vw;
height: 100vh;
}
.container .buttons {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
gap: 1rem;
width: 100%;
height: 100%;
}
.container .buttons button{
font-size: 2rem;
font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
padding: 1rem 2rem;
border-radius: 1rem;
background-color: #e9e9e9;
border: 1px solid #cccccc;
cursor: pointer;
box-shadow: rgba(50, 50, 93, 0.25) 0px 6px 12px -2px, rgba(0, 0, 0, 0.3) 0px 3px 7px -3px;
transition: 0.5s all;
}
.container .buttons button:hover{
box-shadow: rgba(0, 0, 0, 0.12) 0px 1px 3px, rgba(0, 0, 0, 0.24) 0px 1px 2px;
}
</style>
</head>
<body>
<nav class="navbar">WebSerial <span> API</span></nav>
<div class="container">
<div class="buttons">
<div class="textarea">
<textarea name="textarea" id="serial" cols="40" rows="10"></textarea>
</div>
<div>
<button id="connect">Connect</button>
<button id="toggle">On/Off</button>
</div>
</div>
</div>
<script>
let port;
let isToggled = false;
let receivedText = '';
document.getElementById('connect').addEventListener('click', async () => {
port = await navigator.serial.requestPort();
await port.open({ baudRate: 9600 });
const reader = port.readable.getReader();
const processMsg = async () => {
const decoder = new TextDecoder();
const { value, done } = await reader.read();
if (!done) {
receivedText += decoder.decode(value);
document.getElementById('serial').value = receivedText;
processMsg();
} else {
reader.releaseLock();
}
}
processMsg();
});
<textarea name="textarea" id="serial" cols="30" rows="10"></textarea>
document.getElementById('toggle').addEventListener('click', async () => {
const encoder = new TextEncoder()
const writer = port.writable.getWriter();
const dataToSend = isToggled ? '1' : '0';
isToggled = !isToggled;
writer.write(encoder.encode(dataToSend)).then(() => {
console.log("Sent: " + dataToSend);
});
writer.releaseLock();
});
</script>
</body>
</html> -->
from chat gpt
i uploaded a arduino code to serial read "1 "& "0" a.
me testing the code
screenshot
The WebSocket API is an advanced technology that makes it possible to open a two-way interactive communication session between the user's browser and a server. With this API, you can send messages to a server and receive event-driven responses without having to poll the server for a reply.
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
const clients = [];
wss.on('connection', function connection(ws) {
clients.push(ws);
ws.on('message', function incoming(message) {
// Broadcast the received message to all clients except the sender
clients.forEach(client => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(message);
}
});
});
ws.on('close', function() {
// Remove the closed WebSocket connection from the clients array
clients.splice(clients.indexOf(ws), 1);
});
});
code for server.js from chat gpt
to make websocket work we need to run a server
first we have to run the server and then open the html.
<script>
// WebSocket connection establishment
const ws = new WebSocket('ws://192.168.33.22:8080');
// Event handler for successful connection
ws.onopen = function() {
console.log('Connected.');
};
// Event handler for receiving messages
ws.onmessage = function(event) {
// Message handling logic
};
// Function for sending messages
function sendMessage() {
// Message sending logic
}
// Function for displaying messages in the message container
function displayMessage(message) {
// Message display logic
}
</script>
from chat gpt
in the above code
ws://192.168.33.22:8080
.onopen
event handler logs a message when the connection is successfully established.onmessage
event handler processes incoming messages from the WebSocket server. It distinguishes between text messages and Blob (binary data) messages and logs them accordingly.sendMessage()
function retrieves the message from the input field, sends it to the server via the WebSocket connection, and clears the input field.displayMessage()
function is defined but not used in this snippet. It's meant to display messages received from the server in the messageContainer
.communicating using external device and receiving it on server.
websocket allow us for cross device communciation.
when i am messaging with phone there was an issue of blob. i solved it using the below code snippet.
ws.onmessage = function(event) {
if (typeof event.data === 'string') {
// Handle text message
console.log('Received:', event.data);
} else if (event.data instanceof Blob) {
// Convert Blob to text
const reader = new FileReader();
reader.onload = function() {
console.log('Received:', reader.result);
};
reader.readAsText(event.data);
}
};
code to convert blob to text
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebSocket Client</title>
</head>
<body>
<div id="messageContainer"></div> <!-- Container for displaying messages -->
<input type="text" id="messageInput" placeholder="Type your message">
<button onclick="sendMessage()">Send Message</button>
<script>
const ws = new WebSocket('ws://192.168.33.22:8080');
ws.onopen = function() {
console.log('Connected.');
};
ws.onmessage = function(event) {
if (typeof event.data === 'string') {
// Handle text message
console.log('Received:', event.data);
} else if (event.data instanceof Blob) {
// Convert Blob to text
const reader = new FileReader();
reader.onload = function() {
console.log('Received:', reader.result);
};
reader.readAsText(event.data);
}
};
function sendMessage() {
const messageInput = document.getElementById('messageInput');
const message = messageInput.value;
console.log('Sent:', message); // Log the message before sending
ws.send(message);
messageInput.value = ''; // Clear the input field after sending
}
function displayMessage(message) {
const messageContainer = document.getElementById('messageContainer');
// Create a new <p> element to display the message
const messageElement = document.createElement('p');
messageElement.textContent = message;
// Append the message element to the message container
messageContainer.appendChild(messageElement);
}
</script>
</body>
</html>
code fro cleint.js - from chat gpt
i am going to create the interface with my hall effect board in WEEK 11 - INPUT DEVICES using web serail api .lets use chat gpt tool make it happen.
circuit diagram of the setup.
i first prompted in chat gpt
create a web serial api interface to show count of this Arduino code using html
i inputed this arduino code to count magnet as reference.
// Define the pin for the hall effect sensor
const int hallEffectPin = 31;
// Variable to store the count of magnet detections
int magnetCount = 0;
// Flag to track whether the sensor was already triggered
bool sensorTriggered = false;
void setup() {
// Initialize serial communication
Serial.begin(9600);
// Set the hall effect sensor pin as input
pinMode(hallEffectPin, INPUT);
}
void loop() {
// Read the state of the hall effect sensor
int sensorState = digitalRead(hallEffectPin);
// If the sensor detects a magnet (LOW state) and it wasn't triggered before
if (sensorState == LOW && !sensorTriggered) {
// Increment the magnet count
magnetCount++;
// Print the current magnet count
Serial.print("Magnet detected! Count: ");
Serial.println(magnetCount);
// Set the sensor triggered flag to true
sensorTriggered = true;
}
// If the sensor is not detecting a magnet (HIGH state)
// reset the sensor triggered flag to false
if (sensorState == HIGH) {
sensorTriggered = false;
}
// // A short delay to prevent rapid counting due to sensor noise
// delay(100);
}
Initial Arduino Setup:
Developed Arduino code to count magnet detections using a hall effect sensor and transmit count data over serial communication.
HTML and CSS Setup for Web Serial Interface:
Created an HTML template with CSS styling for a web serial interface, featuring a toggle switch and a connect button.
JavaScript for Serial Communication:
Implemented JavaScript to establish and manage serial communication with the Arduino, facilitating data exchange.
Display Setup and Interaction:
Designed the web interface to display real-time magnet count and support user actions such as connecting to the Arduino and resetting the count.
Enhancements and Additional Features:
Integrated additional messages to display various outcomes, enhancing user interaction and system functionality.
here i summarised the whole prompt session into a single one.
Create a web interface that connects to an Arduino via Web Serial. The Arduino code uses a hall effect sensor to detect magnets and sends predefined messages over serial communication. These messages include "$10", "100$", "JACKPOT", "0", "TRY AGAIN", and "250$". Implement a reset functionality so that when a reset button on the web page is clicked, the Arduino resets its message index and sends the message "LET'S START". Ensure the web interface displays these messages in real-time and updates accordingly when a new message is received or after a reset.
inorder to implemen web serial api there are two process. firstly, we need to burn a set of code into arduino for serial reading and other for html and javascript in computer which you can open in any browser.
The Arduino code is responsible for handling the hall effect sensor input and serial communication with the connected computer (or device running a browser).
// Define the pin for the hall effect sensor
const int hallEffectPin = 31;
// Array of messages
const char* messages[] = {"$10", "100$", "JACKPOT", "0", "TRY AGAIN", "250$"};
const int numMessages = 6;
// Variable to store the current message index
int messageIndex = 0;
// Flag to track whether the sensor was already triggered
bool sensorTriggered = false;
void setup() {
// Initialize serial communication
Serial.begin(9600);
// Set the hall effect sensor pin as input
pinMode(hallEffectPin, INPUT);
}
void loop() {
// Check if data is available on the serial port
if (Serial.available()) {
char incomingByte = Serial.read();
// If a 'R' is received, reset the message index and print "LET'S START"
if (incomingByte == 'R') {
messageIndex = 0;
Serial.println("LET'S START");
}
}
// Read the state of the hall effect sensor
int sensorState = digitalRead(hallEffectPin);
// If the sensor detects a magnet (LOW state) and it wasn't triggered before
if (sensorState == LOW && !sensorTriggered) {
// Increment the message index
messageIndex++;
if (messageIndex >= numMessages) {
messageIndex = 0;
}
// Print the current message
Serial.println(messages[messageIndex]);
// Set the sensor triggered flag to true
sensorTriggered = true;
}
// If the sensor is not detecting a magnet (HIGH state), reset the sensor triggered flag to false
if (sensorState == HIGH) {
sensorTriggered = false;
}
// A short delay to prevent rapid counting due to sensor noise
delay(100);
}
Explanation:
messages
array.Setup Function:
hallEffectPin
as an input pin.Loop Function:
Serial Communication:
Serial.available()
and Serial.read()
).messageIndex
to 0 and sends "LET'S START" over serial.Sensor Reading:
hallEffectPin
(digitalRead(hallEffectPin)
).LOW
state) and sensorTriggered
is false
, increments messageIndex
to cycle through messages.Serial.println(messages[messageIndex])
).sensorTriggered
to true
to prevent rapid counting.Delay:
delay(100)
) to prevent rapid multiple counts due to sensor noise.The HTML and JavaScript code provides a user interface to connect to the Arduino via Web Serial API and display messages received from the Arduino.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Magnet Detection Counter</title>
<style>
body {
margin: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
background-color: black;
color: white;
font-family: Arial, sans-serif;
font-size: 3em;
text-align: center;
}
.connect-button, .reset-button {
position: absolute;
top: 20px;
padding: 10px 20px;
background-color: #4CAF50;
border: none;
color: white;
text-align: center;
text-decoration: none;
font-size: 16px;
border-radius: 5px;
cursor: pointer;
}
.connect-button {
right: 20px;
}
.reset-button {
right: 150px;
}
.connect-button:disabled, .reset-button:disabled {
background-color: #888;
cursor: not-allowed;
}
#status {
position: absolute;
top: 20px;
left: 20px;
font-size: 0.5em;
}
</style>
</head>
<body>
<button id="connect" class="connect-button">Connect to Arduino</button>
<button id="reset" class="reset-button">Reset Counter</button>
<p id="status">Status: Not Connected</p>
<div id="count">LET'S START</div>
<script>
const connectButton = document.getElementById('connect');
const resetButton = document.getElementById('reset');
const statusDisplay = document.getElementById('status');
const countDisplay = document.getElementById('count');
let port;
let reader;
async function connect() {
try {
// Request a port and open a connection
port = await navigator.serial.requestPort();
await port.open({ baudRate: 9600 }); // Set baud rate here
statusDisplay.textContent = 'Status: Connected';
// Disable the connect button to prevent multiple connections
connectButton.disabled = true;
connectButton.textContent = 'Connected';
reader = port.readable.getReader();
readLoop();
} catch (error) {
console.error('Error:', error);
statusDisplay.textContent = 'Status: Error connecting to Arduino';
}
}
async function readLoop() {
while (true) {
try {
const { value, done } = await reader.read();
if (done) {
// Allow the serial port to be closed later
reader.releaseLock();
break;
}
// Parse the incoming data and update the display
const text = new TextDecoder().decode(value).trim();
if (text) {
countDisplay.textContent = text;
}
} catch (error) {
console.error('Read error:', error);
break;
}
}
}
async function resetCounter() {
if (port) {
try {
const writer = port.writable.getWriter();
const encoder = new TextEncoder();
await writer.write(encoder.encode('R'));
writer.releaseLock();
countDisplay.textContent = "LET'S START";
} catch (error) {
console.error('Error:', error);
}
}
}
connectButton.addEventListener('click', connect);
resetButton.addEventListener('click', resetCounter);
</script>
</body>
</html>
Explanation:
HTML Structure:
#connect
and #reset
) for connecting to the Arduino and resetting the counter.#status
) and current message (#count
) received from the Arduino.CSS Styling:
JavaScript Functionality:
connectButton.addEventListener('click', connect);
triggers connect()
to initiate a connection to the Arduino via Web Serial API.resetButton.addEventListener('click', resetCounter);
triggers resetCounter()
to send a reset command ('R') to the Arduino and updates the display with "LET'S START".Functions:
connect(): Requests access to the serial port, opens a connection with specified baud rate (9600), updates status display, and starts reading data from the Arduino.
read Loop(): Continuously reads data from the Arduino serial port. When data is received, decodes it, trims any extra whitespace, and updates countDisplay
with the received message.
RESET-COUNTER(): Checks if a port is open, creates a writer to the serial port, sends a 'R' character to the Arduino to reset the message index, updates countDisplay
with "LET'S START".
Together, these codes create a system where a hall effect sensor triggers messages on the Arduino, which are then displayed in real-time on a web page using Web Serial API.
interface
demo
Today, this project has boosted my confidence that I can create any application with proper prompting and understanding.