気の向くままに辿るIT/ICT/IoT
インターネット

AGIでCID name設定でCallerID allも自動設定

ホーム前へ次へ
Asteriskとは?

AGIでCID name設定でCallerID allも自動設定

AGIでCID name設定でCallerID allも自動設定

2026/02/14

 運用中のpjsipなAsteriskに050 plus収容スマホ/パソコン/HT-813アナログ電話においてAGI/Asterisk Gateway Interfaceで外線着信時に電話番号(だけ)ではなく、漢字カナカナかな数字アルファベット電話番号混じりなケース含め、名前/CallerID(name)/CID nameを設定・表示させてみたら、結果、CallerID(all)も表示できた話。

動機

 電話番号だけだと誰からだかピンとこないからというのは、もちろんのことですが、未知の番号を振り分けたかったので。

 携帯電話(ガラケー)を使い始めたのが割と早かった自身も、そもそも、もう15年以上は経過しているFAX付き固定電話機にすら、留守電機能があることに気づかず(迷惑電話、今から録音/戻って録音といった機能については、この記事を書きながら電話機眺めて初めて気づいた........)。

 在宅時は、面倒に思いつつも常に電話に出ていた時期もあり、警察署からの注意喚起の電話中に電話機自体の機能に留守電ってありますよね?と言われて初めて気づくほど固定電話機やその機能には無関心でした。

 そんな中、遅まきながら、3〜4年前、GS HT-813/固定電話機/050 plusで050IP電話機のように、ひかり電話ルーターの内線機能でスマホを子機にしたり、勘違いもあって固定電話機を1台買い足して050電話にしたり、結果、使いませんでしたが、Asteriskを試したりするまでに成長?

 それでも尚、長年、固定電話を持ちながらもナンバーディスプレイも最初だけで使ってこなかったこともあり、詐欺・営業絡みな電話だらけの昨今、さすがに面倒さが勝るようになって今や常時留守電対応。

 とは言え、知人・友人・親族ほか必要な電話すら留守電では...と申し訳けなさが残る日々を過ごす内、知人・友人・親族については、スマホにかけてくれるようになったりで固定電話にかかってくるのは、必要な一方でスマホの番号を教えて、かけてもらうのは、憚られ、微妙という限定的なケースのみになりました。

 今回、Asteriskを入れたことでパソコンのSIPフォンでも、また、当初、単独の電話機として使用していた050電話機も発信専用としていたので意味はありませんでしたが、ATAのおかげでNTTと契約することなくナンバーディスプレイ的に着信時、ディスプレイに電話番号表示はできるようになっていたのでAsteriskに入れた後も当然表示できる中、電話番号ではなく名前を表示できれば、必要な電話を明確に見分けられると同時に未知の電話番号も記録しておくことで以後の対処ができるよねと。

 例えば、未知の電話番号が、電話帳に登録すべき番号だとわかれば、登録したり、Asteriskの機能を拡張してネット上の迷惑電話リストと照合してあれこれやってみたり。

 ひかり電話は近々解約して050電話だけにするつもりながら、何れにせよ、在宅時、既知の連絡先からの着信とわかるものは、着信音が鳴る前の録音しています的な迷惑電話対策メッセージを流したり、留守電にすることなく、出るように、不在などで留守電になるにしても迷惑電話対策メッセージは流さないようにしようかと。

 と思ったものの、よく考えたら、MNPしている番号、普段、日常的にかけてくる人は減ったものの、いろんなところに唯一の連絡先として登録してあるわけで変更って結構手間か...。

