Skip to content

Instantly share code, notes, and snippets.

@crbyxwpzfl
Last active June 2, 2024 18:28
Show Gist options
  • Save crbyxwpzfl/3a48bc661b2cebab0448e1144a098b5a to your computer and use it in GitHub Desktop.
Save crbyxwpzfl/3a48bc661b2cebab0448e1144a098b5a to your computer and use it in GitHub Desktop.

l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e   l o o k  h e r e  


Note

first attentione to the servo limits line 72. make sure you dont crash into sth the servo will move on boot

second your wlan password is stored in plain text in settings.toml so there is a chance someone extracts it via an to me unknown exploit

hey listen

hi, thought i wirte some more since the together copy pasted stuff aboveus is zero readable ..and my comments dont help either

so setup just provide wlan ssid = "youre reading the pw" and pw = "youre reading the pw" plus broker adress = "mqtt.broker", port = "tcp port" and topic = "/chanell" in the settings.toml each in a new line. reset, watch the white light while it connects and done.

then just press boot to send it. each press is queued so hit it until the mqtt server rate limits, the script shits itself, the servo blows up, your hand hurts etc etc


flashing red   ..amazing you broke it   ..now either try a reset à la fix your shit yourself   ..or message me   ..or presuming both didnt help.. connect it to your laptop ls /dev/ttyACM*, lists connected serial port addresses, then screen /dev/tty.ACM0, replace ACM0 with your address, connects you to the serial console alias repl   ..doesnt work see link below.

okok this is the cool part. wait until the error occurs again. yes there is no logging..   since you no send me traceback..   me no fix shit.. ez.. zero valid github issues.   ..when you finally got the error copy paste and I fix it ..probably


other states solid white - connecting or sending,   pulsing white - sending until buffer done,   flashing white - looping connection,   flashing red - hard fault,   green flash - sth good,   light off - running quietly


usefull links

find directions how to connect to serial consol alias repl here
find circuitpython for your board here here
find adafruit libraries here
cool brwoser mqtt client for debugging here
possibly helpfull in case of error here, here, here


todo list

buffer presses - you go smash smash smash smash mqtt go brrrrrr servo go eehhhh eehhh eehh eehh eeeh eeh eeeh - done

missed presses - fixed until proven otherwise - done

no real logging - last self recovered error is pushed this is quite useless - done

improve response times - perhaps cancle tasks but this perhaps doesnt even help

no qos >0 or spamming until seen to avoid spamming broker - or propose better solution

separate send into peer topics - benefit cleaner sessions disadvantage little more effort - perhaps some time

remote interactive debug topic - very risky likely not good

let other see when received or finger reset - perhaps with a display or telephone ping

finger animations - lift speed control or add rotation or wiggle - perhaps some time

presence detection - only lift when recipient sees it - perhaps with mmwave or pir

group or multi peer lifts - requires interface like eg a display

switch to ssl - likely good but takes effort

