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

  1. Installation
  2. Connection Example
  3. API Reference
  4. Complete Example

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())

View full documentation