2019年8月30日金曜日

Openwrtでオレオレなパッケージ

Openwrtでオレオレなパッケージ

温度差と仕事が忙しすぎて、やる気が1/10くらいになっている。
睡眠不足だし、悪循環だよね。
今回は、オレオレなパッケージを作ってみる。
ドライバーの作り方も整理したかったけど、また後で。

オレオレなパッケージ

この手順通りでやってみる
https://openwrt.org/docs/guide-developer/helloworld/start

クロスコンパイルツールチェーンの準備

make toolchain/install

HelloWorldをやってみる

ソースの準備

https://openwrt.org/docs/guide-developer/helloworld/chapter2
まずはこの手順に従い、対象となるHelloWorldを作成する。
[myapp/helloworld/helloworld.c]
#include <stdio.h>
int main(void)
{
    printf("\nHello, world!\n\n");
        return 0;
}
https://openwrt.org/docs/guide-developer/helloworld/chapter3

Makefileの準備

Makefileは上記サンプルからパスのみ変更
[mypackages/examples/helloworld/Makefile]
include $(TOPDIR)/rules.mk

# Name, version and release number
# The name and version of your package are used to define the variable to point to the build directory of your package: $(PKG_BUILD_DIR)
PKG_NAME:=helloworld
PKG_VERSION:=1.0
PKG_RELEASE:=1

# Source settings (i.e. where to find the source codes)
# This is a custom variable, used below
SOURCE_DIR:=/******/myapp/helloworld

include $(INCLUDE_DIR)/package.mk

# Package definition; instructs on how and where our package will appear in the overall configuration menu ('make menuconfig')
define Package/helloworld
 SECTION:=examples
 CATEGORY:=Examples
 TITLE:=Hello, World!
endef

# Package description; a more verbose description on what our package does
define Package/helloworld/description
 A simple "Hello, world!" -application.
endef

# Package preparation instructions; create the build directory and copy the source code. 
# The last command is necessary to ensure our preparation instructions remain compatible with the patching system.
define Build/Prepare
 mkdir -p $(PKG_BUILD_DIR)
 cp $(SOURCE_DIR)/* $(PKG_BUILD_DIR)
 $(Build/Patch)
endef

# Package build instructions; invoke the target-specific compiler to first compile the source file, and then to link the file into the final executable
define Build/Compile
 $(TARGET_CC) $(TARGET_CFLAGS) -o $(PKG_BUILD_DIR)/helloworld.o -c $(PKG_BUILD_DIR)/helloworld.c
 $(TARGET_CC) $(TARGET_LDFLAGS) -o $(PKG_BUILD_DIR)/$1 $(PKG_BUILD_DIR)/helloworld.o
endef

# Package install instructions; create a directory inside the package to hold our executable, and then copy the executable we built previously into the folder
define Package/helloworld/install
 $(INSTALL_DIR) $(1)/usr/bin
 $(INSTALL_BIN) $(PKG_BUILD_DIR)/helloworld $(1)/usr/bin
endef

# This command is always the last, it uses the definitions and variables we give above in order to get the job done
$(eval $(call BuildPackage,helloworld))
結構たくさんやることあるね
https://openwrt.org/docs/guide-developer/helloworld/chapter4

feedとして登場させるための準備

[feeds.conf]
src-link mypackages /******/mypackages
ソースはmyapp、Makefileはmypackagesという設定のようだ。
このあたりは、パラメータで自由に出来るところ。

パッケージの生成

./scripts/feeds update mypackages
./scripts/feeds install -a -p mypackages
これで、
[bin/packages/aarch64_cortex-a53/mypackages]に
Packages
Packages.gz
Packages.manifest
Packages.sig
helloworld_1.0-1_aarch64_cortex-a53.ipk
が生成された!
memuconfigで組み込んだり、単独でコンパイルすることも出来そうだ。
make package/helloworld/compile



やったー。

パッケージのインストール・実行

ここまでくれば、いつものパッケージと同じ
opkg install helloworld_1.0-1_aarch64_cortex-a53.ipk

2019年8月18日日曜日

Openwrtでオレオレなレポジトリ

暑くてやる気が1/3くらいになっている。
そんなんで、いろいろミスするよね・・・。
今回は、fon2405e改にasterisk入れようと思ったけど、フラッシュメモリ8MBじゃあ到底入らなかった。
事前に検証しておけばよかったね。
ということで、タイトルがこんな感じになっている。

久しぶりのソースからビルド

基本的には、前回と同じだけど。
https://continue-to-challenge.blogspot.com/2019/01/fon2405eopenwrt.html
fon2405e用にいくつか変えないといけない。

Openwrtのソース取得→生成

git clone https://git.openwrt.org/openwrt/openwrt.git
cd openwrt
./scripts/feeds update -a
./scripts/feeds install -a

ベースとなる変更

変更点は以下の3ファイル
ファイル名だったりが前回と違うみたい。
grep -lri fon2405e target/
target/linux/ramips/image/rt305x.mk
target/linux/ramips/dts/rt3050_fon_fon2405ekai.dts
target/linux/ramips/base-files/etc/board.d/01_leds

rt305x.mk

前回と記載内容がちょっと異なる。
@@ -527,6 +527,16 @@ define Device/fon_fonera-20n
 endef
 TARGET_DEVICES += fon_fonera-20n
 
 +define Device/fon_fon2405ekai
+  MTK_SOC := rt3050
+  IMAGE_SIZE := 7872k
+  IMAGES += factory.bin
+  DEVICE_VENDOR := Fon
+  DEVICE_MODEL := Fon2405ekai
+  SUPPORTED_DEVICES += fon_fon2405ekai
+endef
+TARGET_DEVICES += fon_fon2405ekai
+
 define Device/hame_mpr-a1
   MTK_SOC := rt5350
   BLOCKSIZE := 4k

rt3050_fon_fon2405ekai.dts

[partition@20000]に「compatible = “denx,uimage”;」を追加した。
これがないとoverlayが出来ないみたい。
@@ -0,0 +1,104 @@
+/dts-v1/;
+
+#include "rt3050.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ compatible = "fon,fon2405ekai", "ralink,rt3050-soc";
+ model = "FON2405E Kai";
+
+ aliases {
+  led-boot = &led_power_green;
+  led-failsafe = &led_power_green;
+  led-running = &led_power_green;
+  led-upgrade = &led_power_green;
+ };
+
+ gpio-keys-polled {
+  compatible = "gpio-keys-polled";
+  poll-interval = <20>;
+
+  reset {
+   label = "reset";
+   gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
+   linux,code = <KEY_RESTART>;
+  };
+
+  wps {
+   label = "wps";
+   gpios = <&gpio0 0 GPIO_ACTIVE_LOW>;
+   linux,code = <KEY_WPS_BUTTON>;
+  };
+ };
+ gpio-leds {
+  compatible = "gpio-leds";
+  wan {
+   label = "fon2405ekai:green:wan";
+   gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
+  };
+  led_power_green: lan {
+   label = "fon2405ekai:green:lan";
+   gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
+  };
+  wps {
+   label = "fon2405ekai:green:wps";
+   gpios = <&gpio0 14 GPIO_ACTIVE_LOW>;
+  };
+ };
+};
+
+&spi0 {
+ status = "okay";
+
+ m25p80@0 {
+  compatible = "jedec,spi-nor";
+  reg = <0>;
+  spi-max-frequency = <10000000>;
+
+  partitions {
+   compatible = "fixed-partitions";
+   #address-cells = <1>;
+   #size-cells = <1>;
+
+            partition@0 {
+                label = "u-boot";
+                reg = <0x0 0x10000>;
+                read-only;
+            };
+
+            devconf: partition@10000 {
+                label = "devconf";
+                reg = <0x10000 0x10000>;
+                read-only;
+            };
+
+            firmware: partition@20000 {
+                compatible = "denx,uimage";
+                label = "firmware";
+                reg = <0x20000 0x7b0000>;
+            };
+        };
+ };
+};
+
+&pinctrl {
+ state_default: pinctrl0 {
+  gpio {
+   ralink,group = "i2c", "jtag", "rgmii", "mdio", "uartf";
+   ralink,function = "gpio";
+  };
+ };
+};
+
+&ethernet {
+ mtd-mac-address = <&devconf 0x4>;
+};
+
+&esw {
+ mediatek,portmap = <0x2f>;
+};
+
+&wmac {
+ ralink,mtd-eeprom = <&devconf 0>;
+};

01_leds

@@ -170,6 +170,7 @@ dlink,dwr-922-e2)
  ucidef_set_led_netdev "4g" "4g" "$boardname:green:4g" "wwan0" "tx rx"
  ;;
 dovado,tiny-ac|\
+fon,fon2405ekai|\
 fon,fonera-20n)
  set_wifi_led "$boardname:orange:wifi"
  ;;

ビルド

make -j4 V=99
ls -l bin/targets/ramips/rt305x/
合計 9972
-rw-r--r-- 1 adeno adeno    2505  8月 18 16:36 config.buildinfo
-rw-r--r-- 1 adeno adeno     263  8月 18 16:36 feeds.buildinfo
-rw-r--r-- 1 adeno adeno    3099  8月 18 16:39 openwrt-ramips-rt305x-fon-fon2405ekai.manifest
-rw-r--r-- 1 adeno adeno 3361462  8月 18 16:39 openwrt-ramips-rt305x-fon_fon2405ekai-initramfs-kernel.bin
-rw-r--r-- 1 adeno adeno 3407898  8月 18 16:39 openwrt-ramips-rt305x-fon_fon2405ekai-squashfs-factory.bin
-rw-r--r-- 1 adeno adeno 3408666  8月 18 16:39 openwrt-ramips-rt305x-fon_fon2405ekai-squashfs-sysupgrade.bin
drwxr-xr-x 2 adeno adeno    4096  8月 18 16:37 packages
-rw-r--r-- 1 adeno adeno     740  8月 18 16:39 sha256sums
-rw-r--r-- 1 adeno adeno      17  8月 18 16:36 version.buildinfo
これの[openwrt-ramips-rt305x-fon_fon2405ekai-initramfs-kernel.bin]を使って書き換えを行う

Luciアクセス

Web(Lcui)にアクセスしてみる


(OpenWrt SNAPSHOT, r0+10779-51fec85)

[openwrt-ramips-rt305x-fon_fon2405ekai-squashfs-sysupgrade.bin]にてファームアップを行う。これで、overlayされる。
#df -h
Filesystem                Size      Used Available Use% Mounted on
/dev/root                 3.0M      3.0M         0 100% /rom
tmpfs                    13.9M    432.0K     13.5M   3% /tmp
tmpfs                    13.9M     68.0K     13.8M   0% /tmp/root
tmpfs                   512.0K         0    512.0K   0% /dev
/dev/mtdblock5            4.5M    248.0K      4.2M   5% /overlay
overlayfs:/overlay        4.5M    248.0K      4.2M   5% /
これで準備できた

オレオレなリポジトリ

https://qiita.com/hnw/items/17f3a63dbc153f8a5c34
を参考にオレオレのリポジトリを追加する

サーバー側の準備

ls -l bin/packages/mipsel_24kc/
合計 20
drwxr-xr-x 2 adeno adeno 4096  8月 18 16:37 base
drwxr-xr-x 2 adeno adeno 4096  8月 18 02:10 luci
drwxr-xr-x 2 adeno adeno 4096  8月 18 02:11 packages
drwxr-xr-x 2 adeno adeno 4096  8月 18 01:30 routing
drwxr-xr-x 2 adeno adeno 4096  8月 18 16:38 telephony
このデイレクトリをルートにhttpサーバーを構築する。
今回は一時的に欲しいだけなのでphpを用いて
php -S 192.168.2.10:8000
これでOK

デバイス側の準備

/etc/opkg/customfeeds.conf
# add your custom package feeds here
#
# src/gz example_feed_name http://www.example.com/path/to/files
src/gz my_feed_base http://192.168.2.10:8000/base
src/gz my_feed_luci http://192.168.2.10:8000/luci
src/gz my_feed_packages http://192.168.2.10:8000/packages
src/gz my_feed_routing http://192.168.2.10:8000/routing
src/gz my_feed_telephony http://192.168.2.10:8000/telephony
これでOK
opkg updateとかやってみて、ちゃんとオレオレから取得出るかを確認する

asteriskのインストール(容量不足で失敗)

opkg install asterisk16 asterisk16-cdr asterisk16-chan-sip \
asterisk16-codec-gsm asterisk16-codec-ulaw asterisk16-format-gsm \
asterisk16-format-pcm asterisk16-res-agi asterisk16-res-rtp-asterisk
途中まではうまく行ったけど、容量不足で失敗…。
こうなったらeMMCとかMMCカードか?
今日はここまで。

