プログラムの事とか

お約束ですが「掲載内容は私個人の見解です」

WEB PUSHをASP.NETとか使ってC#でやってみる

EdgeもPreview版では対応しているらしいしハードルも当初に比べると下がっているらしいので試してみました

WEB PUSHの詳しいあれこれはググってください、私はよくわかってませんので

今回の記事で出来上がったものはこちらに上げてあります

github.com

簡単な動き

  • サーバー側で公開鍵と秘密鍵を準備する

  • クライアント側で通知先のURLとか作る

  • 通知したい人が上の情報を使って通知する

って感じらしいです

鍵の作り方とかよくわかってないので偉い人の作ってくれたライブラリをつかいましょう

作ってみる

Webサーバー

まずは基本となるWebページをASP.NET MVC5のテンプレート使って準備して

Install-Package WebPush

そのままなやつがNuGetにあるので入れましょう、これが面倒なところをみんなやってくれます。らくちんちんちんですね

クライアント表示時に公開鍵を教えてあげる必要があるのでControllerに処理を書きます

public ActionResult Index()
{
    var model = new HomeModel();
    var pushInformation = PushInformation.Load(AppDomain.CurrentDomain.BaseDirectory + "../info.xml");   // 保存先はてきとうに
    if (pushInformation == null)    // VAPIDで使用する公開鍵を作成
    {
        pushInformation = new PushInformation();
        var vapidKeys = VapidHelper.GenerateVapidKeys();
        pushInformation.VapidPublic = vapidKeys.PublicKey;
        pushInformation.VapipPrivate = vapidKeys.PrivateKey;
        PushInformation.Save(pushInformation, AppDomain.CurrentDomain.BaseDirectory + "../info.xml");    // 作ったら保存しとく
    }
    model.VapidPublic = pushInformation.VapidPublic;
    model.Data = Request.QueryString.Get("data");
    return View(model);
}

あとはクライアントから通知に必要な情報もらう口をつくっておきます

[HttpPost]
public void Post(NotificationTarget target)
{
    var pushInformation = PushInformation.Load(AppDomain.CurrentDomain.BaseDirectory + "../info.xml");  // 保存先はてきとうに
    if (pushInformation == null) return;
    pushInformation.Targets.Remove(pushInformation.Targets.FirstOrDefault(t => t.EndPoint == target.EndPoint));
    pushInformation.Targets.Add(target);
    PushInformation.Save(pushInformation, AppDomain.CurrentDomain.BaseDirectory + "../info.xml");
}

Webクライアント

javascriptを頑張って書きましょう

developers.google.com

この辺参考にすればなんとかなるんじゃないでしょうか

一つ気を付けるのはserviceWorkerに読み込ませるスクリプトはルートに置かないといつまでたっても読み込めない、ってところくらいですね

javascriptだからってScriptsフォルダに入れてもだめだよ!!

ここまで出来たらChromeでページを開いてみます

f:id:puni-o:20180309171412j:plain

通知の許可が出て許可すると購読が始まります

Pushアプリ

コンソールアプリを起動すると起動時パラメーターを上で登録したクライアントにPushするアプリを作ります

Install-Package WebPush
var pushInformation = PushInformation.Load(AppDomain.CurrentDomain.BaseDirectory + "../../../info.xml");  // ASP.NETが保存しているファイルを見ます

var webPushClient = new WebPushClient();
var vapidDetails = new VapidDetails("mailto:yourname@mail.net", pushInformation.VapidPublic, pushInformation.VapipPrivate);
var targetList = pushInformation.Targets.ToArray();
foreach (var target in targetList)
{
    try
    {
        var subscription = new PushSubscription(target.EndPoint, target.PublicKey, target.AuthSecret);
        webPushClient.SendNotification(subscription, args[0], vapidDetails);
    }
    catch (Exception exp)
    {
        if (exp.Message == "Subscription no longer valid")  // 購読者がいなくなるとこんな感じの例外を吐くので送信先から消しておこう
        {
            pushInformation.Targets.Remove(target);
        }
    }
}
PushInformation.Save(pushInformation, AppDomain.CurrentDomain.BaseDirectory + "../../../info.xml");

Webサーバーが保存した情報を使って通知するだけです

実行すると

f:id:puni-o:20180309183143j:plain

通知がやってきて

f:id:puni-o:20180309183202j:plain

ページが開きました

これだけでAndroidChromeだとロックしていても通知受けてくれるようになるんですよね

iOSも頑張ってほしいけど望み薄ですかねー

音声認識を作る時に周りに人がいてしゃべるのが恥ずかしいのでどうにかしようと思った話

UWPでの話です

アプリに音声認識機能を入れたいんですがそのテストに困ることありませんか?

オフィスの静かなところでマイクに向かってぶつぶついって白い目で見られたり、そもそも英語のネイティブな発音できなくて困ったり、という私に向けた内容です

答え

喋りたくないならしゃべってもらえばいいじゃない

準備

まずはPCでしゃべらせた内容をマイクに入れないといけないのでその設定

f:id:puni-o:20171228132006j:plain

ステレオミキサーをデフォルトの録音デバイスにします(ステレオミキサーが無いとかそういうのはググってどうにかしましょう)

私の環境の場合、スピーカーのレベルとステレオミキサーのレベルをどちらも100%にしないと入力が小さすぎました(入力が無いと困ったら一度レベルを確認してみるといいかもしれません)

あとはUWPでしゃべらせることもしゃべった内容を認識させることもできるので二つを合わせてしまえばいいだけです

github.com

こちらにサンプルがあるのでコピペして出来上がり


Speech to SpeechRecognize

おk

注意

UWPのSpeechRecognizerはアプリのフォーカスが外れると止まってしまいます

多分フォーカス外れても動かし続けることは今の時点では無理だと思います(できるなら教えてください、何でもはできません)

本当はGoogle先生にでもしゃべってもらうつもりだったんですがそれができなくて自分自身でしゃべるようにしました。

ってこんなんじゃ使えないよ!!!

追記

Edge先生にしゃべってもらい続けてそれを聞き取ることにしました


Speech to SpeechRecognize 2

ASP.NETのWeb APIの戻りを圧縮して返す

.NET FrameworkASP.NETの話です(Coreは知らない)

Web APIででっかいjson返すようなときにgzipで圧縮してほしい、ってことを定期的に調べているので自分用に書いておきます

自動でやってくれない・・・よね?

準備

Visual Studio 2017で「ASP.NET Web アプリケーション (.NET Framework)」のテンプレート使って新しいプロジェクト作ります。(Web APIのチェック忘れずに)

ValuesControllerができていると思うのでちょっとだけ修正

public IEnumerable<string> Get()
{
    return new string[] { "value",
        "value", "value", "value",
// ・・・
// たくさん返す
// 
        "value", "value", "value",
    };
}

4K以上(?)の戻りでないと圧縮してくれないようなのでたくさん返すようにします

とりあえずこれでIISに発行して上記APIをEdgeで呼んでみます

f:id:puni-o:20171215170552j:plain

Accept-Encoding:gzip,deflateとなってますが応答は圧縮されてません

圧縮するようにする

Nugetから下の二つをげと

PM> Install-Package Microsoft.AspNet.WebApi.Extensions.Compression.Server

PM> Install-Package System.Net.Http.Extensions.Compression.Client

Global.asax.csに一行追加

protected void Application_Start()
{
    GlobalConfiguration.Configuration.MessageHandlers.Insert(0, new ServerCompressionHandler(new GZipCompressor(), new DeflateCompressor()));

んでやり直し

f:id:puni-o:20171215170834j:plain

ちゃんとgzipで圧縮して返してくれました