古事連記帖

趣味のこと、技術的なこと、適当につらつら書きます。

MADOSMA 買いました

発売日に買いました!

f:id:ChiiAyano:20150618094916j:plain
これのうち1つが自分のです。


開封の儀
f:id:ChiiAyano:20150618095237j:plain
f:id:ChiiAyano:20150618095336j:plain
f:id:ChiiAyano:20150618095709j:plain
f:id:ChiiAyano:20150618095833j:plain


期待通りというか、IS12Tから4年かかってようやくでた端末ですし、発売してとてもよかったと思っています。


Lumia 830と比べて、同じインチで同じ解像度なのに、MADOSMAの方はdpiが小さめになっていました。そのためか、アクションセンターのボタンは5個あり (Lumia 830は4個)、メールの一覧に表示される本文は2行 (Lumia 830は1行) だったり、スタート画面のタイル列数が3列固定だったりと、画面の大きな端末向けの設定になっていました。一度に見れる情報量が多くなって俯瞰しやすくなった一方、アプリの文字サイズなどが小さくなったのでやや読みにくくなった感じがしました。


欲を言うなら、

  • カメラボタンはつけてほしかった
  • もうちょっと最低輝度を落としてほしかった (結構明るい)
  • Lumiaのクイックビュー、HTCのドットビューなど、その端末に特徴的な何かを今後搭載した端末があるといいなーって
  • ストラップホールはほしい
  • 保護シート貼り付け済みはありがたいけど、せめて防脂タイプの保護シートがよかったかなぁ
  • アンテナピクトに、通信状態を示す矢印表示がほしかった (Lumiaには存在していたので、OEM設定でできるんじゃないかと推測)


マウスコンピューターの次の一手に期待しつつ、僕らもアプリを作って盛り上げていきたいところ。

MADOSMA 予約してきました

マウスコンピューターが発売する、日本で2台目、Windows Phone 8.1端末として日本初の MADOSMA (マドスマ) がいよいよ 6月18日に発売されると言うことで…


f:id:ChiiAyano:20150603193830j:plain


ヨドバシカメラで予約してきました。今から待ち遠しい限りです。


楽天にあるMCJの公式オンラインストアでは予定数に達して予約受付を終了してしまったり、ビックカメラヨドバシカメラオンラインストアでは売上1位を獲得するなど発売前からかなり話題になっているようで、Windows Phoneにたいする注目度の高さがうかがい知れます。待ってました。


今後freetelのNinjaと呼ばれる端末や、COMPUTEXでBangBangameが発表した「Wolf 2」の日本発売を予定しているなど、今年や来年にかけて徐々にWindows PhoneもしくはWindows 10 Mobile端末が増えて行くことは間違いないと思います。
僕自身も、Windows Phoneや次のWindows 10 Mobileのアプリをどんどん作って応援していきたいところ。


マウスコンピュータ SIMフリースマートフォン MADOSMA MADOSMAQ501WH

マウスコンピュータ SIMフリースマートフォン MADOSMA MADOSMAQ501WH

Windows ストアアプリでNTPから時刻を受信する

Windowsストアアプリ、つまるところの WinRT でNTPサーバーに接続して時刻を受信したい欲求があったので実装してみました。


NTPはおなじみの時刻同期に使用するプロトコルです。Windowsには標準でNTPクライアントが実装されているので、知らぬまま時刻同期されていたり、意識している人はNICTに接続するようにしたり、同期間隔を変更したりしていると思います。
ストアアプリでは、特にWindowsPhoneではシステム時刻を自由に設定できないのであまりNTPとつなげる意味はないですが、時計アプリを作りたいとか、OAuthなどで時刻を認証の一要素として使うなどで一時的な利用には十分つかえるはずです。


NTPについてのRFC原文はこちらに、有志による日本語訳はこちらにあります。
NTPはUDPを使って通信するのでソケット通信が必要です。ストアアプリ結構めんどくさいんすよ。


NTPで時刻同期をする際、伝送の遅延などを考慮する必要があるため、4つの時間が必要になります。

  • (クライアント) NTPへ接続を開始した時間
  • (サーバー) クライアントから要求を受けた時間
  • (サーバー) クライアントへ時刻を送信した時間
  • (クライアント) NTPから時刻を受けた、補正前の時間

これらはそれぞれRFCでは T1, T2, T3, T4 と定義されていて、遅延時間を考慮する計算式が書かれています。

NTPについてはこの辺がわかっていれば、あとは受信した情報を解析してやるだけです。


ストアアプリの場合のUDP通信は Windows.Networking.Sockets.DatagramSocket クラスを使います。
MSDNにも書いてありますが、このクラスを使う場合は

  1. クラスのインスタンスを作成する
  2. MessageReceived イベントをハンドラーに割り当てる
  3. BindEndpointAsync メソッドもしくは BindServiceNameAsync メソッドを呼び出す
  4. ConnectAsync メソッドを呼び出す