パソコン/スマホ/電話機...対象は?

 とは言え、CallerID name/CID nameを設定できるのは、GUIで数字以外受け付けないアプリを除くパソコンOS用ソフトフォンか、文字種はともあれ、外部からのCallerID(name)設定を受け入れるIP電話機や何れも対応のATA+アナログ電話機のみと微妙に限定されそうです。

 iPhone/iOSは未確認ながら、Androidスマホ・タブレット用アプリについては、諸般の事情から設定することは無理そうですが、SIPフォンが利用権限を持つGoogle連絡帳か、自前の電話帳に登録済みであれば、その名称が表示されることでしょう(が、イエデンやオフィス代表固定電話の子機というか外線着信用となり得るスマホ・タブレットが複数ある場合、電話帳も同期しておくなりしない限り...)。

 以前は、スマホ・パソコン共にLinphoneを使っていたのですが、使いづらくなったように感じ、今回、baresip+を採用していたものの、baresip+は、番号表示しかできないことが判明したのでスマホについては、前述の通り、条件付きではあるものの、名前も表示できるLinphonに戻すことに。

 一方、パソコン版LinphoneがCallerID name/CID nameを設定できるのか否かは未確認も、スマホ版は、Linphoneもご多分にもれず、名前表示ができたところで前述の通りの仕様なのでPCもそうなら、そうする必要はなく、何れにせよ、既に使っているAGIからCallerID(name)を設定できるパソコン版にしてCLIなbaresipかGUIなBlink他で今尚迷い中。

 VoIPアダプタ/アナログ電話アダプタGrandstream社製Handy ToneシリーズHT-813に接続のアナログ電話機Panasonic VE-GD27-Wについては、ひかり電話で使っている電話機、また、050電話として使っていた電話機の子機は電話帳機能を持ち、漢字非対応、半角・全角は不明ながらカタカナ表示には対応も、子機なしで買った親機は電話帳機能がなく、番号表示のみな仕様でH-813から番号を変更することはできたものの、全角・半角に関わらず文字は受け付けないようだったので諦めました。

 尤もH-813+アナログ電話機は、まだ新しく、捨てるには惜しく、あるのに使わないのはモッタイナイ、あまり可能性はありませんが、従前通り、発信には使うこともあるかも...という立ち位置で着信時に使うことは、まずないので良いですが。

[2026/02/21]

 Linphone、スマホでも自前電話帳がなくてもAGI設定を受けて入れくれている様子、応答ポップはCALLERID(name)のみ、着信履歴は、CALLERID(all)で前者がAGIでセットしたものであることに気づきました...あれ?未知の番号で「不明」って出るのデフォルトじゃないよね?

Python3/PostgreSQLで電話番号から名前抽出

 本件については、AGI/Asterisk Gateway InterfaceスクリプトとしてPython 3、電話番号からの名前の取得には、PostgreSQLで実装することにしました。

 Python 2時代に流行ったSIP用にPythonラッパもあったようで2だけでなく、3にも対応したものもあるようですが、Python 3にバッチリ適合するものはなさそうなのでラッパ・ライブラリは使わず、STDOUTを利用した素のAGIで。

 また、RDBMSに限らず、テキストリストでもjsonでも良いのですが、自身の場合、別件で既に稼働中、かつ、Asteriskファイル全般に所有者をasterisk:asteriskにしてあり、OSのasteriskユーザーからRDBMSのateriskユーザーが作ったデータベース、テーブルを操作するようにすることでファイル所有者やパーミッションを気にすることのないRDBMSの内、PostgreSQLを使うことにしました。

 ファイルごとに所有者やパーミッションを変えるとなると面倒なので。

 root:asteriskなら、asteriskグループに所属していれば、asterisk:rootならasteriskユーザーで機能するのでまだ良いにしても、仮にroot:rootなら誰でもOKなotherパーミッションに実行権限を付与しておかないと検証でroot実行している場合は問題なくても本番稼働してみて気づけば、asteriskユーザーでは動かない、書き込むべきところで書き込めないといったことが起こる可能性とか...考えるのも管理するのも面倒ですよね?

PostgreSQL ユーザー/DB/Table作成
raspberry_pi_os $ grep asterisk /etc/passwd
asterisk:x:1001:1001::/home/asterisk:/bin/bash
raspberry_pi_os $ grep asterisk /etc/group
asterisk:x:1001:
raspberry_pi_os $

 まず、Linux上にasteriskユーザーが存在するか確認、存在しなければ作成します。

