micropidash 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- micropidash-1.0.0/LICENSE +21 -0
- micropidash-1.0.0/PKG-INFO +183 -0
- micropidash-1.0.0/README.md +169 -0
- micropidash-1.0.0/micropidash/__init__.py +8 -0
- micropidash-1.0.0/micropidash/micropidash.py +192 -0
- micropidash-1.0.0/micropidash.egg-info/PKG-INFO +183 -0
- micropidash-1.0.0/micropidash.egg-info/SOURCES.txt +10 -0
- micropidash-1.0.0/micropidash.egg-info/dependency_links.txt +1 -0
- micropidash-1.0.0/micropidash.egg-info/top_level.txt +1 -0
- micropidash-1.0.0/pyproject.toml +3 -0
- micropidash-1.0.0/setup.cfg +4 -0
- micropidash-1.0.0/setup.py +19 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kritish
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: micropidash
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A lightweight web dashboard for MicroPython (ESP32, Pico W)
|
|
5
|
+
Home-page: https://github.com/kritishmohapatra/micropidash
|
|
6
|
+
Author: Kritish Mohapatra
|
|
7
|
+
Author-email: kritishmohapatra06norisk@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
|
|
15
|
+
# 🚀 micropidash: Lightweight MicroPython IoT Dashboard
|
|
16
|
+
|
|
17
|
+
**micropidash** is a high-performance, asynchronous web dashboard library specifically designed for microcontrollers like the **Raspberry Pi Pico 2W** (RP2350/RP2040) and ESP32. It enables the creation of real-time, responsive web interfaces for IoT projects using minimal MicroPython code.
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<a href="https://micropython.org/"><img src="https://img.shields.io/badge/MicroPython-✓-green?logo=micropython&logoColor=white" alt="MicroPython"></a>
|
|
21
|
+
<a href="https://www.espressif.com/en/products/socs/esp32"><img src="https://img.shields.io/badge/ESP32-Supported-orange?logo=espressif&logoColor=white" alt="ESP32"></a>
|
|
22
|
+
<a href="https://www.raspberrypi.com/products/raspberry-pi-pico/"><img src="https://img.shields.io/badge/Raspberry%20Pi%20Pico%20 2 W-Compatible-darkgreen?logo=raspberrypi&logoColor=white" alt="Pico 2 W"></a>
|
|
23
|
+
<a href="https://github.com/kritishmohapatra/micropython-sevenseg/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-green?logo=open-source-initiative&logoColor=white" alt="License"></a>
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
</p>
|
|
27
|
+
|
|
28
|
+
**Author:** [Kritish Mohapatra]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## ✨ Key Features
|
|
34
|
+
* **Asynchronous Engine:** Built on `uasyncio` for non-blocking, multi-tasking performance.
|
|
35
|
+
* **Real-Time Sync:** AJAX-based polling ensures all connected devices (Mobile & Laptop) stay synced without page refreshes.
|
|
36
|
+
* **Client-Side Theming:** Every connected user can independently toggle between Dark and Light modes.
|
|
37
|
+
* **Order Preservation:** Uses alphabetical sorting for widget IDs to ensure your layout stays exactly as intended.
|
|
38
|
+
* **Memory Efficient:** Optimized for devices with limited RAM, featuring chunked data transmission and frequent garbage collection.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 📦 Installation
|
|
43
|
+
|
|
44
|
+
1. Upload `micropidash.py` to your microcontroller's root directory.
|
|
45
|
+
2. Create a `main.py` file to implement your project logic.
|
|
46
|
+
3. Ensure your device is connected to a stable 2.4GHz Wi-Fi network.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
## 📂 Project Structure
|
|
50
|
+
├── micropidash/
|
|
51
|
+
│ ├── init.py
|
|
52
|
+
│ └── micropidash.py
|
|
53
|
+
│
|
|
54
|
+
├── examples/
|
|
55
|
+
| ├── basic_1.py
|
|
56
|
+
│ └── esp_32_example.py
|
|
57
|
+
│
|
|
58
|
+
├── README.md
|
|
59
|
+
└── LICENSE
|
|
60
|
+
## 📚 API Documentation
|
|
61
|
+
|
|
62
|
+
### `Dashboard(title)`
|
|
63
|
+
Creates a new dashboard instance with the specified title.
|
|
64
|
+
* **title**: (String) The name displayed at the top of your web dashboard.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
### `add_toggle(id, label)`
|
|
69
|
+
Adds a binary switch (On/Off) to the dashboard.
|
|
70
|
+
* **id**: (String) Unique identifier for the widget. Also used for alphabetical sorting on the UI.
|
|
71
|
+
* **label**: (String) The text displayed above the switch.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### `add_label(id, label)`
|
|
76
|
+
Adds a text box designed for displaying live sensor data or status strings.
|
|
77
|
+
* **id**: (String) Unique identifier for the widget.
|
|
78
|
+
* **label**: (String) The descriptive text for the data being shown.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
### `add_level(id, label, color)`
|
|
83
|
+
Adds a graphical progress bar, perfect for humidity, tank levels, or battery percentage.
|
|
84
|
+
* **id**: (String) Unique identifier for the widget.
|
|
85
|
+
* **label**: (String) The descriptive text for the progress bar.
|
|
86
|
+
* **color**: (Hex/CSS Color) The color of the fill bar (e.g., `#2196F3` or `red`).
|
|
87
|
+
* **Value Range**: Expects an integer between $0$ and $100$.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
### `update_value(id, value)`
|
|
92
|
+
Injects new data into an existing widget. This change is pushed instantly to all connected web clients via the next poll.
|
|
93
|
+
* **id**: (String) The ID of the widget you want to update.
|
|
94
|
+
* **value**: (String/Int) The new data to display.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
## 🚀 Quick Start (Simple Example)
|
|
98
|
+
|
|
99
|
+
Use this minimal example to test your connection and ensure the dashboard is being served correctly on your local network.
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from micropidash import Dashboard
|
|
103
|
+
import network
|
|
104
|
+
|
|
105
|
+
# 1. WiFi Setup
|
|
106
|
+
wlan = network.WLAN(network.STA_IF)
|
|
107
|
+
wlan.active(True)
|
|
108
|
+
|
|
109
|
+
wlan.connect('YOUR_SSID', 'YOUR_PASSWORD')
|
|
110
|
+
|
|
111
|
+
print("Connecting...")
|
|
112
|
+
while not wlan.isconnected(): pass
|
|
113
|
+
print("Connected! IP:", wlan.ifconfig()[0])
|
|
114
|
+
|
|
115
|
+
# 2. Dashboard Initialization
|
|
116
|
+
dash = Dashboard("MicroPiDash v1.0")
|
|
117
|
+
|
|
118
|
+
# 3. Adding Basic Widgets
|
|
119
|
+
dash.add_toggle("led", "Test Switch") # A binary toggle
|
|
120
|
+
dash.add_label("status", "System Status") # A text display
|
|
121
|
+
dash.add_level("level", "Signal Strength") # A progress bar (0-100)
|
|
122
|
+
|
|
123
|
+
# 4. Start the Web Server
|
|
124
|
+
# Access the dashboard via the IP address printed above
|
|
125
|
+
dash.run()
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 🔌 ESP32 Onboard LED Example
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
import machine, network, uasyncio as asyncio
|
|
133
|
+
from micropidash import Dashboard
|
|
134
|
+
|
|
135
|
+
# 1. ESP32 Pin Setup (Most boards use GPIO 2 for built-in LED)
|
|
136
|
+
led = machine.Pin(2, machine.Pin.OUT)
|
|
137
|
+
|
|
138
|
+
# 2. WiFi Connectivity
|
|
139
|
+
wlan = network.WLAN(network.STA_IF)
|
|
140
|
+
wlan.active(True)
|
|
141
|
+
wlan.connect('YOUR_SSID', 'YOUR_PASSWORD')
|
|
142
|
+
|
|
143
|
+
print("Connecting...")
|
|
144
|
+
while not wlan.isconnected(): pass
|
|
145
|
+
print("Server Live at IP:", wlan.ifconfig()[0])
|
|
146
|
+
|
|
147
|
+
# 3. Dashboard Configuration
|
|
148
|
+
dash = Dashboard("ESP32 Control Hub")
|
|
149
|
+
dash.add_toggle("1_led", "Built-in LED")
|
|
150
|
+
dash.add_label("2_status", "Live Status")
|
|
151
|
+
|
|
152
|
+
# 4. Hardware & Web UI Sync Task
|
|
153
|
+
async def sync_task():
|
|
154
|
+
while True:
|
|
155
|
+
# Dashboard UI state ko physical LED se link karna
|
|
156
|
+
led.value(dash.elements["1_led"]["value"])
|
|
157
|
+
|
|
158
|
+
# Dashboard par status update bhejni
|
|
159
|
+
state = "GLOWING" if led.value() else "OFF"
|
|
160
|
+
dash.update_value("2_status", f"LED is {state}")
|
|
161
|
+
|
|
162
|
+
await asyncio.sleep(0.5)
|
|
163
|
+
|
|
164
|
+
# 5. Execution
|
|
165
|
+
async def main():
|
|
166
|
+
asyncio.create_task(sync_task())
|
|
167
|
+
dash.run()
|
|
168
|
+
|
|
169
|
+
asyncio.run(main())
|
|
170
|
+
```
|
|
171
|
+
## 🤝 Contributing
|
|
172
|
+
As an **Electrical Engineering student**, I built **micropidash** to simplify MicroPython IoT development and bridge the gap between hardware and web interfaces.
|
|
173
|
+
|
|
174
|
+
If you find bugs, have feature ideas, or want to optimize the code further, feel free to open an **issue** or submit a **pull request**! Let's build the future of embedded systems together.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
## 🌐 Author
|
|
178
|
+
|
|
179
|
+
**Kritish Mohapatra**
|
|
180
|
+
🔗 [GitHub](https://github.com/kritishmohapatra)
|
|
181
|
+
📧 kritishmohapatra06norisk@gmail.com
|
|
182
|
+
|
|
183
|
+
✨ *Made with passion for Embedded Systems and MicroPython learners.*
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# 🚀 micropidash: Lightweight MicroPython IoT Dashboard
|
|
2
|
+
|
|
3
|
+
**micropidash** is a high-performance, asynchronous web dashboard library specifically designed for microcontrollers like the **Raspberry Pi Pico 2W** (RP2350/RP2040) and ESP32. It enables the creation of real-time, responsive web interfaces for IoT projects using minimal MicroPython code.
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://micropython.org/"><img src="https://img.shields.io/badge/MicroPython-✓-green?logo=micropython&logoColor=white" alt="MicroPython"></a>
|
|
7
|
+
<a href="https://www.espressif.com/en/products/socs/esp32"><img src="https://img.shields.io/badge/ESP32-Supported-orange?logo=espressif&logoColor=white" alt="ESP32"></a>
|
|
8
|
+
<a href="https://www.raspberrypi.com/products/raspberry-pi-pico/"><img src="https://img.shields.io/badge/Raspberry%20Pi%20Pico%20 2 W-Compatible-darkgreen?logo=raspberrypi&logoColor=white" alt="Pico 2 W"></a>
|
|
9
|
+
<a href="https://github.com/kritishmohapatra/micropython-sevenseg/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-green?logo=open-source-initiative&logoColor=white" alt="License"></a>
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
**Author:** [Kritish Mohapatra]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## ✨ Key Features
|
|
20
|
+
* **Asynchronous Engine:** Built on `uasyncio` for non-blocking, multi-tasking performance.
|
|
21
|
+
* **Real-Time Sync:** AJAX-based polling ensures all connected devices (Mobile & Laptop) stay synced without page refreshes.
|
|
22
|
+
* **Client-Side Theming:** Every connected user can independently toggle between Dark and Light modes.
|
|
23
|
+
* **Order Preservation:** Uses alphabetical sorting for widget IDs to ensure your layout stays exactly as intended.
|
|
24
|
+
* **Memory Efficient:** Optimized for devices with limited RAM, featuring chunked data transmission and frequent garbage collection.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 📦 Installation
|
|
29
|
+
|
|
30
|
+
1. Upload `micropidash.py` to your microcontroller's root directory.
|
|
31
|
+
2. Create a `main.py` file to implement your project logic.
|
|
32
|
+
3. Ensure your device is connected to a stable 2.4GHz Wi-Fi network.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
## 📂 Project Structure
|
|
36
|
+
├── micropidash/
|
|
37
|
+
│ ├── init.py
|
|
38
|
+
│ └── micropidash.py
|
|
39
|
+
│
|
|
40
|
+
├── examples/
|
|
41
|
+
| ├── basic_1.py
|
|
42
|
+
│ └── esp_32_example.py
|
|
43
|
+
│
|
|
44
|
+
├── README.md
|
|
45
|
+
└── LICENSE
|
|
46
|
+
## 📚 API Documentation
|
|
47
|
+
|
|
48
|
+
### `Dashboard(title)`
|
|
49
|
+
Creates a new dashboard instance with the specified title.
|
|
50
|
+
* **title**: (String) The name displayed at the top of your web dashboard.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
### `add_toggle(id, label)`
|
|
55
|
+
Adds a binary switch (On/Off) to the dashboard.
|
|
56
|
+
* **id**: (String) Unique identifier for the widget. Also used for alphabetical sorting on the UI.
|
|
57
|
+
* **label**: (String) The text displayed above the switch.
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
### `add_label(id, label)`
|
|
62
|
+
Adds a text box designed for displaying live sensor data or status strings.
|
|
63
|
+
* **id**: (String) Unique identifier for the widget.
|
|
64
|
+
* **label**: (String) The descriptive text for the data being shown.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
### `add_level(id, label, color)`
|
|
69
|
+
Adds a graphical progress bar, perfect for humidity, tank levels, or battery percentage.
|
|
70
|
+
* **id**: (String) Unique identifier for the widget.
|
|
71
|
+
* **label**: (String) The descriptive text for the progress bar.
|
|
72
|
+
* **color**: (Hex/CSS Color) The color of the fill bar (e.g., `#2196F3` or `red`).
|
|
73
|
+
* **Value Range**: Expects an integer between $0$ and $100$.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
### `update_value(id, value)`
|
|
78
|
+
Injects new data into an existing widget. This change is pushed instantly to all connected web clients via the next poll.
|
|
79
|
+
* **id**: (String) The ID of the widget you want to update.
|
|
80
|
+
* **value**: (String/Int) The new data to display.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
## 🚀 Quick Start (Simple Example)
|
|
84
|
+
|
|
85
|
+
Use this minimal example to test your connection and ensure the dashboard is being served correctly on your local network.
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from micropidash import Dashboard
|
|
89
|
+
import network
|
|
90
|
+
|
|
91
|
+
# 1. WiFi Setup
|
|
92
|
+
wlan = network.WLAN(network.STA_IF)
|
|
93
|
+
wlan.active(True)
|
|
94
|
+
|
|
95
|
+
wlan.connect('YOUR_SSID', 'YOUR_PASSWORD')
|
|
96
|
+
|
|
97
|
+
print("Connecting...")
|
|
98
|
+
while not wlan.isconnected(): pass
|
|
99
|
+
print("Connected! IP:", wlan.ifconfig()[0])
|
|
100
|
+
|
|
101
|
+
# 2. Dashboard Initialization
|
|
102
|
+
dash = Dashboard("MicroPiDash v1.0")
|
|
103
|
+
|
|
104
|
+
# 3. Adding Basic Widgets
|
|
105
|
+
dash.add_toggle("led", "Test Switch") # A binary toggle
|
|
106
|
+
dash.add_label("status", "System Status") # A text display
|
|
107
|
+
dash.add_level("level", "Signal Strength") # A progress bar (0-100)
|
|
108
|
+
|
|
109
|
+
# 4. Start the Web Server
|
|
110
|
+
# Access the dashboard via the IP address printed above
|
|
111
|
+
dash.run()
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 🔌 ESP32 Onboard LED Example
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
import machine, network, uasyncio as asyncio
|
|
119
|
+
from micropidash import Dashboard
|
|
120
|
+
|
|
121
|
+
# 1. ESP32 Pin Setup (Most boards use GPIO 2 for built-in LED)
|
|
122
|
+
led = machine.Pin(2, machine.Pin.OUT)
|
|
123
|
+
|
|
124
|
+
# 2. WiFi Connectivity
|
|
125
|
+
wlan = network.WLAN(network.STA_IF)
|
|
126
|
+
wlan.active(True)
|
|
127
|
+
wlan.connect('YOUR_SSID', 'YOUR_PASSWORD')
|
|
128
|
+
|
|
129
|
+
print("Connecting...")
|
|
130
|
+
while not wlan.isconnected(): pass
|
|
131
|
+
print("Server Live at IP:", wlan.ifconfig()[0])
|
|
132
|
+
|
|
133
|
+
# 3. Dashboard Configuration
|
|
134
|
+
dash = Dashboard("ESP32 Control Hub")
|
|
135
|
+
dash.add_toggle("1_led", "Built-in LED")
|
|
136
|
+
dash.add_label("2_status", "Live Status")
|
|
137
|
+
|
|
138
|
+
# 4. Hardware & Web UI Sync Task
|
|
139
|
+
async def sync_task():
|
|
140
|
+
while True:
|
|
141
|
+
# Dashboard UI state ko physical LED se link karna
|
|
142
|
+
led.value(dash.elements["1_led"]["value"])
|
|
143
|
+
|
|
144
|
+
# Dashboard par status update bhejni
|
|
145
|
+
state = "GLOWING" if led.value() else "OFF"
|
|
146
|
+
dash.update_value("2_status", f"LED is {state}")
|
|
147
|
+
|
|
148
|
+
await asyncio.sleep(0.5)
|
|
149
|
+
|
|
150
|
+
# 5. Execution
|
|
151
|
+
async def main():
|
|
152
|
+
asyncio.create_task(sync_task())
|
|
153
|
+
dash.run()
|
|
154
|
+
|
|
155
|
+
asyncio.run(main())
|
|
156
|
+
```
|
|
157
|
+
## 🤝 Contributing
|
|
158
|
+
As an **Electrical Engineering student**, I built **micropidash** to simplify MicroPython IoT development and bridge the gap between hardware and web interfaces.
|
|
159
|
+
|
|
160
|
+
If you find bugs, have feature ideas, or want to optimize the code further, feel free to open an **issue** or submit a **pull request**! Let's build the future of embedded systems together.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
## 🌐 Author
|
|
164
|
+
|
|
165
|
+
**Kritish Mohapatra**
|
|
166
|
+
🔗 [GitHub](https://github.com/kritishmohapatra)
|
|
167
|
+
📧 kritishmohapatra06norisk@gmail.com
|
|
168
|
+
|
|
169
|
+
✨ *Made with passion for Embedded Systems and MicroPython learners.*
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import uasyncio as asyncio
|
|
2
|
+
import json, gc
|
|
3
|
+
|
|
4
|
+
class Dashboard:
|
|
5
|
+
def __init__(self, title="Pi IoT Lab"):
|
|
6
|
+
self.title = title
|
|
7
|
+
self.elements = {}
|
|
8
|
+
|
|
9
|
+
def add_toggle(self, id, label):
|
|
10
|
+
self.elements[id] = {"type": "toggle", "label": label, "value": 0}
|
|
11
|
+
|
|
12
|
+
def add_label(self, id, label):
|
|
13
|
+
self.elements[id] = {"type": "label", "label": label, "value": "---"}
|
|
14
|
+
|
|
15
|
+
def add_level(self, id, label, color="#4CAF50"):
|
|
16
|
+
self.elements[id] = {"type": "level", "label": label, "value": 0, "color": color}
|
|
17
|
+
|
|
18
|
+
def update_value(self, id, value):
|
|
19
|
+
if id in self.elements:
|
|
20
|
+
self.elements[id]["value"] = value
|
|
21
|
+
|
|
22
|
+
async def _send_html(self, writer):
|
|
23
|
+
# Header + CSS
|
|
24
|
+
html_start = f"""<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1">
|
|
25
|
+
<title>{self.title}</title>
|
|
26
|
+
<style>
|
|
27
|
+
:root {{
|
|
28
|
+
--bg:#f4f4f4;
|
|
29
|
+
--card:#fff;
|
|
30
|
+
--text:#000;
|
|
31
|
+
--primary:#4CAF50; }}
|
|
32
|
+
body {{
|
|
33
|
+
margin:0;
|
|
34
|
+
font-family:
|
|
35
|
+
sans-serif;
|
|
36
|
+
background:var(--bg);
|
|
37
|
+
color:var(--text);
|
|
38
|
+
text-align:center;
|
|
39
|
+
padding:10px; }}
|
|
40
|
+
.header {{
|
|
41
|
+
display:flex;
|
|
42
|
+
justify-content:
|
|
43
|
+
space-between;
|
|
44
|
+
align-items:center;
|
|
45
|
+
max-width:600px;
|
|
46
|
+
margin:0 auto 20px; }}
|
|
47
|
+
.grid {{ display: grid;
|
|
48
|
+
repeat(auto-fit, minmax(160px, 1fr));
|
|
49
|
+
gap: 15px;
|
|
50
|
+
max-width: 800px;
|
|
51
|
+
margin: 0 auto; }}
|
|
52
|
+
.card {{ background:var(--card);
|
|
53
|
+
padding:15px;
|
|
54
|
+
border-radius:12px;
|
|
55
|
+
box-shadow:0 3px 6px rgba(0,0,0,.1);
|
|
56
|
+
display:flex;
|
|
57
|
+
flex-direction:column;
|
|
58
|
+
align-items:center; gap:8px; }}
|
|
59
|
+
.p-bg {{ width:100%;
|
|
60
|
+
height:12px;
|
|
61
|
+
background:#bbb;
|
|
62
|
+
border-radius:6px;
|
|
63
|
+
overflow:hidden; }}
|
|
64
|
+
.p-fill {{
|
|
65
|
+
height:100%;
|
|
66
|
+
transition:width .4s; }}
|
|
67
|
+
.switch {{
|
|
68
|
+
position:relative;
|
|
69
|
+
width:48px;
|
|
70
|
+
height:26px; }}
|
|
71
|
+
.switch input {{
|
|
72
|
+
opacity:0;
|
|
73
|
+
width:0;
|
|
74
|
+
height:0; }}
|
|
75
|
+
.slider {{
|
|
76
|
+
position:absolute;
|
|
77
|
+
cursor:pointer;
|
|
78
|
+
inset:0;
|
|
79
|
+
background:#ccc;
|
|
80
|
+
border-radius:26px;
|
|
81
|
+
transition:.3s; }}
|
|
82
|
+
.slider:before {{
|
|
83
|
+
content:"";
|
|
84
|
+
position:absolute;
|
|
85
|
+
height:20px;
|
|
86
|
+
width:20px;
|
|
87
|
+
left:3px;
|
|
88
|
+
bottom:3px;
|
|
89
|
+
background:#fff;
|
|
90
|
+
border-radius:50%;
|
|
91
|
+
transition:.3s; }}
|
|
92
|
+
input:checked + .slider {{ background:var(--primary); }}
|
|
93
|
+
input:checked + .slider:before {{ transform:translateX(22px); }}
|
|
94
|
+
</style>
|
|
95
|
+
<script>
|
|
96
|
+
let dark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
97
|
+
function applyTheme() {{
|
|
98
|
+
document.documentElement.style.setProperty('--bg', dark ? '#121212' : '#f4f4f4');
|
|
99
|
+
document.documentElement.style.setProperty('--card', dark ? '#1e1e1e' : '#fff');
|
|
100
|
+
document.documentElement.style.setProperty('--text', dark ? '#fff' : '#000');
|
|
101
|
+
}}
|
|
102
|
+
function updateData(){{
|
|
103
|
+
fetch('/data').then(r=>r.json()).then(d=>{{
|
|
104
|
+
for(let id in d){{
|
|
105
|
+
let i=d[id]; let tx=document.getElementById(id); let sw=document.getElementById(id+"-sw");
|
|
106
|
+
if(!tx)continue;
|
|
107
|
+
if(i.type==="level"){{ tx.style.width=i.value+"%"; document.getElementById(id+"-txt").innerText=i.value+"%"; }}
|
|
108
|
+
else if(i.type==="toggle"){{ tx.innerText=i.value?"ON":"OFF"; tx.style.color=i.value? "var(--primary)":"#888"; if(sw) sw.checked=!!i.value; }}
|
|
109
|
+
else {{ tx.innerText=i.value; }}
|
|
110
|
+
}}
|
|
111
|
+
}});
|
|
112
|
+
}}
|
|
113
|
+
setInterval(updateData, 1200);
|
|
114
|
+
function sendCmd(id){{ fetch('/?'+id+'=toggle'); }}
|
|
115
|
+
|
|
116
|
+
// FIXED BRACES HERE
|
|
117
|
+
function toggleTheme() {{
|
|
118
|
+
dark=!dark;
|
|
119
|
+
applyTheme();
|
|
120
|
+
document.getElementById("themeBtn").innerText = dark ? "☀️" : "🌙";
|
|
121
|
+
}}
|
|
122
|
+
|
|
123
|
+
</script></head><body onload="applyTheme()">
|
|
124
|
+
<div class="header">
|
|
125
|
+
<h1>{self.title}</h1>
|
|
126
|
+
<button id="themeBtn" onclick="toggleTheme()" style="background:none;border:none;font-size:24px;cursor:pointer;">🌙</button>
|
|
127
|
+
</div>
|
|
128
|
+
<div class="grid">"""
|
|
129
|
+
|
|
130
|
+
writer.write(b"HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n")
|
|
131
|
+
writer.write(html_start.encode())
|
|
132
|
+
|
|
133
|
+
# Cards generation
|
|
134
|
+
sorted_keys = sorted(self.elements.keys())
|
|
135
|
+
|
|
136
|
+
for id in sorted_keys:
|
|
137
|
+
info = self.elements[id]
|
|
138
|
+
card = f"<div class='card'><strong>{info['label']}</strong>"
|
|
139
|
+
if info["type"] == "level":
|
|
140
|
+
card += f'<div id="{id}-txt">{info["value"]}%</div><div class="p-bg"><div id="{id}" class="p-fill" style="width:{info["value"]}%;background:{info["color"]}"></div></div>'
|
|
141
|
+
elif info["type"] == "toggle":
|
|
142
|
+
state = "ON" if info["value"] else "OFF"
|
|
143
|
+
c = "checked" if info["value"] else ""
|
|
144
|
+
|
|
145
|
+
card += f'''
|
|
146
|
+
<div style="display:flex;align-items:center;gap:10px;">
|
|
147
|
+
<span id="{id}" style="font-weight:bold;color:{'var(--primary)' if info["value"] else '#888'}">
|
|
148
|
+
{state}
|
|
149
|
+
</span>
|
|
150
|
+
<label class="switch">
|
|
151
|
+
<input type="checkbox" id="{id}-sw" onchange="sendCmd('{id}')" {c}>
|
|
152
|
+
<span class="slider"></span>
|
|
153
|
+
</label>
|
|
154
|
+
</div>
|
|
155
|
+
'''
|
|
156
|
+
else:
|
|
157
|
+
card += f"<div id='{id}' style='font-size:20px;font-weight:bold;'>{info['value']}</div>"
|
|
158
|
+
card += "</div>"
|
|
159
|
+
writer.write(card.encode())
|
|
160
|
+
|
|
161
|
+
writer.write(b"</div></body></html>")
|
|
162
|
+
await writer.drain()
|
|
163
|
+
|
|
164
|
+
async def _handle_request(self, reader, writer):
|
|
165
|
+
try:
|
|
166
|
+
raw = await reader.readline()
|
|
167
|
+
if not raw: return
|
|
168
|
+
req = raw.decode()
|
|
169
|
+
while await reader.readline() != b'\r\n': pass
|
|
170
|
+
|
|
171
|
+
if "/data" in req:
|
|
172
|
+
body = json.dumps({k: {"type": v["type"], "value": v["value"]} for k,v in self.elements.items()})
|
|
173
|
+
writer.write(b"HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n")
|
|
174
|
+
writer.write(body.encode())
|
|
175
|
+
elif "toggle" in req:
|
|
176
|
+
for k,v in self.elements.items():
|
|
177
|
+
if f"{k}=toggle" in req: v["value"] ^= 1
|
|
178
|
+
writer.write(b"HTTP/1.1 200 OK\r\n\r\n")
|
|
179
|
+
else:
|
|
180
|
+
await self._send_html(writer)
|
|
181
|
+
await writer.drain()
|
|
182
|
+
except Exception as e:
|
|
183
|
+
print("Dashboard error:", e)
|
|
184
|
+
finally:
|
|
185
|
+
await writer.wait_closed()
|
|
186
|
+
gc.collect()
|
|
187
|
+
|
|
188
|
+
def run(self, port=80):
|
|
189
|
+
print(f"Pico Dashboard Live on Port {port}")
|
|
190
|
+
loop = asyncio.get_event_loop()
|
|
191
|
+
loop.create_task(asyncio.start_server(self._handle_request, "0.0.0.0", port))
|
|
192
|
+
loop.run_forever()
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: micropidash
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A lightweight web dashboard for MicroPython (ESP32, Pico W)
|
|
5
|
+
Home-page: https://github.com/kritishmohapatra/micropidash
|
|
6
|
+
Author: Kritish Mohapatra
|
|
7
|
+
Author-email: kritishmohapatra06norisk@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
|
|
15
|
+
# 🚀 micropidash: Lightweight MicroPython IoT Dashboard
|
|
16
|
+
|
|
17
|
+
**micropidash** is a high-performance, asynchronous web dashboard library specifically designed for microcontrollers like the **Raspberry Pi Pico 2W** (RP2350/RP2040) and ESP32. It enables the creation of real-time, responsive web interfaces for IoT projects using minimal MicroPython code.
|
|
18
|
+
|
|
19
|
+
<p align="center">
|
|
20
|
+
<a href="https://micropython.org/"><img src="https://img.shields.io/badge/MicroPython-✓-green?logo=micropython&logoColor=white" alt="MicroPython"></a>
|
|
21
|
+
<a href="https://www.espressif.com/en/products/socs/esp32"><img src="https://img.shields.io/badge/ESP32-Supported-orange?logo=espressif&logoColor=white" alt="ESP32"></a>
|
|
22
|
+
<a href="https://www.raspberrypi.com/products/raspberry-pi-pico/"><img src="https://img.shields.io/badge/Raspberry%20Pi%20Pico%20 2 W-Compatible-darkgreen?logo=raspberrypi&logoColor=white" alt="Pico 2 W"></a>
|
|
23
|
+
<a href="https://github.com/kritishmohapatra/micropython-sevenseg/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-green?logo=open-source-initiative&logoColor=white" alt="License"></a>
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
</p>
|
|
27
|
+
|
|
28
|
+
**Author:** [Kritish Mohapatra]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## ✨ Key Features
|
|
34
|
+
* **Asynchronous Engine:** Built on `uasyncio` for non-blocking, multi-tasking performance.
|
|
35
|
+
* **Real-Time Sync:** AJAX-based polling ensures all connected devices (Mobile & Laptop) stay synced without page refreshes.
|
|
36
|
+
* **Client-Side Theming:** Every connected user can independently toggle between Dark and Light modes.
|
|
37
|
+
* **Order Preservation:** Uses alphabetical sorting for widget IDs to ensure your layout stays exactly as intended.
|
|
38
|
+
* **Memory Efficient:** Optimized for devices with limited RAM, featuring chunked data transmission and frequent garbage collection.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 📦 Installation
|
|
43
|
+
|
|
44
|
+
1. Upload `micropidash.py` to your microcontroller's root directory.
|
|
45
|
+
2. Create a `main.py` file to implement your project logic.
|
|
46
|
+
3. Ensure your device is connected to a stable 2.4GHz Wi-Fi network.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
## 📂 Project Structure
|
|
50
|
+
├── micropidash/
|
|
51
|
+
│ ├── init.py
|
|
52
|
+
│ └── micropidash.py
|
|
53
|
+
│
|
|
54
|
+
├── examples/
|
|
55
|
+
| ├── basic_1.py
|
|
56
|
+
│ └── esp_32_example.py
|
|
57
|
+
│
|
|
58
|
+
├── README.md
|
|
59
|
+
└── LICENSE
|
|
60
|
+
## 📚 API Documentation
|
|
61
|
+
|
|
62
|
+
### `Dashboard(title)`
|
|
63
|
+
Creates a new dashboard instance with the specified title.
|
|
64
|
+
* **title**: (String) The name displayed at the top of your web dashboard.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
### `add_toggle(id, label)`
|
|
69
|
+
Adds a binary switch (On/Off) to the dashboard.
|
|
70
|
+
* **id**: (String) Unique identifier for the widget. Also used for alphabetical sorting on the UI.
|
|
71
|
+
* **label**: (String) The text displayed above the switch.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### `add_label(id, label)`
|
|
76
|
+
Adds a text box designed for displaying live sensor data or status strings.
|
|
77
|
+
* **id**: (String) Unique identifier for the widget.
|
|
78
|
+
* **label**: (String) The descriptive text for the data being shown.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
### `add_level(id, label, color)`
|
|
83
|
+
Adds a graphical progress bar, perfect for humidity, tank levels, or battery percentage.
|
|
84
|
+
* **id**: (String) Unique identifier for the widget.
|
|
85
|
+
* **label**: (String) The descriptive text for the progress bar.
|
|
86
|
+
* **color**: (Hex/CSS Color) The color of the fill bar (e.g., `#2196F3` or `red`).
|
|
87
|
+
* **Value Range**: Expects an integer between $0$ and $100$.
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
### `update_value(id, value)`
|
|
92
|
+
Injects new data into an existing widget. This change is pushed instantly to all connected web clients via the next poll.
|
|
93
|
+
* **id**: (String) The ID of the widget you want to update.
|
|
94
|
+
* **value**: (String/Int) The new data to display.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
## 🚀 Quick Start (Simple Example)
|
|
98
|
+
|
|
99
|
+
Use this minimal example to test your connection and ensure the dashboard is being served correctly on your local network.
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
from micropidash import Dashboard
|
|
103
|
+
import network
|
|
104
|
+
|
|
105
|
+
# 1. WiFi Setup
|
|
106
|
+
wlan = network.WLAN(network.STA_IF)
|
|
107
|
+
wlan.active(True)
|
|
108
|
+
|
|
109
|
+
wlan.connect('YOUR_SSID', 'YOUR_PASSWORD')
|
|
110
|
+
|
|
111
|
+
print("Connecting...")
|
|
112
|
+
while not wlan.isconnected(): pass
|
|
113
|
+
print("Connected! IP:", wlan.ifconfig()[0])
|
|
114
|
+
|
|
115
|
+
# 2. Dashboard Initialization
|
|
116
|
+
dash = Dashboard("MicroPiDash v1.0")
|
|
117
|
+
|
|
118
|
+
# 3. Adding Basic Widgets
|
|
119
|
+
dash.add_toggle("led", "Test Switch") # A binary toggle
|
|
120
|
+
dash.add_label("status", "System Status") # A text display
|
|
121
|
+
dash.add_level("level", "Signal Strength") # A progress bar (0-100)
|
|
122
|
+
|
|
123
|
+
# 4. Start the Web Server
|
|
124
|
+
# Access the dashboard via the IP address printed above
|
|
125
|
+
dash.run()
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### 🔌 ESP32 Onboard LED Example
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
import machine, network, uasyncio as asyncio
|
|
133
|
+
from micropidash import Dashboard
|
|
134
|
+
|
|
135
|
+
# 1. ESP32 Pin Setup (Most boards use GPIO 2 for built-in LED)
|
|
136
|
+
led = machine.Pin(2, machine.Pin.OUT)
|
|
137
|
+
|
|
138
|
+
# 2. WiFi Connectivity
|
|
139
|
+
wlan = network.WLAN(network.STA_IF)
|
|
140
|
+
wlan.active(True)
|
|
141
|
+
wlan.connect('YOUR_SSID', 'YOUR_PASSWORD')
|
|
142
|
+
|
|
143
|
+
print("Connecting...")
|
|
144
|
+
while not wlan.isconnected(): pass
|
|
145
|
+
print("Server Live at IP:", wlan.ifconfig()[0])
|
|
146
|
+
|
|
147
|
+
# 3. Dashboard Configuration
|
|
148
|
+
dash = Dashboard("ESP32 Control Hub")
|
|
149
|
+
dash.add_toggle("1_led", "Built-in LED")
|
|
150
|
+
dash.add_label("2_status", "Live Status")
|
|
151
|
+
|
|
152
|
+
# 4. Hardware & Web UI Sync Task
|
|
153
|
+
async def sync_task():
|
|
154
|
+
while True:
|
|
155
|
+
# Dashboard UI state ko physical LED se link karna
|
|
156
|
+
led.value(dash.elements["1_led"]["value"])
|
|
157
|
+
|
|
158
|
+
# Dashboard par status update bhejni
|
|
159
|
+
state = "GLOWING" if led.value() else "OFF"
|
|
160
|
+
dash.update_value("2_status", f"LED is {state}")
|
|
161
|
+
|
|
162
|
+
await asyncio.sleep(0.5)
|
|
163
|
+
|
|
164
|
+
# 5. Execution
|
|
165
|
+
async def main():
|
|
166
|
+
asyncio.create_task(sync_task())
|
|
167
|
+
dash.run()
|
|
168
|
+
|
|
169
|
+
asyncio.run(main())
|
|
170
|
+
```
|
|
171
|
+
## 🤝 Contributing
|
|
172
|
+
As an **Electrical Engineering student**, I built **micropidash** to simplify MicroPython IoT development and bridge the gap between hardware and web interfaces.
|
|
173
|
+
|
|
174
|
+
If you find bugs, have feature ideas, or want to optimize the code further, feel free to open an **issue** or submit a **pull request**! Let's build the future of embedded systems together.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
## 🌐 Author
|
|
178
|
+
|
|
179
|
+
**Kritish Mohapatra**
|
|
180
|
+
🔗 [GitHub](https://github.com/kritishmohapatra)
|
|
181
|
+
📧 kritishmohapatra06norisk@gmail.com
|
|
182
|
+
|
|
183
|
+
✨ *Made with passion for Embedded Systems and MicroPython learners.*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
micropidash
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="micropidash",
|
|
5
|
+
version="1.0.0",
|
|
6
|
+
description="A lightweight web dashboard for MicroPython (ESP32, Pico W)",
|
|
7
|
+
long_description=open("README.md", encoding="utf-8").read(),
|
|
8
|
+
long_description_content_type="text/markdown",
|
|
9
|
+
author="Kritish Mohapatra",
|
|
10
|
+
author_email="kritishmohapatra06norisk@gmail.com",
|
|
11
|
+
url="https://github.com/kritishmohapatra/micropidash",
|
|
12
|
+
license="MIT",
|
|
13
|
+
packages=find_packages(),
|
|
14
|
+
classifiers=[
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
],
|
|
19
|
+
)
|