Elixir library for controlling toio™ Core Cubes via Bluetooth Low Energy.
This library provides a high-level API for discovering and controlling toio Core Cubes. Each cube runs in its own supervised process, allowing you to manage multiple cubes simultaneously.
- 🔍 Auto-discovery - Automatically scan for and connect to toio cubes
- 🎮 Motor Control - Move, rotate, and navigate to specific positions
- 💡 LED Control - Control the RGB LED with colors and light scenarios
- 🔊 Sound - Play sound effects and MIDI melodies
- 📡 Event System - Subscribe to button, sensor, battery, and position events
- 🔄 Multi-cube - Control multiple cubes simultaneously with process-based architecture
- 🛡️ Fault Tolerant - Each cube runs under a supervisor for resilience
Add toio to your list of dependencies in mix.exs:
def deps do
[
{:toio, github: "kentaro/toio_ex"}
]
endOnce published to Hex, you can use:
def deps do
[
{:toio, "~> 0.1.0"}
]
end# Discover and connect to toio cubes
{:ok, cubes} = Toio.discover()
# Get the first cube
[cube | _] = cubes
# Move forward
Toio.move(cube, 50, 50)
# Turn on LED
Toio.turn_on_light(cube, 255, 0, 0)
# Play a sound
Toio.play_sound_effect(cube, :enter)
# Handle button events
cube
|> Toio.on(:button, fn event ->
IO.puts("Button: #{if event.pressed, do: "pressed", else: "released"}")
end)# Discover all cubes (scan for 5 seconds by default)
{:ok, cubes} = Toio.discover()
# Discover just one cube
{:ok, [cube]} = Toio.discover(count: 1)
# Scan for 10 seconds
{:ok, cubes} = Toio.discover(duration: 10_000)# Move forward
Toio.move(cube, 50, 50)
# Turn right (left motor forward, right motor backward)
Toio.move(cube, 50, -50)
# Move for 2 seconds then stop automatically
Toio.move_timed(cube, 50, 50, 2000)
# Move to a specific position on the mat
Toio.move_to(cube, 200, 200, 90)
# Stop
Toio.stop(cube)# Turn on red light
Toio.turn_on_light(cube, 255, 0, 0)
# Green light for 2 seconds
Toio.turn_on_light(cube, 0, 255, 0, 2000)
# Rainbow effect
operations = [
{500, 255, 0, 0}, # Red
{500, 255, 127, 0}, # Orange
{500, 255, 255, 0}, # Yellow
{500, 0, 255, 0}, # Green
{500, 0, 0, 255}, # Blue
{500, 75, 0, 130}, # Indigo
{500, 148, 0, 211} # Violet
]
Toio.play_light_scenario(cube, operations, 3) # Repeat 3 times
# Turn off
Toio.turn_off_light(cube)# Play sound effects
Toio.play_sound_effect(cube, :enter)
Toio.play_sound_effect(cube, :mat_in, 200) # With volume
# Play MIDI notes (C major scale)
notes = [
{300, 60, 255}, # C4
{300, 62, 255}, # D4
{300, 64, 255}, # E4
{300, 65, 255}, # F4
{300, 67, 255}, # G4
{300, 69, 255}, # A4
{300, 71, 255}, # B4
{300, 72, 255} # C5
]
Toio.play_midi(cube, notes)
# Stop sound
Toio.stop_sound(cube)The library provides a clean, pipeable API for handling cube events:
# Attach event handlers using the pipe operator
cube
|> Toio.on(:button, fn event ->
IO.puts("Button: #{if event.pressed, do: "pressed", else: "released"}")
end)
|> Toio.on(:sensor, fn event ->
if event.collision, do: IO.puts("Collision!")
end)
|> Toio.on(:battery, fn event ->
IO.puts("Battery: #{event.percentage}%")
end)
# Use filtered handlers for specific conditions
cube
|> Toio.on(:button, & &1.pressed, fn _ ->
IO.puts("Button pressed (filtered)")
end)
|> Toio.on(:battery, &(&1.percentage < 20), fn event ->
IO.puts("Low battery: #{event.percentage}%")
end)
# Remove handlers
Toio.off(cube, :button)Event types:
:button- Button press/release:sensor- Motion, collision, double-tap detection:battery- Battery level updates:id- Position and Standard ID information:motor_response- Motor command responses
# Discover multiple cubes
{:ok, [cube1, cube2]} = Toio.discover(count: 2)
# Control them independently
Toio.turn_on_light(cube1, 255, 0, 0) # Red
Toio.turn_on_light(cube2, 0, 0, 255) # Blue
Toio.move(cube1, 50, 50) # Both move forward
Toio.move(cube2, 50, 50)
# Make them dance!
Task.async(fn ->
Toio.move(cube1, 50, -50) # Spin right
end)
Task.async(fn ->
Toio.move(cube2, -50, 50) # Spin left
end)The library is organized with a process-based architecture:
- Toio.Scanner - Discovers toio cubes via BLE scanning
- Toio.Cube - GenServer managing a single cube connection
- Toio.CubeSupervisor - DynamicSupervisor for cube processes
- Toio.Manager - Manages discovery and automatic cube process startup
- Toio.Specs.* - Binary encoding/decoding for BLE characteristics
- Toio.Types - Type definitions for cube data structures
Each discovered cube runs in its own supervised GenServer process, providing:
- Isolation: One cube crashing won't affect others
- Concurrency: Control multiple cubes simultaneously
- Fault tolerance: Automatic restart on failures
See the examples/ directory for complete working examples:
basic_movement.exs- Basic motor controllight_control.exs- LED control and scenariossound_control.exs- Sound effects and MIDI playbackevent_subscription.exs- Subscribing to cube eventsmultiple_cubes.exs- Controlling multiple cubes
Run examples with:
mix run examples/basic_movement.exsToio.discover/1- Discover and connect to cubesToio.list_cubes/0- List all managed cube processesToio.stop_all/0- Stop all cube processes
Toio.connect/2- Connect to a cubeToio.disconnect/1- Disconnect from a cube
Toio.move/3- Move with left/right motor speedsToio.move_timed/4- Move for a durationToio.move_to/5- Move to target position on matToio.stop/1- Stop movement
Toio.turn_on_light/5- Turn on LED with RGB colorToio.turn_off_light/1- Turn off LEDToio.play_light_scenario/3- Play light animation
Toio.play_sound_effect/3- Play predefined soundToio.play_midi/3- Play MIDI notesToio.stop_sound/1- Stop sound playback
Toio.on/3- Attach event handler (pipeable)Toio.on/4- Attach filtered event handler (pipeable)Toio.off/2- Remove event handlers
Available sound effects:
:enter- Enter sound:selected- Selection sound:cancel- Cancel sound:cursor- Cursor movement:mat_in- On mat detection:mat_out- Off mat detection:get1,:get2,:get3- Collection sounds:effect1,:effect2- Generic effects
- Elixir >= 1.18
- macOS, Linux, or Windows with BLE support
- toio Core Cube (BLE 4.2)
- rustler_btleplug for BLE communication
Apache License 2.0
- toio™ Official Website
- toio™ Technical Specifications
- toio.js - Official JavaScript library
Contributions are welcome! Please feel free to submit a Pull Request.