【ラズパイ】受信したセンサーデータを表示する。

前回までの状況はこちら。

前回はラズパイからセンサーで収集したデータを送信させていましたが、フォーマットがJsonなので、このままでは使用できません。

ラズパイ側のソースコードをgitHubにアップしました。

https://github.com/takishita2nd/pi/blob/master/http.py

今回はこのデータを見やすいように加工します。

GUIのほうが見やすいと思って、軽い気持ちで作ってみたのですが、思った以上にがっつりなことになってしまいました。

WPFを使用しようと思うのですが、今回はPrismという拡張機能を使用してMVVMモデルで作成しようと思います。

メニューの拡張機能からPrismを検索し、Prismをインストールします。

Visual Studioを再起動すると、新規プロジェクトにPrismが追加されているので、Prismのプロジェクトを作成します。

まずは、XAMLの作成。

<Window x:Class="BlankApp1.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        Title="{Binding Title}" Height="180" Width="350">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Label Grid.Row="0" Grid.Column="0" Content="温度" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Label Grid.Row="1" Grid.Column="0" Content="湿度" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Label Grid.Row="2" Grid.Column="0" Content="気圧" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Label Grid.Row="0" Grid.Column="1" Content="{Binding Temperature}"  HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Label Grid.Row="1" Grid.Column="1" Content="{Binding Humidity}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Label Grid.Row="2" Grid.Column="1" Content="{Binding Pressure}"  HorizontalAlignment="Center" VerticalAlignment="Center"/>
        <Button Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Content="Monitor" Command="{Binding ButtonClickCommand}" HorizontalAlignment="Center" VerticalAlignment="Center" Height="20" />
    </Grid>
</Window>

温度、湿度、気圧を表示するだけです。

あとはデータの待ち受けを開始するボタンを配置します。

Jsonを展開するためのクラスを定義します。

    [JsonObject("sensorModel")]
    class Sensor
    {
        [JsonProperty("temperature")]
        public int Temperature { get; set; }
        [JsonProperty("humidity")]
        public int Humidity { get; set; }
        [JsonProperty("pressure")]
        public int Pressure { get; set; }
    }

クラス名は何でもいいですが、パラメータの名前は送信側と合わせる必要があります。

最後にViewModelの処理です。

    public class MainWindowViewModel : BindableBase
    {
        private string _title = "ラズパイモニター";
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }
        private int _temperature;
        private int _humidity;
        private int _pressure;
        public int Temperature 
        { 
            get { return _temperature; } 
            set { SetProperty(ref _temperature, value); }
        }
        public int Humidity
        {
            get { return _humidity; }
            set { SetProperty(ref _humidity, value); }
        }
        public int Pressure
        {
            get { return _pressure; }
            set { SetProperty(ref _pressure, value); }
        }

        public DelegateCommand ButtonClickCommand { get; }

        public MainWindowViewModel()
        {
            ButtonClickCommand = new DelegateCommand(() =>
            {
                Thread thread = new Thread(new ThreadStart(() => {
                    try
                    {
                        HttpListener listener = new HttpListener();
                        listener.Prefixes.Add("http://192.168.1.3:8000/");
                        listener.Start();
                        while (true)
                        {
                            HttpListenerContext context = listener.GetContext();
                            HttpListenerRequest req = context.Request;
                            using (StreamReader reader = new StreamReader(req.InputStream, req.ContentEncoding))
                            {
                                string s = reader.ReadToEnd();
                                Sensor sensor = JsonConvert.DeserializeObject<Sensor>(s);
                                Temperature = sensor.Temperature;
                                Humidity = sensor.Humidity;
                                Pressure = sensor.Pressure;
                            }
                            HttpListenerResponse res = context.Response;
                            res.StatusCode = 200;
                            byte[] content = Encoding.UTF8.GetBytes("HELLO");
                            res.OutputStream.Write(content, 0, content.Length);
                            res.Close();
                        }
                    }
                    catch (Exception ex)
                    {
                    }
                }));

                thread.Start();

            });
        }
    }

ボタンを押すとHTTPを待ち受け開始し、HTTPを受信したらデータ(Json)を展開しオブジェクト化します。

そして、各パラメータをプロパティに設定します。

動作結果はこうなりました。

うん、想定通り。

【C#】【ピクロス】【ALTSEED】数字入力マスを追加する。

前回までの状況はこちら。

最新ソースはこちら。(gitHub)

https://github.com/takishita2nd/Picross

ピクロス解析のヒントとなる数字の入力マスを作成していきます。

イメージとしては、マウスカーソルが上にあると色が変化し、クリックするとパレットを表示する、という感じです。

まずはマスを作成しましょう。

数字を入力するマスのクラスを作成します。

class NumberSquare : ObjectBase
{
    protected int _row;
    protected int _col;
    protected const int setPositionX = 200;
    protected const int setPositionY = 200;
    protected const int fontOffsetX = 19;
    protected const int fontOffsetY = 9;
    private string _value;

    public NumberSquare(int row, int col)
    {
        width = 32;
        height = 32;
        _value = string.Empty;
        _row = row;
        _col = col;
        _x = col * width + setPositionX;
        _y = row * height + setPositionY;

        _backTexture = new asd.TextureObject2D();
        _backTexture.Texture = Resource.GetPicrossTexture();
        _backTexture.Position = new asd.Vector2DF(_x, _y);

        _valueText = new asd.TextObject2D();
        _valueText.Font = Resource.getFont();
        _valueText.Position = new asd.Vector2DF(_x + fontOffsetX, _y + fontOffsetY);
    }

    public void SetValue(string value)
    {
        _value = value;
        _valueText.Text = _value;
    }

