USHER Lua Application Manual
USHER Lua 組み込み開発環境へようこそ。USHER を使うと、スマートフォンから Bluetooth (BLE) 経由で独立した Lua スクリプトを送信し、スマートウォッチのディスプレイ上で Lua ランタイムを直接動かすことができます。
複雑なファームウェアの再コンパイルは不要です。テキストエディタでスクリプトを書き、スマートフォンアプリからデバイスに転送するだけで、瞬時に新しいアプリやウィジェットを実行できます。
主な特長
- 超軽量・高速実行: ESP32-S3 の PSRAM 上で最適化された Lua インタプリタが動作し、最大 60FPS のスムーズな描画を実現。
- 豊富な LVGL 9.4 バインディング: ボタン、ラベル、ARC(円形ゲージ)、スライダー、グラフ、アニメーション、カスタムフォントなどを Lua から直接制御。
- センサー&ハードウェア連携: 6軸加速度/ジャイロセンサー、I2Sデジタルマイク、内蔵RTCクロック、バッテリー残量、画面輝度調整をシンプルな API で操作。
- BLE 双方向通信: スマートフォンアプリとリアルタイムにデータ送受信(キーボード/マウスHID、メディア制御、データパケット)。
- セーブ対応ツール:
fs(ファイルシステム)とjsonAPI を使って、ユーザー設定やゲームのハイスコアを USHER 本体のフラッシュメモリ (LittleFS) に直接保存・読み込みできます。
// CAPABILITIES: 何が作れるのか?
拡充されたバインディング(連携機能)のおかげで、Lua アプリケーションで非常に多彩な表現が可能になっています。
- アクションゲーム & おもちゃ: 高精度な
sys.millis()、ゲームループに使えるlv.timer関数、ハードウェアシードを利用したmath.random()にアクセスできます。Pong、避けゲー、サイコロのようなミニゲームが作成可能です! - サイバーパンク・ダッシュボード: 円形ゲージ (Arc)、プログレスバー (Bar)、グラフ (Chart) などのウィジェットを使って、SF 映画に出てくるような没入感のあるデータリッチなインターフェースを構築できます。
- セーブ対応ツール:
fs(ファイルシステム)とjsonAPI を使って、ユーザー設定やゲームのハイスコアを USHER 本体のフラッシュメモリ (LittleFS) に直接保存・読み込みできます。 - IoT コントローラー: BLE API にアクセスしてスマートフォン側の USHER アプリにデータを送り返したり、画面の明るさなどハードウェア機能を直接操作できます。
// METADATA: アプリの構成とメタデータ
Lua アプリケーションの挙動や表示を制御するために、main.lua の冒頭(最初の10行以内)にコメント形式でメタデータを記述できます。
@icon(アイコンの設定): アプリ一覧画面で表示されるアイコンを指定します(例:-- @icon: Star)。利用可能な名前の一覧は[04. CYBER ICONS] タブを参照してください。@category(カテゴリの設定): アプリの分類を指定します(例:-- @category TOOL)。@home(ホーム画面への登録):trueを指定すると、ホーム画面の watch face ループにウィジェットとして登録されます(例:-- @home: true)。
// WIDGET_GUIDE: ホーム画面ウィジェット開発ガイド
USHER では、同じ Lua スクリプトを 「スタンドアロンアプリ」 と 「ホーム画面に埋め込まれるウィジェット」 の2つのモードで動作させることができます。app.is_interactive() を判定することで、状況に合わせてレイアウトや枠線、入力応答性を動的に切り替えることができます。
1. 独立アプリモード (Standalone App)
フルスクリーンの対話型アプリとして単独起動。すべてのタップ操作、カスタムボタン、ジェスチャー、終了操作をサポート。ミニゲームや電卓、本格的なツール開発に最適です。
2. ホームウィジェットモード (Home Widget)
ホーム画面のスライドショーにインラインで埋め込み動作。ボタンタップ等のUI操作を受け付けつつ、左右・上下スワイプ操作は自動で親画面に伝播してスムーズなページ切り替えを実現します。
// CODE_EXAMPLE: アプリ・ウィジェット開発の実装例
以下は、両モードで適切にレイアウトを分岐させ、タッチイベントを処理する標準的な実装パターンです。
-- 1. Metadata and configuration
-- @name: MyWidget
-- @home: true
-- 2. Fetch screen root & mode
local scr = lv.scr()
local is_app = app.is_interactive()
-- 3. Create styled container
local container = lv.obj_create(scr)
lv.set_size(container, 240, 240)
if is_app then
lv.set_style_border_width(container, 1, 0)
else
lv.set_style_border_width(container, 0, 0)
lv.set_style_bg_opa(container, 0, 0)
end
-- 4. Create and align button
local btn = lv.btn(container, "Tap Me")
lv.align(btn, lv.ALIGN_CENTER, 0, 40)
-- 5. Set up action callback
lv.add_event_cb(btn, function()
print("Clicked!")
end, lv.EVENT_CLICKED)
// OPTIMIZATION: 省電力 & ウェアラブル最適化 (Auto-Sleep / Flash Write 制限)
デバイスのバッテリーおよび内蔵フラッシュメモリ (LittleFS) 寿命を保護するため、以下の開発パターンに従ってください。
[POWER_SAVING] 無操作自動終了 (Auto-Sleep)
スタンドアロンモードで起動されたアプリは、一定時間(例:30秒)操作がない場合に app.save_settings(state) でデータを書き出して lv.close() で自動終了させます。最後の数秒間は画面にスリープ警告を表示すると親切です。
[STORAGE] フラッシュ書き込み制限
ゲームループやシミュレーション動作中に app.save_settings() を頻繁に実行するとフラッシュメモリが劣化します。通常状態はメモリ上(Luaローカル変数)だけで値を変更し、アプリを終了する瞬間(EXITボタンタップや自動終了時)にのみセーブを実行してください。
// API_REFERENCE: API リファレンス
現在 USHER の Lua 実行環境で利用可能なすべてのモジュールと API の詳細仕様です。
1. sys (システム & ハードウェア)
USHER のハードウェアリソース、センサー、タイミング、電源制御、オーディオ機能への直接アクセスを提供します。
| カテゴリ | 関数シグネチャ (SIGNATURE) | 戻り値 (RETURNS) | 機能説明 / 引数仕様 (DESCRIPTION) |
|---|---|---|---|
|
時刻 & タイミング [TIMING] |
sys.millis() |
int |
起動からの経過時間(ミリ秒単位)。デルタタイム計算やゲームループに必須。 |
sys.uptime() |
int |
稼働時間を秒単位で返します。 | |
sys.get_time() |
hour, min, sec |
現在の時 (0-23)、分 (0-59)、秒 (0-59) を3つの整数として返します。時計アプリ向け。 | |
sys.get_date() |
year, month, day, wday |
現在の年月日および曜日 (wday: 1=日, 2=月, ..., 7=土) を返します。 | |
|
センサー & メモリ [SENSORS] |
sys.get_accel() |
x, y, z |
3軸加速度センサーから現在の X, Y, Z 値(単位: G)を取得。傾き操作向け。 |
sys.get_battery() |
int |
現在のバッテリー残量をパーセンテージ (0〜100) で返します。 | |
sys.get_temperature() |
float |
USHER 内部の温度センサー値(℃)を返します。 | |
sys.heap_free() |
int |
現在利用可能な空き RAM 容量(バイト単位)を返します。 | |
sys.heap_min() |
int |
起動以降に記録された最小空き RAM 容量。メモリリーク監視用。 | |
|
ハードウェア制御 [HARDWARE] |
sys.set_brightness(level) |
nil | 液晶バックライト輝度を設定 (0〜255)。 |
sys.set_performance_mode(mode) |
nil | CPUクロック周波数を変更 ("low": 80MHz, "medium": 160MHz, "high": 240MHz)。 |
|
sys.reset_activity() |
nil | 省電力マネージャーの無操作タイマーをリセットし、スリープ移行を抑止。 | |
sys.sleep() |
nil | デバイスを即座にディープスリープモードへ移行させます。 | |
sys.restart() |
nil | USHER 本体をハードウェア再起動します。 | |
|
マイク & 音声 [AUDIO] |
sys.audio_start() |
nil | I2S デジタルマイクのサンプリングを開始します。 |
sys.audio_stop() |
nil | マイクのサンプリング処理を停止して省電力化します。 | |
sys.audio_get_level() |
int |
現在のリアルタイム音量レベル (0〜255) を返します。 | |
sys.audio_get_spectrum([bands]) |
table |
FFT 周波数スペクトル配列を返します(デフォルト: 8バンド)。ビジュアライザー用。 | |
|
コールバック & UI [EVENTS/UI] |
sys.on_shake(callback) |
nil | シェイク検知時のコールバック関数を登録(1秒クールダウン)。nil で解除。 |
sys.on_mic_level(threshold, cb) |
nil | 音量が threshold を超えた際のコールバック関数を登録。500ms クールダウン。 |
|
sys.exit_btn() |
nil | 画面下部に標準EXITボタンを自動生成(スタンドアロン時のみ有効、ウィジェット時は自動非表示)。 |
2. fs (ファイルシステム)
内蔵ストレージ (LittleFS) 上でファイルおよびディレクトリの入出力操作を行います。
| 関数シグネチャ (SIGNATURE) | 戻り値 (RETURNS) | 機能説明 / 引数仕様 (DESCRIPTION) |
|---|---|---|
fs.exists(path) |
bool |
指定したパスにファイルまたはディレクトリが存在すれば true。 |
fs.read(path) |
string / nil |
ファイル全体を一括で文字列として読み込みます。ファイル不在または失敗時は nil。 |
fs.write(path, content) |
bool |
指定パスに文字列を上書き保存します。成功時 true。 |
fs.remove(path) |
bool |
指定したファイルまたは空ディレクトリを削除します。 |
fs.mkdir(path) |
bool |
親階層を含めてディレクトリを再帰的に作成します。 |
fs.list(dir_path) |
table |
指定ディレクトリ内のファイル名一覧を文字列配列テーブルとして返します。 |
3. json (データ解析)
Lua のテーブル構造と JSON 文字列・ファイル間の相互シリアライズを行います。
| 関数シグネチャ (SIGNATURE) | 戻り値 (RETURNS) | 機能説明 / 引数仕様 (DESCRIPTION) |
|---|---|---|
json.load(path) |
table / nil |
JSONファイルを読み込み、Luaテーブルにパースして返します。構文エラー時は nil。 |
json.save(path, table) |
bool |
LuaテーブルをJSON文字列に変換し、指定パスのファイルへ永続保存します。 |
4. app (アプリケーション管理)
実行モードの判定およびアプリ個別設定の永続化管理を行います。
| 関数シグネチャ (SIGNATURE) | 戻り値 (RETURNS) | 機能説明 / 引数仕様 (DESCRIPTION) |
|---|---|---|
app.is_interactive() |
bool |
独立フルスクリーンアプリ時 true、ホーム画面ウィジェット埋め込み時 false。 |
app.save_settings(table) |
bool |
アプリ固有の settings.json にテーブル内容を即時保存します。 |
app.load_settings() |
table / nil |
保存済みのアプリ固有設定を読み込みます。未保存時は nil。 |
5. ble (Bluetooth & ネットワーク)
スマートフォンアプリとの高速バイナリ通信、および HID キーボード/マウス/メディアコントロールを提供します。
| カテゴリ | 関数シグネチャ (SIGNATURE) | 戻り値 (RETURNS) | 機能説明 / 引数仕様 (DESCRIPTION) |
|---|---|---|---|
|
通信 & 状態 [NETWORK] |
ble.send(text) |
nil | スマホ側アプリへテキストを高速送信 (Fire & Forget)。 |
ble.send_reliable(text, [timeout]) |
bool |
TCPライクなACKハンドシェイク付き高信頼性送信。成功時 true。 |
|
ble.is_connected() |
bool |
BLE デバイスが接続中であれば true。 |
|
ble.get_status() |
string |
接続状態文字列 ("idle", "advertising", "bonded", "failed" 等)。 |
|
ble.set_enabled(enable) |
nil | BLE の無線機能を有効化/無効化します。 | |
ble.get_device_name() |
string |
接続先ホストのデバイス名文字列を取得します。 | |
|
コールバック [CALLBACKS] |
ble.on_receive(callback) |
nil | スマホからデータ受信時のコールバックを登録。引数に受信文字列。 |
ble.on_connect(callback) |
nil | BLE 接続が確立された瞬間に呼び出されるコールバック。 | |
ble.on_disconnect(callback) |
nil | BLE 接続が切断された瞬間に呼び出されるコールバック。 | |
|
HID キーボード [KEYBOARD] |
ble.kbd_stroke(key, [mod]) |
nil | キーを1回タイプ (例: "a", "ENTER", "ESC", mod: 0x01=Ctrl, 0x02=Shift)。 |
ble.kbd_press(key, [mod]) |
nil | 指定キーを押した状態を維持します。 | |
ble.kbd_release() |
nil | 押されているすべてのキーを解放します。 | |
ble.kbd_macro(name) |
nil | マクロコマンドを実行 ("copy", "paste", "cut", "lock")。 |
|
|
マウス & メディア [MOUSE/MEDIA] |
ble.mouse_move(dx, dy, [w]) |
nil | マウスカーソルを相対座標で移動します (w: ホイールスクロール)。 |
ble.mouse_click([btn]) |
nil | マウスボタンをクリック (1=左, 2=右, 4=中クリック)。 | |
ble.media_play() / media_next() |
nil | 音楽の再生/一時停止、曲送り/曲戻し。 | |
ble.media_vol_up() / vol_down() |
nil | 接続機器の音量アップ/ダウン、ミュート切替。 | |
|
画像バッファ [IMAGE] |
ble.get_jacket_image_dsc() |
lightuserdata |
BLE 経由で受信したジャケット画像のLVGL記述子を取得(lv.img_set_src 用)。 |
6. lv (LVGL グラフィック & UIエンジン)
LVGL 9.4.0 ベースの円形ディスプレイ用UIウィジェット、レイアウト、スタイル、アニメーションAPIです。
| 分類 | 主要 API 関数 (SIGNATURE) | 機能説明 / 用途 (DESCRIPTION) |
|---|---|---|
|
ウィジェット生成 [CREATION] |
lv.scr(), lv.obj_create(parent) |
画面ルートオブジェクトの取得、および汎用コンテナボックスの生成。 |
lv.btn(parent, [text]), lv.label(parent, [text]) |
タップ可能なボタン、およびテキスト表示用ラベルの生成。 | |
lv.arc_create(parent), lv.bar_create(parent) |
円形アークゲージ (Arc)、および直線プログレスバー (Bar) の生成。 | |
lv.slider_create(parent), lv.chart_create(parent) |
スライダー入力部品、および折れ線・棒グラフ (Chart) の生成。 | |
lv.lottie_create(parent, src, [w], [h])lv.lottie_set_src(lottie, src) |
Lottie ベクターアニメーションウィジェットの生成・更新。src にはファイルパス("images/foo.json")または直接 JSON文字列 を指定可能。PSRAM描画バッファを自動確保・解放。 |
|
|
配置 & レイアウト [LAYOUT] |
lv.set_size(obj, w, h), lv.set_pos(obj, x, y) |
オブジェクトの幅・高さ、および X・Y 座標をピクセル単位で直接指定。 |
lv.align(obj, align_type, x_off, y_off) |
親を基準とした位置合わせ (lv.ALIGN_CENTER, lv.ALIGN_TOP_MID 等)。 |
|
lv.center(obj), lv.set_flex_flow(obj, flow) |
親の中央配置、および Flexbox 自動整列レイアウト (ROW / COLUMN) の設定。 | |
|
スタイル & 装飾 [STYLING] |
lv.set_style_bg_color(obj, color, 0)lv.set_style_bg_opa(obj, opa, 0) |
背景色および不透明度の設定 (opa: lv.OPA_COVER, lv.OPA_TRANSP)。 |
lv.set_style_text_color(obj, color, 0)lv.set_style_text_font(obj, font, 0) |
文字色およびフォントの設定 (lv.font_cyber() でサイバーフォント適用)。 |
|
lv.set_style_border_color / width / radius |
枠線の色・線幅・角丸半径 (Radius) を設定。ネオングロー表現に活用。 | |
|
イベント & タイマー [EVENTS/ANIM] |
lv.add_event_cb(obj, cb, [event_code]) |
クリック (LV_EVENT_CLICKED) やジェスチャー発生時のコールバック登録。 |
lv.timer(ms, callback) |
指定ミリ秒間隔で定期実行されるゲームループ・更新タイマーの生成。 | |
lv.anim(obj, cb, start, end, dur, rep, [dly]) |
イージングアニメーションの登録。プロパティを連続的に滑らかに変化。 | |
|
メモリ & 終了 [SYSTEM] |
lv.obj_delete(obj) / lv.obj_clean(obj) |
不要になったウィジェットの破棄、または子要素全削除によるメモリ解放。 |
lv.close() |
実行中の Lua アプリを即座に安全終了し、OSのメインメニューへ復帰。 |
// LOTTIE VECTOR ANIMATION
USHER は Lottie (.json) ベクターアニメーションをネイティブサポートしています。ファイルパス(LittleFS)からのロードに加え、インラインの JSON文字列データ を直接渡して再生することも可能です。
-- パターン1: LittleFS 内の JSON ファイルを指定
local lottie = lv.lottie_create(scr, "images/cyber_ring.json", 200, 200)
lv.align(lottie, lv.ALIGN_CENTER, 0, 0)
-- パターン2: インライン JSON 文字列データを直接渡す
local json_str = '{"v":"5.5.7","fr":30,"ip":0,"op":60,"w":100,"h":100,"layers":[...]}'
local lottie_inline = lv.lottie_create(scr, json_str, 100, 100)
-- アニメーションの動的差し替え
lv.lottie_set_src(lottie, "images/warning.json")
Lottie は毎フレーム CPU でベクターラスタライズを行うため、常時ループ再生よりも「タップ時や通知時の 1〜2 秒間のサイバー演出」としての利用が最適です。また、30fps(
"fr": 30)のアニメーションを使用すると消費電力を抑えられます。PSRAM 描画バッファはウィジェット削除時に自動解放されます。
7. require & 定数一覧
Lua 標準の require(modname) による分割ファイル読み込み、およびシステム定数一覧です。
| 定数グループ | 定義済み定数名 |
|---|---|
| アラインメント (Align) | lv.ALIGN_CENTER, lv.ALIGN_TOP_MID, lv.ALIGN_BOTTOM_MID, lv.ALIGN_LEFT_MID, lv.ALIGN_RIGHT_MID, lv.ALIGN_TOP_LEFT, lv.ALIGN_BOTTOM_RIGHT |
| イベントコード (Event) | lv.EVENT_CLICKED, lv.EVENT_PRESSED, lv.EVENT_RELEASED, lv.EVENT_VALUE_CHANGED, lv.EVENT_GESTURE, lv.EVENT_DELETE |
| スワイプ方向 (Direction) | lv.DIR_LEFT, lv.DIR_RIGHT, lv.DIR_TOP, lv.DIR_BOTTOM, lv.DIR_ALL |
| オブジェクトフラグ (Flag) | lv.OBJ_FLAG_HIDDEN, lv.OBJ_FLAG_CLICKABLE, lv.OBJ_FLAG_SCROLLABLE |
| カラーヘルパー (Color) | lv.color_hex(0x00FF88), lv.color_white(), lv.color_black(), lv.palette(idx) |
[ICONS] 8. カスタムアイコン (Cyber Icons)
USHER には、12px に最適化された豊富なカスタム・テクニカルアイコンが組み込まれています。これらはフォントとして実装されているため、テキストと同様に色を変えたり、サイズを調整したりできます。
[LIST] アイコン一覧と UTF-8 文字列
Lua スクリプト内でアイコンを表示するには、以下の UTF-8 文字列(エスケープシーケンス)を使用します。
| アイコン名 | Unicode | Lua での記述 (UTF-8) |
|---|---|---|
| Bluetooth | U+E001 | "\xEE\x80\x81" |
| Battery | U+E003 | "\xEE\x80\x83" |
| Settings | U+E004 | "\xEE\x80\x84" |
| Warning | U+E006 | "\xEE\x80\x86" |
| Sun (晴れ) | U+E013 | "\xEE\x80\x93" |
| Music | U+E016 | "\xEE\x80\x96" |
| Check (OK) | U+E020 | "\xEE\x80\xA0" |
※ 利用可能な全アイコン一覧およびカラーコード生成ツールは [ 04. CYBER ICONS ] タブ を参照してください。
[EXAMPLE] 使用例 (Lua)
-- ラベルに Bluetooth アイコンを表示
local label = lv.label(lv.scr())
lv.set_text(label, "\xEE\x80\x81 Bluetooth Active")
lv.set_style_text_color(label, lv.color_hex(0x00FFFF), 0) -- ネオンシアン
lv.center(label)
Welcome to the USHER Lua development environment. USHER allows you to execute standalone Lua scripts on the round smartwatch display, transmitted wirelessly over Bluetooth LE from your phone.
This document serves as the complete technical reference for Lua capabilities, lifecycle management, and API bindings.
// CAPABILITIES
- Games & Interactive Toys: High-precision
sys.millis(),lv.timer, and hardware-seededmath.random()for building mini-games. - Cyberpunk Dashboards: Circular arcs, bar gauges, and line charts for data-rich wearable interfaces.
- State Storage:
fsandjsonAPIs write persistently to LittleFS on SPI flash. - IoT & BLE Control: Stream sensor telemetry back to smartphones or trigger phone controls via BLE HID commands.
// METADATA ANNOTATIONS
Configure app attributes in the first 10 lines of main.lua:
-- @icon: <IconName>: Assigns app list icon (e.g.-- @icon: Dice).-- @category: <Category>: Categorizes app in library (e.g.-- @category: GAME).-- @home: true: Registers app as a swipeable home widget carousel item.
// API_REFERENCE: LUA API SPECIFICATIONS
Comprehensive reference for all standard modules available in the USHER Lua runtime environment.
1. sys (System & Hardware)
Direct low-level access to USHER hardware resources, onboard sensors, timers, power states, and audio processing.
| GROUP | SIGNATURE | RETURNS | DESCRIPTION |
|---|---|---|---|
|
Timing & Clock [TIMING] |
sys.millis() |
int |
System uptime in milliseconds. Essential for delta-time and game loops. |
sys.uptime() |
int |
Uptime in whole seconds. | |
sys.get_time() |
hour, min, sec |
Returns 3 integers for current hours, minutes, seconds. | |
sys.get_date() |
year, month, day, wday |
Returns calendar date and weekday (1=Sun, ..., 7=Sat). | |
|
Sensors & Heap [SENSORS] |
sys.get_accel() |
x, y, z |
3-axis accelerometer readings in Gs. Ideal for tilt gestures. |
sys.get_battery() |
int |
Battery level percentage (0 to 100). | |
sys.get_temperature() |
float |
Internal USHER device temperature (in deg C). | |
sys.heap_free() |
int |
Currently available free RAM heap in bytes. | |
sys.heap_min() |
int |
Minimum lifetime free heap recorded (useful for memory leak detection). | |
|
Power & Control [HARDWARE] |
sys.set_brightness(level) |
nil | Sets LCD backlight brightness level (0 to 255). |
sys.set_performance_mode(mode) |
nil | Sets CPU clock speed ("low": 80MHz, "medium": 160MHz, "high": 240MHz). |
|
sys.reset_activity() |
nil | Resets idle timer to prevent auto-sleep during active loops. | |
sys.sleep() |
nil | Immediately transitions device into deep sleep mode. | |
sys.restart() |
nil | Performs hardware reboot of the USHER device. | |
|
Microphone & Audio [AUDIO] |
sys.audio_start() |
nil | Starts background DMA sampling of I2S digital microphone. |
sys.audio_stop() |
nil | Stops microphone sampling to save power. | |
sys.audio_get_level() |
int |
Returns current realtime microphone amplitude (0 to 255). | |
sys.audio_get_spectrum([bands]) |
table |
Returns FFT frequency band amplitudes array (default 8 bands). |
2. fs (File System)
Read, write, and manage persistent files and directories stored on LittleFS flash partition.
| SIGNATURE | RETURNS | DESCRIPTION |
|---|---|---|
fs.exists(path) |
bool |
Returns true if target file or directory exists. |
fs.read(path) |
string / nil |
Reads entire file contents into string. Returns nil on error. |
fs.write(path, content) |
bool |
Overwrites file with string content. Returns true on success. |
fs.remove(path) |
bool |
Deletes target file or empty directory. |
fs.mkdir(path) |
bool |
Creates directory recursively. |
fs.list(dir_path) |
table |
Returns an array of file name strings within the target folder. |
3. json (Data Serialization)
Bridge Lua dictionary tables and JSON files effortlessly.
| SIGNATURE | RETURNS | DESCRIPTION |
|---|---|---|
json.load(path) |
table / nil |
Loads and parses a JSON file into a Lua table. |
json.save(path, table) |
bool |
Serializes Lua table to JSON and persists to flash file. |
4. app & ble (App Lifecycle & Bluetooth)
| MODULE | SIGNATURE | RETURNS | DESCRIPTION |
|---|---|---|---|
app |
app.is_interactive() |
bool |
true for standalone full app, false for home widget. |
app.save_settings(tbl) |
bool |
Saves table into app-specific settings.json. |
|
app.load_settings() |
table / nil |
Loads app-specific persistent settings table. | |
ble |
ble.send(text) |
nil | Sends text packet over BLE (Fire & Forget). |
ble.send_reliable(text) |
bool |
Sends text with ACK flow control handshake. | |
ble.is_connected() |
bool |
Returns true if BLE connection is active. |
|
ble.on_receive(callback) |
nil | Registers handler for incoming messages from host phone. | |
ble.kbd_stroke(key, [mod]) |
nil | Emulates HID keyboard keystroke. | |
ble.media_play() / next() |
nil | Sends Consumer HID media playback command. |
App Integration & BLE Guide
USHER (スマートペンダントデバイス) とスマートフォンコンパニオンアプリ (Flutter) 間のデータ連携、および組み込み Lua アプリを活用した新規機能(マイク・音声・データ同期など)の開発ガイドラインです。
[01] システム連携アーキテクチャ
エコシステムは以下の3レイヤー構造で相互通信を行っています。
lua_emulator.dart)
lua_core_bindings.cpp)
lv.btn, lv.lottie_create 等)
sys.on_mic_level 等)
[02] BLE 通信プロトコル仕様
デバイス側とスマホ側はカスタムGATTサービス経由で相互通信を行います。
| 機能 / チャンネル | 通信方式 | 用途 |
|---|---|---|
| ファイル転送 | Custom GATT Service | Luaスクリプト、画像(.rgb565)、音声データの高速パケット転送 |
| コマンド制御 | Custom GATT Service | アプリ切り替え、設定変更、マイク機能の開始/停止コントロール |
| データ通知 | Custom GATT Service | リアルタイムセンサー、マイク音量レベル、バッテリー通知 |
[CRITICAL] 通信プロトコルの同期ルール
データ構造やコマンドIDを変更する場合は、必ず USHER デバイス側 (C++) と Flutter Dart 側の双方を更新し、バージョン番号をインクリメントしてください。
[03] マイク・音声連携アプリの開発パターン
マイクや音声機能を統合した連携アプリを開発する場合、2つのアプローチが選択可能です。
パターン A: スマホ主導型 (推奨)
スマホの高性能なマイクと音声処理・AIエンジン(文字起こしや音声解析)を活用し、USHER画面をリモートインジケーターとして活用する構成です。
- スマホアプリ: 音声を高音質録音・解析し、結果や音量波形データをBLEでUSHERへ送信。
- USHER (Lua): 受信データから画面にリアルタイム波形描画を行い、タッチ操作で録音の開始/停止コマンドをスマホへ送信。
パターン B: USHER デバイス主導型
USHER本体のI2Sデジタルマイクを直接駆動する構成です。
- 音量検知 (利用可能):
sys.on_mic_level(threshold, callback)による閾値音量検知とイベント発動。 - ストリーミング・録音 (拡張可能): 取得したPCMデータをバッファリングし、BLE経由でスマホへ転送してWAV形式保存。
[04] Luaバインディングとエミュレータの同期
新しいLuaバインディングを追加する際は、実機 (C++) とスマホアプリ内エミュレータ (Dart) の双方に同様のロジック/モックを実装し、エミュレータ上でも完全動作するように維持します。
This technical guide details the integration guidelines between USHER Device and the Smartphone Companion App (Flutter), as well as extending Lua applications with audio/microphone and data sync capabilities.
[01] System Integration Architecture
The ecosystem leverages a 3-tier system architecture for inter-process communication between mobile apps, firmware, and embedded Lua scripts.
lua_emulator.dart)
lua_core_bindings.cpp)
lv.btn, lv.lottie_create etc.)
sys.on_mic_level etc.)
[02] BLE Protocol Specifications
Data packets and control commands are streamed through custom GATT services over Bluetooth LE using custom ACK handshake mechanisms.
[03] Microphone & Audio Integration Patterns
Supports both smartphone-centric high-quality recording and onboard I2S digital mic level detection with real-time spectrum visualizers.
[04] Firmware & Emulator Sync
Ensure any new C++ Lua bindings are mirrored in the Flutter-side Dart VM emulator for seamless prototyping.
USHER Hacker's Hardware Guide
USHER オープンソースエコシステムへようこそ!このドキュメントは、カスタムファームウェアの構築、自作のスマホアプリの開発、またはハードウェアクローンの作成に必要な低レベルの技術仕様を提供します。
[01] ハードウェア仕様 & ピンマップ
USHER は ESP32-S3-WROOM-1U-N16R8 モジュールを採用しています。自作のファームウェア(Arduino や ESP-IDF 等)を書き込んでデバイスをカスタマイズしたい開発者のために、USHERの各周辺機器のPIN配置(GPIOマッピング)を以下に開示します。
| 周辺機器 (PERIPHERAL) | 信号名 (SIGNAL) | GPIO ピン | 機能 & 仕様 (DESCRIPTION) |
|---|---|---|---|
|
ディスプレイ GC9A01 (SPI) |
D_DC |
GPIO 38 | データ / コマンド切替 |
D_CS |
GPIO 39 | SPI チップセレクト | |
D_SCL |
GPIO 40 | SPI クロック (SCL) | |
D_SDA |
GPIO 41 | SPI MOSI (データ送信) | |
D_RESET |
GPIO 42 | ディスプレイハードウェアリセット | |
D_LEDA |
GPIO 2 | バックライト輝度制御 (PWM) | |
|
タッチパネル CST816D (I2C) |
TP_SDA |
GPIO 47 | I2C データ (IMUと共有) |
TP_SCL |
GPIO 48 | I2C クロック (IMUと共有) | |
TP_RST |
GPIO 14 | タッチコントローラリセット | |
TP_INT |
GPIO 13 | タッチ検知 外部割込 | |
|
モーションセンサー 6軸 IMU (I2C) |
IMU_SDA |
GPIO 47 | I2C データ (TPと共有) |
IMU_SCL |
GPIO 48 | I2C クロック (TPと共有) | |
DOUBLE_TAP |
GPIO 9 | ダブルタップ検知 外部割込 | |
|
デジタルマイク I2S Digital Mic |
MIC_BCLK |
GPIO 5 | I2S ビットクロック |
MIC_WS |
GPIO 6 | I2S ワードセレクト (L/R) | |
MIC_DIN |
GPIO 7 | I2S オーディオデータ入力 | |
|
電源管理 Power & Battery |
BAT_VOLT |
GPIO 15 | バッテリー電圧監視 (ADC) |
|
内部予約ピン ※外部利用不可 |
PSRAM_BUS |
GPIO 35, 36, 37 | ESP32-S3 内部 8MB PSRAM (SPIRAM) 専用バス |
[WARNING] Wi-Fi制限と電波曝露(SAR)警告
本製品の公式ハードウェアは、出荷段階でWi-Fi機能を無効化し、極低出力なBLE(Bluetooth Low Energy)接続のみを有効化することで、人体近接時の安全基準であるSAR(比吸収率)の許容値基準を満たしています。自作ファームウェアにおいてWi-Fi機能を有効化した場合、SARの安全基準値を超過するリスクがあり、すべて開発者の完全な自己責任となります。
[02] パーティションマップとメモリレイアウト (重要)
OTAアップデートをサポートし、ファイルシステムを保護するため、USHER は固有のパーティション構成を使用します。自作のカスタムファームウェアを書き込む場合は、ビルド時の partitions.csv が以下のレイアウトと完全に一致している必要があります。これを守らないとOTA機能が文鎮化(破壊)します。
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x4000,
otadata, data, ota, 0xd000, 0x2000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 0x220000,
ota_0, app, ota_0, 0x230000,0x220000,
littlefs, data, spiffs, 0x450000,0xBB0000,
(注: サブタイプは spiffs になっていますが、実際のコード内ではウェアレベリングとディレクトリ対応のために LittleFS としてマウントされます。)
マウントポイント
- LittleFS マウント先:
/littlefs - Lua アプリの保存先:
/littlefs/apps/ - システムアセット:
/littlefs/assets/
[03] Bluetooth LE (GATT) プロトコル
Luaスクリプト、アセット画像、またはカスタムファームウェア(OTA)をワイヤレスでデバイスに送信するには、USHER のBLEサーバーに接続します。
- Command Characteristic (Write): 転送の開始コマンドなどに使用(例:
START_OTA,START_FILE_TRANSFER:/apps/my_app/init.lua)。 - Data Characteristic (Write without Response): 実際のバイナリデータやテキストチャンクをストリーミング送信するために使用。USHERのPSRAMを活かしたPing-Pongバッファ方式を採用し、高速転送を実現しています。
- Notify Characteristic (Read/Notify): デバイスからスマホに対して、ACK(例:
ACK:128KB)やエラーメッセージを返します。
カスタムファームウェアのOTAアップデート手順
- スマホが Command Characteristic に
START_OTA:<file_size>を送信する。 - デバイスが
esp_ota_opsAPI の準備を行い、Notify で応答する。 - スマホが
.binファームウェアファイルを MTU サイズのチャンクに分割し、Data Characteristic へストリーミングする。 - デバイスは 128KB 受信するごとに ACK を返す。
- 送信完了後、スマホが
END_OTAを送信する。 - デバイスが新しいブートパーティションを設定し、自動的に再起動する!
高信頼性 BLEデータ転送 (TCPライクなACK制御)
BLEはMTUサイズやパケットロスの問題から、大容量ファイル(GIFやファームウェアなど)の転送ではタイムアウトしやすく不安定になりがちです。
この問題を解決するため、USHER はBLE上で TCPのようなACK(確認応答)システム を独自実装しています。
- スマホからは「Write Without Response」を用いて、待機時間ゼロでパケットを高速ストリーミングします。
- USHER本体は、内蔵するPSRAMを巨大なバッファとして使い、データを受け止めます。
- 128KB受信するごとに、デバイスからスマホへ確実にACKを通知(Notify)します。
- スマホ側はACKの遅延や消失を検知すると転送を一時停止し、バッファ溢れやBLEのタイムアウトを未然に防ぎます。
このハンドシェイクにより、Wi-Fiを一切使わず、BLE単体で超巨大ファイルの安定転送を実現しています!
[04] 公式コンパニオンスマホアプリ
Flutterで構築されたコンパニオンアプリ(smartphone_app/内)が完全に統合されました。
主な機能
- 高信頼性 BLE 同期: USHER デバイスと自動接続し、カスタム RGB ファイルの転送や OTA ファームウェアアップデートを独自の TCP ライクな ACK ハンドシェイクプロトコルで実行します。
- 組み込み Lua エミュレータ: 円形ベゼルプレビュー、Google Fonts、UTF-8 アイコンマッピング、モック設定永続化ストレージに対応した Lua 5.3 仮想マシンを搭載しています。
- GIPHY 検索 & ダウンローダ: クイック検索とスクロール可能なカテゴリー分け、動画クリップエディタへの直接連携が可能です。
- 再設計された作成済みファイルギャラリー: 自作の RGB プレイヤーを内蔵したグリッドレイアウトで、BLE 圧縮ファイルを直接再生可能です。
- アプリテーマカスタマイザ: 設定内からアクセス可能なインタラクティブなテーマエンジンを搭載しています。
詳細なユーザー操作方法については、Companion App Manual を参照してください。
Welcome to the USHER Open-Source ecosystem! This document provides the low-level technical specifications necessary to build custom firmware, develop your own companion smartphone apps, or create hardware clones.
[01] Hardware Specifications & Pinout
USHER is built around the ESP32-S3-WROOM-1U-N16R8 module. For developers wishing to flash custom firmware (Arduino, ESP-IDF, etc.) and customize the hardware behaviors, we disclose the exact GPIO pin mapping for all onboard peripherals below:
| PERIPHERAL | SIGNAL | GPIO PIN | DESCRIPTION |
|---|---|---|---|
|
Display GC9A01 (SPI) |
D_DC |
GPIO 38 | Data / Command Select |
D_CS |
GPIO 39 | SPI Chip Select | |
D_SCL |
GPIO 40 | SPI Clock (SCL) | |
D_SDA |
GPIO 41 | SPI MOSI (Data Output) | |
D_RESET |
GPIO 42 | Hardware Reset | |
D_LEDA |
GPIO 2 | Backlight PWM Brightness Control | |
|
Touch Panel CST816D (I2C) |
TP_SDA |
GPIO 47 | I2C Data (Shared with IMU) |
TP_SCL |
GPIO 48 | I2C Clock (Shared with IMU) | |
TP_RST |
GPIO 14 | Touch Controller Reset | |
TP_INT |
GPIO 13 | Touch Interrupt Input | |
|
Motion Sensor 6-Axis IMU (I2C) |
IMU_SDA |
GPIO 47 | I2C Data (Shared with TP) |
IMU_SCL |
GPIO 48 | I2C Clock (Shared with TP) | |
DOUBLE_TAP |
GPIO 9 | Double-Tap Interrupt | |
|
Digital Mic I2S Digital Mic |
MIC_BCLK |
GPIO 5 | I2S Bit Clock |
MIC_WS |
GPIO 6 | I2S Word Select (L/R) | |
MIC_DIN |
GPIO 7 | I2S Audio Data Input | |
|
Power & Battery Power Management |
BAT_VOLT |
GPIO 15 | Battery Voltage Monitor (ADC) |
|
Reserved Pins ※NC / Unusable |
PSRAM_BUS |
GPIO 35, 36, 37 | ESP32-S3 8MB Octal PSRAM Dedicated Bus |
[WARNING] Wi-Fi RF Exposure & SAR Compliance Warning
The official hardware is designed and pre-certified for Bluetooth Low Energy (BLE) only, completely disabling Wi-Fi to meet Specific Absorption Rate (SAR) limits for body-worn devices. If you write custom firmware that enables Wi-Fi, you may exceed Specific Absorption Rate (SAR) limits. Enabling Wi-Fi on this hardware is strictly at your own risk.
[02] Partition Map & Memory Layout
To support OTA updates and protect the file system, USHER uses a specific partition layout. If you are flashing custom firmware, you MUST ensure your partitions.csv matches this layout.
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x4000,
otadata, data, ota, 0xd000, 0x2000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 0x220000,
ota_0, app, ota_0, 0x230000,0x220000,
littlefs, data, spiffs, 0x450000,0xBB0000,
[03] Bluetooth LE (GATT) Protocol
Streaming over custom GATT characteristics with ping-pong buffering and ACK flow control.
[04] Official Companion Smartphone App
Full-featured Flutter companion app with live Lua emulator and BLE sync. See Companion App Manual for details.
CYBER ICONS HUD LIBRARY
ファームウェアに組み込まれた 12x12 ピクセルのドットアイコンライブラリ。
リアルタイムにアイコン色・背景色をカスタマイズしてプレビュー可能。UTF-8リテラル文字列や、選択色を反映した LVGL Lua スタイルコード をワンクリックでクリップボードへコピーできます。
Firmware-embedded 12x12 technical pixel icon library.
Customize colors and backgrounds with live interactive rendering. Copy UTF-8 escape sequences, @icon annotations, and pre-styled LVGL Lua snippet blocks with one click.