中古ルーターにAsteriskを入れてみる

Buffalo WZR-HP-AG300Hをハードオフで300円でゲットした。
最初は昔買ったfonとかnanopiに入れようかと思ったけど、
複数のVoIPゲートウェイを接続して見たかったからHUBがあるルーターって選択肢として結構ありかも。

OpenWrtインストール

分解してUARTまで接続したけど、実はそんなことしなくても大丈夫だった。
https://openwrt.org/toh/buffalo/wzr-hp-ag300h
  1. 初期化する
  2. 192.168.11.1にアクセスすると管理画面が開く(root/パス無しで)
  3. ファームアップにて[openwrt-18.06.4-ar71xx-generic-wzr-hp-ag300h-squashfs-factory.bin]を書き込む
  4. 192.168.1.1にアクセスすると管理画面が開く
  5. ファームアップにて[openwrt-18.06.4-ar71xx-generic-wzr-hp-ag300h-squashfs-sysupgrade.bin]を書き込む
これで、OpenWrt化完了
@import “中古ルーターにAsteriskを入れてみる\openwrt.png”
その他の設定は良きに計らう

asteriskをインストール

root@OpenWrt:~# opkg install asterisk15 asterisk15-cdr \
asterisk15-chan-sip asterisk15-codec-ulaw asterisk15-res-rtp-asterisk \
asterisk15-format-gsm asterisk15-codec-gsm asterisk15-format-pcm asterisk15-res-agi
GUIからでも良いけど、なんとなく

まずは相互通話

/etc/asterisk/sip.conf
[general]
context=default
port=5060
bindaddr=0.0.0.0
language=ja
;nat=yes
allowguest=no
allow=ulaw
allow=alaw
allow=gsm

[user1]
type=friend
defaultuser=user1
secret=password1
host=dynamic
canreinvite=no

[user2]
type=friend
defaultuser=user2
secret=password2
host=dynamic
canreinvite=no
/etc/asterisk/extensions.conf
[default]
exten => 1,1,Dial(SIP/user1,30,r)
same  => n,Hangup()

exten => 2,1,Dial(SIP/user2,30,r)
same  => n,Hangup()
/etc/init.d/asterisk restart
通話できた!

USBメモリを使えるようにする

何かと使えるようにしておくと便利か
https://openwrt.org/docs/guide-user/storage/usb-drives-quickstart
https://rc30-popo.hatenablog.com/entry/20160103/1451829248
/etc/asterisk/extensions.conf
exten => 5,1,Goto(my-ivr,s,1)

[my-ivr]
exten => s,1,Set(dir=/mnt/sda1/)
exten => s,n,Ringing()
exten => s,n,Wait(3)
exten => s,n,Answer()
exten => s,n,Playback(${dir}music)
みたいな

USBシリアル変換を使えるようにする

これもついでに
https://qiita.com/hnw/items/9b5c99fa73e3716f67d2
今回は確かこれのはず
http://www.aitendo.com/product/13039
opkg install kmod-usb-serial-pl2303
これで/dev/ttyUSB0みたいに認識できた。
やっはりUSBがあるルーターは便利だ。夢が広がる。
(死ぬほどあるFON2405Eの出番がますます無くなる・・・)

PHPインストール

opkg install php7 php7-cli zoneinfo-asia

phpagi

PCでやった時と同じように
phpagi.php - The main phpagi class.
を/usr/share/asterisk/agi-binに保存する。改行コードとかに注意する。
あとはdtmf.phpを少し変更して
#!/usr/bin/php-cli -q
<?php
    /**************************************************
     *  dtmf.php
     **************************************************/

    set_time_limit(30);
    require_once('phpagi.php');
    error_reporting(E_ALL);
    //die("Syntax ok\n"); // line A: uncomment for syntax test

    define('ANS_TONE', '/usr/share/asterisk/sounds/dtmf');
    define('LOG_PATH', '/tmp/dtmf.log');
    define('TIMEOUT', 1000);

    /* log用 */
    $fp = fopen(LOG_PATH, "w");
    fwrite($fp, date("Y/m/d H:i:s")."\t"."Log File.\n");

    /* AGI */
    $agi = new AGI();
    $agi->answer();

  do
  {
    $result = $agi->get_data('/usr/share/asterisk/sounds/beep', 3000, 20);
    $keys = $result['result'];
    fwrite($fp, date("Y/m/d H:i:s")."\tDTMF=".$keys."\n");
  } while($keys != '111');
  $agi->hangup();