# general info - circuitpython test for adafruit feather esp32 S3, requires adafrui libs connection manager, minimqtt, ticks, asyncio, neopixel, settings.toml with wifi cerdentials and mqtt adress, port, topic
# this lifts a servo for your segnificant other on the same mqtt topic and vice versa. please share your tipps about async i clearly dont understand it.. see below
# trubleshoot - yes theres no real logging.. semi usefull self recoverable errors are published to mqtt.. hard faults well.. you no send me tracback.. me no fix shit.. this shit flawless.. ez..
# ok so for the patient to find serial port via 'ls /dev/ttyACM*' then connect to repl via eg. 'screen /dev/tty.ACM0 115200'.. wait for error then copy paste below for me to fix shit..
import keypad
import asyncio
import os
import supervisor
import board
import neopixel
import pwmio
import ssl
import socketpool
import wifi
import adafruit_minimqtt.adafruit_minimqtt
class commclass: # simple class to communicate with .value to read or write why not one calss istead of many remember more alwas better
def __init__(self, init):
self.value = init
async def catchflanks(aboveuspin, belowusmpin, presses): # count up presses see docs learn.adafruit.com/cooperative-multitasking-in-circuitpython-with-asyncio
with keypad.Keys((aboveuspin, belowusmpin), value_when_pressed=False, pull=True) as keys:
while True:
event = keys.events.get()
if event and event.pressed: # or event.released for high flank event and to find wich key event.key_number
presses.value += 1; pixl.fill((10, 10, 10)) # show user he accomplished sth
await asyncio.sleep(0) # let others do sth
async def sendfs(presses, seen, tosend, heylisten):
while True:
if presses.value: # presses not null then send look here and wait for seen
tosend.value.append("look here"); presses.value -= 1;
heylisten.value.append("sit") # this tells servo to sit
print(f" wait for send queue plus {presses.value} presses in buffer.... ", end="") # wait for seen or timeout
for wait in range(1,5): # purposefull no for break else or retries for unseen presses to avoid spamming broker let user try again
pixl.fill((4*wait, 4*wait, 4*wait))
await asyncio.sleep(0.1) # dwell time let other tasks
await asyncio.sleep(0) # let others do sth
async def move(heylisten): # finger just down for sit and for look here down and in the air again
servo = pwmio.PWMOut(board.A0, duty_cycle=0, frequency=50) # init pwm pin for servo
while True:
if heylisten.value: servo.duty_cycle = 4300; await asyncio.sleep(0.5); servo.duty_cycle = 8200 if heylisten.value.pop(0) == "look here" else 0; await asyncio.sleep(0.5); servo.duty_cycle = 0
await asyncio.sleep(0) # let others do sth
async def pullmqtt(seen, tosend, presses, heylisten):
print(f" try wifi { os.getenv('SSID') } .... ", end=''); wifi.radio.connect( os.getenv("SSID") , os.getenv("PW") ); print("success", end="\n\n"); pixl.fill((10, 10, 10)) # this blocks
print(" init mqtt client .... ",end='') # init mqtt client with callbacks and stuff
def connected(client, userdata, flags, rc): # callback for successfull mqtt connection plus subscribe to all changes on the topic feed
client.subscribe(os.getenv("topic")); print(f"sub to topic {os.getenv('topic')} .... ",end="")
def recive(client, topic, message): # callback for received messages also put finger in the air or answer seen
if client.client_id not in message and "look here" in message: print(" recv look here wait for send queue and heylisten queue .... ", end=""); send("shit"); heylisten.value.append("look here")
if client.client_id not in message and "shit" in message: pixl.fill((0, 20, 0)); print(f" .... this seen {presses.value} presses in buffer", end="\n\n") # print and signal seen should only increment when other answers‚
def send(message): # publish persistant messages to save tracebacks also this causes tiny bug eg unseen press so look here is retained then even soft reload changes clientid then sees own look here aand servos
print(f"publish {message} .... ", end="\n\n"); mqttclient.publish(os.getenv("topic"), f"{mqttclient.client_id} says {message}", retain = True)
pool = socketpool.SocketPool(wifi.radio); sslcontext = ssl.create_default_context() # spawn socket pool for minimqtt also here no ssl cert
mqttclient = adafruit_minimqtt.adafruit_minimqtt.MQTT( # see docs.circuitpython.org/projects/minimqtt for more info
broker = os.getenv("broker"), port = os.getenv("port"), username = "username", password = "password", socket_pool = pool, ssl_context = sslcontext, socket_timeout = 0.5)
mqttclient.on_connect = connected; mqttclient.on_message = recive; print(f"clientid {mqttclient.client_id} .... success", end="\n\n"); pixl.fill((15, 15, 15)) # append callbacks form aboveus
print(f" try mqtt broker {os.getenv("broker")} .... ", end=''); mqttclient.connect(); print("success", end="\n\n"); pixl.fill((20, 20, 20)) # try broker this blocks and only returns on success
print(f" wait for traceback and send queue .... ", end=""); send(f"{supervisor.get_previous_traceback()} {supervisor.runtime.run_reason}"); # prev tb only avalible when last vm ended with uncought exception
print(f" home servo and enter loop .... ", end="\n\n\n\n"); heylisten.value.append("sit"); pixl.fill((25, 25, 25))
for flash in range (0,2): pixl.fill((0, 0, 0)); await asyncio.sleep(0.2); pixl.fill((0, 30, 0)); await asyncio.sleep(0.3); pixl.fill((0, 0, 0)) # visual confirmation done init
while True: # send one message from queue aslo ping mqtt broker
if tosend.value: send(tosend.value.pop(0))
mqttclient.loop(timeout=1)
pixl.fill((0, 0, 0)); await asyncio.sleep(2) # let other tasses time
async def main():
presses = commclass(0); seen = commclass(0); tosend = commclass([]); heylisten = commclass([]) # spawn comm calsses seperate classes here for redabilety
catchfstas = asyncio.create_task( catchflanks(board.BUTTON, board.A1, presses) ) # spawn async tasks who talk via commclass instances
sendfstas = asyncio.create_task( sendfs(presses, seen, tosend, heylisten) )
movetas = asyncio.create_task( move(heylisten) )
pullmqtttas = asyncio.create_task( pullmqtt(seen, tosend, presses, heylisten) )
await asyncio.gather(catchfstas, pullmqtttas, sendfstas, movetas) # gather forever since no task ever exits
print("\n\n\n\n"); pixl = neopixel.NeoPixel(board.NEOPIXEL, 1); pixl.fill((5, 5, 5)); supervisor.set_next_code_file(None ,reload_on_error = True) # see belowus also this catches ctrl c cool cool cool cool
asyncio.run(main()) # works or infinite soft reloads to fix yourself see aboveus this instead of try except so exeption is uncought for supervisor previous traceback to work
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment