コンテンツにスキップ

システムサービス (services.toml)

サービスとは、常駐する小さな仕事のことです。タイマーで起きるか、何かが配信されたときに 起き、窓は持ちません。ネットワークから自分を合わせる時計がそうですし、文章を読み上げる ものもそうです。

これらは全部、サービスホストという 1 つのアプリの中で動きます。小さな常駐仕事が 12 個 あっても、タスクと VM は 1 つずつで済みます。アプリとして常駐させずにサービスにする理由が そこにあります。

Modern 専用

サービスホストは Retro のファームウェアには入っていません。Retro では以下は何も 当てはまりません。Retro のシミュレータも同じ振る舞いをします。

付いてくるもの

サービス 内容
clock 時刻を保ちます
hourly_chime 毎正時に音を鳴らします。WAV を指定すればそれを鳴らします
net ネットワークを見張り、net/state を配信します。アドレスが決まった瞬間にログに出ます
timesync ネットワークにつながったら NTP で時計を合わせます。停電のたびに時計合わせをしなくて済みます
tts 声に出して読みます。tts/say に配信されたものが読み上げられます

Studio には最初の 2 つが入っています。ブラウザのタブには 合わせるべき時計も、呼ぶべきスピーカーもありません。

一覧は 2 つある

ファイル 本体の置き場所
/etc/services.toml /usr/share/services/ ファームウェアに付いてくるもの
/home/services.toml /home/services/ あなたのもの。後から読まれ、項目ごとに勝ちます

項目ごとに勝つので、利用者側の一覧は短くて済みます。付いてくるサービスを止めたいなら、 ファイルの中身はこれだけです。

[hourly_chime]
enable = false

項目

項目
file 本体のファイル名。その一覧に対応する置き場所から探します
class その中のクラス名
enable false にすると、項目は残したまま動かしません。既定は true
interval_ms on_tick を呼ぶ間隔。話題に反応するだけのサービスでは省けます
oneshot true なら起動時に on_start を 1 回呼び、一覧から外します
[<名前>.config] ctx.config としてサービスに渡されます

自分で書く

見本を写して一覧に載せます。

cp /usr/share/samples/services/services.toml.example /home/services.toml
cp /usr/share/samples/services/heartbeat.rb /home/services/heartbeat.rb

決まりごとは、任意の 5 つのメソッドだけです。

class HeartbeatService
  def on_start(ctx)          # ctx がシステムの他の部分への唯一の出口
  def on_tick(now_ms)        # interval_ms ごと
  def on_wake(now_ms)        # ctx.wake_in の後
  def on_event(topic, data)
  def on_stop
end

ctx からは publishwake_inaudiolognow_msconfigstop_self が 使えます。

どのメソッドも短く保ってください。サービスは 1 本のタスクの上で順番に動くので、ここで 使った時間はそのまま他のサービスの待ち時間になります (50ms を超えるとホストが警告を 出します)。例外を出したサービスは 3 回で自動的に止まります。他のサービスは巻き添えに なりません。

起動時にアプリを開く

サービスの代わりにアプリを指定することもできます。

[my_game]
app = "/app/game/robo_explorer/robo_explorer.app.rb"
fullscreen = true      # アプリ自身の窓の指定より優先
delay_ms = 2000        # デスクトップが落ち着くのを待つ
restart = true         # 落ちたら起動し直す (kill したものは止まったまま)

止め方

2 通りあり、意味が違います。

svc stop <名前> (または kill <名前>) そのときだけ。再起動すると戻ります
svc disable <名前> 覚えます。再起動しても止まったままです

svc startsvc enable が対になります。覚えた内容は /home/services_state.toml に ホストが書きます。あなたの services.toml が書き換えられることはありません。シェルの ps はアプリと並べてサービスも出します。Monitor も同じです。

読み上げ

tts は配信された文章を音声にします。一度読んだ文章は WAV として /tmp に残ります。 /tmp はフラッシュではなく PSRAM です。音声は 1 回で数百キロバイトあり、フラッシュは 小さく、書き換えれば減るからです。2 回目からはネットワークなしでそこから鳴り、再起動すると 消えます。

音声の作り方は 2 通りあります。

[tts.config]
server = "http://192.168.10.5:50021"   # パソコンで動かす VOICEVOX
speaker = 1
timeout_ms = 3000
[tts.config]
api_key = "sk-..."                     # パソコンなしで、クラウドで合成する
cloud_model = "gpt-4o-mini-tts"
cloud_voice = "alloy"
cloud_timeout_ms = 10000

鍵はそのまま書かれます。これは個人で使う機器であり、開発版はそもそも /home を HTTP で 公開しています。パスワードを貼ったノートパソコンと同じ扱いをしてください。

ネットワークなしで動かすときは、server の行はそのままにして、単に届かない状態にして ください。取りに行って断られてログが 1 行出るだけで、すでに読んだ文はそのまま鳴ります。 行を消すと鍵が変わり、自分のキャッシュを見つけられなくなります。

ネットワークなしで、しかも電源を切った後にも必ず鳴らしたい文は、キャッシュの仕事では ありません。WAV を /home/voice/ に置いて鳴らしてください。

関連