    public void UpdateTexture(asd.Vector2DF pos)
    {
        if (pos.X > _x && pos.X < _x + width
            && pos.Y > _y && pos.Y < _y + height)
        {
            _backTexture.Texture = Resource.GetSelectedNumberTexture();
        }
        else
        {
            _backTexture.Texture = Resource.GetPicrossTexture();
        }
    }

    public int getValue()
    {
        return int.Parse(_value);
    }
}

これをUIに配置します。

マスのオブジェクトは

List<List<NumberSquare>>

の形で保持します。

一番外のList<>はROWまたはCOLのサイズ分だけ持ち、List<List<>>は入力した数字の数だけ保持します。

これをROW、COLの二つ持ちます。

    private List<List<NumberSquare>> rowNumberSquare = new List<List<NumberSquare>>();
    private List<List<NumberSquare>> colNumberSquare = new List<List<NumberSquare>>();

配置。

        // 数字の入力するマス
        for(int row = 0; row < 10; row++)
        {
            NumberSquare square = new NumberSquare(row, -1);
            asd.Engine.AddObject2D(square.getBackTexture());
            asd.Engine.AddObject2D(square.getTextObject());
            List<NumberSquare> rowList = new List<NumberSquare>();
            rowList.Add(square);
            rowNumberSquare.Add(rowList);
        }
        for (int col = 0; col < 10; col++)
        {
            NumberSquare square = new NumberSquare(-1, col);
            asd.Engine.AddObject2D(square.getBackTexture());
            asd.Engine.AddObject2D(square.getTextObject());
            List<NumberSquare> colList = new List<NumberSquare>();
            colList.Add(square);
            colNumberSquare.Add(colList);
        }

マウスがマスの上にきたときの処理。

        while (asd.Engine.DoEvents())
        {
            asd.Vector2DF pos = asd.Engine.Mouse.Position;
            if(!dialog.IsShow())
            {
                foreach (var rowList in rowNumberSquare)
                {
                    foreach (var s in rowList)
                    {
                        s.UpdateTexture(pos);
                    }
                }
                foreach (var colList in colNumberSquare)
                {
                    foreach (var s in colList)
                    {
                        s.UpdateTexture(pos);
                    }
                }
                foreach (Button button in buttons)
                {
                    button.UpdateTexture(pos);
                }
            }

そして、忘れてはいけないのが、サイズ変更を行ったとき。

サイズ変更を行ったら、それに合わせてListの数も変更しなければいけません。

        dialog.SetAction(() =>
        {
            dialog.Hide();
            int row = dialog.GetRowValue();
            int col = dialog.GetColValue();
            while(row != drawSquares.Count)
            {
                if(drawSquares.Count > row)
                {
                    {
                        // マスの削除
                        var rowList = drawSquares[drawSquares.Count - 1];
                        foreach (var c in rowList)
                        {
                            asd.Engine.RemoveObject2D(c.getBackTexture());
                        }
                        drawSquares.RemoveAt(drawSquares.Count - 1);
                    }

                    {
                        // 数字のマスの削除
                        var rowList = rowNumberSquare[rowNumberSquare.Count - 1];
                        foreach (var s in rowList)
                        {
                            asd.Engine.RemoveObject2D(s.getBackTexture());
                            asd.Engine.RemoveObject2D(s.getTextObject());
                        }
                        rowNumberSquare.RemoveAt(rowNumberSquare.Count - 1);
                    }
                }
                else
                {
                    {
                        // マスの追加
                        List<DrawSquare> rowList = new List<DrawSquare>();
                        for (int c = 0; c < drawSquares[0].Count; c++)
                        {
                            var square = new DrawSquare(drawSquares.Count, c);
                            asd.Engine.AddObject2D(square.getBackTexture());
                            rowList.Add(square);
                        }
                        drawSquares.Add(rowList);
                    }

                    {
                        // 数字のマス追加
                        var square = new NumberSquare(rowNumberSquare.Count, -1);
                        asd.Engine.AddObject2D(square.getBackTexture());
                        asd.Engine.AddObject2D(square.getTextObject());
                        List<NumberSquare> list = new List<NumberSquare>();
                        list.Add(square);
                        rowNumberSquare.Add(list);
                    }
                }
            }
            while(col != drawSquares[0].Count)
            {
                if(drawSquares[0].Count > col)
                {
                    {
                        // マスの削除
                        foreach (var r in drawSquares)
                        {
                            asd.Engine.RemoveObject2D(r[r.Count - 1].getBackTexture());
                            r.RemoveAt(r.Count - 1);
                        }
                    }

                    {
                        // 数字のマスの削除
                        var colList = colNumberSquare[colNumberSquare.Count - 1];
                        foreach (var s in colList)
                        {
                            asd.Engine.RemoveObject2D(s.getBackTexture());
                            asd.Engine.RemoveObject2D(s.getTextObject());
                        }
                        colNumberSquare.RemoveAt(colNumberSquare.Count - 1);
                    }
                }
                else
                {
                    {
                        // マスの追加
                        int rowindex = 0;
                        int colindex = drawSquares[0].Count;
                        foreach (var r in drawSquares)
                        {
                            var square = new DrawSquare(rowindex, colindex);
                            asd.Engine.AddObject2D(square.getBackTexture());
                            r.Add(square);
                            rowindex++;
                        }
                    }

                    {
                        // 数字のマス追加
                        var square = new NumberSquare(-1, colNumberSquare.Count);
                        asd.Engine.AddObject2D(square.getBackTexture());
                        asd.Engine.AddObject2D(square.getTextObject());
                        List<NumberSquare> list = new List<NumberSquare>();
                        list.Add(square);
                        colNumberSquare.Add(list);
                    }
                }
            }
        });

動作はこんな感じになりました。

次回は実際に数字を入力する処理を追加します。