?>

も一緒に保存した。
あとは、
/etc/asterisk/extensions.conf
exten => 6,1,agi(dtmf.php)
これで出来た。

2019年8月11日日曜日

VoIPで遊ぶ

興味半分・仕事1/4、なんとなく1/4くらいの感じ。
アナログ電話をいい感じに制御して遊びたくなった。
今頃っ!? 意外としぶとく残っているよ。
こんなのとかいつかは欲しいね
https://www.amazon.co.jp/Asterisk用-TDM410P-Issabel-Freepbx-asterisknow/dp/B01L5MGR9E/ref=lp_4443506051_1_16?srs=4443506051&ie=UTF8&qid=1565275361&sr=8-16
今回は、お試しとして「LINKSYS PAP2T VoIPアダブタ」を入手してみた
https://www.amazon.co.jp/VoIPアダプタ-VBESTLIFE-VoIPゲートウェイ-アナログ電話アダプタ-V2プロトコル/dp/B07KS2P9G4/ref=sr_1_3?__mk_ja_JP=カタカナ&keywords=VoIPアダプタ+VBESTLIFE+VoIPゲートウェイ+IP電話&qid=1565019126&s=electronics&sr=1-3
https://www.voip-info.jp/index.php/Linksys_PAP2T
コール音を日本風に
https://shin.4-u.jp/blog/kaden/135/



外線につなぐつもりも無いし、契約していないので、
PAP2Tと古いスマホで内線電話構築して遊んでみる。

Asteriskインストール

この手順で、とりあえず開発PCに入れてみた。
https://qiita.com/sgrowd/items/dd1fc682718a2a623e4c

まずは相互通話

/etc/asterisk/sip.conf
[general]
context=default
port=5060
bindaddr=0.0.0.0
language=ja
;nat=yes
allowguest=no
allow=ulaw
allow=alaw
allow=gsm

[user1]
type=friend
defaultuser=user1
secret=password1
host=dynamic
canreinvite=no

[user2]
type=friend
defaultuser=user2
secret=password2
host=dynamic
canreinvite=no
/etc/asterisk/extensions.conf
[default]
exten => 1,1,Dial(SIP/user1,30,r)
same  => n,Hangup()

exten => 2,1,Dial(SIP/user2,30,r)
same  => n,Hangup()
Dialの説明はここ
https://www.voip-info.org/asterisk-cmd-dial/

PAP2T




[Proxy]のところにAstersik SIPサーバーのIPを設定した。

スマホ

MIZUDROIDとZoiperを試してみた。
ともに音が小さいなぜだろう。
ZoiperではSetting→Audio→SpeakerGainを0dBから10dBにしてみたら多少良くなった。

自動応答

電話かけたら自動応答をやってみる。
https://scc.kokushin-u.jp/2019/01/19/asterisk-ivr/

音声ファイルの準備

どうやらgsm形式とかulaw形式のファイルを準備する必要があるみたい
https://p--q.blogspot.com/2015/04/soxsound-exchangemp3.html
 sudo apt-get install sox libsox-fmt-all
 どっちか
 sox src.mp3 -r 8000 -c 1 dst.gsm
 sox src.mp3 -r 8000 -c 1 -e u-law -t wav dst.ulaw

設定ファイル

/etc/asterisk/extensions.conf
exten => 3,1,Goto(my-ivr,s,1)
[my-ivr]
exten => s,1,Set(dir=/home/asterisk/)
exten => s,n,Ringing()
exten => s,n,Wait(3)
exten => s,n,Answer()
exten => s,n,Playback(${dir}dst)
https://www.voip-info.org/asterisk-cmd-playback/
https://www.voip-info.org/convert-wav-audio-files-for-use-in-asterisk/

自動応答の実験

3にコールするとdst.gsm/ulawが再生される。
いいね! 音質はお察しくださいって感じ。

AGIで遊んでみる

AGIとはAsterisk Gateway Interfaceという、外部との連携するしくみ
https://www.voip-info.org/asterisk-agi
https://my-scribble.net/raspberrypiでスマートホーム-〜asteriskで家庭内電話-その3-agiでシ/
いろいろな言語で使えるみたい。
Pythonとかちょっと気になるけど、インターネットから遮断されている環境でも使うかもしれないので、使い慣れたPHPで…