raspberry_pi_os $ grep postgres /etc/passwd
postgres:x:121:131:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
raspberry_pi_os $ grep postgres /etc/group
ssl-cert:x:118:postgres
postgres:x:131:
raspberry_pi_os $

 また、PostgreSQLをインストールした際にLinux用であり、PostgreSQLのスーパーユーザーであるpostgresユーザー・グループが作成されているはずなので一応、確認します。

raspberry_pi_os $ sudo su postgres
raspberry_pi_os $ createuser -d -P asterisk
新しいロールのためのパスワード:
もう一度入力してください:
raspberry_pi_os $ exit
raspberry_pi_os $

 sudo suで現在のユーザーから、そのpostgresユーザーに切り替え、PostgreSQLのcreateuserコマンドでasteriskユーザーを作成しておきます。

 -dオプションは、データベース作成権限を付与、-Pオプションは、ログイン時にパスワードを要求する設定でこのようにパスワード設定と確認を求められますが、-Pを設定しなければ、パスワードなしでログインできるようになります。

raspberry_pi_os $ sudo su asterisk
raspberry_pi_os $ createdb myastdb
raspberry_pi_os $ psql myastdb
ユーザー asterisk のパスワード:
psql (15.15 (Raspbian 15.15-0+deb12u1))
"help"でヘルプを表示します。
 
myastdb=# create table phonebook(num varchar(20) not null, name text not null);
CREATE TABLE
myastdb=# \d
リレーション一覧
スキーマ | 名前 | タイプ | 所有者
----------+-----------+----------+----------
public | phonebook | テーブル | asterisk
(1 行)
 
myastdb=# \d phonebook
テーブル"public.phonebook"
列 | タイプ | 照合順序 | Null 値を許容 | デフォルト
------+-----------------------+----------+---------------+------------
num | character varying(20) | | not null |
name | text | | not null |
インデックス:
"phonebook_pkey" PRIMARY KEY, btree (tel)
 
myastdb=# exit
raspberry_pi_os $ exit
raspberry_pi_os $

 今度は、asteriskユーザーに切り替えてcreatedbコマンドでデータベースを作成、[psql 作成したデータベース名]としてDBに接続し、CREATE TABLE文でテーブルを作成、[\d]でテーブルを、[\d テーブル名]でテーブル定義を正しく作成出来たことを確認しておきます。

raspberry_pi_os $ sudo su asterisk
raspberry_pi_os $ psql myastdb
ユーザー asterisk のパスワード:
psql (15.15 (Raspbian 15.15-0+deb12u1))
"help"でヘルプを表示します。
 
myastdb=# \COPY phonebook FROM '/path/to/file_name.csv' DELIMITER ',' CSV HEADER;
myastdb=# select * from phonebook;
...
myastdb=# exit
raspberry_pi_os $ exit
raspberry_pi_os $

 電話帳データについては、1件ずつ文[insert into TABLE (num,name) values (NUMBER,NAME);]としても良いですし、テキストエディタで複数行をINSERT INTO文に(セミコロンを忘れずに)整形後、プロンプトにコピペして一気に流し込むこともできますし、データ型、カラム数、制約に一致していれば、CSVファイルなどでもレコードを追加することができます。

 例えば、スマホから電話帳データをエクスポート、編集がしやすいとは言い難いものの、.vcfファイルでもExcelやLibreOffice Calcなどでは読めますので編集後、csvファイルとして保存することができます。

 CSVファイルを用意できたら、このように\COPYコマンドを実行、データを確認します。

 尚、どれもプロンプトを変更していないので、やや分かりづらいですが、最後に[raspberry_pi_os $ exit]している部分は、切り替えたpostgresやasteriskユーザから抜け、普段使うユーザーに戻るべく、実行している様子です。

agi-binパスを固定する
raspberry_pi_os $ cat /etc/asterisk/asterisk.conf
...
[directories]
astagidir => /var/lib/asterisk/agi-bin
...
raspberry_pi_os $

 agi-binのパスは、/usr/share/asterisk/agi-binと/var/lib/asterisk/agi-binの2つがあり、何れかを期待して実行してもAsteriskが違う方を想定した場合、機能しないので確実を期すべく、このように/etc/asterisk/asterisk.confでパスを固定していないとしておくと良いでしょう。

