Читать из последовательного порта на Blazor - PullRequest
0 голосов
/ 15 марта 2020

Я новичок в Blazor и пытаюсь создать приложение для чтения через последовательный порт. Сначала я создал консольное приложение, используя .Core 3.1 Все работало с штрафом, поэтому я переместил код в Blazor, и хотя, когда я ставлю точку отладки, я вижу, что код работает, я не могу заставить пользовательский интерфейс отображать значение

@using System;
@using System.Diagnostics;
@using System.IO.Ports;
@using System.Threading;


<head>
    <title>Main Scale Monitor</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="/css/all.css" rel="stylesheet">
    <link href="/css/stylesheet.css" rel="stylesheet">
</head>


<div class="scale-monitor">
    <div class="digital-monitor net-weight grid-line">
        <div class="digital-monitor-left net-left">NET</div>
        <div class="digital-monitor-center net-center" bind="@ScaleValue"></div>
        <div class="digital-monitor-right net-right">Kg</div>
    </div>
</div>


@code {

    public string ScaleValue { get; set; } = "0.001";

    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            System.IO.Ports.SerialPort mySerialPort = new System.IO.Ports.SerialPort("COM3");

            mySerialPort.BaudRate = 9600;
            mySerialPort.Parity = System.IO.Ports.Parity.None;
            mySerialPort.StopBits = System.IO.Ports.StopBits.One;
            mySerialPort.DataBits = 8;
            mySerialPort.Handshake = System.IO.Ports.Handshake.None;

            mySerialPort.NewLine = (@"&N");

            mySerialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(DataReceivedHandler);

            if (!mySerialPort.IsOpen)
            {
                mySerialPort.Open();

            }
        }
    }


    private void DataReceivedHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        System.IO.Ports.SerialPort sp = (System.IO.Ports.SerialPort)sender;

        try
        {
            string indata = sp.ReadLine();
            ScaleValue = indata.ToString(); //WHEN I PUT DEBUG HERE I CAN SEE THE CORRECT VALUE

        }
        catch (Exception ex)
        {
            string msg = ex.Message;
        }

    }
}


<style>

    *, ::after, ::before {
        box-sizing: unset;
    }

    .grid-line {
        border: 1px solid black;
    }

    .scale-monitor {
        display: grid;
        grid-template-columns: 35% 35% 30%;
        grid-template-rows: 50% 50%;
        width: 100%;
        height: 90%;
        margin: 5px;
        width: 1020px;
    }


    /*#region generic*/

    .digital-monitor {
        background: #000000;
        color: greenyellow;
        text-align: right;
        font-family: digitalregular;
        display: grid;
        grid-template-columns: repeat(10, 1fr);
        grid-template-rows: repeat(5, 1fr);
        width: 95%;
        height: 95%;
        margin: 5px;
        border-radius: 15px;
        align-items: center;
    }

    /*#region generic scalemonitor*/
    .digital-monitor-left {
        writing-mode: vertical-rl;
        opacity: 0.5;
        grid-row: 1 / span 5;
        grid-column: 1;
        text-align: center;
        grid-column: 1;
        transform: rotate(180deg);
    }

    .digital-monitor-center {
        grid-row: 2 / span 3;
        grid-column: 2/ span 7;
        text-align: right;
        vertical-align: bottom;
    }

    .digital-monitor-right {
        grid-row: 2 / span 3;
        grid-column: 9/ span 2;
        text-align: right;
        opacity: 0.75;
        margin-bottom: 0.4em;
        margin-right: 3px;
        align-self: self-end;
    }
    /*#endregion*/

    /*#endregion*/


    /*#region NET*/
    .net-weight {
        grid-column: 2;
        grid-row: 1 / span 2;
        height: 98%;
    }

    .net-left {
        font-size: 40px;
    }

    .net-center {
        font-size: 100px;
    }

    .net-right {
        font-size: 40px;
    }

    /*#endregion NET*/
</style>

Есть идеи, как я могу сделать правильное связывание?

Ответы [ 3 ]

1 голос
/ 15 марта 2020

Из документации Blazor Lifecycle : "Асинхронная работа сразу после рендеринга должна выполняться во время события жизненного цикла OnAfterRenderAsyn c.

Даже если вы возвращаете задачу из OnAfterRenderAsyn c, фреймворк не планирует дополнительный цикл рендеринга для вашего компонента после завершения этой задачи. Это позволяет избежать бесконечного рендеринга l oop. Он отличается от других методов жизненного цикла, которые планируют дальнейший цикл рендеринга после завершения возвращенной задачи. "

Попробуйте вызвать StateHasChanged() вручную после установки ScaleValue.

0 голосов
/ 17 марта 2020

Я нашел ответ,
Я не на 100%, это лучшее решение

Создать сервис

public class ReadSerialPortService
{
    public string SerialPortValue { get; set; }

    public ReadSerialPortService()
    {
        System.IO.Ports.SerialPort mySerialPort = new System.IO.Ports.SerialPort("COM3");

        mySerialPort.BaudRate = 9600;
        mySerialPort.Parity = System.IO.Ports.Parity.None;
        mySerialPort.StopBits = System.IO.Ports.StopBits.One;
        mySerialPort.DataBits = 8;
        mySerialPort.Handshake = System.IO.Ports.Handshake.None;

        mySerialPort.NewLine = (@"&N");

        if (!mySerialPort.IsOpen)
        {
            mySerialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(DataReceivedHandler);
            mySerialPort.Open();
        }
    }

    private void DataReceivedHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        System.IO.Ports.SerialPort sp = (System.IO.Ports.SerialPort)sender;
        double scaleDec = 0.00;
        try
        {
            string indata = sp.ReadLine();
            SerialPortValue = indata.ToString();
        }
        catch (Exception ex)
        {
            string msg = ex.Message;
        }

    }

    public Task<string> GetSerialValue()
    {
        return Task.FromResult(SerialPortValue);
    }
}

