Skip to content

Commit

Permalink
Build v0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
dmpayton committed Jan 18, 2023
0 parents commit be35f71
Show file tree
Hide file tree
Showing 45 changed files with 382 additions and 0 deletions.
1 change: 1 addition & 0 deletions .version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v0.2.0
9 changes: 9 additions & 0 deletions boot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import esp
import gc
import machine

esp.osdebug(None)

# Take out the trash
gc.enable()
gc.collect()
Binary file added lib/microdot.mpy
Binary file not shown.
Binary file added lib/microdot_asyncio.mpy
Binary file not shown.
Binary file added lib/ulogging.mpy
Binary file not shown.
Binary file added lib/urequests.mpy
Binary file not shown.
Binary file added lib/utemplate/compiled.mpy
Binary file not shown.
Binary file added lib/utemplate/recompile.mpy
Binary file not shown.
Binary file added lib/utemplate/source.mpy
Binary file not shown.
72 changes: 72 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import gc
import machine
import time

import uasyncio as asyncio
import ulogging as logging

from pasp import ota, plug, pm25, web, wifi, system
from pasp.beacon import beacon
from pasp.collector import collector
from pasp.config import settings
from pasp.controller import controller
from pasp.beacon import beacon

gc.collect()

logging.basicConfig(level=logging.DEBUG if settings.DEBUG else logging.INFO)
log = logging.getLogger('main')


async def collect_garbage():
while True:
gc.collect()
await asyncio.sleep(5)


def main():
log.info(f'PASP Version: {system.version()}')
log.info(f'Wemos C3-Mini: {system.board_version()}')

# Signal that we've started.
beacon.off()
asyncio.run(beacon.animate())

# Wifi, OTA, and AP setup.
asyncio.run(wifi.connect())
ota.check_for_updates()
asyncio.run(wifi.ap_setup())

# Core functionality.
collector.run()
controller.run()
web.run()

# Automatic garbage collection.
asyncio.create_task(collect_garbage())

# Let's get to work!
asyncio.run(beacon.animate())
asyncio.run(beacon.pulse(delay=69))
beacon.on()

loop = asyncio.get_event_loop()

try:
loop.run_forever()
except:
loop.stop()
loop.close()


if __name__ == '__main__':
try:
main()
except Exception as err:
log.error(str(err))
for x in range(20):
beacon.on()
time.sleep(.5)
beacon.off()
time.sleep(.5)
machine.restart()
Binary file added pasp/__init__.mpy
Binary file not shown.
Binary file added pasp/beacon/__init__.mpy
Binary file not shown.
Binary file added pasp/beacon/base.mpy
Binary file not shown.
Binary file added pasp/beacon/led.mpy
Binary file not shown.
Binary file added pasp/beacon/rgb_led.mpy
Binary file not shown.
Binary file added pasp/collector.mpy
Binary file not shown.
Binary file added pasp/config.mpy
Binary file not shown.
Binary file added pasp/controller.mpy
Binary file not shown.
Binary file added pasp/ota.mpy
Binary file not shown.
Binary file added pasp/path.mpy
Binary file not shown.
Binary file added pasp/plug.mpy
Binary file not shown.
Binary file added pasp/pm25.mpy
Binary file not shown.
Binary file added pasp/static/css/style.css.gz
Binary file not shown.
1 change: 1 addition & 0 deletions pasp/static/img/outlet.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pasp/static/img/signal-disconnected.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pasp/static/img/signal-fair.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pasp/static/img/signal-good.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pasp/static/img/signal-great.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pasp/static/img/signal-poor.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pasp/static/img/wifi-exclamation.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions pasp/static/img/wifi.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added pasp/static/js/main.js.gz
Binary file not shown.
Binary file added pasp/system.mpy
Binary file not shown.
6 changes: 6 additions & 0 deletions pasp/templates/includes/head.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{% args ctx %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link type="text/css" rel="stylesheet" href="/static/css/style.css.gz" />
<script>var exports = {};</script>
<script type="text/javascript" src="/static/js/main.js.gz" defer></script>
9 changes: 9 additions & 0 deletions pasp/templates/includes/modal.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<dialog class="form-save-modal is-forced">
<article>
<header>
<strong>Sit tight, this might take a minute...</strong>
</header>
<p class="status"></p>
<progress max="100"></progress>
</article>
</dialog>
11 changes: 11 additions & 0 deletions pasp/templates/includes/nav.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% args ctx %}
<nav class="container-fluid">
<ul>
<li><a href="/" class="brand"><strong>{{ ctx['title'] }}</strong></a></li>
</ul>
<ul>
<li><a href="/settings">Settings</a></li>
<li><a href="/wifi">Wi-Fi</a></li>
<li><a href="/system">System</a></li>
</ul>
</nav>
122 changes: 122 additions & 0 deletions pasp/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
{% args ctx %}
<!doctype html>
<html lang="en" data-theme="dark">
<head>
<title>{{ ctx['title'] }}</title>
{% include "includes/head.html" ctx %}
<script type="text/javascript">
window.PASP = {
THRESHOLD: {{ ctx['THRESHOLD'] }}
}
</script>
</head>
<body class="pasp-dashboard">
{% include "includes/nav.html" ctx %}
<main class="container">
<div class="grid">
<div>
<article>
<header><strong>Connection Status</strong></header>
<div class="connection-list">
<div x-data="wifiWidget('sta')" x-init="initialize()" class="connection connection-sta" :class="signalConnectionClass(data)">
<div class="media">
<div class="media-left">
<span class="icon is-3x" :class="data.connected ? '' : 'is-faded'">
<object type="image/svg+xml" :data="wifiIcon(data)" onload="setIconColor(this);"></object>
</span>
</div>
<div class="media-content">
<p class="connection-title">
<span>Wi-Fi Connection</span>
<span aria-busy="true" x-show="isLoading" x-transition></span>
</p>
<p class="connection-label" x-text="data.ssid ? data.ssid : '–'"></p>
<p class="connection-status" x-text="data.connected ? data.ip : data.status"></p>
</div>
<div class="media-right">
<span class="icon is-3x">
<object type="image/svg+xml" :data="signalIcon()" onload="setIconColor(this);"></object>
</span>
</div>
</div>
</div>

