Python SDK for Frame
The Python SDK enables application development for Frame using Python. It supports all device features through an asynchronous interface.
Table of Contents
Installation
pip install frame-sdk
Connection Example
import asyncio
from frame_sdk import Frame
async def main():
async with Frame() as frame:
print(f"Connected: {frame.bluetooth.is_connected()}")
print(f"Battery: {await frame.get_battery_level()}%")
asyncio.run(main())
API Reference
Display
await frame.display.show_text("Text")
await frame.display.scroll_text("Long text")
await frame.display.draw_rect(x, y, width, height)
# Example of text alignment
await frame.display.write_text("Top-left", align=Alignment.TOP_LEFT)
await frame.display.write_text("Top-Center", align=Alignment.TOP_CENTER)
await frame.display.write_text("Top-Right", align=Alignment.TOP_RIGHT)
await frame.display.write_text("Middle-Left", align=Alignment.MIDDLE_LEFT)
await frame.display.write_text("Middle-Center", align=Alignment.MIDDLE_CENTER)
await frame.display.write_text("Middle-Right", align=Alignment.MIDDLE_RIGHT)
await frame.display.write_text("Bottom-Left", align=Alignment.BOTTOM_LEFT)
await frame.display.write_text("Bottom-Center", align=Alignment.BOTTOM_CENTER)
await frame.display.write_text("Bottom-Right", align=Alignment.BOTTOM_RIGHT)
await frame.display.show()
# Example of drawing rectangles
await frame.display.draw_rect(220, 100, 200, 200, PaletteColors.WHITE)
await frame.display.draw_rect(320-8, 200-8, 16, 16, PaletteColors.RED)
await frame.display.show()
# Example of drawing filled rectangles
await frame.display.draw_rect_filled(100, 100, 200, 200, 8, PaletteColors.RED, PaletteColors.CLOUDBLUE)
await frame.display.write_text("Hello world!", x=110, y=110, w=180, h=180, align=Alignment.MIDDLE_CENTER)
await frame.display.show()
Camera
from frame_sdk.camera import Quality, AutofocusType
# Take photo
photo = await frame.camera.take_photo()
await frame.camera.save_photo("photo.jpg")
# Take photo with more control
photo = await frame.camera.take_photo(
autofocus_seconds=2,
quality=Quality.HIGH,
autofocus_type=AutofocusType.CENTER_WEIGHTED
)
# Save photo
await frame.camera.save_photo("frame-test-photo.jpg")
# Save photo with more control
await frame.camera.save_photo(
"frame-test-photo-2.jpg",
autofocus_seconds=3,
quality=Quality.HIGH,
autofocus_type=AutofocusType.CENTER_WEIGHTED
)
File System
# Write file
await frame.files.write_file("test.txt", b"Content")
# Read file
content = await frame.files.read_file("test.txt")
# Delete file
did_delete = await frame.files.delete_file("main.lua")
print(f"Deleted? {did_delete}")
# Check if file exists
exists = await frame.files.file_exists("main.lua")
print(f"Main.lua {'exists' if exists else 'does not exist'}")
Bluetooth
await frame.bluetooth.connect()
await frame.bluetooth.send_lua("print('hello')")
# Send break signal
await frame.bluetooth.send_break_signal()
# Send reset signal
await frame.bluetooth.send_reset_signal()
# Wait for data
full_file_data = await frame.bluetooth.wait_for_data()
print(full_file_data.decode())
Microphone
# Record audio
audio = await frame.microphone.record_audio()
# Record audio with more control
audio = await frame.microphone.record_audio(
silence_cutoff_length_in_seconds=None,
max_length_in_seconds=5
)
# Save audio file
await frame.microphone.save_audio_file("test-audio.wav")
# Save audio file with more control
await frame.microphone.save_audio_file(
"test-audio.wav",
silence_cutoff_length_in_seconds=None,
max_length_in_seconds=5
)
Motion
# Get direction
direction = await frame.motion.get_direction()
# Run on tap
def on_tap():
print("Frame was tapped!")
await frame.motion.run_on_tap(
lua_script="frame.display.text('I was tapped!',1,1);frame.display.show();",
callback=on_tap
)
# Wait for tap
await frame.motion.wait_for_tap()
Complete Example
import asyncio
from frame_sdk import Frame
from frame_sdk.display import Alignment
import datetime
async def main():
async with Frame() as f:
print(f"Connected: {f.bluetooth.is_connected()}")
print(f"Frame battery: {await f.get_battery_level()}%")
# Write and read file
await f.files.write_file("greeting.txt", b"Hello world")
print((await f.files.read_file("greeting.txt")).decode())
# Display text
await f.run_lua("frame.display.text('Hello world', 50, 100);frame.display.show()")
print(await f.evaluate("1+2"))
# Wait for tap and take photo
print("Tap the Frame to continue...")
await f.display.show_text("Tap the Frame to take a photo", align=Alignment.MIDDLE_CENTER)
await f.motion.wait_for_tap()
await f.display.show_text("Taking photo...", align=Alignment.MIDDLE_CENTER)
await f.camera.save_photo("frame-test-photo.jpg")
await f.display.show_text("Photo saved!", align=Alignment.MIDDLE_CENTER)
photo_bytes = await f.camera.take_photo(autofocus_seconds=1)
# Record audio
print("About to record until you stop talking")
await f.display.show_text("Say something...", align=Alignment.MIDDLE_CENTER)
length = await f.microphone.save_audio_file("test-audio.wav")
print(f"Recorded {length:01.1f} seconds: \"./test-audio.wav\"")
await f.display.show_text(f"Recorded {length:01.1f} seconds", align=Alignment.MIDDLE_CENTER)
await asyncio.sleep(3)
# Motion detection
print("Move around to track intensity of your motion")
await f.display.show_text("Move around to track intensity of your motion", align=Alignment.MIDDLE_CENTER)
intensity_of_motion = 0
prev_direction = await f.motion.get_direction()
for _ in range(10):
await asyncio.sleep(0.1)
direction = await f.motion.get_direction()
intensity_of_motion = max(intensity_of_motion, (direction-prev_direction).amplitude())
prev_direction = direction
print(f"Intensity of motion: {intensity_of_motion:01.2f}")
await f.display.show_text(f"Intensity of motion: {intensity_of_motion:01.2f}", align=Alignment.MIDDLE_CENTER)
print("Tap the Frame to continue...")
await f.motion.wait_for_tap()
# Display battery and time
batteryPercent = await f.get_battery_level()
color = 2 if batteryPercent < 20 else 6 if batteryPercent < 50 else 9
batteryWidth = 150
batteryHeight = 75
await f.display.draw_rect(640-32,40 + batteryHeight//2-8, 32, 16, 1)
await f.display.draw_rect_filled(640-16-batteryWidth, 40-8, batteryWidth+16, batteryHeight+16, 8, 1, 15)
await f.display.draw_rect(640-8-batteryWidth, 40, int(batteryWidth * 0.01 * batteryPercent), batteryHeight, color)
await f.display.write_text(f"{batteryPercent}%", 640-8-batteryWidth, 40, batteryWidth, batteryHeight, Alignment.MIDDLE_CENTER)
await f.display.write_text(datetime.datetime.now().strftime("%-I:%M %p\n%a, %B %d, %Y"), align=Alignment.MIDDLE_CENTER)
await f.display.show()
# Set wake screen
await f.run_on_wake("""frame.display.text('Battery: ' .. frame.battery_level() .. '%', 10, 10);
if frame.time.utc() > 10000 then
local time_now = frame.time.date();
frame.display.text(time_now['hour'] .. ':' .. time_now['minute'], 300, 160);
frame.display.text(time_now['month'] .. '/' .. time_now['day'] .. '/' .. time_now['year'], 300, 220)
end;
frame.display.show();
frame.sleep(10);
frame.display.text(' ',1,1);
frame.display.show();
frame.sleep()""")
# Sleep after 10 seconds
await f.run_lua("frame.sleep(10);frame.display.text(' ',1,1);frame.display.show();frame.sleep()")
asyncio.run(main())