phpagi

http://phpagi.sourceforge.net/
https://sourceforge.net/projects/phpagi/files/
これの[phpagi-2.20.tgz]と[phpagi-examples-2.20.tgz]をダウンロード。
phpagi.php - The main phpagi class.
phpagi-asmanager.php - The Asterisk Manager class.
を/usr/share/asterisk/agi-binに保存する。
改行コードとかに注意する。
サンプルとして
dtmf.php
も一緒に保存した。
あとは、
/etc/asterisk/extensions.conf
exten => 5,1,agi(dtmf.php)
いざ電話をかけてみると、喋らないOrz
AGIのデバック方法をいろいろ調べた。
https://www.linux.com/news/debugging-asterisk-agi-phpagi-and-festival
http://www.ne.jp/asahi/davinci/code/asterisk/install/index2.html
どうやらtxt2wavでつまずいている。
https://github.com/leoburd/asterisk/blob/master/phpagi.conf
text2waveってなにさ
http://manpages.ubuntu.com/manpages/bionic/man1/text2wave.1.html
なるほど、テキストを喋ってくれるのね。
せっかくなら日本語が良いなー。
google TTSの例はあったけど、陸の孤島環境でも使いたいので
そんな迷える僕の強い味方OpenJTalkを使わせてもらう。

OpenJTalkの準備

昔苦労してインストールしたような気がするけど、便利になったね。
http://open-jtalk.sp.nitech.ac.jp/
http://thr3a.hatenablog.com/entry/20180223/1519360909
https://qiita.com/lutecia16v/items/8d220885082e40ace252
sudo apt-get install open-jtalk open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001
meiさんもダウンロード
https://sourceforge.net/projects/mmdagent/files/MMDAgent_Example/
テスト
https://qiita.com/sukesuke/items/be2a4562bd809ccc0fab
echo "こんにちは" | open_jtalk -x /var/lib/mecab/dic/open-jtalk/naist-jdic/  \
-m /usr/share/hts-voice/mei/mei_normal.htsvoice -ow /dev/stdout | aplay --quiet
8kbpsにしようとしてサンプリング周波数設定したらとんでもないことになった
echo "こんにちは" | open_jtalk -x /var/lib/mecab/dic/open-jtalk/naist-jdic/ \
-m /usr/share/hts-voice/mei2/mei_normal.htsvoice -s 8000 -ow /dev/stdout | aplay --quiet
なので、sox使って変更することにした。

phpagiから呼び出す

といってもちょっと書き換えただけ

phpagi.conf

/etc/asterisk/phpagi.conf
[OpenJTalk]
open_jtalk=/usr/bin/open_jtalk
dic=/var/lib/mecab/dic/open-jtalk/naist-jdic/
htsvoice=/usr/share/hts-voice/mei2/mei_happy.htsvoice
other_option='-r 1.1'

phpagi.php

/usr/share/asterisk/agi-bin/phpagi.php
166行目あたり
        // swift TTS config
        if(!isset($this->config['cepstral']['swift'])) $this->config['cepstral']['swift'] = $this->which('swift');

        // Open JTalk
        if(!isset($this->config['OpenJTalk']['open_jtalk'])) $this->config['OpenJTalk']['open_jtalk'] = $this->OpenJTalk('OpenJTalk');
        if(!isset($this->config['OpenJTalk']['dic'])) $this->config['OpenJTalk']['dic'] = $this->OpenJTalk('dic');
        if(!isset($this->config['OpenJTalk']['htsvoice'])) $this->config['OpenJTalk']['htsvoice'] = $this->OpenJTalk('htsvoice');
        if(!isset($this->config['OpenJTalk']['other_option'])) $this->config['OpenJTalk']['other_option'] = $this->OpenJTalk('other_option');

