Compare commits
5 Commits
c53f3511be
...
722abc3056
| Author | SHA1 | Date |
|---|---|---|
|
|
722abc3056 | |
|
|
144e7d556f | |
|
|
9136fb5c97 | |
|
|
aa0a04b76f | |
|
|
5c7b10c7b1 |
|
|
@ -6,6 +6,8 @@
|
||||||
# General
|
# General
|
||||||
/_tmp
|
/_tmp
|
||||||
/.upload_cache
|
/.upload_cache
|
||||||
|
*_bak
|
||||||
|
*_bak[0-9]
|
||||||
|
|
||||||
# Python
|
# Python
|
||||||
__pycache__
|
__pycache__
|
||||||
|
|
@ -18,8 +20,12 @@ __pycache__
|
||||||
*.mpy
|
*.mpy
|
||||||
|
|
||||||
# Configuration files
|
# Configuration files
|
||||||
|
/Makefile.env
|
||||||
|
/src/lightbar_cfg.py
|
||||||
/src/webrepl_cfg.py
|
/src/webrepl_cfg.py
|
||||||
/src/wlan_cfg.py
|
/src/wlan_cfg.py
|
||||||
|
|
||||||
# FreeCAD backups
|
# 3D modeling temporary files (FreeCAD backups, Cura projects, G-code files)
|
||||||
*.FCStd1
|
*.FCStd1
|
||||||
|
*.3mf
|
||||||
|
*.gcode
|
||||||
|
|
|
||||||
21
Makefile
21
Makefile
|
|
@ -1,16 +1,19 @@
|
||||||
# Configuration
|
# Configuration defaults (please use Makefile.env to override these, see Makefile.env.example)
|
||||||
LIGHTBAR_HOST ?= 192.168.17.22
|
LIGHTBAR_HOST = 192.168.13.12
|
||||||
LIGHTBAR_URL := http://$(LIGHTBAR_HOST)
|
LIGHTBAR_URL = http://$(LIGHTBAR_HOST)
|
||||||
WEBREPL_CLI := webrepl_cli.py
|
WEBREPL_CLI = webrepl_cli.py
|
||||||
WEBREPL_HOST := $(LIGHTBAR_HOST)
|
WEBREPL_HOST = $(LIGHTBAR_HOST)
|
||||||
WEBREPL_PASSWORD ?= acab
|
WEBREPL_PASSWORD = ultra-secret-webrepl-password
|
||||||
REPL_TTY_PATH ?= /dev/ttyUSB0
|
REPL_TTY_PATH = /dev/ttyUSB0
|
||||||
|
|
||||||
|
# Include local config
|
||||||
|
-include Makefile.env
|
||||||
|
|
||||||
# Directory for saving timestamps of when files were last uploaded
|
# Directory for saving timestamps of when files were last uploaded
|
||||||
UPLOAD_CACHE_DIR := .upload_cache
|
UPLOAD_CACHE_DIR := .upload_cache
|
||||||
|
|
||||||
# Auto-detect all .py files that should be uploaded
|
# Auto-detect all .py files that should be uploaded
|
||||||
SRC_UPLOAD_TARGETS := $(patsubst %.py,$(UPLOAD_CACHE_DIR)/%.py.timestamp,$(wildcard src/*.py src/**/*.py))
|
SRC_UPLOAD_TARGETS := $(patsubst %.py,$(UPLOAD_CACHE_DIR)/%.py.timestamp,$(wildcard src/*.py src/**/*.py src/**/**/*.py))
|
||||||
LIB_UPLOAD_TARGETS := $(patsubst %.py,$(UPLOAD_CACHE_DIR)/%.py.timestamp,$(wildcard lib/*.py))
|
LIB_UPLOAD_TARGETS := $(patsubst %.py,$(UPLOAD_CACHE_DIR)/%.py.timestamp,$(wildcard lib/*.py))
|
||||||
|
|
||||||
# Default target
|
# Default target
|
||||||
|
|
@ -52,7 +55,7 @@ $(UPLOAD_CACHE_DIR)/%.py.timestamp :: %.py
|
||||||
repl-create-directories:
|
repl-create-directories:
|
||||||
@echo "(Note: If the directory already exists, rshell will print \"Unable to create [DIR]\")"
|
@echo "(Note: If the directory already exists, rshell will print \"Unable to create [DIR]\")"
|
||||||
@echo
|
@echo
|
||||||
rshell -p $(REPL_TTY_PATH) mkdir /pyboard/lib /pyboard/lightbar
|
rshell -p $(REPL_TTY_PATH) mkdir /pyboard/lib /pyboard/lightbar /pyboard/lightbar/endpoints
|
||||||
|
|
||||||
# Clear the .upload_cache directory that contains the last upload timestamps
|
# Clear the .upload_cache directory that contains the last upload timestamps
|
||||||
.PHONY: clear-upload-cache clear-upload-cache-src
|
.PHONY: clear-upload-cache clear-upload-cache-src
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
# This is an example file.
|
||||||
|
# Copy this to Makefile.env and adjust it to the IP and password of your lightbar.
|
||||||
|
|
||||||
|
# IP address or hostname of your lightbar
|
||||||
|
LIGHTBAR_HOST := 192.168.13.12
|
||||||
|
|
||||||
|
# Password for WebREPL as set in webrepl_cfg.py (used to transfer files to the ESP32)
|
||||||
|
WEBREPL_PASSWORD := ultra-secret-webrepl-password
|
||||||
|
|
||||||
|
# Device path to the serial port of the ESP32 when connected via USB
|
||||||
|
REPL_TTY_PATH := /dev/ttyUSB0
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Example file for Lightbar configuration. Copy to src/lightbar_cfg.py, adjust and upload to the board.
|
||||||
|
|
||||||
|
# Port to start the HTTP server on
|
||||||
|
SERVER_PORT = 80
|
||||||
|
|
||||||
|
# Whether the HTTP server should be started in debug mode
|
||||||
|
SERVER_DEBUG = False
|
||||||
|
|
||||||
|
# Amount of LEDs in the lightbar
|
||||||
|
NEOPIXEL_COUNT = 28
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,6 @@
|
||||||
|
Board: ESP32 NodeMCU
|
||||||
|
|
||||||
|
Pins:
|
||||||
|
- Neopixels: GPIO26
|
||||||
|
- Status LED: GPIO4
|
||||||
|
- Button: GPIO21 (against GND)
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
# boot.py -- This file is executed on every boot (including wake-boot from deepsleep)
|
# boot.py -- This file is executed on every boot (including wake-boot from deepsleep)
|
||||||
|
|
||||||
from lightbar import wlan_manager
|
import uasyncio
|
||||||
import webrepl
|
import webrepl
|
||||||
|
|
||||||
# Connect to WLAN as defined in wlan_cfg.py
|
from lightbar import wlan_manager
|
||||||
wlan_manager.connect()
|
|
||||||
|
# Asynchronously connect to WLAN as defined in wlan_cfg.py
|
||||||
|
uasyncio.create_task(wlan_manager.connect_async())
|
||||||
|
|
||||||
# Start WebREPL on default port 8266 with password defined in webrepl_cfg.PASS
|
# Start WebREPL on default port 8266 with password defined in webrepl_cfg.PASS
|
||||||
webrepl.start()
|
webrepl.start()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
import uasyncio
|
||||||
|
from machine import Pin
|
||||||
|
from neopixel import NeoPixel
|
||||||
|
|
||||||
|
# Constants
|
||||||
|
NEOPIXEL_PIN = 26
|
||||||
|
|
||||||
|
|
||||||
|
class LightbarController:
|
||||||
|
"""
|
||||||
|
Controls the LEDs using the NeoPixel library.
|
||||||
|
"""
|
||||||
|
neopixel_count: int
|
||||||
|
neopixel: NeoPixel
|
||||||
|
|
||||||
|
def __init__(self, *, neopixel_count: int):
|
||||||
|
print('[LightbarController] Initializing Neopixels')
|
||||||
|
self.neopixel_count = neopixel_count
|
||||||
|
self.neopixel = NeoPixel(Pin(NEOPIXEL_PIN), neopixel_count)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
uasyncio.create_task(self.run_loop())
|
||||||
|
|
||||||
|
async def run_loop(self):
|
||||||
|
print('[LightbarController] Turning on Neopixels')
|
||||||
|
np = self.neopixel
|
||||||
|
np.fill((0, 0, 0))
|
||||||
|
|
||||||
|
color_set = [
|
||||||
|
(255, 0, 0),
|
||||||
|
(255, 255, 0),
|
||||||
|
(0, 255, 0),
|
||||||
|
(0, 255, 255),
|
||||||
|
(0, 0, 255),
|
||||||
|
(255, 0, 255),
|
||||||
|
]
|
||||||
|
|
||||||
|
while True:
|
||||||
|
for i in range(self.neopixel_count):
|
||||||
|
np[i] = color_set[i % len(color_set)]
|
||||||
|
np.write()
|
||||||
|
|
||||||
|
await uasyncio.sleep(0.5)
|
||||||
|
|
@ -2,11 +2,14 @@ import machine
|
||||||
import uasyncio
|
import uasyncio
|
||||||
from microdot_asyncio import Microdot
|
from microdot_asyncio import Microdot
|
||||||
|
|
||||||
from lightbar.frontend import frontend
|
from lightbar.endpoints.frontend import frontend
|
||||||
from lightbar.rest_api import rest_api
|
from lightbar.endpoints.rest_api import rest_api
|
||||||
|
|
||||||
|
|
||||||
class Lightbar(Microdot):
|
class LightbarServer(Microdot):
|
||||||
|
"""
|
||||||
|
Runs the HTTP server to control the lightbar.
|
||||||
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.mount(frontend)
|
self.mount(frontend)
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import network
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
import network
|
||||||
|
from machine import Pin
|
||||||
|
|
||||||
|
|
||||||
def connect() -> network.WLAN:
|
def connect() -> network.WLAN:
|
||||||
"""
|
"""
|
||||||
|
|
@ -19,13 +21,21 @@ def connect() -> network.WLAN:
|
||||||
wlan = network.WLAN(network.STA_IF)
|
wlan = network.WLAN(network.STA_IF)
|
||||||
wlan.active(True)
|
wlan.active(True)
|
||||||
|
|
||||||
|
status_led = Pin(4, Pin.OUT)
|
||||||
|
status_led.off()
|
||||||
|
|
||||||
if not wlan.isconnected():
|
if not wlan.isconnected():
|
||||||
wlan.connect(wlan_cfg.SSID, wlan_cfg.PASSWORD)
|
wlan.connect(wlan_cfg.SSID, wlan_cfg.PASSWORD)
|
||||||
|
|
||||||
print('[wlan_manager] Connecting to WLAN "{}" '.format(wlan_cfg.SSID), end='')
|
print('[wlan_manager] Connecting to WLAN "{}" '.format(wlan_cfg.SSID), end='')
|
||||||
while not wlan.isconnected():
|
while not wlan.isconnected():
|
||||||
print('.', end='')
|
print('.', end='')
|
||||||
time.sleep(1)
|
|
||||||
|
# Let the LED blink to indicate the connection attempt
|
||||||
|
status_led.on()
|
||||||
|
time.sleep(0.5)
|
||||||
|
status_led.off()
|
||||||
|
time.sleep(0.5)
|
||||||
print('\n[wlan_manager] Connected!')
|
print('\n[wlan_manager] Connected!')
|
||||||
else:
|
else:
|
||||||
print('[wlan_manager] Already connected to WLAN "{}"'.format(wlan.config('essid')))
|
print('[wlan_manager] Already connected to WLAN "{}"'.format(wlan.config('essid')))
|
||||||
|
|
@ -35,4 +45,16 @@ def connect() -> network.WLAN:
|
||||||
wlan.ifconfig(wlan_cfg.IFCONFIG)
|
wlan.ifconfig(wlan_cfg.IFCONFIG)
|
||||||
|
|
||||||
print('[wlan_manager] IP config: {}'.format(wlan.ifconfig()))
|
print('[wlan_manager] IP config: {}'.format(wlan.ifconfig()))
|
||||||
|
|
||||||
|
# Let the LED blink 2 times quickly to indicate that the WLAN is connected
|
||||||
|
for _ in range(2):
|
||||||
|
time.sleep(0.125)
|
||||||
|
status_led.on()
|
||||||
|
time.sleep(0.125)
|
||||||
|
status_led.off()
|
||||||
|
|
||||||
return wlan
|
return wlan
|
||||||
|
|
||||||
|
|
||||||
|
async def connect_async():
|
||||||
|
connect()
|
||||||
|
|
|
||||||
21
src/main.py
21
src/main.py
|
|
@ -1,5 +1,18 @@
|
||||||
from lightbar.app import Lightbar
|
from lightbar.lightbar_controller import LightbarController
|
||||||
|
from lightbar.lightbar_server import LightbarServer
|
||||||
|
|
||||||
print('[main] Starting lightbar HTTP server...')
|
try:
|
||||||
api_server = Lightbar()
|
import lightbar_cfg
|
||||||
api_server.run(port=80, debug=True)
|
except Exception as e:
|
||||||
|
print('[main] Could not import lightbar_cfg.py: {}'.format(str(e)))
|
||||||
|
raise e
|
||||||
|
|
||||||
|
print('[main] Starting lightbar controller')
|
||||||
|
lightbar_controller = LightbarController(neopixel_count=lightbar_cfg.NEOPIXEL_COUNT)
|
||||||
|
lightbar_controller.start()
|
||||||
|
|
||||||
|
print('[main] Starting lightbar HTTP server')
|
||||||
|
api_server = LightbarServer()
|
||||||
|
api_server.run(port=lightbar_cfg.SERVER_PORT, debug=lightbar_cfg.SERVER_DEBUG)
|
||||||
|
|
||||||
|
print('[main] HTTP server shut down! End of main')
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue