HoloLens用のコントローラーブックマークレット

試作版を公開します。

iPhoneのSafariでの動作はできなかったのでiPhoneではとりあえずChrome使ってください。

Solica HoloLensTools
※マルウェア検知されますね・・回避方法はまたあとで考えますが危険なコードは含まれてないです。

インストール方法:
Hololens device portalに接続し
File ExplorerによりDocumentsに
solica.hololens.js
user.hololens.js
をアップします。

スマホやPCのブラウザに
bookmarklet.txtの内容で適当な名前を付けて登録します。
スマホの場合ブックマークの名前はシンプルなものにしてください。

使い方:
接続方法
まずHololens device portalに接続します。
そのページを開いた状態で
PCならブックマークを開きます。
スマホならアドレスバーに先ほど登録したブックマーク名を入力していくと一覧に登録したものが出てくるのでそこで選んで開きます。

起動後
現在の版では下のテキストボックスに文字を入力しソフトウェアキーボードのEnterをすると送信されます。
テキストがない場合そのコードが入力されます。
例えばテキストボックスにカーソルがある状態でバックスペースなどをするとそのまま送信されます。
マウスかタッチにより
上のパネルでドラッグした方向に該当するカーソルキーが入力されます。
キー入力が確定後タッチをやめるなどの解除処理をするまで定期的に処理されます。
3本指で下に動かすとWindowsキーが入力されホーム画面が現れます。
その他詳細は
user.hololens.js
を読み、改造してください。

スクロールやジェスチャーを送信するREST APIも見つけましたが今のところ動作を確認できませんでした。
せめてクリックができればモチベが上がるのですが。

備考:httpsの上クロスサイトドメインの回避の為にブックマークレットによる実装となりました。REST APIをつついてみるのにもよさそうですね。

追記:
書き忘れていたのでですがiPhone Chromeのポップアップブロックを解除する必要もあり。
追記2:
ドラッグ(スワイプ)とフリックが排他制御入ってるせいで操作性が悪くてスクリプト作りづらいですね。
次のバージョンでは修正します。

HoloLens用にカスタマイズしたブラウザ

いろいろあって※
ファイルを直接公開してみるよ。
HoloLensを開発者モードにした後HoloLensのIPにブラウザから接続して(たぶん警告がでるけどそのまま進む)
ユーザーとパスワードを設定すると
Appsというところがあるからそこから直接パッケージインストールしてね。
ブックマークとかタブ機能ないけどクリップボードにURLあったら開けるようにしといたよ。

Scroll WebBrowser

捕捉:現在のURL補完処理概要
.がなければ.comを後ろに(手抜き過ぎる・・)
プロトコル指定がなければhttp://を
なのでtwitterだけでtwitterは開けるよ。
うまくスクロールしないときは普通にブラウザが重くて固まってるので待っててください。

※MSDN入っていると無料でWindowsストアの開発者アカウントが取得できるのに気づかず
そのアカウントで有料でWindowsストアの開発者アカウントを取得してしまう。
すると内部的におかしくなってしまったのか
認証メールがどうやっても送られてこなくソフトの公開ができない状態に
初のインシデントの有効化処理を行い。
その処理が終わったら調査してもらう予定

A-Bike electricの問題点とその解決

以下の方法は推奨するものではなくまねる方は自己責任でお願いします。

もともとA-Bikeは全シリーズ購入しており
A-Bike City
折りたたみ状態での移動は体を傾ける必要があり腰が痛くなるので取っ手MINOURA(ミノウラ) アクセサリーホルダー [SGL-300M] φ28-35mm対応 バー幅130mm シルバー
をつける事で解決し快適に使っていたのですが。

新しく購入したA-Bike electricは同様に転がすと右に曲がっていく問題がありました。
力をいれてもここまでしか曲がらずこの状態でも右に曲がります。
img_3707
これはバッテリーホルダーにペダル軸が当たるためだと判明しました。
img_3499

そこでダイソーで以下のパーツを購入し取り付けてみました。
ダイソーで購入
取り付け
これにより折りたたみ状態でまっすぐどころか左にも曲がるようになり転がすのが楽に。
最大角度

ついでにこの時期は持つ部分が冷たいのでダイソーでシールフェルトを購入
ダイソー シールフェルト

サイズはピッタリだけど下が1cmほど届かない。
ピッタリサイズ

下からもう一枚回して完成
下足りないので二重

折りたたみ時に動かすと開いてしまう問題もダイソーで
カチッとはめるとロックされるような仕組みにしたくて検討した結果
子供用ドアロックでできそう。そのなかでそれなりにまともなデザインなのはこれだけだった。
写真のはセンサーケーブルの上ですが下を通すと展開時も邪魔にならない。
折りたたみ時
展開時
接着力に問題があるのでグルーガンで貼り付けたほうがよさそう

追記:
しばらくすると斜めに落ちてしまう問題が発覚、このままでも左にずれてるので折りたたんでも直進できるのだけど
斜めになる

ダイソーで3つ穴タイプを購入しはめなおした。
3つ穴
3つ穴止める

これで落ちようがない・・はず

TypeScriptでの拡張ではまる

interface String {
format(...arr: any[]): string;
}
String.prototype.format = (...arr: any[]):string=>{
 var str=this;

この直後でブレイクしウォッチを見るとthisは文字列であるがstrはWindowオブジェクトである。

String.prototype.format = function (...arr: any[]): string{

これで解決するがデバッガの挙動が怪しくなるパターンなので気を付けないと・・

TypeScript実験

TypeScriptでジェネリッククラス内でジェネリック型の生成をうまくnew T()する事が出来なかったので。

class ObjectManage<T> {
private CreateObject: () => T;
constructor(createObject: () => T) {
this.CreateObject = createObject;
}

//以下実装省略

}

var mng= new ObjectManage(() => { return new Hoge() });

な感じでやってみたらうまくいったぽい。
ジェネリックの型を省略しても理解してくれてるのは賢いな。

※classの<T>がタグとみなされたのか消え去っていたので修正

WebCaptureソフトを更新しました 2015/8/17版

こんな感じでWPFのUIを独自に作成し
スクリプト上のオブジェクトを紐づけて呼べるように拡張しました。
出来たモジュールをAddonフォルダに入れとくと機能追加されます。

    public class ScriptUIButton : ScriptUIBase<Button>
    {
        public override string this[string key]
        {
            get
            {
                switch (key)
                {
                    case "Text":
                        {
                            if (UI.Content == null)
                                return "";
                            return UI.Content.ToString();
                        }
                }
                return "";
            }
            set
            {
                switch (key)
                {
                    case "Text":
                        UI.Content = value;
                        break;
                }
            }
        }
        public override void Init(IScriptUILib script)
        {
            UI.MinWidth = 16;
            UI.MinHeight = 16;
            UI.Foreground = System.Windows.Media.Brushes.Black;
            UI.Click += (s, e) =>
            {
                script.Excecute(this,"this.onClick()");
            };
        }
    }


var button = ScriptPanel.appendline("button", { Text: "ボタン" });
button.onClick = function () {
alert("click");
}

ScriptPanel.appendline(“button”, { Text: “ボタン” });
でbuttonとScriptUIButtonが紐づいているのは
ScriptUI*でクラス名を取得して小文字で登録してるからです。
ルール外のクラスは登録されません。

サンプルはScritUIBaseという抽象クラスからの派生となっていますが
実際のとこは以下のinterfaceを持つクラスで取得しているのでScritUIBaseからの派生である必要はないです。

    /// <summary>
    /// IScriptUIのInit時に渡される
    /// Excecuteにより対応するスクリプト側のUIオブジェクトの関数を呼び出す事ができる
    /// </summary>
    public interface IScriptUILib
    {
        string FileName { get;  }
        string Description { get;  }
        string Namespace { get;  }
        string Name { get;  }
        bool IsEnable { get; set; }
        void Excecute(IScriptUI ui,string call);
    }

    /// <summary>
    /// ScriptUI* 名でクラスを定義する
    /// 例:ScriptUIButtonならbutton名で実体化する
    /// </summary>
    public interface IScriptUI
    {
        int UIID { get; set; }
        UIElement ScriptUI { get; }
        /// <summary>
        /// UIパラメータの設定と取得ができる
        /// </summary>
        /// <param name="key">UIのパラメータ名</param>
        /// <returns>Script側のget(key)にて取得できる値</returns>
        string this[string key] { get; set; }
        /// <summary>
        /// この関数内でUIのイベント等をスクリプトと関連付ける、UIの初期値を設定する等行う
        /// UI生成後呼ばれる
        /// </summary>
        /// <param name="script">スクリプト情報 ExcecuteによりScript側の関数を実行する</param>
        void Init(IScriptUILib script);
    }

Capture機能をScriptに追加しました。
var rect=Capture.getrect();//キャプチャ位置の取得
Capture.setrect(rect);//キャプチャ位置の設定
Capture.shot();//一枚画像の取り込み
ここでrectは
{X:,Y:,W:,H:}
となります。

これらを利用したスクリプトを追加しました。
WebCapture

WebCaptureソフトを更新しました

スクリプトUIにtextが追加されました。

スクリプトUIとのやり取りが双方向になりました。
同梱スクリプトがサンプルになっています

var text = ScriptPanel.appendline("text", { Text: "" });
text.onTextChanged = function (text) {
//変更時呼ばれます
}
var button5 = ScriptPanel.appendline("button", { Text: "テキスト内容取得" });
button5.onClick = function () {
alert(text.get("Text"));
}

FileAPIを追加しました
現在以下の機能があります。
File.write(ファイル名,文字列);
File.read(ファイル名); ※なければ空文字を返します
File.list();
File.delete(ファイル名);
なおファイル名はセキュリティーの為英数字のみとなっておりファイル階層をさかのぼったりできない仕様です。

Scriptで何らかの状態を保持するのに使えるかと思います。

WebCapture

テラクラウドAPI C#アクセス

テラクラウドAPI
C#ではこんな感じでUserにアクセスできます
ライブラリとしてDynamicJsonを利用しています。
型的に緩い作りになっていますがその分追加変更があっても対応が楽ですね。
APIキーについてはこちら

※TreaCloudになっていたのでこっそり修正

ライブラリ側

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Codeplex.Data;
namespace TeraCloud
{
    public class TeraCloudAPI
    {
        public TeraCloudAPI(string apiKey)
        {
            ApiKey=apiKey;
        }
        public string Version="v2";
        public string url="https://api.teracloud.jp/";
        public string ApiKey="";
        public DynamicJson GetUser(string user,string password)
        {
            StringBuilder sb=new StringBuilder();
            sb.AppendFormat(url+"{0}/api/user/;api_key={1}",
                Version,ApiKey);
            WebRequest req = HttpWebRequest.Create(sb.ToString());
            req.Method = "GET";
            req.Credentials = new NetworkCredential(user, password);
            //受信
            HttpWebResponse res = (HttpWebResponse) req.GetResponse();
            System.IO.Stream st = res.GetResponseStream();
            System.IO.StreamReader sr = new System.IO.StreamReader(st);
            var json=DynamicJson.Parse(sr.ReadToEnd());
            return json;
        }
    }
}

使用する側

            var api = new TeraCloudAPI(APIKEY);
            dynamic user = api.GetUser(USERID, PASSWORD);
            Console.WriteLine(user.user);
            Console.WriteLine(user.introduce_code);
            Console.WriteLine(user.webdav_url);
            Console.WriteLine(user.capacity);