А потом в компоненте

@inject ReadSerialPortService _readSerialPortService
<head>
   <title>Main Scale Monitor</title>
   <meta name="viewport" content="width=device-width, initial-scale=1">
   <link href="/css/all.css" rel="stylesheet">
   <link href="/css/stylesheet.css" rel="stylesheet">
</head>

<div class="scale-monitor">
   <div class="digital-monitor net-weight grid-line" @onclick="GetValue">
      <div class="digital-monitor-left net-left">NET</div>
      <div class="digital-monitor-center net-center">@ScaleValue</div>
      <div class="digital-monitor-right net-right">Kg</div>
   </div>
</div>


@code {
private int Count { get; set; } = 100;
Timer _updateTimer;
public string ScaleValue { get; set; } = "0.000";    

protected override async Task OnInitializedAsync()
{
    ScaleValue = await _readSerialPortService.GetSerialValue();
    _updateTimer = new Timer(state => { InvokeAsync(GetValue); }, null, 0, 100);
}


public async Task GetValue()
{
    ScaleValue = await _readSerialPortService.GetSerialValue();
    await InvokeAsync(() => StateHasChanged());
}

public void Dispose()
{
    _updateTimer.Dispose();
}

}

0 голосов
/ 15 марта 2020

Ваша проблема связана с попыткой связать значение с div.

Элемент div не является компонентом и не будет поддерживать атрибут связывания.

Попробуйте это: <div class="digital-monitor-center net-center">@ScaleValue</div>

Поскольку ваш код не зависит от визуализации страницы, настройте его на использование другого метода жизненного цикла.

Попробуйте ввести его в protected override void OnInitialized() { }

Редактировать:

Читайте о жизненных циклах Блазора здесь: https://docs.microsoft.com/en-us/aspnet/core/blazor/lifecycle?view=aspnetcore-3.1

Редактировать: Пример кода

@using System;
@using System.Diagnostics;
@using System.IO.Ports;
@using System.Threading;

@page "/Test";


<head>
    <title>Main Scale Monitor</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="/css/all.css" rel="stylesheet">
    <link href="/css/stylesheet.css" rel="stylesheet">
</head>


<div class="scale-monitor">
    <div class="digital-monitor net-weight grid-line">
        <div class="digital-monitor-left net-left">NET</div>
        <div class="digital-monitor-center net-center">@ScaleValue</div>
        <div class="digital-monitor-right net-right">Kg</div>
    </div>
</div>


@code {

    public string ScaleValue { get; set; } = "0.001";

    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
        }
    }

    protected override void OnInitialized()
    {

        System.IO.Ports.SerialPort mySerialPort = new System.IO.Ports.SerialPort("COM3");

        mySerialPort.BaudRate = 9600;
        mySerialPort.Parity = System.IO.Ports.Parity.None;
        mySerialPort.StopBits = System.IO.Ports.StopBits.One;
        mySerialPort.DataBits = 8;
        mySerialPort.Handshake = System.IO.Ports.Handshake.None;

        mySerialPort.NewLine = (@"&N");

        mySerialPort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(DataReceivedHandler);

        ScaleValue = "test";

        //I skipped this part with a return, since I don't have COM3 locally

        if (!mySerialPort.IsOpen)
        {
            mySerialPort.Open();

        }
    }


    private void DataReceivedHandler(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        System.IO.Ports.SerialPort sp = (System.IO.Ports.SerialPort)sender;

        try
        {
            string indata = sp.ReadLine();
            ScaleValue = indata.ToString(); //WHEN I PUT DEBUG HERE I CAN SEE THE CORRECT VALUE

        }
        catch (Exception ex)
        {
            string msg = ex.Message;
        }

    }
}


<style>

    *, ::after, ::before {
        box-sizing: unset;
    }

    .grid-line {
        border: 1px solid black;
    }

    .scale-monitor {
        display: grid;
        grid-template-columns: 35% 35% 30%;
        grid-template-rows: 50% 50%;
        width: 100%;
        height: 90%;
        margin: 5px;
        width: 1020px;
    }


    /*#region generic*/

    .digital-monitor {
        background: #000000;
        color: greenyellow;
        text-align: right;
        font-family: digitalregular;
        display: grid;
        grid-template-columns: repeat(10, 1fr);
        grid-template-rows: repeat(5, 1fr);
        width: 95%;
        height: 95%;
        margin: 5px;
        border-radius: 15px;
        align-items: center;
    }

    /*#region generic scalemonitor*/
    .digital-monitor-left {
        writing-mode: vertical-rl;
        opacity: 0.5;
        grid-row: 1 / span 5;
        grid-column: 1;
        text-align: center;
        grid-column: 1;
        transform: rotate(180deg);
    }

    .digital-monitor-center {
        grid-row: 2 / span 3;
        grid-column: 2/ span 7;
        text-align: right;
        vertical-align: bottom;
    }

    .digital-monitor-right {
        grid-row: 2 / span 3;
        grid-column: 9/ span 2;
        text-align: right;
        opacity: 0.75;
        margin-bottom: 0.4em;
        margin-right: 3px;
        align-self: self-end;
    }
    /*#endregion*/

    /*#endregion*/


    /*#region NET*/
    .net-weight {
        grid-column: 2;
        grid-row: 1 / span 2;
        height: 98%;
    }

    .net-left {
        font-size: 40px;
    }

    .net-center {
        font-size: 100px;
    }

    .net-right {
        font-size: 40px;
    }

    /*#endregion NET*/
</style>
...