の順番にこなさないと InvalidOperationException で簡単に蹴られます。
さらに、MSDNには

アプリケーションが DatagramSocket オブジェクトのリモート エンドポイントからのデータの受信を望む場合、DatagramSocket が特定のリモート エンドポイントに束縛されるため、ConnectAsync メソッドを使用しないでください。代わりに BindServiceNameAsync または BindEndpointAsync メソッドを使用します。

と書いていますが、これは受信のみをおこなう場合だけであって、送信も受信もする場合は両方を呼び出さないとダメです。送信は出来ても受信できなかったり、その逆とかが発生して悲しみを生みます。(この辺でだいぶはまった…


このあたりの問題がさくっとわかると、UDP接続はあっさり終わります。

private DateTimeOffset requestStartDate;
private DateTimeOffset responseReceivedDate;
private DateTimeOffset serverReceivedDate;
private DateTimeOffset serverSentDate;

public async Task RequestNtpTimeAsync()
{
    // 送信開始時タイムスタンプ
    this.requestStartDate = DateTimeOffset.Now;

    var ntpData = new byte[48];
    // サーバーにクライアントからの要求であることを通知
    // LI: 00 警告なし(No Warning), VN: 011 (Version 3), Mode: 011 (Client: 3)
    ntpData[0] = 0x1B;

    var udpClient = new DatagramSocket();

    // 応答の受信イベントを定義
    udpClient.MessageReceived += UdpClient_MessageReceived;

    // 接続の確立
    // 受信データの受け口はシステム既定を使うのでこんな感じ。
    await udpClient.BindEndpointAsync(null, string.Empty);
    // NTP は UDP: 123
    await udpClient.ConnectAsync(new HostName("ntp.nict.jp"), "123");

    // 要求の送信
    var sender = new DataWriter(udpClient.OutputStream);
    sender.WriteBytes(ntpData);
    await sender.StoreAsync();
}

private void UdpClient_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
    // あとにつづく
}


UDPを使ったNTPへの送信はこれでOKです。
この後はNTPサーバーから受け取る情報の解析です。
既にC#で実装されている SNTP in C# がわかりやすいかと思うので参考程度に。


サーバーからの情報はクライアントで渡すものとデータ構造は一緒です。最初に、同期した日に閏秒があるかが返ってきますが、今回は無視します。(Windowsでは閏秒を考慮しませんし)

private void UdpClient_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args)
{
    // 受信完了したタイムスタンプ
    this.responseReceivedDate = DateTimeOffset.Now;

    var ntpData = new byte[48];
    var dr = args.GetDataReader();
    dr.ReadBytes(ntpData);

    // 受信タイムスタンプ
    this.serverReceivedDate = ComputeDate(GetMilliSeconds(ntpData, 32));
    // 送信タイムスタンプ
    this.serverSentDate = ComputeDate(GetMilliSeconds(ntpData, 40));

    // 誤差調整
    // 通信にしたことで発生した遅延の計算
    var delay = ((this.responseReceivedDate - this.requestStartDate) - (this.ServerReceivedDate - this.ServerSentDate));
    // サーバーとクライアントの時刻の差
    var diff =
        TimeSpan.FromMilliseconds(
            ((this.ServerReceivedDate - this.requestStartDate) + (this.ServerSentDate - this.responseReceivedDate)).TotalMilliseconds / 2);

    // 補正後の値
    var corrected = (DateTimeOffset.Now + diff - delay);
}

private static ulong GetMilliSeconds(byte[] data, int offset)
{
    // この辺は SNTP in C# に書かれているコードをほとんどコピーしたやーつ
    // 64ビットタイムスタンプをミリ秒に変換するコード
    var intPart = data.Skip(offset).Take(4).Aggregate<byte, ulong>(0, (current, item) => 256 * current + item);
    var fractionPart = data.Skip(offset + 4).Take(4).Aggregate<byte, ulong>(0, (current, item) => 256 * current + item);

    var milliseconds = intPart * 1000 + (fractionPart * 1000) / 0x100000000;

    return milliseconds;
}

private static DateTimeOffset ComputeDate(ulong milliseconds)
{
    // 1900年1月1日から、指定したミリ秒分足して時刻に変換
    var time = new DateTimeOffset(1900, 1, 1, 0, 0, 0, TimeSpan.FromHours(0));
    var result = (time + TimeSpan.FromMilliseconds(milliseconds)).ToLocalTime();

    return result;
}

サーバーから受けるデータで大事なのは、サーバーから返る時刻の情報です。得られたバイト配列の32バイト目から64ビット分がクライアントからの要求を受け取ったサーバー時間、40バイト目から64ビット分がサーバーからクライアントへ応答したサーバー時間です。これを受け取って、補正すると正しい時間として同期が完了するという感じです。