1334行目あたり
    function text2wav($text, $escape_digits='', $frequency=8000)
    {
        省略
    }

    function open_jtalk($text, $escape_digits='', $frequency=8000)
    {
        $text = trim($text);
        if($text == '') return true;

        $hash = md5($text);
        $fname = $this->config['phpagi']['tempdir'] . DIRECTORY_SEPARATOR;
        $fname .= 'open_jtalk' . $hash;

        // create wave file
        if(!file_exists("$fname.wav"))
        {
          // write text file
          if(!file_exists("$fname.txt"))
          {
            $fp = fopen("$fname.txt", 'w');
            fputs($fp, $text);
            fclose($fp);
          }

          shell_exec("cat $fname.txt | {$this->config['OpenJTalk']['open_jtalk']} -x {$this->config['OpenJTalk']['dic']} -m {$this->config['OpenJTalk']['htsvoice']}  {$this->config['OpenJTalk']['other_option']} -ow $fname.wav.wk");
          shell_exec("sox $fname.wav.wk -r 8000 $fname.wav");
        }
        else
        {
          touch("$fname.txt");
          touch("$fname.wav.wk");
          touch("$fname.wav");
        }

        // stream it
        $ret = $this->stream_file($fname, $escape_digits);

        // clean up old files
        $delete = time() - 2592000; // 1 month
        foreach(glob($this->config['phpagi']['tempdir'] . DIRECTORY_SEPARATOR . 'open_jtalk*') as $file)
          if(filemtime($file) < $delete)
            unlink($file);

        return $ret;
    }

dtmf.php

/usr/share/asterisk/agi-bin/dtmf.php
日本語だぜー

#!/usr/bin/php -q
<?php
  set_time_limit(30);
  require('phpagi.php');
  error_reporting(E_ALL);
  //die("Syntax ok\n"); // line A: uncomment for syntax test

  $agi = new AGI();
  $agi->answer();

  $agi->open_jtalk("こんにちわ。今日も暑いですね。");
  do
  {
  //  $agi->text2wav('Enter some numbers and then press the pound key. Press 1 1 1 followed by the pound key to q$
    $agi->open_jtalk("ボタンを押して何か数字を入力してください。終了する場合は、111と入力してください。");
    $result = $agi->get_data('/var/lib/asterisk/sounds/beep', 3000, 20);
    $keys = $result['result'];
    $agi->open_jtalk("あなたが入力したのは $keys です。");
  } while($keys != '111');
  $agi->open_jtalk('さようなら!');
  $agi->hangup();
?>
とりあえず今日はここまで。

2019年8月2日金曜日

バックアップについて

12月頃にHOMEサーバーの環境を移行してから、バックアップが手薄になっていた。
https://continue-to-challenge.blogspot.com/2018/10/nextcloud.html
https://continue-to-challenge.blogspot.com/2018/12/gogs.html
今回はせめて再構築が用意になるように外付けHDDにバックアップを行うことにした。
対象
  • nextcloud
  • gogs
  • redmine
nextcloudには、家族の写真とかがあるので特に大事。

バックアップ

nextcloud

ほぼ先人と同じ
https://docs.nextcloud.com/server/15/admin_manual/maintenance/backup.html
https://denor.jp/nextcloudサーバのデータ自動バックアップ設定-snap版
https://takuya-1st.hatenablog.jp/entry/2018/11/20/020000
#!/bin/bash
NCPATH="/mnt/***/www/html/nextcloud"
NCDATA_PATH="/mnt/***/nextcloud/data"
TARGET="/mnt/usbhdd/nextcloud_backup"

echo start at `date`

echo "(STEP1)HDD spin-up"
sdparm -r --command=start /dev/sdd

echo "(STEP2)Maintenance Mode [ ON ]"
sudo -u www-data php ${NCPATH}/occ maintenance:mode --on

echo "(STEP3)Backup Config"
rsync -vAax ${NCPATH} ${TARGET}

echo "(STEP4)Backup Data"
rsync -vAax ${NCDATA_PATH} ${TARGET}

echo "(STEP5)Backup Database"
mysqldump --single-transaction -h localhost -u nextcloud -p****** nextcloud > ${TARGET}/nextcloud-sqlbkp.bak

echo "(STEP6)Maintenance Mode [ OFF ]"
sudo -u www-data php ${NCPATH}/occ maintenance:mode --off

echo "(STEP7)HDD spin-down"
sdparm -r --command=stop /dev/sdd

echo end at `date`

省電力化のためにスピンダウン入れてみたけど、効果は未知数。
smartで起動しちゃうみたいだし・・・。

gogs

大体ここの内容と同じ
https://gogs.io/docs/upgrade/upgrade_from_binary
#!/bin/bash
GGSPATH="/***/git/gogs"
GGSRPPATH="/***/git/gogs-repositories"
TARGET="/mnt/usbhdd/gogs_backup"

echo start at `date`

echo "(STEP1)gogs [ STOP ]"
systemctl stop gogs

echo "(STEP2)Backup Custom"
rsync -vAax ${GGSPATH}/custom ${TARGET}

echo "(STEP3)Backup Data"
rsync -vAax ${GGSPATH}/data ${TARGET}

echo "(STEP4)Backup Log"
rsync -vAax ${GGSPATH}/log ${TARGET}

echo "(STEP5)Backup Database"
mysqldump --single-transaction -h localhost -u gogs -p****** gogs_git  > ${TARGET}/gogs-sqlbkp.bak

echo "(STEP6)Backup Repository"
rsync -vAax ${GGSRPPATH} ${TARGET}

echo "(STEP7)gogs [ START ]"
systemctl start gogs

#echo "(STEP7)HDD spin-down"
#sdparm -r --command=stop /dev/sdd
echo end at `date`

redmine

本体はdocker、データベースはローカルのMariaDBを使用している。
https://continue-to-challenge.blogspot.com/2019/07/redmine.html
バックアップの方法
https://qiita.com/mikoski01/items/7d71ef7d167a6b78219a
http://redmine.jp/faq/system_management/backup/
#!/bin/bash
RMPATH="/srv/docker/redmine/redmine/files"
TARGET="/mnt/usbhdd/redmine_backup"

echo start at `date`

echo "(STEP1)redmine [ STOP ]"
docker stop redmine

echo "(STEP2)Backup Data"
rsync -vAax ${RMPATH} ${TARGET}

echo "(STEP3)Backup Database"
mysqldump --single-transaction -h localhost -u redmine -p****** redmine  > ${TARGET}/redmine-sqlbkp.bak

echo "(STEP4)redmine [ START ]"
docker start redmine

リストア

gogsの復元

ほぼ、この前の環境構築と同じ
https://continue-to-challenge.blogspot.com/2018/12/gogs.html
今回はテストとしてNanoPiに環境構築してみた。
  1. gogsインストールして
  2. MariaDBにデータベース作成
  3. バックアップからデータリストア
  4. 起動
の簡単4ステップ

redmineの復元

環境構築は、この前の手順で
https://continue-to-challenge.blogspot.com/2019/07/redmine.html
復元手順は
http://redmine.jp/faq/system_management/backup/
すいすい行くと思いきや
standard_init_linux.go:211: exec user process caused "exec format error"
なんだと!
どうやらNanoPiではARM用のイメージを使わないといけないらしい。
https://matatsuna.hatenablog.com/entry/2017/08/16/223039
公式のものがARM64対応していたのでそれにしてみる。
https://hub.docker.com/_/redmine
docker run --name=redmine -it --rm \
-e REDMINE_DB_USERNAME=redmine -e REDMINE_DB_PASSWORD=****** \
-e REDMINE_DB_DATABASE=redmine \
-e REDMINE_DB_MYSQL=192.168.1.13 -e REDMINE_DB_PORT=3306 \
-p 3000:3000 \
-v /srv/docker/files:/usr/src/redmine/files \
library/redmine:4.0.4
初期状態で起動が確認できたら、
  1. /srv/docker/redmineにfilesの中身を展開する
  2. データベースの復元
を行う。
できた!

nextcloudの復元

nextcloudには30GBくらいのデータが保存されているため、NanoPIのSDカードでは到底復元の環境に出来ない。
そこで、NanoPIに外付けHDDを装着した。 段々とNASキットが欲しくなる。
http://wiki.friendlyarm.com/wiki/index.php/1-bay_NAS_Dock_v1.2_for_NanoPi_NEO/NEO2#Hardware_Spec
https://www.friendlyarm.com/index.php?route=product/product&path=93&product_id=222
http://akizukidenshi.com/catalog/g/gM-12591/
ま、我慢だけどね。
ルートを外付けHDDに変更するには
nand-sata-install
https://lubtech.geo.jp/2017-09-10/?p=3048
環境構築はこの前の手順で
https://continue-to-challenge.blogspot.com/2018/10/nextcloud.html
こちらは特にARM/X86_64で違いはなく、当時の方法を思い出して行けば大丈夫。
ただし、復旧までの暫定・データ取り出しを目的としているためSSLは除外した。
うーん。眠い。