Python 3でAGIスクリプト
raspberry_pi_os $ sudo python3-psycopg2
...
raspberry_pi_os $ cat /var/lib/asterisk/agi-bin/telnum_name.py
#!/usr/bin/env python3
import sys
import psycopg2
 
while True:
  line = sys.stdin.readline().strip()
  if line == "":
    break
 
number = sys.argv[1].strip()
 
try:
  conn = psycopg2.connect(
    dbname="myastdb",
    user="asterisk",
    password="ANY_PASSWORD",
    host="localhost",
    port="5432"
  )
  cur = conn.cursor()
  cur.execute("SELECT name FROM phonebook WHERE num=%s", (number,))
  row = cur.fetchone()
  name = row[0] if row else "該当なし"
 
except Exception as e:
  print(f'SET VARIABLE caller_name "ERROR: {str(e)}"')
  sys.stdout.flush()
  sys.exit(0)
 
print(f'SET VARIABLE caller_name "{name}"')
raspberry_pi_os $ sudo chown asterisk:asterisk /var/lib/asterisk/agi-bin/telnum_name.py
raspberry_pi_os $ sudo chmod u+x /var/lib/asterisk/agi-bin/telnum_name.py
raspberry_pi_os $

 aptならPython用AGIライブラリpython3-psycopg2をインストールしておきます。

 pipでpsycopg2でも良いですが、ユーザーをまたぐ場合や、仮想環境を要すなど、多少面倒な部分を回避できたりするのでapt。

 シンプルなAGIスクリプトがこれで、CallerID(num)を引数として受け取り、asteriskユーザーとパスワード(ANY_PASSWORDは置き換える)でURIがlocalhost、ポート5432のPostgreSQLにおいてDB[tel_num]にアクセス、select文でテーブル[phonebook]に対し、where句でCallerID(num)と一致するレコードがあれば、当該データを1件抽出、なければ[該当なし]を返します。

 所有者をユーザー:グループ共にasterisk:asteriskにして、asteriskユーザーに実行権限を与えておきます。

 他の所有者の組み合わせやパーミッションのバリエーションもあり得ますし、検証時などは、asteriskユーザーに切り替えることなく、sudoでrootとして行うケースもあるでしょうが、運用中は、asteriskユーザーが実行することを考慮すると全てに渡って、こうしておくのが無難かなと。

extensions.conf例
raspberry_pi_os $ cat /etc/asterisk/extensions.conf
...
[from-050plus]
exten => s,1,NoOp(050plus incoming)
...
same => n,GotoIf($["${CALLERID(num)}"=""]?set_no_num)
same => n,AGI(telnum_name.py,${CALLERID(num)})
same => n(set_no_num),Set(caller_name=非通知)
same => n,Set(CALLERID(name)=${caller_name})
same => n,NoOp(Caller name: ${caller_name})
same => n,Dial(PJSIP/1001&PJSIP/1004)
same => n,Hangup()
...
raspberry_pi_os $

 extensions.confのダイヤルプランは、例えば、こんな風にすると内線端末がCALLERID(name)の設定を受け入れる前提でCALLERID(name)がカラなら[非通知]、そうでないならデータベースで番号を照会、ヒット0件なら[該当なし]、1件なら該当する名前の何れかが内線端末1001や1004に表示されます。

 該当する名前もCALLERID(num)とCALLERID(name)が揃えば、Asteriskが自動的に読み取り専用っぽいCALLERID(all)を設定してくれるらしいので、これに対応する内線端末(なり、アプリなり)であれば、[名前 <電話番号>]が表示されることでしょう。

 前述のように、どのアプリに関わらず、これを受け入れることはないと思われるAndroidスマホで、かつ、名前表示できるアプリであってもAsteriskでセットしたものではなく、自前の電話帳に該当する場合のみ名前が表示されるものであり、他の挙動はアプリ次第となるでしょう。

ホーム前へ次へ