espark-core 0.5.5__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.
Potentially problematic release.
This version of espark-core might be problematic. Click here for more details.
- espark_core-0.5.5/LICENSE +21 -0
- espark_core-0.5.5/MANIFEST.in +4 -0
- espark_core-0.5.5/PKG-INFO +139 -0
- espark_core-0.5.5/README.md +102 -0
- espark_core-0.5.5/espark_core.egg-info/PKG-INFO +139 -0
- espark_core-0.5.5/espark_core.egg-info/SOURCES.txt +85 -0
- espark_core-0.5.5/espark_core.egg-info/dependency_links.txt +1 -0
- espark_core-0.5.5/espark_core.egg-info/requires.txt +21 -0
- espark_core-0.5.5/espark_core.egg-info/top_level.txt +1 -0
- espark_core-0.5.5/esparkcore/__init__.py +0 -0
- espark_core-0.5.5/esparkcore/constants.py +11 -0
- espark_core-0.5.5/esparkcore/data/__init__.py +1 -0
- espark_core-0.5.5/esparkcore/data/database.py +15 -0
- espark_core-0.5.5/esparkcore/data/models/__init__.py +6 -0
- espark_core-0.5.5/esparkcore/data/models/device.py +15 -0
- espark_core-0.5.5/esparkcore/data/models/notification.py +11 -0
- espark_core-0.5.5/esparkcore/data/models/outbox.py +20 -0
- espark_core-0.5.5/esparkcore/data/models/telemetry.py +12 -0
- espark_core-0.5.5/esparkcore/data/models/trigger.py +13 -0
- espark_core-0.5.5/esparkcore/data/models/version.py +6 -0
- espark_core-0.5.5/esparkcore/data/repositories/__init__.py +7 -0
- espark_core-0.5.5/esparkcore/data/repositories/base_repository.py +70 -0
- espark_core-0.5.5/esparkcore/data/repositories/device_repository.py +26 -0
- espark_core-0.5.5/esparkcore/data/repositories/notification_repository.py +7 -0
- espark_core-0.5.5/esparkcore/data/repositories/outbox_repository.py +22 -0
- espark_core-0.5.5/esparkcore/data/repositories/telemetry_repository.py +48 -0
- espark_core-0.5.5/esparkcore/data/repositories/trigger_repository.py +7 -0
- espark_core-0.5.5/esparkcore/data/repositories/version_repository.py +11 -0
- espark_core-0.5.5/esparkcore/notifications/__init__.py +2 -0
- espark_core-0.5.5/esparkcore/notifications/notifier.py +14 -0
- espark_core-0.5.5/esparkcore/notifications/slack_notifier.py +17 -0
- espark_core-0.5.5/esparkcore/routers/__init__.py +5 -0
- espark_core-0.5.5/esparkcore/routers/base_router.py +97 -0
- espark_core-0.5.5/esparkcore/routers/device_router.py +57 -0
- espark_core-0.5.5/esparkcore/routers/notification_router.py +10 -0
- espark_core-0.5.5/esparkcore/routers/telemetry_router.py +55 -0
- espark_core-0.5.5/esparkcore/routers/trigger_router.py +10 -0
- espark_core-0.5.5/esparkcore/routers/version_router.py +10 -0
- espark_core-0.5.5/esparkcore/schedules/__init__.py +2 -0
- espark_core-0.5.5/esparkcore/schedules/outbox.py +24 -0
- espark_core-0.5.5/esparkcore/schedules/scheduler.py +8 -0
- espark_core-0.5.5/esparkcore/services/__init__.py +1 -0
- espark_core-0.5.5/esparkcore/services/mqtt.py +175 -0
- espark_core-0.5.5/esparkcore/utils/__init__.py +1 -0
- espark_core-0.5.5/esparkcore/utils/logging.py +11 -0
- espark_core-0.5.5/requirements.dev.txt +11 -0
- espark_core-0.5.5/requirements.txt +8 -0
- espark_core-0.5.5/setup.cfg +7 -0
- espark_core-0.5.5/setup.py +30 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Alan Tai
|
|
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,139 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: espark-core
|
|
3
|
+
Version: 0.5.5
|
|
4
|
+
Summary: The core module of the Espark ESP32-based IoT device management framework.
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: aiomqtt>=2.5.0
|
|
10
|
+
Requires-Dist: apscheduler>=3.11.2
|
|
11
|
+
Requires-Dist: fastapi>=0.128.0
|
|
12
|
+
Requires-Dist: packaging>=25.0
|
|
13
|
+
Requires-Dist: slack-sdk==3.39.0
|
|
14
|
+
Requires-Dist: sqlalchemy>=2.0.45
|
|
15
|
+
Requires-Dist: sqlmodel>=0.0.31
|
|
16
|
+
Requires-Dist: uvicorn[standard]>=0.40.0
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: aiosqlite==0.22.1; extra == "dev"
|
|
19
|
+
Requires-Dist: autopep8==2.3.2; extra == "dev"
|
|
20
|
+
Requires-Dist: build==1.3.0; extra == "dev"
|
|
21
|
+
Requires-Dist: fastapi-cli[standard-no-fastapi-cloud-cli]==0.0.20; extra == "dev"
|
|
22
|
+
Requires-Dist: httpx==0.28.1; extra == "dev"
|
|
23
|
+
Requires-Dist: pycodestyle==2.14.0; extra == "dev"
|
|
24
|
+
Requires-Dist: pylint==4.0.4; extra == "dev"
|
|
25
|
+
Requires-Dist: pytest==9.0.2; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-asyncio==1.3.0; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-cov==7.0.0; extra == "dev"
|
|
28
|
+
Requires-Dist: twine==6.2.0; extra == "dev"
|
|
29
|
+
Dynamic: description
|
|
30
|
+
Dynamic: description-content-type
|
|
31
|
+
Dynamic: license
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
Dynamic: provides-extra
|
|
34
|
+
Dynamic: requires-dist
|
|
35
|
+
Dynamic: requires-python
|
|
36
|
+
Dynamic: summary
|
|
37
|
+
|
|
38
|
+
# Espark
|
|
39
|
+
|
|
40
|
+
Espark is a lightweight framework for building scalable and efficient ESP32-based IoT applications. It provides a modular architecture, easy-to-use APIs, and built-in support for common IoT protocols.
|
|
41
|
+
|
|
42
|
+
## Project Goals
|
|
43
|
+
|
|
44
|
+
- Simplify the development of ESP32 applications.
|
|
45
|
+
- Provide a modular and extensible architecture.
|
|
46
|
+
- Support common IoT protocols like MQTT.
|
|
47
|
+
- Ensure efficient resource management for low-power devices.
|
|
48
|
+
- Provide a clean and easy-to-use API.
|
|
49
|
+
- Provide an user-friendly UI for configuration and monitoring.
|
|
50
|
+
|
|
51
|
+
## Features
|
|
52
|
+
|
|
53
|
+
- **Device Provisioning**: Easy setup and configuration of ESP32 devices.
|
|
54
|
+
- **Telemetry Collection**: Built-in support for collecting and sending telemetry data.
|
|
55
|
+
- **Scalable Architecture**: Designed to handle a large number of devices efficiently.
|
|
56
|
+
- **Seamless Communication**: Support for MQTT protocol.
|
|
57
|
+
|
|
58
|
+
## Hardware Requirements
|
|
59
|
+
|
|
60
|
+
- ESP32 Development Board
|
|
61
|
+
- USB Cable for programming and power
|
|
62
|
+
- Optional: Sensors and triggers for specific applications
|
|
63
|
+
|
|
64
|
+
## Project Structure
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
espark/
|
|
68
|
+
├── espark-core/
|
|
69
|
+
│ ├── esparkcore/ # FastAPI backend framework
|
|
70
|
+
│ │ ├── data/ # Models, repositories
|
|
71
|
+
│ │ ├── routers/ # API endpoints
|
|
72
|
+
│ │ ├── schedules/ # Background tasks
|
|
73
|
+
│ │ ├── services/ # Business logic, MQTT handling
|
|
74
|
+
│ │ └── utils/ # Utility functions
|
|
75
|
+
│ └── Makefile
|
|
76
|
+
├── espark-node/
|
|
77
|
+
│ ├── esparknode/ # MicroPython application framework
|
|
78
|
+
│ │ ├── actions/ # Action handlers
|
|
79
|
+
│ │ ├── data/ # Data storage
|
|
80
|
+
│ │ ├── libraries/ # External libraries
|
|
81
|
+
│ │ ├── networks/ # Network management
|
|
82
|
+
│ │ ├── sensors/ # Sensor interfaces
|
|
83
|
+
│ │ ├── triggers/ # Trigger interfaces
|
|
84
|
+
│ │ ├── utils/ # Utility functions
|
|
85
|
+
│ │ └── base_node.py # Main application file
|
|
86
|
+
│ └── Makefile
|
|
87
|
+
└── espark-react/ # React frontend application
|
|
88
|
+
├── src/
|
|
89
|
+
│ ├── data/ # Data models and data providers
|
|
90
|
+
│ ├── i18n/ # Internationalization files
|
|
91
|
+
│ ├── pages/ # Application pages
|
|
92
|
+
│ ├── routes/ # Application routing
|
|
93
|
+
│ ├── utils/ # Utility functions
|
|
94
|
+
│ ├── App.tsx # Main application component
|
|
95
|
+
│ └── index.tsx # Application entry point
|
|
96
|
+
└── package.json
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Development Workflows
|
|
100
|
+
|
|
101
|
+
### Setting up the backend
|
|
102
|
+
|
|
103
|
+
1. Add espark-core as a dependency in your FastAPI project.
|
|
104
|
+
2. Configure database connections and MQTT settings as environment variables.
|
|
105
|
+
3. Implement additional data models, repositories, routers, and business logic if needed.
|
|
106
|
+
4. Add the `DeviceRouter`, `TelemetryRouter`, and other additional routers to your FastAPI app.
|
|
107
|
+
|
|
108
|
+
### Setting up the ESP32 application
|
|
109
|
+
|
|
110
|
+
1. Clone the espark-node repository to your local machine.
|
|
111
|
+
2. Copy `espark-core/Makefile.template` to `Makefile` and customize it for your device.
|
|
112
|
+
3. Run `make upgrade` to copy the espark-core library to your device project.
|
|
113
|
+
4. Implement device-specific actions, sensors, and triggers as needed.
|
|
114
|
+
5. Run `make flash` to upload the firmware to your ESP32 device.
|
|
115
|
+
6. Run `make deploy` to upload the application to the device.
|
|
116
|
+
|
|
117
|
+
### Setting up the frontend
|
|
118
|
+
|
|
119
|
+
1. Add espark-react as a dependency in your React project.
|
|
120
|
+
2. Render `<EsparkApp />` in your main application file.
|
|
121
|
+
|
|
122
|
+
### Configurations
|
|
123
|
+
|
|
124
|
+
- **espark-core**: Use environment variables, or `.env` file, for database and MQTT configurations.
|
|
125
|
+
- **espark-node**: Use `esparknode.configs` for device-specific configurations.
|
|
126
|
+
- **espark-react**: Customise `EsparkApp` props for application settings.
|
|
127
|
+
|
|
128
|
+
## Examples and Patterns
|
|
129
|
+
|
|
130
|
+
- **Router Example**: `device_router.py` in `espark-core/esparkcore/routers/` demonstrates how to create API endpoints for device management.
|
|
131
|
+
- **Respository Example**: `device_repository.py` in `espark-core/esparkcore/data/repositories/` shows how to implement data access logic for devices.
|
|
132
|
+
- **Action Example**: `esp32_relay.py` in `espark-node/esparknode/actions/` illustrates how to define actions for ESP32 devices.
|
|
133
|
+
- **Sensor Example**: `sht20_sensor.py` in `espark-node/esparknode/sensors/` demonstrates how to read data from a SHT20 sensor.
|
|
134
|
+
- **Trigger Example**: `gpio_trigger.py` in `espark-node/esparknode/triggers/` shows how to create GPIO-based triggers for device actions.
|
|
135
|
+
- **List, Show, Edit Screens Example**: `DeviceList`, `DeviceShow`, and `DeviceEdit` components in `espark-react/src/pages/devices/` demonstrate how to create CRUD screens for device management.
|
|
136
|
+
|
|
137
|
+
## Example Projects
|
|
138
|
+
|
|
139
|
+
- **Espartan**: A smart thermostat and open-door alert automation system using ESP32-C3 devices, leveraging espark for device management and telemetry, available at [https://github.com/ayltai/Espartan](https://github.com/ayltai/Espartan).
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Espark
|
|
2
|
+
|
|
3
|
+
Espark is a lightweight framework for building scalable and efficient ESP32-based IoT applications. It provides a modular architecture, easy-to-use APIs, and built-in support for common IoT protocols.
|
|
4
|
+
|
|
5
|
+
## Project Goals
|
|
6
|
+
|
|
7
|
+
- Simplify the development of ESP32 applications.
|
|
8
|
+
- Provide a modular and extensible architecture.
|
|
9
|
+
- Support common IoT protocols like MQTT.
|
|
10
|
+
- Ensure efficient resource management for low-power devices.
|
|
11
|
+
- Provide a clean and easy-to-use API.
|
|
12
|
+
- Provide an user-friendly UI for configuration and monitoring.
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
- **Device Provisioning**: Easy setup and configuration of ESP32 devices.
|
|
17
|
+
- **Telemetry Collection**: Built-in support for collecting and sending telemetry data.
|
|
18
|
+
- **Scalable Architecture**: Designed to handle a large number of devices efficiently.
|
|
19
|
+
- **Seamless Communication**: Support for MQTT protocol.
|
|
20
|
+
|
|
21
|
+
## Hardware Requirements
|
|
22
|
+
|
|
23
|
+
- ESP32 Development Board
|
|
24
|
+
- USB Cable for programming and power
|
|
25
|
+
- Optional: Sensors and triggers for specific applications
|
|
26
|
+
|
|
27
|
+
## Project Structure
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
espark/
|
|
31
|
+
├── espark-core/
|
|
32
|
+
│ ├── esparkcore/ # FastAPI backend framework
|
|
33
|
+
│ │ ├── data/ # Models, repositories
|
|
34
|
+
│ │ ├── routers/ # API endpoints
|
|
35
|
+
│ │ ├── schedules/ # Background tasks
|
|
36
|
+
│ │ ├── services/ # Business logic, MQTT handling
|
|
37
|
+
│ │ └── utils/ # Utility functions
|
|
38
|
+
│ └── Makefile
|
|
39
|
+
├── espark-node/
|
|
40
|
+
│ ├── esparknode/ # MicroPython application framework
|
|
41
|
+
│ │ ├── actions/ # Action handlers
|
|
42
|
+
│ │ ├── data/ # Data storage
|
|
43
|
+
│ │ ├── libraries/ # External libraries
|
|
44
|
+
│ │ ├── networks/ # Network management
|
|
45
|
+
│ │ ├── sensors/ # Sensor interfaces
|
|
46
|
+
│ │ ├── triggers/ # Trigger interfaces
|
|
47
|
+
│ │ ├── utils/ # Utility functions
|
|
48
|
+
│ │ └── base_node.py # Main application file
|
|
49
|
+
│ └── Makefile
|
|
50
|
+
└── espark-react/ # React frontend application
|
|
51
|
+
├── src/
|
|
52
|
+
│ ├── data/ # Data models and data providers
|
|
53
|
+
│ ├── i18n/ # Internationalization files
|
|
54
|
+
│ ├── pages/ # Application pages
|
|
55
|
+
│ ├── routes/ # Application routing
|
|
56
|
+
│ ├── utils/ # Utility functions
|
|
57
|
+
│ ├── App.tsx # Main application component
|
|
58
|
+
│ └── index.tsx # Application entry point
|
|
59
|
+
└── package.json
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Development Workflows
|
|
63
|
+
|
|
64
|
+
### Setting up the backend
|
|
65
|
+
|
|
66
|
+
1. Add espark-core as a dependency in your FastAPI project.
|
|
67
|
+
2. Configure database connections and MQTT settings as environment variables.
|
|
68
|
+
3. Implement additional data models, repositories, routers, and business logic if needed.
|
|
69
|
+
4. Add the `DeviceRouter`, `TelemetryRouter`, and other additional routers to your FastAPI app.
|
|
70
|
+
|
|
71
|
+
### Setting up the ESP32 application
|
|
72
|
+
|
|
73
|
+
1. Clone the espark-node repository to your local machine.
|
|
74
|
+
2. Copy `espark-core/Makefile.template` to `Makefile` and customize it for your device.
|
|
75
|
+
3. Run `make upgrade` to copy the espark-core library to your device project.
|
|
76
|
+
4. Implement device-specific actions, sensors, and triggers as needed.
|
|
77
|
+
5. Run `make flash` to upload the firmware to your ESP32 device.
|
|
78
|
+
6. Run `make deploy` to upload the application to the device.
|
|
79
|
+
|
|
80
|
+
### Setting up the frontend
|
|
81
|
+
|
|
82
|
+
1. Add espark-react as a dependency in your React project.
|
|
83
|
+
2. Render `<EsparkApp />` in your main application file.
|
|
84
|
+
|
|
85
|
+
### Configurations
|
|
86
|
+
|
|
87
|
+
- **espark-core**: Use environment variables, or `.env` file, for database and MQTT configurations.
|
|
88
|
+
- **espark-node**: Use `esparknode.configs` for device-specific configurations.
|
|
89
|
+
- **espark-react**: Customise `EsparkApp` props for application settings.
|
|
90
|
+
|
|
91
|
+
## Examples and Patterns
|
|
92
|
+
|
|
93
|
+
- **Router Example**: `device_router.py` in `espark-core/esparkcore/routers/` demonstrates how to create API endpoints for device management.
|
|
94
|
+
- **Respository Example**: `device_repository.py` in `espark-core/esparkcore/data/repositories/` shows how to implement data access logic for devices.
|
|
95
|
+
- **Action Example**: `esp32_relay.py` in `espark-node/esparknode/actions/` illustrates how to define actions for ESP32 devices.
|
|
96
|
+
- **Sensor Example**: `sht20_sensor.py` in `espark-node/esparknode/sensors/` demonstrates how to read data from a SHT20 sensor.
|
|
97
|
+
- **Trigger Example**: `gpio_trigger.py` in `espark-node/esparknode/triggers/` shows how to create GPIO-based triggers for device actions.
|
|
98
|
+
- **List, Show, Edit Screens Example**: `DeviceList`, `DeviceShow`, and `DeviceEdit` components in `espark-react/src/pages/devices/` demonstrate how to create CRUD screens for device management.
|
|
99
|
+
|
|
100
|
+
## Example Projects
|
|
101
|
+
|
|
102
|
+
- **Espartan**: A smart thermostat and open-door alert automation system using ESP32-C3 devices, leveraging espark for device management and telemetry, available at [https://github.com/ayltai/Espartan](https://github.com/ayltai/Espartan).
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: espark-core
|
|
3
|
+
Version: 0.5.5
|
|
4
|
+
Summary: The core module of the Espark ESP32-based IoT device management framework.
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Dist: aiomqtt>=2.5.0
|
|
10
|
+
Requires-Dist: apscheduler>=3.11.2
|
|
11
|
+
Requires-Dist: fastapi>=0.128.0
|
|
12
|
+
Requires-Dist: packaging>=25.0
|
|
13
|
+
Requires-Dist: slack-sdk==3.39.0
|
|
14
|
+
Requires-Dist: sqlalchemy>=2.0.45
|
|
15
|
+
Requires-Dist: sqlmodel>=0.0.31
|
|
16
|
+
Requires-Dist: uvicorn[standard]>=0.40.0
|
|
17
|
+
Provides-Extra: dev
|
|
18
|
+
Requires-Dist: aiosqlite==0.22.1; extra == "dev"
|
|
19
|
+
Requires-Dist: autopep8==2.3.2; extra == "dev"
|
|
20
|
+
Requires-Dist: build==1.3.0; extra == "dev"
|
|
21
|
+
Requires-Dist: fastapi-cli[standard-no-fastapi-cloud-cli]==0.0.20; extra == "dev"
|
|
22
|
+
Requires-Dist: httpx==0.28.1; extra == "dev"
|
|
23
|
+
Requires-Dist: pycodestyle==2.14.0; extra == "dev"
|
|
24
|
+
Requires-Dist: pylint==4.0.4; extra == "dev"
|
|
25
|
+
Requires-Dist: pytest==9.0.2; extra == "dev"
|
|
26
|
+
Requires-Dist: pytest-asyncio==1.3.0; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-cov==7.0.0; extra == "dev"
|
|
28
|
+
Requires-Dist: twine==6.2.0; extra == "dev"
|
|
29
|
+
Dynamic: description
|
|
30
|
+
Dynamic: description-content-type
|
|
31
|
+
Dynamic: license
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
Dynamic: provides-extra
|
|
34
|
+
Dynamic: requires-dist
|
|
35
|
+
Dynamic: requires-python
|
|
36
|
+
Dynamic: summary
|
|
37
|
+
|
|
38
|
+
# Espark
|
|
39
|
+
|
|
40
|
+
Espark is a lightweight framework for building scalable and efficient ESP32-based IoT applications. It provides a modular architecture, easy-to-use APIs, and built-in support for common IoT protocols.
|
|
41
|
+
|
|
42
|
+
## Project Goals
|
|
43
|
+
|
|
44
|
+
- Simplify the development of ESP32 applications.
|
|
45
|
+
- Provide a modular and extensible architecture.
|
|
46
|
+
- Support common IoT protocols like MQTT.
|
|
47
|
+
- Ensure efficient resource management for low-power devices.
|
|
48
|
+
- Provide a clean and easy-to-use API.
|
|
49
|
+
- Provide an user-friendly UI for configuration and monitoring.
|
|
50
|
+
|
|
51
|
+
## Features
|
|
52
|
+
|
|
53
|
+
- **Device Provisioning**: Easy setup and configuration of ESP32 devices.
|
|
54
|
+
- **Telemetry Collection**: Built-in support for collecting and sending telemetry data.
|
|
55
|
+
- **Scalable Architecture**: Designed to handle a large number of devices efficiently.
|
|
56
|
+
- **Seamless Communication**: Support for MQTT protocol.
|
|
57
|
+
|
|
58
|
+
## Hardware Requirements
|
|
59
|
+
|
|
60
|
+
- ESP32 Development Board
|
|
61
|
+
- USB Cable for programming and power
|
|
62
|
+
- Optional: Sensors and triggers for specific applications
|
|
63
|
+
|
|
64
|
+
## Project Structure
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
espark/
|
|
68
|
+
├── espark-core/
|
|
69
|
+
│ ├── esparkcore/ # FastAPI backend framework
|
|
70
|
+
│ │ ├── data/ # Models, repositories
|
|
71
|
+
│ │ ├── routers/ # API endpoints
|
|
72
|
+
│ │ ├── schedules/ # Background tasks
|
|
73
|
+
│ │ ├── services/ # Business logic, MQTT handling
|
|
74
|
+
│ │ └── utils/ # Utility functions
|
|
75
|
+
│ └── Makefile
|
|
76
|
+
├── espark-node/
|
|
77
|
+
│ ├── esparknode/ # MicroPython application framework
|
|
78
|
+
│ │ ├── actions/ # Action handlers
|
|
79
|
+
│ │ ├── data/ # Data storage
|
|
80
|
+
│ │ ├── libraries/ # External libraries
|
|
81
|
+
│ │ ├── networks/ # Network management
|
|
82
|
+
│ │ ├── sensors/ # Sensor interfaces
|
|
83
|
+
│ │ ├── triggers/ # Trigger interfaces
|
|
84
|
+
│ │ ├── utils/ # Utility functions
|
|
85
|
+
│ │ └── base_node.py # Main application file
|
|
86
|
+
│ └── Makefile
|
|
87
|
+
└── espark-react/ # React frontend application
|
|
88
|
+
├── src/
|
|
89
|
+
│ ├── data/ # Data models and data providers
|
|
90
|
+
│ ├── i18n/ # Internationalization files
|
|
91
|
+
│ ├── pages/ # Application pages
|
|
92
|
+
│ ├── routes/ # Application routing
|
|
93
|
+
│ ├── utils/ # Utility functions
|
|
94
|
+
│ ├── App.tsx # Main application component
|
|
95
|
+
│ └── index.tsx # Application entry point
|
|
96
|
+
└── package.json
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Development Workflows
|
|
100
|
+
|
|
101
|
+
### Setting up the backend
|
|
102
|
+
|
|
103
|
+
1. Add espark-core as a dependency in your FastAPI project.
|
|
104
|
+
2. Configure database connections and MQTT settings as environment variables.
|
|
105
|
+
3. Implement additional data models, repositories, routers, and business logic if needed.
|
|
106
|
+
4. Add the `DeviceRouter`, `TelemetryRouter`, and other additional routers to your FastAPI app.
|
|
107
|
+
|
|
108
|
+
### Setting up the ESP32 application
|
|
109
|
+
|
|
110
|
+
1. Clone the espark-node repository to your local machine.
|
|
111
|
+
2. Copy `espark-core/Makefile.template` to `Makefile` and customize it for your device.
|
|
112
|
+
3. Run `make upgrade` to copy the espark-core library to your device project.
|
|
113
|
+
4. Implement device-specific actions, sensors, and triggers as needed.
|
|
114
|
+
5. Run `make flash` to upload the firmware to your ESP32 device.
|
|
115
|
+
6. Run `make deploy` to upload the application to the device.
|
|
116
|
+
|
|
117
|
+
### Setting up the frontend
|
|
118
|
+
|
|
119
|
+
1. Add espark-react as a dependency in your React project.
|
|
120
|
+
2. Render `<EsparkApp />` in your main application file.
|
|
121
|
+
|
|
122
|
+
### Configurations
|
|
123
|
+
|
|
124
|
+
- **espark-core**: Use environment variables, or `.env` file, for database and MQTT configurations.
|
|
125
|
+
- **espark-node**: Use `esparknode.configs` for device-specific configurations.
|
|
126
|
+
- **espark-react**: Customise `EsparkApp` props for application settings.
|
|
127
|
+
|
|
128
|
+
## Examples and Patterns
|
|
129
|
+
|
|
130
|
+
- **Router Example**: `device_router.py` in `espark-core/esparkcore/routers/` demonstrates how to create API endpoints for device management.
|
|
131
|
+
- **Respository Example**: `device_repository.py` in `espark-core/esparkcore/data/repositories/` shows how to implement data access logic for devices.
|
|
132
|
+
- **Action Example**: `esp32_relay.py` in `espark-node/esparknode/actions/` illustrates how to define actions for ESP32 devices.
|
|
133
|
+
- **Sensor Example**: `sht20_sensor.py` in `espark-node/esparknode/sensors/` demonstrates how to read data from a SHT20 sensor.
|
|
134
|
+
- **Trigger Example**: `gpio_trigger.py` in `espark-node/esparknode/triggers/` shows how to create GPIO-based triggers for device actions.
|
|
135
|
+
- **List, Show, Edit Screens Example**: `DeviceList`, `DeviceShow`, and `DeviceEdit` components in `espark-react/src/pages/devices/` demonstrate how to create CRUD screens for device management.
|
|
136
|
+
|
|
137
|
+
## Example Projects
|
|
138
|
+
|
|
139
|
+
- **Espartan**: A smart thermostat and open-door alert automation system using ESP32-C3 devices, leveraging espark for device management and telemetry, available at [https://github.com/ayltai/Espartan](https://github.com/ayltai/Espartan).
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
requirements.dev.txt
|
|
5
|
+
requirements.txt
|
|
6
|
+
setup.cfg
|
|
7
|
+
setup.py
|
|
8
|
+
../README.md
|
|
9
|
+
./esparkcore/__init__.py
|
|
10
|
+
./esparkcore/constants.py
|
|
11
|
+
./esparkcore/data/__init__.py
|
|
12
|
+
./esparkcore/data/database.py
|
|
13
|
+
./esparkcore/data/models/__init__.py
|
|
14
|
+
./esparkcore/data/models/device.py
|
|
15
|
+
./esparkcore/data/models/notification.py
|
|
16
|
+
./esparkcore/data/models/outbox.py
|
|
17
|
+
./esparkcore/data/models/telemetry.py
|
|
18
|
+
./esparkcore/data/models/trigger.py
|
|
19
|
+
./esparkcore/data/models/version.py
|
|
20
|
+
./esparkcore/data/repositories/__init__.py
|
|
21
|
+
./esparkcore/data/repositories/base_repository.py
|
|
22
|
+
./esparkcore/data/repositories/device_repository.py
|
|
23
|
+
./esparkcore/data/repositories/notification_repository.py
|
|
24
|
+
./esparkcore/data/repositories/outbox_repository.py
|
|
25
|
+
./esparkcore/data/repositories/telemetry_repository.py
|
|
26
|
+
./esparkcore/data/repositories/trigger_repository.py
|
|
27
|
+
./esparkcore/data/repositories/version_repository.py
|
|
28
|
+
./esparkcore/notifications/__init__.py
|
|
29
|
+
./esparkcore/notifications/notifier.py
|
|
30
|
+
./esparkcore/notifications/slack_notifier.py
|
|
31
|
+
./esparkcore/routers/__init__.py
|
|
32
|
+
./esparkcore/routers/base_router.py
|
|
33
|
+
./esparkcore/routers/device_router.py
|
|
34
|
+
./esparkcore/routers/notification_router.py
|
|
35
|
+
./esparkcore/routers/telemetry_router.py
|
|
36
|
+
./esparkcore/routers/trigger_router.py
|
|
37
|
+
./esparkcore/routers/version_router.py
|
|
38
|
+
./esparkcore/schedules/__init__.py
|
|
39
|
+
./esparkcore/schedules/outbox.py
|
|
40
|
+
./esparkcore/schedules/scheduler.py
|
|
41
|
+
./esparkcore/services/__init__.py
|
|
42
|
+
./esparkcore/services/mqtt.py
|
|
43
|
+
./esparkcore/utils/__init__.py
|
|
44
|
+
./esparkcore/utils/logging.py
|
|
45
|
+
espark_core.egg-info/PKG-INFO
|
|
46
|
+
espark_core.egg-info/SOURCES.txt
|
|
47
|
+
espark_core.egg-info/dependency_links.txt
|
|
48
|
+
espark_core.egg-info/requires.txt
|
|
49
|
+
espark_core.egg-info/top_level.txt
|
|
50
|
+
esparkcore/__init__.py
|
|
51
|
+
esparkcore/constants.py
|
|
52
|
+
esparkcore/data/__init__.py
|
|
53
|
+
esparkcore/data/database.py
|
|
54
|
+
esparkcore/data/models/__init__.py
|
|
55
|
+
esparkcore/data/models/device.py
|
|
56
|
+
esparkcore/data/models/notification.py
|
|
57
|
+
esparkcore/data/models/outbox.py
|
|
58
|
+
esparkcore/data/models/telemetry.py
|
|
59
|
+
esparkcore/data/models/trigger.py
|
|
60
|
+
esparkcore/data/models/version.py
|
|
61
|
+
esparkcore/data/repositories/__init__.py
|
|
62
|
+
esparkcore/data/repositories/base_repository.py
|
|
63
|
+
esparkcore/data/repositories/device_repository.py
|
|
64
|
+
esparkcore/data/repositories/notification_repository.py
|
|
65
|
+
esparkcore/data/repositories/outbox_repository.py
|
|
66
|
+
esparkcore/data/repositories/telemetry_repository.py
|
|
67
|
+
esparkcore/data/repositories/trigger_repository.py
|
|
68
|
+
esparkcore/data/repositories/version_repository.py
|
|
69
|
+
esparkcore/notifications/__init__.py
|
|
70
|
+
esparkcore/notifications/notifier.py
|
|
71
|
+
esparkcore/notifications/slack_notifier.py
|
|
72
|
+
esparkcore/routers/__init__.py
|
|
73
|
+
esparkcore/routers/base_router.py
|
|
74
|
+
esparkcore/routers/device_router.py
|
|
75
|
+
esparkcore/routers/notification_router.py
|
|
76
|
+
esparkcore/routers/telemetry_router.py
|
|
77
|
+
esparkcore/routers/trigger_router.py
|
|
78
|
+
esparkcore/routers/version_router.py
|
|
79
|
+
esparkcore/schedules/__init__.py
|
|
80
|
+
esparkcore/schedules/outbox.py
|
|
81
|
+
esparkcore/schedules/scheduler.py
|
|
82
|
+
esparkcore/services/__init__.py
|
|
83
|
+
esparkcore/services/mqtt.py
|
|
84
|
+
esparkcore/utils/__init__.py
|
|
85
|
+
esparkcore/utils/logging.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
aiomqtt>=2.5.0
|
|
2
|
+
apscheduler>=3.11.2
|
|
3
|
+
fastapi>=0.128.0
|
|
4
|
+
packaging>=25.0
|
|
5
|
+
slack-sdk==3.39.0
|
|
6
|
+
sqlalchemy>=2.0.45
|
|
7
|
+
sqlmodel>=0.0.31
|
|
8
|
+
uvicorn[standard]>=0.40.0
|
|
9
|
+
|
|
10
|
+
[dev]
|
|
11
|
+
aiosqlite==0.22.1
|
|
12
|
+
autopep8==2.3.2
|
|
13
|
+
build==1.3.0
|
|
14
|
+
fastapi-cli[standard-no-fastapi-cloud-cli]==0.0.20
|
|
15
|
+
httpx==0.28.1
|
|
16
|
+
pycodestyle==2.14.0
|
|
17
|
+
pylint==4.0.4
|
|
18
|
+
pytest==9.0.2
|
|
19
|
+
pytest-asyncio==1.3.0
|
|
20
|
+
pytest-cov==7.0.0
|
|
21
|
+
twine==6.2.0
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
esparkcore
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
ENV_DATABASE_URL : str = 'DATABASE_URL'
|
|
2
|
+
ENV_MQTT_HOST : str = 'MQTT_HOST'
|
|
3
|
+
ENV_MQTT_PORT : str = 'MQTT_PORT'
|
|
4
|
+
ENV_UPLOAD_PATH : str = 'UPLOAD_PATH'
|
|
5
|
+
|
|
6
|
+
TOPIC_ACTION : str = 'espark/action'
|
|
7
|
+
TOPIC_DEVICE : str = 'espark/device'
|
|
8
|
+
TOPIC_REGISTRATION : str = 'espark/registration'
|
|
9
|
+
TOPIC_TELEMETRY : str = 'espark/telemetry'
|
|
10
|
+
TOPIC_OTA : str = 'espark/ota'
|
|
11
|
+
TOPIC_CRASH : str = 'espark/crash'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .database import async_session, init_db
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from os import getenv
|
|
2
|
+
|
|
3
|
+
from sqlalchemy.ext.asyncio import async_sessionmaker, AsyncSession, create_async_engine
|
|
4
|
+
from sqlmodel import SQLModel
|
|
5
|
+
|
|
6
|
+
from ..constants import ENV_DATABASE_URL
|
|
7
|
+
|
|
8
|
+
# pylint: disable=invalid-name
|
|
9
|
+
engine = create_async_engine(getenv(ENV_DATABASE_URL, 'sqlite+aiosqlite:///database.db'), echo=True)
|
|
10
|
+
async_session = async_sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
async def init_db():
|
|
14
|
+
async with engine.begin() as conn:
|
|
15
|
+
await conn.run_sync(SQLModel.metadata.create_all)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Dict, Optional
|
|
3
|
+
|
|
4
|
+
from sqlalchemy import Column
|
|
5
|
+
from sqlmodel import SQLModel, Field, JSON
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Device(SQLModel, table=True):
|
|
9
|
+
id : str = Field(primary_key=True, description='Unique identifier for the device')
|
|
10
|
+
display_name : Optional[str] = Field(default=None, description='Human-readable name of the device')
|
|
11
|
+
app_name : Optional[str] = Field(default=None, foreign_key='appversion.id', ondelete='CASCADE', description='Name of the application running on the device')
|
|
12
|
+
app_version : Optional[str] = Field(default=None, description='Version of the application running on the device')
|
|
13
|
+
capabilities : Optional[str] = Field(default=None, description='Comma separated capabilities of the device')
|
|
14
|
+
parameters : Dict[str, str | int | bool] = Field(default_factory=dict, sa_column=Column(JSON), description='JSON string of capability-specific parameters')
|
|
15
|
+
last_seen : datetime = Field(index=True, description='Last time the device was seen online')
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from typing import Dict
|
|
2
|
+
|
|
3
|
+
from sqlalchemy import Column
|
|
4
|
+
from sqlmodel import SQLModel, Field, JSON
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Notification(SQLModel, table=True):
|
|
8
|
+
id : int = Field(primary_key=True, description='Unique identifier for the notification')
|
|
9
|
+
name : str = Field(index=True, unique=True, description='Name of the notification')
|
|
10
|
+
provider : str = Field(index=True, description='Notification provider (e.g., Slack, Twilio)')
|
|
11
|
+
config : Dict[str, str] = Field(default_factory=dict, sa_column=Column(JSON), description='JSON string of provider-specific configuration parameters')
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Dict, Optional
|
|
3
|
+
from uuid import UUID, uuid4
|
|
4
|
+
|
|
5
|
+
from sqlalchemy import Column
|
|
6
|
+
from sqlmodel import SQLModel, Field, JSON, UniqueConstraint
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class OutboxEvent(SQLModel, table=True):
|
|
10
|
+
__table_args__ = (
|
|
11
|
+
UniqueConstraint('device_id', 'event_type', 'is_processed', name='uq_device_event'),
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
id : UUID = Field(default_factory=uuid4, primary_key=True, description='Unique identifier for the outbox event')
|
|
15
|
+
device_id : str = Field(foreign_key='device.id', ondelete='CASCADE', index=True, description='Identifier of the device associated with the event')
|
|
16
|
+
event_type : str = Field(index=True, description='Type of the event')
|
|
17
|
+
payload : Dict[str, str] = Field(default_factory=dict, sa_column=Column(JSON), description='JSON string of event-specific payload data')
|
|
18
|
+
created_at : datetime = Field(default_factory=datetime.now, index=True, description='Timestamp when the event was created')
|
|
19
|
+
processed_at : Optional[datetime] = Field(default=None, index=True, description='Timestamp when the event was processed')
|
|
20
|
+
is_processed : bool = Field(default=False, index=True, description='Flag indicating whether the event has been processed')
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from sqlmodel import SQLModel, Field
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Telemetry(SQLModel, table=True):
|
|
8
|
+
id : Optional[int] = Field(primary_key=True, default=None)
|
|
9
|
+
device_id : str = Field(foreign_key='device.id', ondelete='CASCADE', description='Device that sent this data')
|
|
10
|
+
timestamp : datetime = Field(index=True, description='Timestamp of the data')
|
|
11
|
+
data_type : str = Field(index=True, description='Type of the data (e.g., motion, temperature)')
|
|
12
|
+
value : int = Field(description='Value of the data (e.g., temperature, human presence detected or not)')
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from sqlmodel import Field, SQLModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Trigger(SQLModel, table=True):
|
|
7
|
+
id : Optional[int] = Field(primary_key=True, description='Unique identifier for the trigger')
|
|
8
|
+
name : str = Field(index=True, unique=True, description='Name of the trigger')
|
|
9
|
+
device_id : Optional[str] = Field(index=True, default=None, description='Identifier of the associated device')
|
|
10
|
+
data_type : Optional[str] = Field(index=True, default=None, description='Type of telemetry data the trigger monitors (e.g., temperature, humidity)')
|
|
11
|
+
condition : str = Field(description='Condition to evaluate (e.g., ">", "<=")')
|
|
12
|
+
value : int = Field(description='Value to compare against for the trigger condition')
|
|
13
|
+
notification_ids : Optional[str] = Field(default=None, description='Comma-separated list of associated notification IDs to be sent when the trigger condition is met')
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from .base_repository import AsyncRepository
|
|
2
|
+
from .device_repository import DeviceRepository
|
|
3
|
+
from .notification_repository import NotificationRepository
|
|
4
|
+
from .outbox_repository import OutboxRepository
|
|
5
|
+
from .telemetry_repository import TelemetryRepository
|
|
6
|
+
from .trigger_repository import TriggerRepository
|
|
7
|
+
from .version_repository import AppVersionRepository
|