Created
April 17, 2024 08:20
-
-
Save RajivCodeLab/3485549df9427d4fd1c387896a5158ae to your computer and use it in GitHub Desktop.
WebSocket on Raspberry Pi Pico W using (MicroDot)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>Live Temperature Dashboard</title> | |
<meta charset="UTF-8"> | |
<!-- Include Chart.js library --> | |
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> | |
<style> | |
@import url(https://fonts.googleapis.com/css?family=Open+Sans:700,300); | |
.frame { | |
position: absolute; | |
top: 50%; | |
left: 7%; | |
width: 400px; | |
height: 400px; | |
margin-top: -200px; | |
margin-left: -200px; | |
border-radius: 2px; | |
overflow: hidden; | |
background: #222; | |
color: #333; | |
font-family: 'Open Sans', Helvetica, sans-serif; | |
-webkit-font-smoothing: antialiased; | |
-moz-osx-font-smoothing: grayscale; | |
background: #222; | |
} | |
.center { | |
position: absolute; | |
top: 50%; | |
left: 50%; | |
transform: translate(-50%,-50%); | |
} | |
.temparature-meter__container { | |
position: relative; | |
height: 200px; | |
width: 200px; | |
border-radius: 200px; | |
box-shadow: 0 1px 2px rgba(0, 0, 0, .07); | |
border: solid 10px #fff; | |
overflow: hidden; | |
&:after { | |
position: absolute; | |
content: ""; | |
height: 120px; | |
width: 120px; | |
background-color: #fff; | |
z-index: 0; | |
transform: rotate(45deg); | |
bottom: -40px; | |
left: 40px; | |
z-index: 1; | |
} | |
} | |
.temparature-meter__inner { | |
display: flex; | |
text-align: center; | |
height: 100%; | |
width: 100%; | |
border-radius: 100%; | |
box-shadow: inset 0 0 10px rgba(0, 0, 0, .4); | |
background: linear-gradient(to right, #148d04 0%,#f52c3d 100%); | |
overflow: hidden; | |
.temparature-meter__inner-ring { | |
cursor: pointer; | |
position: relative; | |
margin: auto; | |
display: flex; | |
flex-direction: column; | |
justify-content: center; | |
height: 130px; | |
width: 130px; | |
background-color: #fff; | |
border-radius: 100%; | |
box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.2); | |
z-index: 9; | |
&:after { | |
content: ""; | |
position: absolute; | |
width: 1px; | |
height: 50%; | |
background-image: linear-gradient(#148d04 15px, transparent 0); | |
top: 0; | |
left: 50%; | |
transform-origin: bottom; | |
transform: rotatez(-35deg); | |
transition: all 0.8s ease-in-out; | |
} | |
&:hover:after { | |
transform: rotatez(-20deg); | |
} | |
.temparature-count { | |
display: block; | |
position: absolute; | |
width: 100%; | |
text-align: center; | |
transition: all 0.8s ease-in-out; | |
&.c2 { | |
opacity: 0; | |
transform: translatex(50px) scale(0.5); | |
} | |
} | |
&:hover { | |
.c1 { | |
opacity: 0; | |
transform: translatex(-50px) scale(0.5); | |
} | |
.c2 { | |
opacity: 1; | |
transform: translatex(0) scale(1); | |
} | |
} | |
} | |
.temparature-inside { | |
position: relative; | |
font-size: 50px; | |
display: inline-block; | |
letter-spacing: -5px; | |
font-weight: 500; | |
color: #148d04; | |
height: 58px; | |
.temperature-sup { | |
font-size: 20px; | |
position: absolute; | |
position: relative; | |
right: -45px; | |
top: -30px; | |
} | |
} | |
.temparature-outside { | |
font-size: 13px; | |
} | |
.temparature-meter__inner-label { | |
font-size: 13px; | |
} | |
} | |
body { | |
background-color: #222; | |
color: #fff; | |
font-family: Arial, sans-serif; | |
} | |
h1 { | |
text-align: center; | |
color: #148d04; | |
} | |
.chart-container { | |
margin-left: 300px; | |
margin-top:20px; | |
text-align:center; | |
height: 70vh; /* Set the height to half of the viewport height */ | |
} | |
header { | |
background-color: #333; | |
color: #fff; | |
padding: 10px; | |
text-align: center; | |
/* Remove default margin */ | |
display: flex; /* Use flexbox to align items */ | |
align-items: center; /* Vertically center items */ | |
} | |
#temperature { | |
text-align: center; | |
font-size: 24px; | |
margin-bottom: 20px; | |
margin-top:30px; | |
} | |
canvas { | |
text-align:center; | |
width:100%; | |
} | |
.logo { | |
width: 50px; /* Adjust the width of the logo */ | |
height: auto; /* Maintain aspect ratio */ | |
margin-right: 10px; /* Add some space between logo and title */ | |
margin-left: 35px; | |
} | |
</style> | |
</head> | |
<body> | |
<header> | |
<img src="data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA3MS42OSA5Mi4xMDkiPjxkZWZzPjxzdHlsZT4uY2xzLTF7ZmlsbDojNDZhZjRifS5jbHMtMntmaWxsOiNjZDIzNTV9PC9zdHlsZT48L2RlZnM+PHBhdGggZD0iTTcxLjUzIDUyLjk4Yy0uNDEtNC4yNjYtMi4zMjgtOC4wNi01LjA1MS0xMC4wNmExMi40NzMgMTIuNDczIDAgMCAwLTIuMzQ0LTQuNTYgMTMuOTg2IDEzLjk4NiAwIDAgMC00Ljk3Ny05LjQgNS4yNTUgNS4yNTUgMCAwIDAgMS4xNTItMS40MDVjMy4zMDYtMS40NzYgNS42MzYtNC41NzYgNS45MDctNi44ODFhOS4wNDUgOS4wNDUgMCAwIDAgMi44NTctNS45MjUgNS42NjUgNS42NjUgMCAwIDAtLjUwNi0yLjY2NyA1LjA2OCA1LjA2OCAwIDAgMCAxLjMyMS01LjIzYy0uOTg3LTIuODYtNC40NDQtNC43MTUtOS4wODgtNC45MTJBNy4zMiA3LjMyIDAgMCAwIDU1Ljc0LjIwOGExMS42OTkgMTEuNjk5IDAgMCAwLTIuNzMyLjMzNkE2LjIxOSA2LjIxOSAwIDAgMCA1MC4zMjIgMCAxMC41MSAxMC41MSAwIDAgMCA0NS4yIDEuMzk3YTQuNzA5IDQuNzA5IDAgMCAwLS42MTgtLjA0Yy0yLjMwNiAwLTQuNjEgMS41ODgtNS43NzkgMi41MzVhMTcuNTIgMTcuNTIgMCAwIDAtMy4wMzcgMy4xNjQgMTcuNTI0IDE3LjUyNCAwIDAgMC0zLjAzNy0zLjE2NGMtMS4xNjktLjk0Ny0zLjQ3My0yLjUzNS01Ljc3OS0yLjUzNmE0LjcxMiA0LjcxMiAwIDAgMC0uNjE4LjA0QTEwLjUxMiAxMC41MTIgMCAwIDAgMjEuMjA4IDBhNi4yMiA2LjIyIDAgMCAwLTIuNjg2LjU0NEExMS42OTggMTEuNjk4IDAgMCAwIDE1Ljc5LjIwOGE3LjMyIDcuMzIgMCAwIDAtNS4wNiAxLjczMmMtNC42NDUuMTk3LTguMTAzIDIuMDUzLTkuMDkgNC45MTJhNS4wNjggNS4wNjggMCAwIDAgMS4zMjEgNS4yMyA1LjY2NyA1LjY2NyAwIDAgMC0uNTA1IDIuNjY3IDkuMDQ0IDkuMDQ0IDAgMCAwIDIuODU3IDUuOTI1Yy4yNyAyLjMwNSAyLjYwMSA1LjQwNSA1LjkwNiA2Ljg4MmE1LjI1MyA1LjI1MyAwIDAgMCAxLjE1MiAxLjQwMyAxMy45ODcgMTMuOTg3IDAgMCAwLTQuOTc2IDkuNDAyIDEyLjQ3MSAxMi40NzEgMCAwIDAtMi4zNDQgNC41NTlDMi4zMjggNDQuOTIuNDEgNDguNzE0IDAgNTIuOThjLS40MDggNC4yNC43NTUgOC4xOTggMy4xMjMgMTAuNzA1YTE1LjE1OCAxNS4xNTggMCAwIDAgMi41NzQgNS45MTFBMTUuMzgzIDE1LjM4MyAwIDAgMCA5LjU4IDc4LjU3YTE1Ljg5NyAxNS44OTcgMCAwIDAgOC41NjQgNS4wODkgMjAuNzMzIDIwLjczMyAwIDAgMCA2Ljg0OCA0LjI0IDE1Ljg4OCAxNS44ODggMCAwIDAgMjEuNTQ2IDAgMjAuNzM4IDIwLjczOCAwIDAgMCA2Ljg0OC00LjI0IDE1Ljg5NyAxNS44OTcgMCAwIDAgOC41NjMtNS4wODkgMTUuMzgzIDE1LjM4MyAwIDAgMCAzLjg4NC04Ljk3MiAxNS4xNTQgMTUuMTU0IDAgMCAwIDIuNTc0LTUuOTEyYzIuMzY3LTIuNTA3IDMuNTMtNi40NjUgMy4xMjMtMTAuNzA1WiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLjA4IC4wMDIpIi8+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDQuNDQ2IDYuMThhLjM2Ni4zNjYgMCAwIDEgLjQ2NS4zOWMtLjExNiAxLjA5NS41NDcuOTU3LjcwMy43NjJhNS43MzggNS43MzggMCAwIDEgNS4xODktMi40ODkuMzY2LjM2NiAwIDAgMSAuMjUuNTljLS42NS45NjUuMDUgMS4xNDguMzEuOTc1IDIuNjU0LTEuNjYgNS4xODctMS42NjMgNi4xNi0uOTY2YS4zNjYuMzY2IDAgMCAxIC4wMjEuNTY5Yy0uOTgzLjgzNy0uNDMyIDEuMjU0LS4wODUgMS4xMjcgMi42OTUtLjk1MiA2LjQxNi0uMTEgNy43MTUuOTg3YS4zNjkuMzY5IDAgMCAxIC4wMDkuNTU5IDcuMzEyIDcuMzEyIDAgMCAwLTIuODE1IDQuOTFjLS4wNzMuNjQ2Ljk5OC41MSAxLjQ1LjM5M2EuMzY2LjM2NiAwIDAgMSAuNDU2LjM0MmMuMDQxIDEuNTUyLTEuNDI3IDMuMjU4LTMuNjEgNC43MTctLjI5My4xOTUtLjI1MS42NjQuNDE2LjY4MWEuMzYyLjM2MiAwIDAgMSAuMzExLjU0NWMtLjc3OSAxLjQ0NS0xLjgzOCAyLjgwNi01LjQ0NSAzLjc0YS4zNy4zNyAwIDAgMC0uMDUuNjk4LjM1NC4zNTQgMCAwIDEgLjExNS42MjVjLTMuNTkyIDMuMDg1LTEyLjY5NSAxLjg2OS0xMy44NS0zLjMyNGEuMzY1LjM2NSAwIDAgMSAuMDY1LS4yOTcgMzQuNjAzIDM0LjYwMyAwIDAgMSAxNS4wOTYtMTEuNDg2LjI4Ny4yODcgMCAwIDAtLjE0Mi0uNTUzIDI0LjY4NSAyNC42ODUgMCAwIDAtMTYuMzk0IDkuODg0LjM3LjM3IDAgMCAxLS40Ny4xMDZjLTUuODM1LTMuMDEyLTEuMDQzLTExLjkwOCA0LjEzLTEzLjQ4NVpNMTAuMTM5IDIwLjI3MmEuMzYyLjM2MiAwIDAgMSAuMzEtLjU0NWMuNjY4LS4wMTcuNzEtLjQ4Ni40MTctLjY4MS0yLjE4NC0xLjQ2LTMuNjUxLTMuMTY1LTMuNjEtNC43MTdhLjM2Ni4zNjYgMCAwIDEgLjQ1Ni0uMzQyYy40NTIuMTE3IDEuNTIzLjI1MyAxLjQ1LS4zOTNhNy4zMTIgNy4zMTIgMCAwIDAtMi44MTUtNC45MS4zNjkuMzY5IDAgMCAxIC4wMS0uNTU5YzEuMjk3LTEuMDk3IDUuMDE5LTEuOTM5IDcuNzE0LS45ODcuMzQ3LjEyNy44OTctLjI5LS4wODUtMS4xMjdhLjM2Ni4zNjYgMCAwIDEgLjAyMi0uNTY5Yy45NzItLjY5NyAzLjUwNC0uNjk0IDYuMTYuOTY2LjI1OS4xNzMuOTU5LS4wMS4zMDktLjk3NGEuMzY2LjM2NiAwIDAgMSAuMjUtLjU5MSA1LjczOCA1LjczOCAwIDAgMSA1LjE4OSAyLjQ4OWMuMTU2LjE5NS44MTkuMzMzLjcwMy0uNzYzYS4zNjYuMzY2IDAgMCAxIC40NjUtLjM4OWM1LjE3MyAxLjU3NyA5Ljk2NCAxMC40NzMgNC4xMyAxMy40ODVhLjM3LjM3IDAgMCAxLS40Ny0uMTA2QTI0LjY4NSAyNC42ODUgMCAwIDAgMTQuMzUgOS42NzVhLjI4Ny4yODcgMCAwIDAtLjE0Mi41NTMgMzQuNjAzIDM0LjYwMyAwIDAgMSAxNS4wOTUgMTEuNDg2LjM2NC4zNjQgMCAwIDEgLjA2Ni4yOTdjLTEuMTU2IDUuMTkzLTEwLjI1OSA2LjQwOS0xMy44NSAzLjMyNGEuMzU0LjM1NCAwIDAgMSAuMTE1LS42MjUuMzcuMzcgMCAwIDAtLjA1LS42OThjLTMuNjA3LS45MzQtNC42NjYtMi4yOTUtNS40NDUtMy43NFoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC4wOCAuMDAyKSIvPjxwYXRoIGNsYXNzPSJjbHMtMiIgZD0iTTU4Ljc1NCAzNi4xNDZjMS40OTYgMy45OC4zMyA1Ljg5NC0zLjIxOSAzLjg2OGEyNS40NCAyNS40NCAwIDAgMS03LjQ1NC02LjI0OWMtMi42NzQtMy4xNzYtLjkzNi00LjU5MSAzLjI3NS0zLjgyOGExMS4zNjggMTEuMzY4IDAgMCAxIDcuMzk4IDYuMjA5Wk00Mi44MzQgMzEuNjY4YzUuMDc2IDQuMjE5LS43NCA3LjIwNS03LjA3IDcuMjA1cy0xMi4xNDQtMi45ODYtNy4wNjgtNy4yMDVhMTEuMjg2IDExLjI4NiAwIDAgMSAxNC4xMzggMFpNMTIuNzc2IDM2LjE0NmExMS4zNjggMTEuMzY4IDAgMCAxIDcuMzk4LTYuMjFjNC4yMTEtLjc2MiA1Ljk0OS42NTMgMy4yNzUgMy44M2EyNS40NCAyNS40NCAwIDAgMS03LjQ1NCA2LjI0OGMtMy41NSAyLjAyNi00LjcxNi4xMTItMy4yMi0zLjg2OFpNNS40MzMgNTguMjY0YTExLjM2NCAxMS4zNjQgMCAwIDEgLjg0NC05LjY3YzEuODc1LTMuMTkxIDMuNzYzLTMuMDY0IDQuNTEyLS4zNmExNi45NTQgMTYuOTU0IDAgMCAxLS45NzcgMTEuMTc0Yy0xLjM4OSAyLjc2LTMuMTI2IDEuODI3LTQuMzc5LTEuMTQ0Wk0xOC45NTcgNzguOTMyYTExLjI5NyAxMS4yOTcgMCAwIDEtOC40OTgtMTAuMDgyYy43MDQtMTYuMzgyIDI0LjMxNCAxMi44NzQgOC40OTggMTAuMDgyWk0xOS40MzcgNTguNTI4Yy0zLjk1OS0yLjI4NS01LjAwNy03Ljg4My0yLjM0LTEyLjUwMnM4LjAzOS02LjUxMSAxMS45OTgtNC4yMjUgNS4wMDcgNy44ODQgMi4zNCAxMi41MDMtOC4wMzkgNi41MS0xMS45OTggNC4yMjRaTTQyLjM3MiA4NS4xODRhMTEuMzA3IDExLjMwNyAwIDAgMS0xMy4yMTQgMGMtMy45MjMtMi43MDkuMDI0LTUuODI2IDYuNjA3LTUuODI2czEwLjUzIDMuMTE3IDYuNjA3IDUuODI2WiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLjA4IC4wMDIpIi8+PGVsbGlwc2UgY2xhc3M9ImNscy0yIiBjeD0iMzUuODQ1IiBjeT0iNjcuMzc4IiByeD0iOS4xOSIgcnk9IjcuODc3Ii8+PHBhdGggY2xhc3M9ImNscy0yIiBkPSJNNDAuMDk1IDU0LjMwNGMtMi42NjctNC42Mi0xLjYyLTEwLjIxNyAyLjM0LTEyLjUwM3M5LjMzLS4zOTQgMTEuOTk4IDQuMjI1IDEuNjE5IDEwLjIxNy0yLjM0IDEyLjUwMmMtMy45NiAyLjI4Ni05LjMzMS4zOTUtMTEuOTk4LTQuMjI0Wk01Mi41NzMgNzguOTMyYy0xNS44MTYgMi43OTIgNy43OTQtMjYuNDY0IDguNDk4LTEwLjA4MmExMS4yOTcgMTEuMjk3IDAgMCAxLTguNDk4IDEwLjA4MlpNNjYuMDk2IDU4LjI2NGMtMS4yNTIgMi45NzEtMi45OSAzLjkwNC00LjM3OCAxLjE0NGExNi45NTQgMTYuOTU0IDAgMCAxLS45NzctMTEuMTc1Yy43NDktMi43MDMgMi42MzYtMi44MyA0LjUxMi4zNmExMS4zNjQgMTEuMzY0IDAgMCAxIC44NDMgOS42NzFaIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSguMDggLjAwMikiLz48L3N2Zz4=" class="logo"> | |
<h1>Live Temperature Dashboard</h1> | |
</header> | |
<div class="frame"> | |
<div class="center"> | |
<div class="temparature-meter__container"> | |
<div class="temparature-meter__inner"> | |
<div class="temparature-meter__inner-ring"> | |
<div class="temparature-inside"> | |
<span id="temp-meter" class="temparature-count c1"></span> | |
<span class="temperature-sup">°</span> | |
</div> | |
<div class="temparature-meter__inner-label">Bedroom</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div id="temperature">Temperature: --</div> | |
<div class="chart-container"> | |
<canvas id="temperatureGraph"></canvas> | |
</div> | |
<script> | |
const socket = new WebSocket('ws://' + location.host + '/temperature'); | |
let chart; // Reference to the chart object | |
socket.addEventListener('message', ev => { | |
console.log(ev); | |
const temperature = parseFloat(ev.data); | |
updateGraph('temperatureGraph', 'Temperature (°C)', temperature); | |
updateTemperatureDisplay(temperature); | |
}); | |
function updateTemperatureDisplay(temperature) { | |
document.getElementById('temperature').textContent = `Temperature: ${temperature.toFixed(2)} °C`; | |
document.getElementById('temp-meter').textContent = temperature.toFixed(2); | |
} | |
function updateGraph(chartId, label, value) { | |
const ctx = document.getElementById(chartId).getContext('2d'); | |
if (!chart) { | |
chart = new Chart(ctx, { | |
type: 'line', | |
data: { | |
labels: Array.from({ length: 15 }, (_, i) => i + 1), | |
datasets: [{ | |
label: label, | |
data: Array(25).fill(value), // Fills array with 10 same values for initial chart setup | |
fill: true, | |
borderColor: '#148d04', | |
tension: 0.4 | |
}] | |
}, | |
options: { | |
scales: { | |
x: { | |
title: { | |
display: true, | |
text: 'Time', | |
color: '#ccc' | |
}, | |
grid: { | |
color: '#444' | |
}, | |
ticks: { | |
color: '#ccc' | |
} | |
}, | |
y: { | |
title: { | |
display: true, | |
text: label, | |
color: '#ccc' | |
}, | |
grid: { | |
color: '#444' | |
}, | |
ticks: { | |
color: '#ccc' | |
} | |
} | |
}, | |
plugins: { | |
legend: { | |
labels: { | |
color: '#ccc' | |
} | |
} | |
} | |
} | |
}); | |
} else { | |
// Update the existing chart data | |
chart.data.labels.push(new Date().toLocaleTimeString()); | |
chart.data.datasets[0].data.push(value); | |
if (chart.data.labels.length > 10) { | |
chart.data.labels.shift(); // Remove the oldest label | |
chart.data.datasets[0].data.shift(); // Remove the oldest data point | |
} | |
chart.update(); | |
} | |
} | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import machine | |
import time | |
import network | |
from microdot import Microdot, send_file | |
from microdot.websocket import with_websocket | |
def connect_to_wifi(): | |
sta_if = network.WLAN(network.STA_IF) | |
if not sta_if.isconnected(): | |
print("Connecting to the network...") | |
sta_if.active(True) | |
sta_if.connect("Airtel_RAJEEV", "00351553") | |
while not sta_if.isconnected(): | |
pass | |
print("Connected to IP: ", sta_if.ifconfig()[0]) | |
connect_to_wifi() | |
app = Microdot() | |
@app.route('/') | |
async def index(request): | |
return send_file("index.html") | |
@app.route('/temperature') | |
@with_websocket | |
async def index(request, ws): | |
while True: | |
adc = machine.ADC(4) # Use ADC pin GP4 | |
conversion_factor = 3.3 / (65535) # ADC conversion factor | |
sensor_value = adc.read_u16() * conversion_factor | |
temperature = 27 - (sensor_value - 0.706) / 0.001721 # Convert sensor value to temperature (formula may vary) | |
await ws.send(str(temperature)) | |
time.sleep(1) | |
app.run(debug= True) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment