UfoCtrl Ver1.00 U.F.O. TW U.F.O. SA A10サイクロンSA (+PLUSプラス) バッハスマート ROCKET+1D 等BLE制御アプリ

久し振りの処理全体見直しにより、遂に従来のUfoTwCtrlとUfoSaCtrlTripとを一つのアプリに統合しました。

このアプリはBLE(Bluetooth Low Energy)通信機能を持つAndroid4.3(API18)以上の機器でU.F.O. TW、U.F.O. SA、A10サイクロンSA +PLUS(プラス)バッハスマートROCKET+1Dなどの+1D対応グッズをランダムコントロールしたり任意の固定パターンを登録して制御出来たりする野良アプリです。
また、上記以外の機器でも条件が合致する機器であれば接続情報を正しく設定に記述することで同様に制御できる可能性があります。

対象となるデバイスは以下になります。

なお、ROCKET2
ROCKET2
についても、
筆者が購入していないため動作するか不明ですが、販売サイトの画像を見た限りですとROCKET+1Dと同じ「ROCKET」というデバイス名を使用している可能性が高く、このアプリはデバイス名で接続機器を判別しているため「ROCKET」で認識できるかもしれません。(が確証も責任も持てませんのでその辺りは各ご自身の判断にてお願いいたします。)

機能説明

やたらと多機能ですので、端折れるところは端折ります。

まず、野良アプリですので、野良アプリをインストールできるようにしてください。

起動しますと、いきなりこんな画面。

うわってなるかと思いますが、UfoCtrlではU.F.O. TW(もしくはそれに類する機器)を1セットと、その他+1D対応機器を最大4台同時接続してコントロールできます。
これは、両乳首と前後で最大4つのデバイスまで対応出来れば完璧じゃろ? というだけでありまして、U.F.O. TWとそれ以外は結構仕組みが異なるので制御枠から画面表示まで別扱いにしておりまして、こんな感じになっております。

ですが、ほとんどの人にとってこんなに枠は要らないはず。筆者も最大でも3台あれば十分です。
というわけで、必要無い枠は非表示に出来ます。
なので、最初に要らない枠を非表示にしてしまった方が見易いし画面操作もし易くなると思います。

画面右上のメニューの『︙』をタップしますと、『Switches』というメニューがありますので、そこをタップしてください。

Switches

一番上の行『U.F.O. TWを使う』のチェックボックスをU.F.O. TWを使用しない方は外してください。
その下の行『TW以外』の0〜4のラジオボタンはU.F.O. TW以外の機器で使用する数を選んでください。

例えば、U.F.O. TWは使用して、TW以外を2とした場合。

少し見慣れた感じの画面になるかと思います。
なお、表示しないだけですので、例えば3)とか4)とかの枠で機器接続をしてから非表示にしたりすると制御は続行しますのでvol上げると動きます。

ついでにこの『Switches』画面の説明をしておきます。
『LCDOFFボタンを使う』チェックボックスをオンにするとメイン画面のロックアイコンに色が付いてボタンが機能するようになります。

このボタンをタップすると画面を消灯してロックまでします。本当は画面消灯だけしてロックはしたくないのですが方法が見つからずロックまでしてしまいます。(多分セキュリティの問題で画面消灯だけというのは無い)
一応、出来る限り画面を再点灯した際にロック解除をせずともすぐに当アプリの画面表示になるようにプログラムしておりますが、機種によってはそれでもロック解除が必要になってしまうかもしれません。
そういう場合でも画面ロックを「なし」にしているAndroid機では単なる画面消灯と同じになりますので使えるかと思います。(盗難等のリスクを考えると画面ロックなしはオススメ出来ないのですが重要な情報を入れないロックしなくて良い専用機みたいなのを持っていると楽で良いですよ?)
ただし、この機能を使用するには管理権限に許可していただく必要があります。
初めてボタンをタップしたときにこの権限を許可するかどうか設定できる画面が開くかと思いますので、許可してください。
しかし、この管理権限というのはかなり端末を自由に弄れる権限のようでして、筆者はこれを画面の消灯&ロックにしか使用していませんが、場合によっては結構恐ろしいことも出来るようです。
権限許可画面の説明を良く読んで、筆者のアプリをそこまで信用してないよという方は権限を許可せず、このボタンも使用しないでください。
また、もしこの管理権限を許可した場合は、今度はこのアプリをアンインストールする際に管理権限を外してからでないとアンインストール出来ないようになりますのでご注意ください。
親切な機種なら管理権限を外せる画面に誘導してくれるのですが、不親切な機種ですと自分で管理権限の設定を探して許可を外さないとアンインストール出来ないことになります。
機種によってはこんなボタンに頼らなくても、ステータスバーをダブルタップしたり、◀バックボタン長押しで画面消灯したりすると思いますし、そもそも電源ボタン押せば消灯するわけですので、UfoCtrlアプリの画面上タップで消灯したいという方だけオンにして使用してください。

『モーター稼働積算計を使う』チェックボックスをオンにするとメイン画面のお仕事アイコンに色が付いてボタンが機能するようになります。

このアプリからどれだけ動作指示を出力したかのカウンタを表示する画面が出てきます。(後述)

『近接センサーをON/OFF切替に使う』チェックボックスをオンにするとAndroid端末に近接センサーが付いている場合、この近接センサーに手などをかざす度にVolumeを0にしたり戻したりします。
Volume0でないときの値を記憶していて、その値とゼロとを切り替えることでON/OFFスイッチ的に使用することが出来ます。
近接センサーは通話が出来る機種であればまず付いていると思いますが、通話機能の無いタブレット等では無い可能性が高いです。また、近接センサーは受話口もしくはその近辺にあることが多いです。
なお、このVolumeのオンオフ切替はメディアキーの再生や停止など、ジョイパッドのあらゆるボタン、キーボードの[Space]キーや[Enter]キーなどでも反応するようにしています。

『Volumeボタンを』
『ON/OFF切替に使う』上記同様、Volumeを0にしたり戻したり。Volume上下どちらを押しても切り替えます。
『Volume調整に使う』VolumeUpは1つ上げ、VolumeDownは1つ下げ。サイクリック(ループします。3から上げると0に。0から下げると3に)。
『Ptn変更に使う』全ての接続枠ごとに選択している制御パターンの選択を1つずらします。VolumeUpは前の選択肢にVolumeDownは次の選択肢に。サイクリック(ループ)です。動きが良く分からない場合は一切接続してない状態で構わないのでアプリで実際に動かしてみてください。
『Rel変更に使う』同じタイプの機器を複数接続している場合(U.F.O. TWは1台で左右あるので複数であると見なします)に同期するか反転するかあるいは無関係に制御するかという関連性の選択肢を1つずらします。同じくサイクリックです。接続してない状態で表示の動きを確認できます。
『Gradual/PWM切替に使う』UfoCtrl独自の制御機能であるGradual制御/PWM制御を有効にするかどうかを切り替えます。全てのVolumeに対して一斉に切り替えます。VolumeDownでGradual制御の一斉反転切替、VolumeUpでPWM制御の一斉反転切替です。現在の状況を反転させますので、一律にオンになったりオフになったりするわけではありません。接続してない状態で表示の動きを確認できます。
なお、Android機本体のVolumeボタンの他、メディアキーのVolume(アナログVolumeには反応しません)、ジョイパッドやカーソルキーの上下左右、PgUp/PgDnなどもVolumeボタンを押されたとみなして動くようにしています。

『送り戻しボタンを』の設定も『Volumeボタンを』と同様です。
『ON/OFF切替に使う』上記同様、Volumeを0にしたり戻したり。送り/戻しどちらを押しても切り替えます。
『Volume調整に使う』送りボタンは1つ上げ、戻しボタンは1つ下げ。
『Ptn変更に使う』全ての接続枠ごとに選択している制御パターンの選択を1つずらします。送りボタンは次の選択肢に戻しボタンは前の選択肢に。
『Rel変更に使う』関連性の選択肢を1つずらします。br />『Gradual/PWM切替に使う』戻しボタンでGradual制御の一斉反転切替、送りボタンでPWM制御の一斉反転切替です。
なお、送り戻しボタンというのは音楽機器のリモコンで◀◀とか▶▶とかのことを指していまして、他にメディアキーの送り戻しキーやジョイパッドのLRボタンなどでも動くようにしています。

モーター稼働積算計

上記『Switches』で有効にしていますと、お仕事アイコンが緑か赤になっており、そのアイコンをタップすることで以下の画面を表示できます。

モーターへの出力指示は0〜100で行われます。これをどのくらいの時間出力指示したかを掛け合わせてカウントしています。
時間の単位は100msで1。1秒で10です。後述しますが、選択したパターンによりそのパターンで設定されている重み付け値も掛け合わせます。
想定している用途は充電必要性の目安です。
毎回充電しているという方には全く不要な機能かと思いますが、筆者は充電間隔が結構が空くので充電を忘れてオナニー中にバッテリーが切れるなんていう失敗をしていたので設けた機能です。
カウントは接続枠毎に積算しています。デバイス毎ではありませんので、同じデバイスでカウントを監視したい場合は接続する枠をいつも同じ枠にするようにしてください。
特にU.F.O. TWなんかはデバイスの固定が難しい(どっちが親機になるか不確定なので)と思いますし、どのみち目安程度にしかならないことにご留意ください。

接続枠ごとに現在のカウント値とカウント値を0に戻すリセットボタン、一番右には『注意値』とありますが、ここにアラートを出す基準値を書き込めます。
一つでもこの注意値を超えている枠があればアラートが発生しメイン画面のアイコンが赤くなります。

注意値を0としている枠ではアラート判定を行いません。
充電したらリセットボタンを押すなどしてご活用ください。

リセットボタンを間違って押してゼロにしてしまった場合、そのままもう一度リセットボタンをタップしてください。元の値に戻ります。ただし、ゼロにした状態でこの画面を終えてしまうとゼロで記憶してしまうので復帰できません。ご注意を。

メイン画面

右の『Connect』ボタンをタップするとグッズとの接続処理を開始し、『(none)』となっている所と共に、現在の接続処理の状況や接続がされた場合にはそのデバイス名称が表示されるようになります。
この接続処理は処理混乱の元になりやすいので、複数のグッズを一遍に接続しようとせずに一つ一つ確実に行ってください。また、アプリでも接続処理自体は同時に一つのみ行うようにはしています。

接続処理中は『Scanning…』と表示されます。処理を中断したいときは『Cancel』ボタン(さっきまで『Connect』と表示されていた同じボタンです)をタップしてください。
また、接続処理中では他の接続枠で処理が輻輳しないように、

こんな風に『Connect』ボタンを押せなくしています。

接続が無事できますと、

接続できたデバイス名が表示され『Connect』だったボタンは『DisConn』ボタンに変わっています。意図して接続を切りたい場合はこの『DisConn』ボタンをタップしてください。

左に『TW』とあるのはU.F.O. TW及びその類似グッズがある場合はそれ限定です。
逆に『1)』〜『4)』の枠ではU.F.O. TWを検知しません。その他のグッズの接続枠です。
処理に違いが多いため、接続枠そのものを分けています。ご注意を!

接続状況とデバイス名称の行の下には、

回転方向限定トグルボタンと制御パターン選択スピナーがあります。
左のボタンはタップするたびに『←−』『⇄±』『→+』と切り替わります。これはU.F.O.等の回転系は右回転左回転があるので制御値にも±があるのですが、単純なロータ―とかですとマイナス値に反応しなかったりする場合があります。その場合に制御値の限定をすることで動く範囲の値のみでコントロールするようになります。
U.F.O系でも右回転だけにしたいなんていう場合に『→+』にするなど制御できます。
逆に上手く動かないグッズはここを切り替えて反応を探ってみてください。(大抵は『→+』だと思うんですけどね。)
『→+』にしか対応していないグッズに対して『←−』設定していたら一切動きませんし、『⇄±』設定していたら半分くらい動かないことになりますので、ご注意を!

制御パターンを選択できるところではそのグッズに合ったパターンを選択してください。
後述しますが、自分でパターンを作成し設定することも可能です。
制限はしていないのでどのグッズでも全てのパターンを選択できるようになっていますが、例えばA10サイクロンSA +PLUS(プラス)U.F.O. TW向けのパターンを選択したりすると、全体的に動きが弱過ぎて不満が出るかと思います。

『TW』接続枠だけはこの行が2つ並んでいます。左右で別々に方向制限や違うパターン選択が出来るようになっています。
例えば、左は左回転のみ、右は右回転のみみたいな制限をすることも可能です。

『Rel』という行はU.F.O. SAを2台など同じ種類のグッズを複数接続したときのみ機能します。U.F.O. TWは1台で左右ありますのでそれも複数接続とみなします。
これは関連のあるグッズ同士で制御を連携させるかどうかを指定出来るものです。
選択肢として以下があります。

『Random』 以下のUnrelated、Mirror、Syncを適宜切り替える
『Unrelated』 無関係に動く
『Mirror』 反転して動く
『Sync』 同期して動く
『Flip』 Mirror、Syncを適宜切り替える

Mirror、Sync、Flipの場合は上の枠に設定した制御パターンに追従しますので実質下の枠の制御パターンは無効化されます。
なお、同種のグッズが3台以上ある場合は同種のグッズの一番上の枠の制御パターンに追従します。(同種3台以上なんて接続しないと思うけど)

ちなみに同種グッズとしているのは筆者みたいにU.F.O. SAを片乳ずつ計2台接続して動かすことを意識したものでして、別種グッズに反応させないようにしたのは別グッズでは出力のスイートスポットが違うので弱過ぎたり強過ぎたりしてしまうので同調する意味が無いと判断しました。

左の列がVolumeです。『0』で止まります。
なお、キーボードやテンキーの『0』『1』『2』『3』でもダイレクトにVolumeを変更できるようにしています。
ちなみに画面消灯時はキーボード等押すとまずは一旦画面が点灯するようです。画面点灯時のキーボード押下で反応するみたいです。

真ん中の列の上3つはそれぞれのVolumeを選択したときにGradual制御をするかどうかを示すオンオフ切替ボタンです。
Gradual制御と言うのは、いきなり出力を変更するのではなくて、目的の出力までじりじりと時間を掛けて変化させて行く制御のことです。
いきなり速くなったり止まったりするのではなくて、だんだん速くなったりだんだんゆっくりになったりします。
このGradual制御をオンにしたからと言って、全ての遷移がゆっくりになるわけではありません。そこは制御パターンのセッティング次第です。
ですが、オフにすると一切Gradual制御は行わなくなりますので、出力の変化は全て唐突に行われるようになります。

右の列の上3つはそれぞれのVolumeを選択したときにPWM制御をするかどうかを示すオンオフ切替ボタンです。
PWM制御と言うのは、小刻みに動かしたり止めたりを繰り返す制御でして、トトトトトっとメリハリの効いた動きをさせたいときにオンにしてください。
こちらもオンにしたからと言って全ての出力が小刻みにされるわけではなく、刻み方も含めて制御パターンの設定次第です。
そして、オフにすると一切そのVolumeではPWM制御をしなくなります(一定出力になります)。

真ん中の列の下のボタンは『Always』と『LCD』を切り替えるトグルボタンです。
『Always』では常にVolume設定が反映されます。つまりVolume0以外にすると動きます。
『LCD』にしていると画面点灯時には動きません。画面を消灯したときにVolume0以外だと動くようになります。
これはこのアプリが長時間使用されることを想定してバッテリーに配慮した機能です。

右の列の下のボタンは『VolOnly』。このボタンをタップすると画面のほぼ全てがVolumeボタンのみとなります。

このアプリではAndroid機本体のVolumeボタンや近接センサー、音楽再生用のメディアキーやキーボード、ジョイパッドなどVolumeを変更できる手段を多数用意していますが、画面をリモコンのようにして使いたいという場合にこちらをご使用ください。
元に戻すときはAndroid機本体のバック(戻る)ボタンか、画面左上のアプリアイコンの辺りをタップしてください。
なお、メディアキーのイジェクトやクローズ、キーボードの[BackSpace]キー[Delete]キー[Break]キーなどでもバックボタン同様に機能するようにしています。

なお、タップは一度にしてください。それ以上タップするとアプリそのものが終了します。メディアキーやキーボードでも同様です。

逆に、このアプリは画面消灯しても動き続けるためにForegroudServiceという形態を取っていてWakeLockを掛けています。
このアプリの使用を終えるときはきちんとAndroid機本体のバック(戻る)ボタンか、画面左上のアプリアイコンの辺りをタップして当アプリを終了させてください。
でないと無駄にバッテリーを消耗し続けることになります。
このアプリが起動しているときは通知アイコンを出してますので、通知にこのアプリが残っているときはまだこのアプリが終了出来ていないことになりますので、ご注意ください。

こんな風に通知アイコンが出ているときはUfoCtrlアプリが起動したままです。

通知の内容はこんな感じです。

必要な権限

基本操作は以上になりますが、BLE機器を接続するときには相応の権限が必要となりますので、許可が必要だったり、そもそもBLEをオフにしている場合はオンにしないと接続できません。
この辺りはAndroidOSのバージョンや機種によって異なりますが、とりあえずアプリの方で出来る限り必要な権限はオンにしてもらうように表示を出したりしています。
基本的にはこのアプリから切り替わって表示される権限や機能はオンにしないと接続できないものと思ってください。
また、全ての機種に対して完璧な対処が出来ているわけではないので、出てきた画面全てで許可したりオンにしたりしたのにグッズ接続が出来ないなんてケースも発生し得えます。

この辺りは詳しく説明すると長大になりますが、過去記事『UfoSaCtrlTrip Ver4.00 U.F.O. SA TW A10サイクロンSA (+PLUS プラス) バッハスマート ROCKET+1D ランダムコントロールアプリ』に『大変更点(権限周りの整理)』というその長大な説明がありますので、そちらをご参照ください。
特にAndroid6〜11では「何でこんな権限が必要なんだよ!?」って思うような不可解な権限を要求されるかもしれませんが、その権限を許可しないと接続できないようにAndroidOS側がしているせいなのでAndroidOSを恨んでください。

Settings

上記までの説明で快適に利用できるという方はここを読む必要はありません。
このアプリは自由度の高い設定変更が出来るようになっていますが、自由度が高い分難解だったりします。
それでも、より自分に合った制御パターンを作成したいとか、規定で設定している接続対象機器以外のグッズを接続して制御したいなど、よりディープな要求が発生したときにこちらを弄ってみてください。
あ、ディープじゃないけどVolumeボタンの高さの変更もできますので、規定のボタン類の大きさに不満の有る方もこちらへどうぞ。

まず先にそのVolumeボタン高さ変更だけ軽く触れておきますね。

画面右上のメニューの『︙』をタップしますと、『Settings』というメニューがありますので、そこをタップしてください。

どーんっと文字列が表示されまして、設定は全てこの文字列で指定しています。
機種によっては反応が鈍くなったりするかもしれないので、全文コピーして他のエディタとかで編集して戻したりしても良いかもしれません。

#SwitchHeightWeight:int or float(0~): Volume等下部ボタンの画面高さを指定(1で接続表示部の行と同じ高さ)
1

というところを探してください。真ん中よりやや下にあります。
長ったらしい文字列はただの説明でして、肝心なのはその下の行の『1』。
ここの数字を変えることでVolumeボタンの高さが変わります。
『1』というのはVolumeボタン以外の行と同じ高さであることを示しています。
これを例えば『1.5』にしてメイン画面に戻ってみますと。

と、他の行に対してVolumeボタンの行が一律1.5倍の高さを持って表示されるようになります。
ここで気を付けていただきたいのは、設定の数値は全て半角(幅が狭い数字)で記載するようにお願いします。


従来のUfoTwCtrlやUfoSaCtrlTripと同様に『Settings』画面のメニューにはこのアプリ内で設定を記憶出来るスロットを3つ用意しております。
『Save』で現在の設定文字列がセーブされ、『Load』でセーブされている設定文字列を設定画面に反映させます。
従来と違うのは簡易なエラーチェックをこちらの『Settings』画面からメイン画面に戻ろうとするときに行うようにしていて、そこでエラーチェックに引っ掛かった場合はメイン画面に戻れません。
どうにもエラーが解消出来なくて困ったりしたらメニューから『RecoveryBasicData』のタップしてこのアプリに予め設定されている既定値に戻してください。
なお、エラーチェックはあくまでも簡易ですので、エラーチェックは抜けるがアプリそのものが落ちてしまうような設定を意図的に書くことも可能となってしまっています。
正しく記述していただく前提の『Settings』ですので、宜しくお願い致します。

コメントの書き方が変わりました。行頭に半角の『#』を書くとその行をコメントと見なします。行頭しか反応しません。スペースとかが行頭に入っていてもコメント扱いにはならないのでご注意ください。
基本的にコメントはいくらでも自由に書いて構わないのですが、可変長になる設定がありまして、その終わりを示すコメントが3つ、必ず必要になります。

#RandomEnd
#ConnectConfigEnd
#DataEnd

の3つのコメント行です。
この後ろにさらに文字を書いても良いですが、上記のコメント行は必ず記載しなくてはなりません。無いとアプリがデータを正しく解釈できません。(最後の『#DataEnd』は無くても大丈夫だけど、多分。)

設定は大きく分けて上から順に、ランダムパターンの設定(いくつでも書ける)、その他の設定(行固定)、機器接続設定(いくつでも書ける)、任意固定パターンの設定(いくつでも書ける)、と4つのブロックに分かれます。

ここから実際にこのアプリで既定値としているデータを見ながら個々に解説していきます。

ランダムパターン設定

#Random
Random(U.F.O. TW)

最初の行にはそのパターンの名称のみを書きます。ここは全角文字が入っても大丈夫なはず。

#Start,Stop,Displacement Threshold: int(0~100): Gradual動作開始時,減速時,似たようなPowerを続けないための最低変化量, CounterWeight: int(0〜): モーター稼働積算計に加算するときの乗数
1,1,5,1

カンマ区切りで4つ整数値を書きます。
Start Thresholdは動き始めの出力値が小さい場合に動き出せないグッズがあるため、最低でもここに書いた数値から始めますよ、という値です。U.F.O. TWは低速でも動くので「1」としていますが、U.F.O. SAではヘタってたりすると「12」くらいないと動き出してくれなかったりします。
Stop Thresholdは逆に動いている状態から減速していくときにどこまで粘るかです。動き出しよりかは減速していく方が低い数値でも動いてくれるのですが、グッズによってはそれでもまだゼロになってないのに止まってしまうケースがあり動いているつもりで実際の停止時間が長くなってしまうためこの値より下がる場合は即ゼロにして停止させて次の動作に移ります。こちらもU.F.O. TWは「1」でも動きますがU.F.O. SAは止まってしまうので「5」とかにしています。
Displacement Thresholdはランダム制御をしていると、本当にランダムだとたまたま同じような動きが延々と続いてしまうこともあり得るわけなんですが、それは嫌だということで、少なくともこれだけ出力の差が起こるようにする、という閾値です。「5」くらい変わればまあ変わったことが分かるかな。
CounterWeightはモーター稼働積算計のカウンターを加算するときにここの値を重み付けとして掛けて足し込みます。筆者はU.F.O. SAのコントローラーにU.F.O.のカップ以外の負荷の軽いロータ―などを接続して使うこともあるため、重み付けを変えないと充電の目安にならなかったのでこの設定値を設けています。

#Vol.1 PowerPattern: int(0~100): 要素数は自由(ランダムに選ばれる)
0,1,5,10,15,20,25
#Vol.2 PowerPattern: int(0~100): 要素数はVol.1と合わせる(ランダムに選ばれる)
0,7,14,21,28,35,42
#Vol.3 PowerPattern: int(0~100): 要素数はVol.1と合わせる(ランダムに選ばれる)
20,25,30,35,40,45,50

各Volumeごとに出力値のバリエーションをカンマ区切りの整数値で書きます。ゼロが停止です。負の値は書く必要ありません。
上の例では各7つの数値を書いていますが、ここの数は自由です。ただし、各Volumeとも同じ個数の数値を書いてください。
また、同じ数値を複数書くことで選択される確率を変化させることも出来ます。が、上記にあるように同じ数値が続かないようにするロジックも入っていますので、あまり同じ数値ばかり書いても効果は上がりません。
『Volume1』が弱くて『Volume3』が強いイメージがあるのでVolumeが上がるに従って大きな数字を記載していますが、別にどう設定しても良いです。3種類のVolume設定が出来るし必ず3種類分の定義が必要だとお考えください。

#TimePattern: int(1~): 要素数は自由(ランダムに選ばれる) 単位100msec
10,16,22,28,34,40,46,52

上記で選ばれた出力値をどれだけ続けるかを整数値で書きます。いくつ書いても構いません。確率を上げるために同じ数値を複数書いても良いです。
Gradual制御中は関係なく、目的の出力値に到達してからの維持する時間を表しています。

#TimeIndexRange: int(1~): 要素数はPowerPatternと合わせる 各数値はTimePattern要素数以内とする "1-"省略化
1-5,1-8,1-6,1-8,1-8,1-6,1-4

例えば停止時間はあまり長くしたくないとか、強い出力が長く続くのはしんどい等、全ての出力値で同じ時間継続するのには不都合がある場合、ここでそれを制限できます。
書ける値は1〜TimePatternに書いた要素数まで。この例ではTimePatternを8つ書いているので1〜8の数値を書けます。
TimePatternを選択する範囲を『3-5』みたいに書きます。この例ではTimePatternは『22,28,34』からランダムに選択されるようになります。
これを各Volumeに書いた数だけ書いてください。各のVolumeの要素と対になっています。
この例ですとVol.1の『0』、Vol.2の『0』、Vol.3の『20』(1番目の要素)が選択されているときには『1-5』の記述に従ってTimePatternの1〜5番目となる『10,16,22,28,34』からランダム選択され、『40,46,52』はこの出力のときには使用されない、ということになります。

『1-5』などで『1-』の部分は省略して『5』と書いても同じように動きます。また『5-1』と逆に書いても同じように動きます。

#GradualPattern: int(0,1〜){/int(1〜)}: 要素数は自由。Power変化値/時間(単位100msec)の分数型で記載。時間が1のときは分母省略可能。約分せず。0はGradualさせない(確率を変えるために複数使用)
0,0,0,0,1,3/2,2,3,1/2,3/4,1/3,2/3

目的の出力値にじわじわと近付けて行く制御を当アプリではGradual制御と呼んでいますがその設定です。
『0』はGradual制御を行わずに即目的の出力値にする場合に書きます。
変化の勾配を整数値、もしくは整数値同士の分数で書くことが可能です。
『1』で100ms当たり出力値を1ずつ目的の値に近付けていきます。『2』では100ms当たり2ずつ。
逆に『1/2』とすると200ms当たり1ずつ変化させます。
ここで分数は約分しません。『2/3』は300msごとに2変化させますが、『4/6』は600msごとに4変化。つまり、『4/6』では300ms時点では変化が起こりません。
確率を大きくするために同じ値を何度書いても良いです。

#PWMPattern: int(0,2〜){/int(2〜)/int(0〜)}: 要素数は自由。On時間(単位100msec)/Off時間(単位100msec)/OnのときPowerを何%に増(減)速するか(増減させないとき/100を省略可)。約分せず。0はPWMさせない(確率を変えるために複数使用)
0,0,0,0,0,2/2/175,4/2/150,2/4/200,4/4/125,4/8/175

小刻みにオンとオフを繰り返して回転や振動に大きな変化を産む制御を当アプリではPWM制御と呼んでいますがその設定です。
目的の出力値は上記PowerPatternで、その持続時間はTimePatternから選出されますが、その持続時間の間、ここの設定に従ってオンオフを繰り返します。
『0』はPWM制御を行わず出力を一定に保ちます。
『/』区切りで3つ整数値を書く必要があり、Onを続ける時間 / Offを続ける時間 / 出力の倍率。時間は100msで1、出力の倍率はパーセントで書いてください。
例えば『4/8/175』ですと400msオンにして800msオフを持続時間中繰り返す。ただし、オンのときの出力値は本来の値の175%に増幅する、となります。
出力値を増減させない場合、つまり『/100』と書く場合にはこの『/100』は省略可能です。
こちらも確率を大きくするために同じ値を何度書いても良いです。

現実問題としてグッズの制御は200msを下回る間隔で頻繁に書き込み通信していると制御不能に陥る危険性が高まるため、このアプリでは標準制御間隔を200msに設定しています。(この設定も変更できます)ので、そのままですとオンオフの時間に『1』を書く意味がありませんので最低値を『2』として書いています。
ただ単にオンオフするだけですと、一定の出力を続けているよりも単純にオフになる時間が増えるだけで刺激が激減します。また、制御としては頻繁にオンオフを繰り返しますがグッズの動きが完全に追従する前にオフにしてしまう可能性もあるため、増幅パラメータを用意して、出力値を予め高くしてオンオフすることが出来るようにしています。
ここの増幅の結果が本来の制御値の範疇である100を超えてしまっても大丈夫なようにアプリは作っていますので、PowerPatternの値を気にせずに増幅値を決めてもらって構いません。ただ溢れた分は全部最大出力の100になりますので、そればっかりになったらつまらないのでご注意を。

Gradual制御とPWM制御との兼ね合いがどんな感じになるか説明しますと、例えば停止状態からPower40に向けてGradual制御が2/4、PWM制御が2/2/175となっている場合、
まず最初にStart Thresholdの値から始めます。例として12から始めるとしましょうか。そこから400ms経過するごとに2ずつ出力を増加して5.6秒後に目的の出力40に到達。そこでPWM制御のパラメタに従って175%に増幅した出力70で200ms動かして200ms停止するというオンオフ動作を繰り返す。
という動きになります。

これでランダムパターンの設定値ひとかたまりです。
この書き順を遵守してくれればコメント行も含めて幾つパターンを書いても構いません。
ただし、設定の終わりが判別できないので、ランダムパターンの設定が終わりましたらコメント行

#RandomEnd

を挿入してください。

その他の設定

続きまして。

#MinimumInterval: int(1〜): 最小通信時間間隔。通信取りこぼしが発生する場合は数値を大きめに取ってみてください。 単位100msec
2

ここがその制御間隔の設定場所、規定では『2』つまり200msに設定しています。
もしかしたら新しい機種ではその辺りの追従性が良くなって『1』つまり100msにしても綺麗に動くのかもしれませんが、筆者が未だにメインで使用しているU.F.O. SAでは100msだと頻繁にキャッシュオーバーでパケ詰まりみたいな症状を起こしてしばらく無反応に陥ってから復旧を繰り返すので200msの方が安定しています。と言いますか、200msにしていても毎回通信しているとキャッシュオーバーして無反応状態になりますので、適度に間隔空けてあげるのは大事です。
一応、このアプリでは本当に通信が必要になるときしか通信していないつもりではありますが、……
ちなみに逆に『3』とか遅くして行くとPWM制御等でオンオフ間隔が空くのでそれはそれでつまらなくなると思います。
大きな問題が無い限りは『2』のままにしておくのが無難です。

#RelationChangePhases min,max: int(1~): Rel設定でRandom,Flipを選択している際に、Sync,Mirror,Unrelatedを切り替えるまでにいくつのパターンを消化するか、の最小値最大値を指定
3,7

これは同じ種類のグッズを複数接続しているときにその関連性『Rel』のパターンを「Random」か「Flip」にしている場合、頻繁に関連を切り替えているとそれは全くのランダムと変わらない、もしくは規則正しいMirrorとSyncの繰り返しというのもつまらないものですので、何回か同じ関連性を続けてから切り替えるようにしています。ここはその最小継続数と最大継続数を書く場所です。

#SwitchHeightWeight:int or float(0~): Volume等下部ボタンの画面高さを指定(1で接続表示部の行と同じ高さ)
1

これは既に上記で説明しました。

接続デバイスパラメタ設定

#ConnectConfig: デバイス名パターン正規表現,制御書き込み対象Characteristicパターン正規表現,書き込み値/区切りで3バイト固定(int)制御値入る所をnに(TWのみ2箇所n)
(?i)ufo.?tw.*,.*2222.*,5/n/n
(?i)ufo.?sa.*,.*2222.*,2/1/n
(?i)cyc.?sa.*,.*2222.*,1/1/n
(?i)bach.?smart.*,.*2222.*,6/3/n
(?i).*rocket.*,.*2222.*,7/3/n

ここは筆者のUfoCtrlシリーズで初搭載となります目玉設定。
接続するデバイスのパラメータをここに記載することで、今まで対象外だった機器もコントロール出来るかもしれない、という設定項目です。

制御できるかもしれない条件その1。Bluetoothデバイス名を持っていること。
このアプリは接続対象のグッズをそのデバイス名で判定しています。条件を正規表現で記載してください。
カンマ区切りで次のパラメータを書くので正規表現にはカンマ『,』を含めないようにしてください。エスケープするなり『.+』などで誤魔化してください。
上記の例ですと『(?i)ufo.?tw.*』は『(?i)』で英大文字小文字を区別しない、ufoとtwの間にある『.?』は何か1文字入るかもしれないし入らないかもしれない、最後の『.*』はどんな文字が何文字あっても無くても良い、という条件です。
実際、U.F.O. TWは左右のカップが連携するときに片方のデバイス名が『UFO TW』となりもう一方が『UFO-TW』となります。このアプリがどちらと接続するかはそのとき次第で変わります。(まあ、『.?』は『.{1}』とかでも良いのかもしれませんが)
他のデバイスで条件を緩めに書いていることにあまり意味はありません。ただ、ROCKETだけはROCKET2
ROCKET2
の存在があるので役に立つ可能性もあるかも?
条件を緩く書き過ぎて複数の条件に合致したりしないように気を付けてください。本来当て嵌まって欲しくない方の条件でマッチしてしまうと、異なるデバイス用の設定で動かそうとしてしまいますので、当然のことながら全く動かないと思います。

制御できるかもしれない条件その2。制御書き込み対象のCharacteristicが一つに絞り込めること。
これはBLE機器の解析が出来るアプリなどを使用して探してみてください。例えばU.F.O. SAですと、

一個だけ青地に白抜きで『W』というマークが付いているCharacteristicがありますよね。
ここがアプリからグッズに対してBLE通信にて制御値を書き込める所となっており、このアプリはこのCharacteristicに向かって随時書き込みをすることでグッズの動作制御をしているわけです。
そのUUIDだけを絞り込めるような条件を正規表現で記載してください。
今まで動作対象としてきたグッズは一様に『2222』という文字列を含んでいるUUIDが書き込めるCharacteristicになっていたため、現在の設定でも『.*2222.*』つまり『2222』を含んでいれば前後は何でも良いという条件にしています。
余談ですがU.F.O. TWはこれ以外にも書き込みできるCharacteristicが見つかったりして混乱するのですが、U.F.O. TWの場合はU.F.O. TW同士でも通信し合うため、U.F.O. TW同士専用の書き込みCharacteristicを持っています。
外部からは『.*2222.*』のCharacteristicで受け付けて、その内容をもう一方のU.F.O. TWにも転送する、みたいなイメージです。なので、U.F.O. TWとアプリの接続は片方としか行ってなくて、両方分の制御値をその接続した片方に一遍に書き込んで制御してるんですよ。

制御できるかもしれない条件その3。書き込める制御値が1つか2つで必ず合計3バイト。制御値の範囲は-100〜0〜+100、もしくはロータ―みたいに回転方向が無いものは0〜100。ただしバイト表現としては正の値はそのままですが負の値は-0が0x80で-100が0xE4という若干変則的な値で書き込みますのでその値で動作すること。
そして書き込む3バイトの値を『/』区切りで十進数で記述してください。
数値が書いてあるところは常にその数値固定です。制御値を書き込むところ(値を変動させるところ)には『n』と書いてください。
通常のグッズでは制御値は1つだけですので『n』と書くところは1箇所だけになるはずです。
U.F.O. TWだけは例外で1つの接続で左右両カップ向けの制御値を書き込むため『n』が2箇所になります。

いやいや固定の数値とか知らんし。そうですよね。上の画像のようなBLE機器の解析が出来るアプリでは書き込みも出来たりしますので、実際に動く数値を何パターンも打ち込んで探し出してください。筆者もほとんど自力で探し出しています。(一部情報提供をいただきました)

このアプリでは『n』を2つ書いているデバイスについては画面一番上の「TW」の枠を使って接続及び制御を行うこととします。
もし、U.F.O. TW以外にもU.F.O. TWと似たような制御が出来るグッズがあれば、ここにその接続パラメタを追記して「TW」の枠を使って接続及び制御が出来るかもしれません。
『n』が1つの場合には「1)」から「4)」の枠を使って接続及び制御を行います。
同じ接続パラメタで接続したグッズは同種と見なされ「Rel」行(暗い青色の行)の関連設定が生きてきますのでそのおつもりで。
なので、特にデバイス名の正規表現のところは2つ以上マッチしたりしないように条件の記載にはお気を付けください。
例えば楽して『(?i)ufo.*』とかにしてしまうとU.F.O. TWもU.F.O. SAもマッチしてしまいますので接続が不確実になります。

ここの設定もいくつでも書けるため、書き終えたらコメント行

#ConnectConfigEnd

を挿入してください。

固定パターン設定

最後に任意の固定パターンを定義することができます。
固定パターンは最後まで消化したら先頭に戻って繰り返し続けるように動きます。

#Custom1 Vol.1: 先頭行にパターン名称、2行目にStart,Stop,Displacement Threshold,CounterWeight、3行目以降にパターンをPower,Time,Gradual,PWMで記述。行数自由。ここからはコメント行がデータの区切りとして扱われます。1パターンにつき3ボリューム分のデータが必要です。
Demo
12,5,4,3
42,15,0,0
0,15,0,0
42,10,2,2/2/175
-42,10,2,2/2/50
0,10,1/2,0
#Custom1 Vol.2
42,30,0,0
0,10,0,0
42,32,0,2/2
0,10,0,0
42,32,0,6/2
0,10,0,0
42,32,0,2/6
0,10,0,0
#Custom1 Vol.3
42,32,2,4/4/175
-42,32,1/2,2/6/50
-12,6,5,0
-24,50,1/3,8/2/100

固定パターンは最初の行にパターン名称のみ(全角文字も可)を記載し、次の行はランダムパターンのときと同様にStart,Stop,Displacement Threshold,CounterWeightを記載します。
3行目からはVolume1のパターンを1つの動作につき1行で書きます。何行でも書けます。終わりが分からなくなるのでコメント行(行の先頭に『#』)が現れるまでそのVolumeのパターン定義が続きます。
逆に言うと、固定パターンの記述ではコメント行は自由に書けません。必ずVolumeの区切りやパターンの区切りとしてコメント行は使用されますので、例えばコメント行を2行続けて書いてしまったりするとVolume2の定義が無くてVolume3の定義に飛んでしまうみたいなことが起こりますのでご注意を。

固定パターンですので、各行にはカンマ区切りで出力値(Power -100〜100)ランダムと違って回転方向も決め打つ必要があるので負の値も必要であれば記載してください。負の値を書いていても画面の方で回転方向を『→+』に限定していたりする場合はアプリの方で反転させますのでご安心を。
続いて、その出力値の持続時間(Time)を100ms単位で。
続いて、その出力値に至るまでGradual制御をさせたい場合はランダムパターンのときと同じように値を書いてください。Gradual制御せずにすぐにその出力値にする場合は『0』としてください。

最後にPWM制御の記載なのですが、従来のUfoSaCtrlTripやUfoTwCtrlでは固定パターンでは増幅値を書かない(100固定)としていたのですが、書いても良いことにしました。
と言うのは、増幅値100以外の数値を許容することで動き方の幅が広がるからです。
ただ、下位互換性を考慮して今までみたいに増幅値を書かない書き方でも許容します。省略した場合は増幅値は100、つまり増減させないと見なします。

増幅値を書けるようになったメリットとして例えばですね、出力100を指定してGradual制御でじりじり100に近付けておきながらPWM制御で増幅値に50を指定して出力50でオンオフを繰り返すみたいなトリッキーなパターンも作れたりします。

パターン名称、Threshold、Volume1のパターン×n、区切りのコメント行、Volume2のパターン×n、区切りのコメント行、Volume3のパターン×n、区切りのコメント行、で一つの固定パターンの塊を形成します。
各Volumeに書いたパターンを全て消化しますとまた一番上に書いたパターンから繰り返します。Volumeごとに書く行数を合わせる必要はありません。

その固定パターンもいくつも書けるので、最後の固定パターンのVolume3の定義が終わりましたら、その後のコメント行は

#DataEnd

と記述して設定データそのものがこれで完全に終了したということを明確にしてください。

以上で設定データは終了です。
このアプリに慣れて来たら是非自分好みのパターンを発掘すべく、設定変更にチャレンジしてみてください。
エラーチェック等ゆるゆるですので、受け付けられない設定でも読み込んでしまうことがあり、異常終了してしまうかもしれません。ご了承ください。

なお、参考までに、筆者はA10サイクロンSAやバッハスマートなど所持しておらず、逆にU.F.O. SAには自作のグッズを接続したりしますので個人用に設定を持っています。また、固定パターンも使用しないので端折ってます。
コメントを極限まで減らした状態でここに載せておきますね。

Random SA
12,5,4,3
0,5,9,13,17,21,25
0,10,15,20,25,30,35
14,20,26,32,38,44,50
10,16,22,28,34,40,46,52
1-5,1-8,1-6,1-8,1-8,1-6,1-4
0,0,0,0,1,3/2,2,3,1/2,3/4,1/3,2/3
0,0,0,0,0,2/2/175,4/2/150,2/4/200,4/4/125,4/8/175
Random MicroRtr
4,4,4,2
0,4,8,12,16,20,24
0,6,12,18,24,30,36
10,17,24,31,38,45,50
10,16,22,28,34,40,46,52
1-5,1-8,1-8,1-7,1-6,1-5,1-4
0,0,0,0,1,3/2,2,3,4,5
0,0,2/2/175,4/2/150,2/4/200,4/4/125,2/6/200,6/2/100
Random ClipRtr
5,5,5,1
0,10,20,30,40,50,60
0,15,30,45,60,75,90
40,50,60,70,80,90,100
10,16,22,28,34,40,46,52
1-5,1-8,1-8,1-7,1-6,1-5,1-4
0,0,0,0,1,3/2,2,3,4,5
0,0,2/2/175,4/2/150,2/4/200,4/4/125,2/6/200,6/2/100
Random TabletRtr
5,5,5,1
0,20,40,60,80,90,100
0,40,55,70,80,90,100
40,50,60,70,80,90,100
10,16,22,28,34,40,46,52
1-5,1-8,1-6,1-8,1-8,1-6,1-4
0,0,0,0,1,3/2,2,3,1/2,3/4,1/3,2/3
0,2/2/100,4/2/100,2/4/100,4/4/100,4/8/100
Random ROCKET+1D
20,15,5,1
0,20,25,30,35,40,45
0,20,28,36,44,52,60
50,58,66,74,82,90,100
10,16,22,28,34,40,46,52
1-5,1-8,1-6,1-8,1-8,1-6,1-4
0,0,0,0,1,3/2,2,3,1/2,3/4,1/3,2/3
0,0,0,0,0,2/2/175,4/2/150,2/4/200,4/4/125,4/8/175
Random TW
1,1,5,1
0,1,5,10,15,20,25
0,7,14,21,28,35,42
20,25,30,35,40,45,50
10,16,22,28,34,40,46,52
1-5,1-8,1-6,1-8,1-8,1-6,1-4
0,0,0,0,1,3/2,2,3,1/2,3/4,1/3,2/3
0,0,0,0,0,2/2/175,4/2/150,2/4/200,4/4/125,4/8/175
LowRandom TW
1,1,4,1
0,1,3,5,7,9,11
0,1,4,7,10,13,16
4,8,12,16,20,24,28
10,16,22,28,34,40,46,52
1-5,1-8,1-6,1-8,1-8,1-6,1-4
0,0,0,0,1,3/2,2,3,1/2,3/4,1/3,2/3
0,0,0,0,0,2/2/175,4/2/150,2/4/200,4/4/125,4/8/175
#RandomEnd
2
3,7
1
(?i)ufo.?tw.*,.*2222.*,5/n/n
(?i)ufo.?sa.*,.*2222.*,2/1/n
(?i)cyc.?sa.*,.*2222.*,1/1/n
(?i)bach.?smart.*,.*2222.*,6/3/n
(?i).*rocket.*,.*2222.*,7/3/n
#ConnectConfigEnd
#DataEnd

その他免責事項など

このアプリはメディアリモコンやキーボードやジョイパッドなどでもある程度操作できるようにしていますが、これらの機器がBluetooth機器である場合、当アプリを起動中に他のBluetooth機器を接続したりすると当アプリが強制終了されてしまう場合が多々あります。
これは回避手段を筆者が知らず現状対処不可能です。アプリを再起動していただくか、当アプリの操作に使用したいBluetooth機器は先に接続を済ませてから当アプリの起動をするようにお願い致します。
また、Android4.xでは画面消灯時にメディアリモコンキーに反応しません。これはAndroidOSによる制限です。(5から対応)

どうしても思った通りの動きにならない場合、あまりに頻繁な通信を連続して行っているせいでグッズ側が反応しきれず一時的に無反応に陥っている可能性を考えてください。実を言うとGradual制御やPWM制御は頻繁な通信が連続するためグッズ側が一時的に無応答に陥って処理がズレ込んだりすっ飛んだりしていることがままあります。
また例えば2台を同期取るように制御していたとしても、プログラムとしては同時処理が出来ているわけではなく逐次処理で通信しているため、例えば筆者手持ちのOukitel U22というSoCにMT6580を搭載しているローエンドスマホなんかですと、2台分処理している間に平均して5ms〜7msくらいの時差が発生します。

頑張って作りましたが、全てのケースでテストしきれているわけではありません。
正しく動作しないところがありましたらごめんなさい。
筆者が気付き次第修正してリリースしますので気長にお待ちいただくか、もしくはより正しく動作する過去のバージョンを探してそちらで我慢してください。

あと、宣言どおり約136KBと今までになくアプリサイズを縮小することに成功致しました。褒めて!
念願のUfoTwCtrlとの統合も果たせたし、最大同時接続数がさらに増えたり、接続デバイスの種類にも幅を持たせたりと機能も増やしつつアプリサイズ抑えたんだぜえ。
まあ、そのほとんどがアプリアイコンの変更によるものなんですが……(^^ゞ
元々Ufo**Ctrlシリーズのアプリアイコンは筆者のWebサイトのアイコンを流用したものだったのですが、数年前にWebサイトのアイコンをリニューアルしていたのでそれに合わせて変更しました。
より簡素な形になったのでサイズが落とせたんですよね。
もっと言うとこのアイコンすら廃止して、通知に出している「U」の真ん中に点を打った乳首アイコンで良いじゃないか、という案もあったのですが、一応筆者の著作権と個人ブランドのアイデンティティが唯一残せる場所ということでここは我侭で個人アイコンを採用させていただきました。

Androidアプリのサイズを抑えるのって結構大変なことでして、大雑把に言うと新しい技術を使うとサイズが膨れ上がるのでむしろ極力新しい技術を排除して作っているんです。
本当は技術的にはJetpackComposeとか使ってみたいしMaterialにも対応すべきなんだろうけどそんなことするとアプリサイズがあっという間に最低でもMB単位に膨れ上がります。
もっとサイズ縮小を追求する場合は、例えばAndroid4.xでの動作を切ってAndroid5.0以上とすれば、画像ファイルを用意せずにxmlだけで良くなったり、4.x専用のコードを書いている部分があったりするのでそういう部分が削れるかもしれません。が、今のところまだ4.xで使っている人も居るかもしれないので。

また今回、膨大な機能を全て網羅して説明するために細かいところを端折っています。
「なんでこんな動きや判断してるんだおかしいだろ」みたいに思われる部分があるかも知れませんが、筆者が取り逃しているバグでない限りはそれ相応の経緯や葛藤があって現在を形作っています。
それらを全て改めて記載などしていたら誰も読まなくなってしまいますので、興味が有る方は大変でしょうが筆者の過去記事を漁ってみてください。
うんざりするくらい悩んだ形跡がありますので。

ダウンロードファイル

勝手な再配布はしないでください。
また、このファイルのみへの直接リンクを貼ることもご遠慮ください。
特に、うちのサイトは弱小なので、検索で上位に表示されるサイトに勝手にコピーされると、盗まれたのとほぼ同じ状況に陥ります。
何かしらの問題が発覚して、こちらのサイトでファイルを差し替えても、それが皆さんの元には反映されなくなることにも繋がります。

諸事情によりアプリの無料配布を終了致しました。
今後は活動を支援してくださる方とのみ細細と共有していければと思います。

今後のUfoCtrlアプリ配布ページはこちらです。
UfoCtrl Ver1.00 (UfoCtrl開発活動支援プラン)

2024-07-12

この記事のタグ

U.F.O.

TW

SA

アプリ

制御

電動

自作

チクニー

開発