MMDVMHost / DMRGateway「ini フォーマット変更」徹底調査レポート

— なぜ変わったのか、バイナリと ini のバージョンの関係 —

調査日: 2026-08-27 調査方法: g4klx/MMDVMHost および g4klx/DMRGateway の公式リポジトリを取得し、該当コミットの実際の差分(diff)とソースコードを直接検証した。推測ではなく、すべてコードで裏付けている。

1. 結論(最初に要点)

「ini フォーマット変更」は目的ではなく、結果である。

本当の変更は、MMDVMHost ⇄ DMRGateway 間の内部プロトコルから DMRC メッセージ(設定パケット)を廃止したこと。コミットメッセージそのものが答えだった:

  • MMDVMHost 側: b7d15b8 “Remove the DMRC startup message.” (2026-07-13)
  • DMRGateway 側: 61771e2 “Generate the DMRC message locally from the ini file and not via the network.” (2026-05-18)
b7d15b861771e2 のような 7 桁の英数字は、Git のコミット ID(コミットハッシュの短縮形)である。リポジトリへの変更 1 件ごとに自動で付与される固有の識別子で、これによりプログラムの「版」を正確に特定できる。git show b7d15b8 のように指定すると、その時点の差分やソースコードを参照できる。本文中の #43edd65 のように # を付けた表記も同じコミット ID を指す。

[Info] セクションは「DMRC メッセージの中身を作るため」だけに存在していた。DMRC が死んだので [Info] は存在理由を失い削除された。周波数だけはモデム自身が SET_FREQ コマンドで必要とするため生き残り、本来の居場所である [Modem] へ移動した。

さらに重要な副作用として、両プログラムの master 反映日が約8週間ずれた(DMRGateway: 5/18、MMDVMHost: 7/13)。この期間、master 同士ですら噛み合わない「非互換の期間」が存在した。


2. DMRC メッセージとは何だったのか

Homebrew リピータプロトコルの設定パケット。旧設計では MMDVMHost が 10秒ごと(pingタイマー兼用) に DMRGateway へ送っていた。実際の生成コード(旧 DMRNetwork.cpp writeConfig()):

::memcpy(buffer + 0U, "DMRC", 4U);
::memcpy(buffer + 4U, m_id, 4U);          // DMR ID (9桁)
::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%c%-40.40s%-40.40s",
    m_callsign.c_str(),                    // コールサイン 8文字
    m_rxFrequency, m_txFrequency,          // RX/TX 周波数 各9桁
    power, m_colorCode, slots,             // 出力・CC・スロット
    m_version, software);                  // バージョン・HW種別
return write((unsigned char*)buffer, 119U); // 119バイト

本機の DMRGateway ログに出ていたダンプがまさにこれである:

Unknown packet from the MMDVM
0000: 44 4D 52 43 ... *DMRC.:..JR2DHR  *
0010: ...             *4307500004307500*
...                   *MDVM_MMDVM_HS_Ha*

10秒間隔で繰り返し出ていたのは、ping タイマー周期そのもの

DMRC が担っていた役割(旧設計)

  1. DMRGateway への自局情報の伝達 — Id・コールサイン・周波数等。DMRGateway はこれを保存し、TGIF 等のマスターへログインするときの ID と、ログイン後に送る configuration message にそのまま使った。
  2. キープアライブ(ping) — DMRGateway は DMRC を受けると DMRP(4バイト)を返す。これが生存確認を兼ねた。
  3. 起動順序の強制 — 旧 DMRGateway は DMRC が届く(= m_configLen > 0 && id > 1000)まで Waiting for MMDVM to connect..... でブロックし、外部ネットワークを一切開かなかった。

3. なぜ廃止したのか(設計意図の分析)

コードの差分から読み取れる設計判断は「関心の分離」である。

情報実際に使う者旧設計での置き場所新設計での置き場所
RX/TX 周波数モデム(SET_FREQ)MMDVMHost の [Info] → DMRC でも転送MMDVMHost の [Modem]
Id・コールサインマスターへのログインMMDVMHost の [General] → DMRC で転送DMRGateway.ini の [General] Id / [Info] Callsign
Power/緯度経度/Location/Description/URLマスターへの設定送信MMDVMHost の [Info] → DMRC で転送DMRGateway.ini の [Info]

旧 ini の [Info] にはこういうコメントが元々あった:

# The following lines are only needed if a direct connection to a DMR master is being used

つまり作者自身が「この情報の本当の消費者はマスター側」と認識していた。マスターと話すのは DMRGateway なのだから、その情報は DMRGateway が持つべき — これが変更の論理である。結果:

  • MMDVMHost からネットワーク向けメタデータが全て消え、約315行削除の大幅な簡素化
  • ping は双方向とも 4バイトの DMRP
  • DMRGateway は MMDVMHost を待たずに即座に外部ネットワークへログインできるようになった(起動順序の依存が消えた)
  • 周波数は「モデムのパラメータ」という本来の位置([Modem])に正規化された

4. 時系列(非互換の期間)

日付リポジトリコミット内容
2026-04-06DMRGateway79edbc4旧方式(DMRC受信)の最後の master コミット。hat1〜hat3 と本機がピン留めした版
2026-05-18DMRGateway61771e2master へ直接: DMRC 受信ハンドラ削除。DMRP のみ受理、他は Unknown packet。Id/Info を自分の ini から読む方式に
2026-05-18MMDVMHostbdc1aed同日に作者がホスト側も変更。ただし Remove_DMRC ブランチに留まる
2026-05-29MMDVMHost43edd65master はまだ旧方式。実行ファイル名変更(MMDVMHost→MMDVM-Host)のコミット。本機がピン留めした版
2026-07-13MMDVMHostb7d15b8ブランチが master へ合流。[Info] 削除・周波数 [Modem] 移動・DMRC 送信廃止
2026-08-01〜両方dea6e9b / 2a3306d本機が最初に clone してしまった「最新版」
注目点: 作者(G4KLX)は 2026-05-18 の同じ日に両側の変更をコミットしている。設計としては「対」で、片方だけ使う想定はない。しかし DMRGateway 側だけ即 master に載り、MMDVMHost 側は約8週間ブランチに留まった。この間、master 同士を素直に pull しても噛み合わない状態が公式に存在した。

5. 互換マトリクス(本調査の核心)

5-1. MMDVMHost バイナリ × MMDVM-Host.ini

パーサーはセクション厳格で、フォールバックは一切ないことをコードで確認した。旧 Conf.cpp は SECTION::INFO の中でのみ、新 Conf.cpp は SECTION::MODEM の中でのみ RXFrequency を読む。