うまくいくとこんな感じ
f:id:ChiiAyano:20150510222303p:plain
エミュレーターだとすぐ時間ずれるんで、結構わかりやすいです


これで仮にシステム時刻を変えたりする場合、正確な時刻と大きな差があったりする場合は、いきなりその時刻にせず徐々に近づけていくなどをおこなうのが正しい実装らしいです。ただ表示するだけのようなケースの場合は特にそのへん気にしなくて良いと思います。

MapFanがWindows 8.1/Windows Phone 8.1向けの地図アプリをリリースしたみたいです

Windows Phoneに地図革命くるか(大げさ

ケータイWatchおよびMapFan公式サイトにて、MapFanのWindowsストア版/Windows Phone 8.1版のアプリがリリースされたとアナウンスがありました。

k-tai.impress.co.jp
www.mapfan.com

まさかのWindows Phone 8.1版リリースです。
見る感じユニバーサルWindowsアプリとして作られたっぽいですね。ようやく日本でもユニバーサルの恩恵を得られるというところでしょうか…。

もうすぐ日本でも発売される予定のWindowsPhone端末に向けて、着々と準備が進んでいくことを期待しています。


apps.microsoft.com
www.windowsphone.com

freetelが日本国内でWindowsPhone発売を決定したようです

ついに波がきた!


SIMフリースマートフォンブランドfreetel 最新のWindows Phone OS搭載モデルを 2015年夏までに国内発売 | プラスワン・マーケティング株式会社

MWCでお披露目で、2015年夏までに発売するみたいです。

スペックは

OS:Windows Phone 8.1
CPU:クアッドコア 64bit プロセッサ
ディスプレイ:5.0インチ HD マルチタッチスクリーン
メモリ:1GB RAM、8GB ROM
カメラ:B8.0/F2.0MP
バッテリー:2500mAh

と、まあまあな感じ。WindowsPhone的には標準なスペックかと。
ストレージが8GBしかないのがちょっと心細いですね…microSDカードが挿せればいいんですが。

マウスコンピュータがWindowsPhoneベース端末の開発を表明したそうです


マウス、SIMロックフリーWindows Phone端末の開発に着手 - PC Watch


LTE対応のSIMフリーWindows Phoneの開発をマウスコンピューターが着手! - 週アスPLUS


2015.02.23 ニュースリリース|マウスコンピューター、Windows Phone ベースのデバイス開発契約を締結し、開発着手のお知らせ|マウスコンピューター

まじか…まじか…!ゴゴゴゴゴ
BTOメーカーからでてくるとは想定してませんでした


この時期の表明で考えられる想定としては、

  • Windows 10 for phones プリイン端末を今年後半に発売
  • W10p が十分動く端末として Windows Phone 8.1 端末を近いうちに発売
  • まさかの Windows Embedded 8.1 Handheld

といったところかなーと思いつつ、次の情報をドキドキしながら待ちます

Windows Phone の MapControl に Bing Mapsを載せる方法

id:kazuakix 先生がマップ関連でお困りだったようで

Windows Phone 8 の MapControl に Bing Mapsを載せる方法がわからんということなので、メモ程度に書いておこうかと思います。


WP8.x から Map コントロールがBingからHereにかわり、使い勝手がやや変わっていますが、実はずいぶん前、WP7.x時代に高橋忍さんが実践していたことがほぼそのまま使えるんです。
MSDN Blogs

とりあえずコード。
まず MainPage.xaml

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App7"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:Maps="using:Windows.UI.Xaml.Controls.Maps"
    x:Class="App7.MainPage"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <Maps:MapControl x:Name="Map"/>
    </Grid>
</Page>

残念ながらXAMLだけで完結できないので、仕方なくコードビハインドにも。
MainPage.xaml.cs

using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Maps;
using Windows.UI.Xaml.Navigation;

namespace App7
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            this.NavigationCacheMode = NavigationCacheMode.Required;
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            // 20141226 追記
            this.Map.Style = MapStyle.None;

            var mapTile = new MapTileSource
            {
                DataSource = 
                new HttpMapTileDataSource("http://ecn.t1.tiles.virtualearth.net/tiles/r{quadkey}.png?g=1&mkt=ja-jp")
            };
            this.Map.TileSources.Insert(0, mapTile);
        }
    }
}

これで地図はこうなります
f:id:ChiiAyano:20141225103220p:plain

Bing Mapsキター でも元あったHere Mapsの情報は残ったままですね…
これを消す方法は見当たらなかったので、誰か教えてください。


ちなみに、気合い入れればWP7.x時代のBing Map Controlを、WP8.x Silverlight なら使うこともできます。WinRTだとたぶんダメですが…

2014年12月26日追記

Here Mapsの地図が載っかったままだったのは id:kazuakix さんが解決法を教えてくれました。


MapControl.Style プロパティを MapStyle.None にすればよかったみたいです。
上記コードに追記しておきました。