<div x-data="wifiWidget('ap')" x-init="initialize()" class="connection connection-ap" :class="data && data.active ? 'connection-great' : 'connection-disconnected'">
<div class="media">
<div class="media-left">
<span class="icon is-3x" :class="data.active ? '' : 'is-faded'">
<object type="image/svg+xml" data="/static/img/wifi.svg" onload="setIconColor(this);"></object>
</span>
</div>
<div class="media-content">
<p class="connection-title">
<span>Access Point</span>
<span aria-busy="true" x-show="isLoading" x-transition></span>
</p>
<p class="connection-label" x-text="data.ssid ? data.ssid : '–'"></p>
<p class="connection-status" x-text="data.connected ? data.ip : data.status"></p>
</div>
</div>
</div>

<div x-data="plugWidget()" x-init="initialize()" class="connection connection-plug" :class="signalConnectionClass(data)">
<div class="media">
<div class="media-left">
<span class="icon is-3x" :class="data.relay_state ? '' : 'is-faded'">
<object type="image/svg+xml" data="/static/img/outlet.svg" onload="setIconColor(this);"></object>
</span>
</div>
<div class="media-content">
<p class="connection-title">
<span>Smart Plug</span>
<span aria-busy="true" x-show="isLoading" x-transition></span>
</p>
<p class="connection-label">
<span x-text="data.alias ? data.alias : '–'"></span>
</p>
<p class="connection-status" x-text="hardware"></p>
</div>
<div class="media-right">
<span class="icon is-3x">
<object type="image/svg+xml" :data="signalIcon()" onload="setIconColor(this);"></object>
</span>
</div>
</div>
</div>
</div>
</article>
</div>
<div>
<article x-data="pm25Widget()" x-init="initialize()" class="air-quality">
<header>
<div class="loading" x-show="isLoading" aria-busy="true"></div>
<strong>Air Quality</strong>
</header>

<div class="section grid">
<div class="air-widget" :class="data.realtime_key">
<div class="label">Real Time</div>
<div class="value" x-text="data.realtime_pm25 || '–'"></div>
<div class="label">PM2.5</div>

</div>
<div class="air-widget" :class="data.hour_key">
<div class="label">1-Hour Avg.</div>
<div class="value" x-text="data.hour_pm25 || '–'"></div>
<div class="label">PM2.5</div>
</div>
</div>

<div class="section">
<div id="id_hour_plot" class="plot"></div>
</div>

<div class="section">
<div id="id_day_plot" class="plot"></div>
</div>
</article>
</div>
</div>
</main>
</body>
</html>
51 changes: 51 additions & 0 deletions pasp/templates/settings.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{% args ctx %}
<!doctype html>
<html lang="en" data-theme="dark">
<head>
<title>Settings | {{ ctx['title'] }}</title>
{% include "includes/head.html" ctx %}
</head>
<body class="pasp-settings">
{% include "includes/nav.html" ctx %}
<main class="container">
<article>
<header>
<strong>General Settings</strong>
</header>
<form x-data="{
THRESHOLD: '{{ ctx['settings'].THRESHOLD }}',
AP_CHANNEL: {{ ctx['settings'].AP_CHANNEL }}
}" action="/settings" method="POST" @submit.prevent="submitFormAndRefresh">
<div>
<label for="THRESHOLD">Sensitivity</label>
<select name="THRESHOLD" x-model="THRESHOLD">
<option value="moderate">Moderate</option>
<option value="unhealthy_sensitive">Unhealthy for Sensitive Groups</option>
<option value="unhealthy">Unhealthy</option>
</select>
<small>Adjust the air quality level at which the air purifier will be activated.</small>
</div>

<div x-data="{show_advanced: false}">
<p><a href="#" @click.prevent="show_advanced = !show_advanced">Advanced Settings</a></p>

<div x-show="show_advanced" x-transition>
<div>
<label for="AP_CHANNEL">Access Point Channel</label>
<select name="AP_CHANNEL" x-model="AP_CHANNEL">
{% for x in range(1, 12) %}
<option value="{{ x }}">{{ x }}</option>
{% endfor %}
</select>
<small>If you don't know what this is, you can probably leave it alone. That said, 1, 6, and 11 are usually good choices.</small>
</div>
</div>
</div>

<button type="submit">Save Settings</button>
</form>
</article>
</main>
{% include "includes/modal.html" %}
</body>
</html>
Loading

0 comments on commit be35f71

Please sign in to comment.