バイナリ \ ini旧 ini(周波数が [Info])新 ini(周波数が [Modem])
旧バイナリ(〜2026-07-12, #43edd65 含む)✅ 正常❌ 周波数 0 → 起動ループ
新バイナリ(b7d15b8 以降)❌ 周波数 0 → 起動ループ✅ 正常

失敗のメカニズム(両方向とも同一):

該当セクションに周波数キーが無い
→ m_modemRXFrequency が初期値 0 のまま
→ Modem::open() 内の setFrequency() が 0Hz を送信
→ ADF7021 ファーム側が帯域外として NAK
→ open() 失敗 → (systemd Restart=on-failure なら)無限再起動ループ

ログの決定的サイン: TX Frequency: 0Hz の表示、および SET_FREQ への NAK。

5-2. MMDVMHost × DMRGateway(localhost プロトコル)

ホスト \ ゲートウェイ旧 GW(〜79edbc4)新 GW(61771e2 以降)
旧ホスト(DMRC を10秒毎送信)✅ 正常(hat1〜3・本機の構成)⚠️ 動くが異常: Unknown packet が10秒毎に出続け、GW は自分の ini 既定値(Id=12345, G9BF)でマスターへログイン → 未登録 ID のため TGIF はタイムアウト
新ホスト(DMRP のみ)❌ GW が Waiting for MMDVM to connect.....永久待機(DMRC が永遠に来ないため。ソースの待機条件 m_configLen > 0 && id > 1000 を確認済み)✅ 正常(ただし DMRGateway.ini に自局の Id・[Info] を記入することが必須)

5-3. 正しい組み合わせは 2 つだけ

【旧セット】 MMDVMHost 〜#43edd65  +  旧ini([Info])  +  DMRGateway 〜#79edbc4
【新セット】 MMDVMHost b7d15b8〜   +  新ini([Modem]) +  DMRGateway 61771e2〜 + DMRGateway.iniに自局Id/Info記入
4項目(ホストのバイナリ・ホストの ini・GW のバイナリ・GW の ini)が全部同じ世代で揃って初めて動く。1つでも混ざると、上の表のどれかの故障モードに落ちる。

6. 本機で起きたことの再解釈(重要な訂正)

この調査により、構築時の事象の解釈が一部変わる。

6-1. 最初の TGIF タイムアウトの真因

当時のログ:

DMR Network 3 Parameters
    Id: 12345                          ← ★
TGIF_Network: configuration message: G9BF    435000000435000000...  ← ★
TGIF_Network, Connection to the master has timed out, retrying connection

当時は「Id: 12345 は MMDVMHost 接続前の仮表示」と解釈したが、誤りだった。新 DMRGateway のコードは:

if (id == 0U)
    id = m_id;              // ← m_conf.getId() = DMRGateway.ini の [General] Id

であり、雛形既定値の Id=12345 で実際に TGIF へログインを試みていたG9BF / 435MHz も新 ini 雛形の [Info] 既定値である。12345 は未登録 ID なので TGIF が応答せずタイムアウトした — これが真因である可能性が極めて高い。

したがって、当時疑った「ESSID 12 の二重ログイン」は主因ではなかった可能性が高い。 ESSID 12→99 の変更は無害だが、おそらく不要だった(戻す必要もない)。ログインが通ったのは ESSID を変えたからではなく、DMRGateway を #79edbc4 に戻して、Id が MMDVMHost の DMRC(440072899)から供給されるようになったからである。旧 GW での成功ログが Id: 440072899 と正しい値を示していることが裏付けになる。

6-2. 「Unknown packet」の10秒間隔

DMRC 送信は ping タイマー(10秒)に載っている。ログのタイムスタンプ 07:36:40.283 → 07:36:50.291 の間隔がぴったり10秒だったのは、この周期の直接の現れ。

6-3. 新 DMRGateway が即座に TGIF へ接続開始した理由

旧 GW は Waiting for MMDVM to connect..... と待つのに、新 GW は起動直後に TGIF へ向かった。これは新設計で「MMDVMHost を待つ必要がなくなった」(設定を自前の ini から得る)ため。ログの挙動差もコードと一致する。


7. もし新セットへ移行するなら(参考手順)

将来、最新版に追従したくなった場合の要点。4項目を同時に切り替える。

  1. MMDVMHost を最新化する。
    cd /opt/MMDVMHost
    git stash && git checkout master && git pull
    make clean && make -j$(nproc)
  2. MMDVM-Host.ini を新フォーマットへ移行する。新雛形の MMDVM-Host.ini を元に作り直し、周波数は [Modem] セクション内に RXFrequency=/TXFrequency= を書く。[Info] セクションは存在しない(書いても読まれない)。
  3. DMRGateway を最新化する(git stash pop で TGIF 設定を書き戻す)。
    cd /opt/DMRGateway
    git stash && git checkout master && git pull
    make clean && make -j$(nproc)
    git stash pop
  4. DMRGateway.ini に自局情報を追記する(新方式の必須事項)。
    [General]
    Id=440072899          ← これがマスターへのログインID。雛形の12345のままでは絶対に動かない
    [Info]
    Callsign=JR2DHR
    RXFrequency=430750000
    TXFrequency=430750000
    Power=1
    ColorCode=1
    Duplex=0
ただし現時点では、既存機 hat1〜hat3 と手順書資産が旧セット前提で揃っているため、旧セット維持が合理的。移行するなら全機一斉に行うのが混乱がない。

8. 教訓

  1. git pull は「対」で考える。 MMDVMHost と DMRGateway は独立リポジトリだが、localhost プロトコルで密結合している。片方だけの更新が最も危険で、master 同士ですら8週間の不整合期間が実在した。
  2. コミットメッセージが最短の答えだった。 “Remove the DMRC message” — この一行に、ini 変更・Unknown packet・Id=12345・起動順序の変化、すべての説明が含まれていた。障害調査では git log を最初に読む価値がある。
  3. パーサーはセクション厳格・フォールバック無し。 「キーはあるのに読まれない」は MMDVM 系 ini の典型的な罠。キー名だけでなく、どのセクションの中にあるかまで一致させる必要がある。
  4. 雛形既定値でログインしてしまう設計に注意。 新 DMRGateway は ini を埋めないと Id=12345/G9BF で実ネットワークへ出て行く。テンプレートをコピーしたら、まず [General] Id と [Info] を自局値にする。
  5. 症状からの推理は、ソースで裏を取るまで確定しない。 「ESSID 重複」は筋の通った仮説だったが、真因は別(Id=12345)だった。ログの Id: 12345 という小さな違和感が、実は最大の手がかりだった。

付録: 検証に使った主なコマンド

git clone https://github.com/g4klx/MMDVMHost
git clone https://github.com/g4klx/DMRGateway

# 変更コミットの特定と差分
git log --oneline --since="2026-05-01"
git show b7d15b8 --stat
git show b7d15b8 -- MMDVM-Host.ini          # [Info]削除・[Modem]へ移動の実diff
git show b7d15b8 -- DMRNetwork.cpp          # writeConfig(DMRC 119B)→writePing(DMRP 4B)
git show 61771e2 -- DMRGateway.ini          # [General]Id / [Info]新設
git show 61771e2 -- MMDVMNetwork.cpp        # DMRC受信ハンドラ削除の実diff

# 系譜の検証
git merge-base --is-ancestor bdc1aed 43edd65   # → NO(別ブランチ)

# パーサーのセクション厳格性
git show 43edd65:Conf.cpp | grep -B1 '"RXFrequency"'   # 旧: SECTION::INFO 内のみ
git show dea6e9b:Conf.cpp | grep -B1 '"RXFrequency"'   # 新: SECTION::MODEM 内のみ

# 旧GWの待機条件 / 新GWのId供給元
git show 79edbc4:DMRGateway.cpp   # m_configLen>0 && id>1000 まで待機
git show 61771e2:DMRGateway.cpp   # if (id==0) id = m_id (= ini の Id)

追補(2026-08-27): 説明・対比表・新旧の具体的な書き方

A. DMRC とは何か(かみ砕いた説明)

DMRC = 「DMR Configuration」、自局の名刺パケット。

MMDVMHost が DMRGateway に「私はこういう局です」と自己紹介する 119 バイトのデータで、中身はコールサイン・DMR ID・RX/TX 周波数・出力・カラーコード・スロット・機種名。先頭 4 バイトが文字 DMRC

旧設計を名刺に例えると: MMDVMHost は 10 秒ごとに名刺を差し出し続け(生存確認の ping 兼用)、DMRGateway はその名刺を 2 つのことに使った。①TGIF へのログイン ID(名刺の 440072899 を使用)、②TGIF に送る自己紹介文(ログの configuration message: JR2DHR 430750000...)。DMRGateway は「名刺を預かってマスターへ取り次ぐ受付係」であり、だから名刺が届くまで Waiting for MMDVM to connect..... と待った。

新設計は「受付係が自分の ini に名刺を持つ」方式。MMDVMHost は名刺を配らず、「生きてます」の 4 バイト DMRP だけ送る。DMRGateway は自分の ini の [General] Id[Info] から名刺を自作する。新旧を混ぜると、旧ホストが差し出す名刺を新受付が「知らない紙」と捨てる(= Unknown packet)。

B. 対比表

表1: バージョン年表

日付リポジトリコミット世代内容
2026-04-06DMRGateway79edbc4旧世代の最終版。hat1〜3・本機が採用
2026-05-18DMRGateway61771e2DMRC 受信廃止。Id/Info を自分の ini から読む方式へ
2026-05-29MMDVMHost43edd65まだ旧世代(DMRC 送信)。実行ファイル名変更。本機が採用
2026-07-13MMDVMHostb7d15b8DMRC 送信廃止。[Info] 削除、周波数を [Modem] へ
2026-07-20DMRGatewayd94c67d新 ini 雛形のキー名 typo(TXFRequency)を修正
2026-08 時点両 masterdea6e9b / 2a3306d本機が最初に誤って clone した版

5/18〜7/13 の約 8 週間は、master 同士でも新旧が混在する「非互換の期間」。

表2: 世代の見分け方

見る場所旧世代新世代
MMDVM-Host.ini[Info] に周波数がある[Info] が無く、周波数は [Modem]
MMDVMHost の gitgit merge-base --is-ancestor b7d15b8 HEADNO同 → YES
DMRGateway.ini[General]Id=無い[General] Id=[Info] Callsign= 等がある
DMRGateway 起動ログWaiting for MMDVM to connect..... と待つ待たずに即マスターへ接続開始

表3: 組み合わせ対比表(6 パターンの運命)

#Host バイナリHost iniGW バイナリ結果
1旧([Info])正常(hat1〜3・本機の構成)
2新([Modem])新 + GW ini に自局 Id/Info 記入✅ 正常
3❌ 周波数 0Hz → SET_FREQ NAK → 起動ループ
4❌ 同上(パーサーが逆セクションを読まない)
5⚠️ Unknown packet 10秒毎 + GW が既定 Id=12345 でログイン → タイムアウト(本機が最初に踏んだ)
6❌ GW が名刺(DMRC)待ちで永久に Waiting
覚え方: 4 点セット(Host バイナリ・Host ini・GW バイナリ・GW ini)を全部同じ世代で揃える。1 つでも混ざると #3〜6 のどれかに落ちる。

C. 結局どのバージョンを使うべきか

今は「旧セット」継続が正解(本機・hat1〜3 の現構成)。理由: ①既存 3 台と手順書・メモ資産が全部この世代で揃っている ②動作実績とハマりどころを把握済み ③新旧に無線側の機能差はほぼ無い(変わったのは内部の設定伝達方式)。

新セットも条件付きで使える: 4 点を同時に新世代へ切り替え、DMRGateway.ini に自局情報を記入すること。移行は全機一斉が鉄則。

長期的には新セット移行が避けられない(旧世代に今後のバグ修正は入らない)。急ぐ必要はなく、D-STAR/YSF 追加などで大きく触るタイミングで全機まとめて、が現実的。

D. 新旧の書き方 具体対比

D-1. MMDVM-Host.ini — 変わるのは周波数の置き場所だけ

旧(#43edd65)— [Info] セクションに書く:

[General]
Callsign=JR2DHR
Id=440072899
...

[Info]                      ← このセクションが存在する
RXFrequency=430750000       ← ここに書く
TXFrequency=430750000
Power=1
Latitude=0.0
Longitude=0.0
Location=Nowhere
Description=Multi-Mode Repeater
URL=www.google.co.uk

[Modem]
Protocol=uart
UARTPort=/dev/ttyUSB0
...                          ← 周波数はここには書かない

新(b7d15b8 以降)— [Modem] セクションに書く:

[General]
Callsign=JR2DHR
Id=440072899                ← ここは変わらず
...
                             ← [Info] は存在しない(書いても無視される)
[Modem]
Protocol=uart
UARTPort=/dev/ttyUSB0
LocalPort=3335

RXFrequency=430750000       ← [Modem] の中に書く
TXFrequency=430750000

TXInvert=1
...

Power/緯度経度/Location/Description/URL は新ホストには書く場所そのものが無い(DMRGateway 側へ引っ越した)。

D-2. DMRGateway.ini — 新世代では書くべきものが増える(最重要)

旧(#79edbc4)— 自局情報は書かない:

[General]
Timeout=10                  ← Id= は存在しない
RptAddress=127.0.0.1
...

[Info]
Latitude=0.0                ← 位置情報だけ。コールサイン・周波数・Id は無い
Longitude=0.0
Location=Nowhere
...

自局の Id・コールサイン・周波数は MMDVMHost から DMRC で自動的に届くので書く必要がない(書く場所も無い)。

新(61771e2 以降)— 自局情報を自分で書く(必須):

[General]
Id=440072899                ← ★必須。マスターへのログイン ID はここ。
Timeout=10                     雛形の 12345 のままでは未登録 ID でログイン失敗
...

[Info]
Callsign=JR2DHR             ← ★新設。自局値に書き換える(雛形は G9BF)
TXFrequency=430750000       ← ★新設
RXFrequency=430750000
Power=1
ColorCode=1
Duplex=0                    ← 単信なら 0
Slot1=1
Slot2=1
Latitude=0.0
...

一言まとめ: 旧は「名刺はホストが配る(GW には書かない)」、新は「名刺は GW の ini に自分で書く(書かないと偽名 G9BF / 12345 で出て行く)」。

D-3. 小さな罠: 初期テンプレートのキー名 typo

新世代の初期 ini 雛形(2026-05-18〜07-20)はキーが TXFRequency / RXFRequency(R が大文字)と打ち間違っており、パーサーは正しい TXFrequency / RXFrequency を期待するため、雛形どおり書くと周波数が黙って無視された(d94c67d で修正済み)。「キー名は 1 文字違うだけで黙って無視される」という MMDVM 系 ini の性質を象徴する例。新セットへ移行する際はキー名を現行雛形からコピーすること。

あわせて読みたい(関連記事)

📝 執筆:JI2TAB(尾張旭 DMR デジピーター 管理人)
🏛 JJ2YYK あいちデジタルコミュニケーションハムクラブ

JJ2YYK
  • JJ2YYK

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です