Skip to content

Commit c45180a

Browse files
authored
feat(ISerialService): add ISerialService service (#4487)
* feat: 增加串口 * chore: 增加串口通讯服务 * doc: 更新示例 * refactor: 更新 Option 简化逻辑 * doc: 更新示例 * feat: 更新接口定义 * doc: 更新按钮状态 * feat: 实现写入逻辑 * doc: 更新示例文档 * refactor: 重构接收数据方法逻辑 * doc: 更新示例 * refactor: 调整写入方法参数 * doc: 更新示例 * style: 微调 Console 组件样式 * feat: 更新关闭逻辑 * doc: 更新示例 * doc: 更新示例 * refactor: 移除 console 代码 * doc: 实现循环发送逻辑 * doc: 分类更改为服务 * doc: 完善发送数据逻辑 * feat: 继承 IAsyncDispose 接口 * refactor: 代码优化 * refactor: 更正关闭串口逻辑 * refactor: 申请串口增加保护逻辑 * doc: 更新文档 * refactor: 更新文档 * doc: 更新文字 * doc: 增加新组件标志 * chore: bump version 8.10.4-beta03 * test: 更新单元测试 * refactor: 重命名类 * doc: 更新示例 * test: 更新单元测试 * test: 更新单元测试
1 parent fdd92e1 commit c45180a

22 files changed

+1095
-414
lines changed

src/BootstrapBlazor.Server/Components/Samples/WebSerials.razor

Lines changed: 111 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -7,147 +7,137 @@
77

88
<p>@((MarkupString)Localizer["WebSerialDescription"].Value)</p>
99

10-
<PackageTips Name="BootstrapBlazor.WebAPI" />
10+
<Pre>[Inject, NotNull]
11+
private ISerialService? SerialService { get; set; }</Pre>
12+
13+
<Tips>
14+
<ul class="ul-demo">
15+
<li>@((MarkupString)Localizer["WebSerialTipsLi1"].Value)</li>
16+
<li>@((MarkupString)Localizer["WebSerialTipsLi2"].Value)</li>
17+
</ul>
18+
<div>@((MarkupString)Localizer["WebSerialTipsTitle"].Value)</div>
19+
</Tips>
1120

1221
<DemoBlock Title="@Localizer["WebSerialNormalTitle"]" Introduction="@Localizer["WebSerialNormalIntro"]" Name="WebSerialNormal">
1322
<GroupBox Title="串口设置">
14-
<div class="row g-3">
15-
<div class="col-12 col-sm-6 col-md-4">
16-
<Select Color="Color.Primary" Items="BaudRateList" @bind-Value="@SelectedBaudRate" ShowLabel="true" />
23+
<div class="row form-inline g-3">
24+
<div class="col-12 col-sm-6">
25+
<Select Items="_baudRateList" @bind-Value="@_serialOptions.BaudRate" ShowLabel="true" DisplayText="@Localizer["BaudRateText"]" />
1726
</div>
18-
<div class="col-12 col-sm-6 col-md-4">
19-
<BootstrapInputNumber Color="Color.Primary" @bind-Value="@options.DataBits" ShowLabel="true" />
27+
<div class="col-12 col-sm-6">
28+
<Select Items="_dataBits" @bind-Value="@_serialOptions.DataBits" ShowLabel="true" DisplayText="@Localizer["DataBitsText"]" />
2029
</div>
21-
<div class="col-12 col-sm-6 col-md-4">
22-
<BootstrapInputNumber Color="Color.Primary" @bind-Value="@options.StopBits" ShowLabel="true" />
30+
<div class="col-12 col-sm-6">
31+
<Select Items="_stopBits" @bind-Value="@_serialOptions.StopBits" ShowLabel="true" DisplayText="@Localizer["StopBitsText"]" />
2332
</div>
24-
<div class="col-12 col-sm-6 col-md-4">
25-
<Select Color="Color.Primary" @bind-Value="@options.FlowControlType" ShowLabel="true" />
33+
<div class="col-12 col-sm-6">
34+
<Select @bind-Value="@_serialOptions.ParityType" ShowLabel="true" DisplayText="@Localizer["ParityTypeText"]" />
2635
</div>
27-
<div class="col-12 col-sm-6 col-md-4">
28-
<Select Color="Color.Primary" @bind-Value="@options.ParityType" ShowLabel="true" />
36+
<div class="col-12 col-sm-6">
37+
<Select Items="_bufferSizes" @bind-Value="@_serialOptions.BufferSize" ShowLabel="true" DisplayText="@Localizer["BufferSizeText"]" />
2938
</div>
30-
</div>
31-
</GroupBox>
32-
<GroupBox Title="其他功能" class="mt-3">
33-
<div class="row g-3">
34-
<div class="col-12 col-sm-6 col-md-4">
35-
<BootstrapInputNumber Color="Color.Primary" @bind-Value="@options.BufferSize" ShowLabel="true" />
39+
<div class="col-12 col-sm-6">
40+
<Select @bind-Value="@_serialOptions.FlowControlType" ShowLabel="true" DisplayText="@Localizer["FlowControlTypeText"]" />
41+
</div>
42+
<div class="col-12">
43+
<Button OnClick="GetPort" Text="@Localizer["RequestPortText"]"></Button>
44+
<Button IsDisabled="CheckOpen" OnClick="OpenPort" Text="@Localizer["OpenPortText"]" class="ms-2"></Button>
45+
<Button IsDisabled="CheckClose" OnClick="ClosePort" Text="@Localizer["ClosePortText"]" class="ms-2"></Button>
46+
</div>
47+
<div class="col-12">
48+
<Console Items="@_messages" Height="126" IsAutoScroll="true" HeaderText="@Localizer["ReadDataText"]" />
49+
</div>
50+
<div class="col-12">
51+
<div>@Localizer["WriteDataText"]</div>
3652
</div>
37-
<div class="col-12 col-sm-6 col-md-4">
38-
<Select Color="Color.Primary" @bind-Value="@options.AutoFrameBreakType" ShowLabel="true" />
53+
<div class="col-12">
54+
<Textarea IsDisabled="CheckClose" @bind-Value="@_sendData" rows="3"></Textarea>
3955
</div>
40-
<div class="col-12 col-sm-6 col-md-4">
41-
<BootstrapInput Color="Color.Primary" @bind-Value="@options.FrameBreakChar" ShowLabel="true" />
56+
<div class="col-12 col-sm-6">
57+
<Checkbox @bind-Value="_appendCRLF" ShowAfterLabel="true" DisplayText="@Localizer["CRLFText"]"></Checkbox>
58+
<Checkbox @bind-Value="_isHEX" ShowAfterLabel="true" DisplayText="@Localizer["HEXText"]" class="ms-3"></Checkbox>
4259
</div>
43-
<div class="col-12 col-sm-6 col-md-4">
44-
<Switch ShowLabel="true" @bind-Value="@options.AutoConnect" />
60+
<div class="col-12 col-sm-6">
61+
<Checkbox @bind-Value="_isLoop" ShowAfterLabel="true" DisplayText="@Localizer["LoopSendText"]" class="me-3"></Checkbox>
62+
<BootstrapInputGroup>
63+
<BootstrapInputGroupLabel DisplayText="@Localizer["LoopIntervalText"]"></BootstrapInputGroupLabel>
64+
<BootstrapInput @bind-Value="_sendInterval"></BootstrapInput>
65+
</BootstrapInputGroup>
4566
</div>
46-
<div class="col-12 col-sm-6 col-md-4">
47-
<Switch ShowLabel="true" @bind-Value="@options.OutputInHex" />
67+
<div class="col-12">
68+
<Button IsDisabled="CheckClose" OnClick="Write" Text="@Localizer["WriteButtonText"]"></Button>
4869
</div>
49-
<div class="col-12 col-sm-6 col-md-4">
50-
<Switch ShowLabel="true" @bind-Value="@options.InputWithHex" />
70+
<div class="col-12 col-sm-6">
71+
<Checkbox Value="_ring" ShowAfterLabel="true" DisplayText="RING"></Checkbox>
72+
<Checkbox Value="_dsr" ShowAfterLabel="true" DisplayText="DSR" class="ms-3"></Checkbox>
5173
</div>
52-
<div class="col-12 col-sm-6 col-md-4">
53-
<Switch ShowLabel="true" @bind-Value="@options.AutoGetSignals" />
74+
<div class="col-12 col-sm-6">
75+
<Checkbox Value="_cts" ShowAfterLabel="true" DisplayText="CTS"></Checkbox>
76+
<Checkbox Value="_dcd" ShowAfterLabel="true" DisplayText="DCD" class="ms-3"></Checkbox>
77+
</div>
78+
<div class="col-12">
79+
<Button IsDisabled="CheckClose" OnClick="GetSignals" Text="@Localizer["GetSignalsButtonText"]"></Button>
80+
</div>
81+
<div class="col-12 col-sm-6">
82+
<Display Value="@_usbInfo?.UsbVendorId" ShowLabel="true" DisplayText="VendorId"></Display>
83+
</div>
84+
<div class="col-12 col-sm-6">
85+
<Display Value="@_usbInfo?.UsbProductId" ShowLabel="true" DisplayText="ProductId"></Display>
86+
</div>
87+
<div class="col-12">
88+
<Button IsDisabled="CheckClose" OnClick="GetInfo" Text="@Localizer["GetInfoButtonText"]"></Button>
5489
</div>
5590
</div>
5691
</GroupBox>
92+
</DemoBlock>
5793

58-
<GroupBox Title="操作" class="mt-3">
59-
<div class="mt-3">
60-
@if (Flag)
61-
{
62-
<WebSerial @ref="WebSerial"
63-
OnConnect="@OnConnect"
64-
OnReceive="@OnReceive"
65-
OnSignals="@OnSignals"
66-
OnLog="@OnLog"
67-
OnError="@OnError"
68-
Options="@options" Debug
69-
ShowUI="false" />
70-
71-
<div @ref="WebSerial.Element">
72-
<div class="row m-3">
73-
<div class="col-12">
74-
<BootstrapInputGroup>
75-
<Button data-action="butConnect" Text="@options.ConnectBtnTitle" />
76-
@if (!IsConnected)
77-
{
78-
<Button Text="关闭" OnClick="OnApply" Icon="fa-fw fa-solid fa-close" />
79-
}
80-
else
81-
{
82-
<Button Text="@options.GetSignalsBtnTitle" OnClick="WebSerial.GetSignals" />
83-
}
84-
</BootstrapInputGroup>
85-
</div>
86-
</div>
87-
<div class="row m-3">
88-
<div class="col-6">
89-
<textarea class="form-control" type="text" data-action="fname" style="visibility:hidden;" />
90-
</div>
91-
<div class="col-6">
92-
<Button data-action='butwrite' style="visibility:hidden;" Text="@options.WriteBtnTitle" />
93-
</div>
94-
</div>
95-
@if (WebSerial != null && IsConnected)
96-
{
97-
<div class="row m-3">
98-
<div class="col-12 col-sm-4 col-md-3 col-lg-auto">
99-
<Switch @bind-Value="WebSerial.DTR" ShowLabel="true" OnValueChanged="WebSerial.SetSignalDTR" />
100-
</div>
101-
<div class="col-12 col-sm-4 col-md-3 col-lg-auto">
102-
<Switch @bind-Value="WebSerial.RTS" ShowLabel="true" OnValueChanged="WebSerial.SetSignalRTS" />
103-
</div>
104-
<div class="col-12 col-sm-4 col-md-3 col-lg-auto">
105-
<Switch @bind-Value="WebSerial.Break" ShowLabel="true" OnValueChanged="WebSerial.SetSignalBreak" />
106-
</div>
107-
</div>
108-
<div class="row m-3">
109-
<div class="col-12 col-sm-4 col-md-3 col-lg-auto">
110-
RING
111-
<Light Color="@(Signals.RING?Color.Success:Color.None)"></Light>
112-
</div>
113-
<div class="col-12 col-sm-4 col-md-3 col-lg-auto">
114-
DSR
115-
<Light Color="@(Signals.DSR?Color.Success:Color.None)"></Light>
116-
</div>
117-
<div class="col-12 col-sm-4 col-md-3 col-lg-auto">
118-
CTS
119-
<Light Color="@(Signals.CTS?Color.Success:Color.None)"></Light>
120-
</div>
121-
<div class="col-12 col-sm-4 col-md-3 col-lg-auto">
122-
DCD
123-
<Light Color="@(Signals.DCD?Color.Success:Color.None)"></Light>
124-
</div>
125-
</div>
126-
}
127-
</div>
128-
<pre data-action="log"></pre>
129-
}
130-
else
131-
{
132-
<div class="col-6">
133-
<Button Text="应用" OnClick="OnApply" Icon="fa-fw fa-solid fa-play" />
134-
</div>
135-
}
136-
</div>
137-
</GroupBox>
94+
<p class="code-label mt-3">1. 服务注入</p>
13895

139-
<section ignore>
140-
<p>注意:本例子改变设置要点关闭再重新应用</p>
141-
<pre style="overflow-y:scroll;max-height:500px;">@_message</pre>
142-
<pre style="color:green">@_statusMessage</pre>
143-
<pre style="color:red">@_errorMessage</pre>
144-
<hr />
145-
<a href="https://github.com/densen2014/Densen.Extensions/blob/master/Demo/Receive_DSP.ino">附件: Arduino源码示例</a>
146-
</section>
147-
</DemoBlock>
96+
<Pre>[Inject]
97+
[NotNull]
98+
private ISerialService? SerialService { get; set; }</Pre>
14899

100+
<p class="code-label">2. 申请串口权限</p>
101+
<p>调用 <code>SerialService</code> 实例方法 <code>GetPort</code> 即可,通过 <code>IsSupport</code> 进行浏览器是否支持判断</p>
102+
103+
<Pre>_serialPort = await SerialService.GetPort();
104+
if (SerialService.IsSupport == false)
105+
{
106+
await ToastService.Error(Localizer["NotSupportSerialTitle"], Localizer["NotSupportSerialContent"]);
107+
}</Pre>
108+
109+
<p class="code-label">3. 打开串口</p>
110+
111+
<ul class="ul-demo">
112+
<li>如果需要读取数据,请先设置 <code>ISerialPort</code> 实例 <code>DataReceive</code> 参数</li>
113+
<li>调用 <code>ISerialPort</code> 实例方法 <code>Open</code> 打开串口,可通过 <code>SerialPortOptions</code> 参数设置 <code>波特率</code> 等信息</li>
114+
</ul>
115+
116+
<Pre>private async Task OpenPort()
117+
{
118+
if (_serialPort != null)
119+
{
120+
_serialPort.DataReceive = async data =>
121+
{
122+
_messages.Add(new ConsoleMessageItem()
123+
{
124+
IsHtml = true,
125+
Message = $"{DateTime.Now}: --> Text: {Encoding.ASCII.GetString(data)} HEX: {Convert.ToHexString(data)}"
126+
});
127+
await InvokeAsync(StateHasChanged);
128+
};
129+
await _serialPort.Open(_serialOptions);
130+
}
131+
}</Pre>
149132

150-
<AttributeTable Items="@GetAttributes()" />
133+
<p class="code-label">4. 关闭串口</p>
151134

152-
<AttributeTable Title="@Localizer["WebSerialOptionsText"]" Items="@GetWebSerialOptionsAttributes()" />
135+
<p>调用 <code>ISerialPort</code> 实例方法 <code>Close</code> 关闭串口,请注意路由切换时,请调用其 <code>DisposeAsync</code> 方法释放资源</p>
153136

137+
<Pre>private async Task ClosePort()
138+
{
139+
if (_serialPort != null)
140+
{
141+
await _serialPort.Close();
142+
}
143+
}</Pre>

0 commit comments

Comments
 (0)