一口メッセージ:遅延配信

アスタリスクのメッセージ(ala SMS)のトピックはHabréの最初のトピックではありませんが、すべての出版物には1つの欠点があります。メッセージ配信の遅延の機能はありません。 受信者がオフラインの場合、メッセージを送信しようとすると、これに関するメッセージと、後で試すようにという提案が表示されます。

画像






混乱!



FreePBXがインストールされたアスタリスク11を使用します。 従来は、今回は「設定なし」は機能しません。



そのため、WebMords設定→アスタリスクSIP設定のセクションで、メッセージを有効にし、メッセージの処理コンテキストを指定します。 一番下で、sip.confのカスタムフィールドを追加し、以下を指定します。



accept_outofcall_message = yes outofcall_message_context = messages auth_message_requests = no
      
      





extensions_custom.confにこのコンテキストを作成します。



 [messages] exten => _.,1,Set(MSG_TO=${CUT(MESSAGE(to),@,1)}) exten => _.,n,MessageSend(${MSG_TO},${MESSAGE(from)}) exten => _.,n,GotoIf($["${MESSAGE_SEND_STATUS}" != "SUCCESS"]?sendfailedmsg) exten => _.,n,Hangup() exten => _.,n(sendfailedmsg),Set(MSG_TMP=${CUT(MESSAGE(from),<,2)}) exten => _.,n,Set(MSG_FROM=${CUT(MSG_TMP,@,1)}) exten => _.,n,Set(ODBC_SAVE_MESSAGE("${MESSAGE(from)}","${MSG_TO}","${MESSAGE(body)}")=1) exten => _.,n,Set(MESSAGE(body)="[${STRFTIME(${EPOCH},,%d%m%Y-%H:%M:%S)}]    ${EXTEN}  .   ,     .") exten => _.,n,MessageSend(${MSG_FROM}, SYSTEM) exten => _.,n,Hangup()
      
      





このコンテキストでは、MySQL DBMSに「SMS」を保存するODBC関数の呼び出しがあります。 個別のデータベースとDSNにだまされないように、既存のasteriskcdrdbデータベースにテーブルを作成しました。



 CREATE TABLE IF NOT EXISTS `messages` ( `id` int(11) NOT NULL AUTO_INCREMENT, `dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `mfrom` varchar(100) CHARACTER SET utf8 NOT NULL, `mto` varchar(100) CHARACTER SET utf8 NOT NULL, `mbody` text CHARACTER SET utf8 NOT NULL, `delivered` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
      
      





func_odbc.confファイルで、ODBC_関数自体を追加します。



 [SAVE_MESSAGE] writesql = INSERT INTO messages (mfrom,mto,mbody) VALUES ('${ARG1}','${ARG2}','${BASE64_ENCODE(${ARG3})}') dsn = asteriskcdrdb
      
      





ご覧のとおり、メッセージテキストは保存前にbase_64でエンコードされています。 このような単純な方法で、キリル文字を使用してグリッチを回避します。 ちなみに、メッセージのコンテキストでのテキスト送信は引用符で囲む必要があります。そうでない場合、テキストにカンマが表示されると、ダイヤルパンはこれをパラメータ区切り文字と見なします:)



したがって、ネットワークに加入者がいないときにデータベースに保存したメッセージ。 このメッセージを彼に配信するメカニズムを構成することは残っています。 phpで行います。スクリプトを/etc/asterisk/send_delayes_messages.phpに配置します。



 <?php #asteriskcdrdb database #mysql settings $hostname = "localhost"; $username = "asteriskuser"; $password = "password"; $dbName = "asteriskcdrdb"; mysql_connect($hostname,$username,$password) or die("no connect to MySQL."); mysql_select_db($dbName) or die("ERROR: ".mysql_error()); mysql_query("set names 'utf8'"); $messages_query = mysql_query('SELECT `id`,`mfrom`,`mto`,`mbody` FROM `messages` WHERE `delivered` = "0000-00-00 00:00:00" ORDER BY `dt`') or die("ERROR: ".mysql_error()); while($message = mysql_fetch_array($messages_query, MYSQL_ASSOC)) { $peer_to = explode(":", $message['mto']); if (peer_online($peer_to[1])) { //print_r($message); file_put_contents('/tmp/delayed_message_'.$peer_to[1].'_'.time(), 'Channel: Local/s@default'."\r\n".'Application: MessageSend'."\r\n".'Set: MESSAGE(body)='.base64_decode($message['mbody'])."\r\n".'Data: '.$message['mto'].','.$message['mfrom']."\r\n"); exec("mv /tmp/delayed_message_* /var/spool/asterisk/outgoing/"); mysql_query('UPDATE `messages` SET `delivered` = "'.date("Ymd H:i:s").'" WHERE `id` = '.$message['id']." LIMIT 1") or die("ERROR: ".mysql_error()); } } function peer_online($peer) { $raw = shell_exec('asterisk -rx "sip show peer '.$peer.'" | grep "Status" | grep "OK"'); print $raw; if(!empty($raw)) return true; else return false; } ?>
      
      





配信の事実のラベルとして、タイムスタンプ型の配信フィールドを使用します。ゼロがある場合、メッセージは配信が必要です。 したがって、保存された未配信メッセージを実行して、cliコマンドでピア登録の存在を確認し、ネットワーク上にある場合、このメッセージを配信する発信コールファイルを作成します。 その後、スクリプトはデータベース内のメッセージにマークを付け、送信日を設定します。



php -f /etc/asterisk/send_delayes_messages.phpを使用してスクリプトを毎分クラウンに固定し、1分ごとにメッセージを確認して配信しようとします。



この実装の欠点は何ですか? 1つ目は、休憩後のしばらくの間、ごちそうのステータスの登録が保持されることです。ごちそうは短時間登録されて落ち、システムは1分以内にメッセージを「送信」し、配信されたと見なします。 コールファイルでアプリケーションを使用せずに、変数$ {MESSAGE_SEND_STATUS}のステータスを確認してコンテキストにデータを転送することで、取得できます。 おそらく、呼び出しファイルのSetを介して変数を設定することにより、既存のコンテキストを使用することが可能になります。

しかし、これまでのところ、私はこれに落ち着きました:一度。



頑張って



All Articles