bh003- Blazor hybrid / Maui 使用蓝牙BLE快速教程

这篇具有很好参考价值的文章主要介绍了bh003- Blazor hybrid / Maui 使用蓝牙BLE快速教程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 建立工程 bh003_ble

源码 https://github.com/densen2014/BlazorHybrid/tree/master/bh100days/bh003_ble?WT.mc_id=DT-MVP-5005078

2. 添加 nuget 包

<PackageReference Include="BlazorHybrid.Maui.Permissions" Version="0.0.2" />
<PackageReference Include="BootstrapBlazor" Version="7.*" />
<PackageReference Include="Densen.Extensions.BootstrapBlazor" Version="7.*" />

BlazorHybrid.Maui.Permissions 因为源码比较长,主要是一些检查和申请权限,BLE权限相关代码,就不占用篇幅列出,感兴趣的同学直接打开源码参考

顺便打开可空 <Nullable>enable</Nullable>

3. 添加蓝牙权限

安卓

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application>
  <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  <uses-permission android:name="android.permission.INTERNET" />
  <!--蓝牙-->
  <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />

  <!-- csproj文件指定SupportedOSPlatformVersion android 28.0 可以继续使用安卓9的权限 -->
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
  <uses-permission android:name="android.permission.BLUETOOTH"/>
  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

  <!-- csproj文件指定SupportedOSPlatformVersion android 31.0 使用安卓12的权限 -->
  <!-- Android 12以下才需要定位权限,Android 9以下官方建议申请ACCESS_COARSE_LOCATION -->

  <!--<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30"/>
	<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30"/>
	<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"/>
	<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"/>-->

  <!-- Android 12在不申请定位权限时,必须加上android:usesPermissionFlags="neverForLocation",否则搜不到设备 -->
  <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation"/>

  <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
  <!--蓝牙 END-->
</manifest>

iOS

Info.plist

    <key>UIBackgroundModes</key>
    <array>
        <string>bluetooth-central</string>
        <string>bluetooth-peripheral</string>
    </array>
    <key>NSBluetoothPeripheralUsageDescription</key>
    <string>此应用程序需要访问您的蓝牙。请根据要求授予权限.</string>
    <key>NSBluetoothAlwaysUsageDescription</key>
    <string>此应用程序需要访问您的蓝牙。请根据要求授予权限.</string>

以下是完整文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>LSRequiresIPhoneOS</key>
    <true/>
    <key>UIDeviceFamily</key>
    <array>
        <integer>1</integer>
        <integer>2</integer>
    </array>
    <key>UIRequiredDeviceCapabilities</key>
    <array>
        <string>arm64</string>
    </array>
    <key>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>UISupportedInterfaceOrientations~ipad</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationPortraitUpsideDown</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
    <key>XSAppIconAssets</key>
    <string>Assets.xcassets/appicon.appiconset</string>
    <key>UIBackgroundModes</key>
    <array>
        <string>bluetooth-central</string>
        <string>bluetooth-peripheral</string>
    </array>
    <key>NSBluetoothPeripheralUsageDescription</key>
    <string>此应用程序需要访问您的蓝牙。请根据要求授予权限.</string>
    <key>NSBluetoothAlwaysUsageDescription</key>
    <string>此应用程序需要访问您的蓝牙。请根据要求授予权限.</string>

</dict>
</plist>

Windows

Package.appxmanifest

bh003- Blazor hybrid / Maui 使用蓝牙BLE快速教程

4. 编辑 Index.html 文件,引用 BootstrapBlazor UI 库.

完整文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
    <title>bh003_ble</title>
    <base href="/" />
    <link href="_content/BootstrapBlazor.FontAwesome/css/font-awesome.min.css" rel="stylesheet">
    <link href="_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css" rel="stylesheet">
    <link href="_content/BootstrapBlazor/css/motronic.min.css" rel="stylesheet">
    <link href="css/app.css" rel="stylesheet" />
    <link href="bh003_ble.styles.css" rel="stylesheet" />
</head>

<body>

    <div class="status-bar-safe-area"></div>

    <div id="app">Loading...</div>

    <div id="blazor-error-ui">
        An unhandled error has occurred.
        <a href="" class="reload">Reload</a>
        <a class="dismiss"><i class="fa-solid fa-xmark"></i></a>
    </div>

    <script src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js"></script>
    <script src="_framework/blazor.webview.js" autostart="false"></script>

</body>

</html>

bh003- Blazor hybrid / Maui 使用蓝牙BLE快速教程

5. 添加 BootstrapBlazorRoot 组件

Main.razor 文件添加 BootstrapBlazorRoot 组件

bh003- Blazor hybrid / Maui 使用蓝牙BLE快速教程

6. 添加命名空间引用

_Imports.razor

@using BootstrapBlazor.Components

7. 添加服务

MauiProgram.cs

添加

            builder.Services.AddDensenExtensions();
            builder.Services.ConfigureJsonLocalizationOptions(op =>
            {
                // 忽略文化信息丢失日志
                op.IgnoreLocalizerMissing = true;

            });
            builder.Services.AddSingleton<BluetoothLEServices>();
            builder.Services.AddScoped<IStorage, StorageService>();

完整文件

using bh003_ble.Data;
using Microsoft.Extensions.Logging;
using BlazorHybrid.Maui.Shared;
using BootstrapBlazor.WebAPI.Services;

namespace bh003_ble
{
    public static class MauiProgram
    {
        public static MauiApp CreateMauiApp()
        {
            var builder = MauiApp.CreateBuilder();
            builder
                .UseMauiApp<App>()
                .ConfigureFonts(fonts =>
                {
                    fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                });

            builder.Services.AddMauiBlazorWebView();

#if DEBUG
		builder.Services.AddBlazorWebViewDeveloperTools();
		builder.Logging.AddDebug();
#endif

            builder.Services.AddSingleton<WeatherForecastService>();
            builder.Services.AddDensenExtensions();
            builder.Services.ConfigureJsonLocalizationOptions(op =>
            {
                // 忽略文化信息丢失日志
                op.IgnoreLocalizerMissing = true;

            });
            builder.Services.AddSingleton<BluetoothLEServices>();
            builder.Services.AddScoped<IStorage, StorageService>();

            return builder.Build();
        }
    }
}

8. 添加代码后置文件 Pages/Index.razor.cs

Index.razor.cs ``` using BlazorHybrid.Core.Device; using BlazorHybrid.Maui.Shared; using BootstrapBlazor.Components; using BootstrapBlazor.WebAPI.Services; using Microsoft.AspNetCore.Components; using System.Diagnostics.CodeAnalysis;

namespace bh003_ble.Pages;

public partial class Index : IAsyncDisposable
{
[Inject, NotNull]
BluetoothLEServices? MyBleTester { get; set; }
[Inject, NotNull] protected IStorage? Storage { get; set; }
[Inject, NotNull] protected ToastService? ToastService { get; set; }

public void SetTagDeviceName(BleTagDevice ble)
{
    MyBleTester.TagDevice = ble;

    if (!isInit)
    {
        MyBleTester.OnMessage += OnMessage;
        MyBleTester.OnDataReceived += OnDataReceived;
        MyBleTester.OnStateConnect += OnStateConnect;
        isInit = true;
    }
}

public event Action<string>? OnMessage;
public event Action<string>? OnDataReceived;
public event Action<bool>? OnStateConnect;

bool isInit = false;

public async Task<List<BleDevice>?> StartScanAsync() => await MyBleTester.StartScanAsync();

public async Task<List<BleService>?> ConnectToKnownDeviceAsync(Guid deviceID, string? deviceName = null) => await MyBleTester.ConnectToKnownDeviceAsync(deviceID, deviceName);

public async Task<List<BleCharacteristic>?> GetCharacteristicsAsync(Guid serviceid) => await MyBleTester.GetCharacteristicsAsync(serviceid);

public async Task<string?> ReadDeviceName(Guid? serviceid, Guid? characteristic) => await MyBleTester.ReadDeviceName(serviceid, characteristic);

public async Task<byte[]?> ReadDataAsync(Guid characteristic) => await MyBleTester.ReadDataAsync(characteristic);

public async Task<bool> SendDataAsync(Guid characteristic, byte[] ary) => await MyBleTester.SendDataAsync(characteristic, ary);

public async Task<bool> DisConnectDeviceAsync() => await MyBleTester.DisConnectDeviceAsync();


public Task<bool> BluetoothIsBusy() => MyBleTester.BluetoothIsBusy();




private bool IsScanning = false;
private List<BleDevice>? Devices { get; set; }
private List<BleService>? Services { get; set; }
private List<BleCharacteristic>? Characteristics { get; set; }
private string? ReadResult { get; set; }
private string? Message { get; set; } = "";

BleTagDevice BleInfo { get; set; } = new BleTagDevice();

private List<SelectedItem> DemoList { get; set; } = new List<SelectedItem>() { new SelectedItem() { Text = "测试数据", Value = "" } };
private List<SelectedItem> DeviceList { get; set; } = new List<SelectedItem>();
private List<SelectedItem> ServiceidList { get; set; } = new List<SelectedItem>();
private List<SelectedItem> CharacteristicList { get; set; } = new List<SelectedItem>();

private Dictionary<string, object>? IsScanningCss => IsScanning ? new() { { "disabled", "" }, } : null;

bool IsAutoConnect { get; set; }
bool IsAuto { get; set; }
bool IsInit { get; set; }

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        await Init();
    }
}

async Task<bool> Init()
{
    try
    {

        if (IsInit) return true;

        if (await BluetoothIsBusy())
        {
            await ToastService.Warning("蓝牙正在使用中,请稍后再试");
            return false;
        }
        OnMessage += Tools_OnMessage;
        OnDataReceived += Tools_OnDataReceived;
        OnStateConnect += Tools_OnStateConnect;
        SetTagDeviceName(BleInfo);
        IsInit = true;

        StateHasChanged();

        var deviceID = await Storage.GetValue("bleDeviceID", string.Empty);
        if (!string.IsNullOrEmpty(deviceID))
        {
            BleInfo.Name = await Storage.GetValue("bleDeviceName", string.Empty);
            BleInfo.DeviceID = Guid.Parse(deviceID);
            var serviceid = await Storage.GetValue("bleServiceid", string.Empty);
            if (!string.IsNullOrEmpty(serviceid)) BleInfo.Serviceid = Guid.Parse(serviceid);
            var characteristic = await Storage.GetValue("bleCharacteristic", string.Empty);
            if (!string.IsNullOrEmpty(characteristic)) BleInfo.Characteristic = Guid.Parse(characteristic);
            var auto = await Storage.GetValue("bleAutoConnect", string.Empty);
            if (auto == "True")
            {
                IsAuto = true;
                await AutoRead();

            }
        }
        return true;

    }
    catch (Exception ex)
    {
        System.Console.WriteLine(ex.Message);
    }
    return false;
}


private async Task AutoRead()
{
    Services = null;
    Characteristics = null;
    Message = "";
    ReadResult = "";
    Devices = new List<BleDevice>() { new BleDevice() { Id = BleInfo.DeviceID, Name = BleInfo.Name } };
    DeviceList = new List<SelectedItem>() { new SelectedItem() { Text = BleInfo.Name, Value = BleInfo.DeviceID.ToString() } };
    IsAutoConnect = true;
    await OnDeviceSelect();
    IsAutoConnect = false;
}

private async Task OnStateChanged(bool value)
{
    await Storage.SetValue("bleAutoConnect", value.ToString());
}

private void Tools_OnStateConnect(bool obj)
{

}

private async void Tools_OnDataReceived(string message)
{
    ReadResult = message;
    Tools_OnMessage(message);
    await InvokeAsync(StateHasChanged);
}

private async void Tools_OnMessage(string message)
{
    if (Message != null && Message.Length > 500) Message = Message.Substring(0, 500);
    Message = $"{message}\r\n{Message}";
    await InvokeAsync(StateHasChanged);
}


//扫描外设
private async void ScanDevice()
{
    if (!await Init()) return;

    IsScanning = true;
    Devices = null;
    Services = null;
    Characteristics = null;
    Message = "";
    ReadResult = "";
    DeviceList = new List<SelectedItem>() { new SelectedItem() { Text = "请选择...", Value = "" } };

    //开始扫描
    Devices = await StartScanAsync();

    if (Devices != null)
    {
        Devices.ForEach(a => DeviceList.Add(new SelectedItem() { Active = IsAutoConnect && a.Id == BleInfo.DeviceID, Text = a.Name ?? a.Id.ToString(), Value = a.Id.ToString() }));
    }

    IsScanning = false;

    //异步更新UI
    await InvokeAsync(StateHasChanged);
}

//连接外设
private async Task OnDeviceSelect(SelectedItem item)
{
    if (IsAutoConnect || item.Value == "") return;
    BleInfo.Name = item.Text;
    BleInfo.DeviceID = Guid.Parse(item.Value);
    await OnDeviceSelect();
}

private async Task OnDisConnectDevice()
{
    if (await DisConnectDeviceAsync())
        await ToastService.Success("断开成功");
    else
        await ToastService.Error("断开失败");
}

private async Task OnDeviceSelect()
{

    Services = null;
    Characteristics = null;
    Message = "";
    ReadResult = "";
    ServiceidList = new List<SelectedItem>() { new SelectedItem() { Text = "请选择...", Value = "" } };
    //连接外设
    Services = await ConnectToKnownDeviceAsync(BleInfo.DeviceID, BleInfo.Name);
    if (Services != null)
    {
        Services.ForEach(a => ServiceidList.Add(new SelectedItem() { Active = IsAutoConnect && a.Id == BleInfo.Serviceid, Text = a.Name ?? a.Id.ToString(), Value = a.Id.ToString() }));
        await Storage.SetValue("bleDeviceID", BleInfo.DeviceID.ToString());
        await Storage.SetValue("bleDeviceName", BleInfo.Name ?? "上次设备");
        if (BleInfo.Serviceid != Guid.Empty && IsAutoConnect)
        {
            await OnServiceidSelect();
        }
    }

    //异步更新UI
    await InvokeAsync(StateHasChanged);
}


private async Task OnServiceidSelect(SelectedItem item)
{
    if (IsAutoConnect || item.Value == "") return;
    BleInfo.Serviceid = Guid.Parse(item.Value);
    await OnServiceidSelect();
}
private async Task OnServiceidSelect()
{
    Characteristics = null;
    Message = "";
    ReadResult = "";
    CharacteristicList = new List<SelectedItem>() { new SelectedItem() { Text = "请选择...", Value = "" } };
    Characteristics = await GetCharacteristicsAsync(BleInfo.Serviceid);
    if (Characteristics != null)
    {
        Characteristics.ForEach(a => CharacteristicList.Add(new SelectedItem() { Active = IsAutoConnect && a.Id == BleInfo.Characteristic, Text = a.Name ?? a.Id.ToString(), Value = a.Id.ToString() }));
        await Storage.SetValue("bleServiceid", BleInfo.Serviceid.ToString());
        if (BleInfo.Characteristic != Guid.Empty && IsAutoConnect)
        {
            await ReadDeviceName();
        }
    }
    await InvokeAsync(StateHasChanged);
}

private async Task OnCharacteristSelect(SelectedItem item)
{
    if (IsAutoConnect) return;
    BleInfo.Characteristic = Guid.Parse(item.Value);
    await ReadDeviceName();
}

//读取数值
private async Task ReadDeviceName()
{
    Message = "";

    //读取数值
    ReadResult = await ReadDeviceName(BleInfo.Serviceid, BleInfo.Characteristic);
    await Storage.SetValue("bleCharacteristic", BleInfo.Characteristic.ToString());

    if (!string.IsNullOrEmpty(ReadResult)) await ToastService.Information("读取成功", ReadResult);
    //异步更新UI
    await InvokeAsync(StateHasChanged);
}

private async Task ReadDataAsync()
{
    Message = "";
    //读取数值
    var res = await ReadDataAsync(BleInfo.Characteristic);
    if (!string.IsNullOrEmpty(ReadResult)) await ToastService.Information("读取成功", res.ToString());

    //异步更新UI
    await InvokeAsync(StateHasChanged);
}

private async Task SendDataAsync()
{
    Message = "";
    //读取数值
    var res = await SendDataAsync(BleInfo.Characteristic, null);
    await ToastService.Information("成功发送", res.ToString());

    //异步更新UI
    await InvokeAsync(StateHasChanged);
}

ValueTask IAsyncDisposable.DisposeAsync()
{
    OnMessage -= Tools_OnMessage;
    OnDataReceived -= Tools_OnDataReceived;
    OnStateConnect -= Tools_OnStateConnect;
    return new ValueTask();
}

}

</details>

### 9. 添加 UI Pages/Index.razor

Index.razor

@page "/"

蓝牙

@if (Devices != null) {
<div class="row g-3">
    <div class="col-12 col-sm-3">
        <Select TValue="Guid" Items="DeviceList" OnSelectedItemChanged="OnDeviceSelect" />
    </div>
    @if (Services != null)
    {
        <div class="col-12 col-sm-3">
            <Select TValue="Guid" Items="ServiceidList" OnSelectedItemChanged="OnServiceidSelect" />
        </div>
        @if (Characteristics != null)
        {
            <div class="col-12 col-sm-3">
                <Select TValue="Guid" Items="CharacteristicList" OnSelectedItemChanged="OnCharacteristSelect" />
            </div>
            @if (ReadResult != null)
            {
                <div class="col-12 col-sm-3">
                    <Display TValue="string" Value="@ReadResult" />
                </div>
            }
        }
    }
</div>

}

@if (BleInfo.Name != null)
{

<div class="g-3">
    历史连接 <br />
    @BleInfo.Name <br />
    @BleInfo.DeviceID <br />
    @BleInfo.Serviceid <br />
    @BleInfo.Characteristic <br />
    @ReadResult <br />
</div>

}
文章来源地址https://www.toymoban.com/news/detail-664907.html

@Message

### 10. 运行
 
![](https://img2023.cnblogs.com/blog/1980213/202308/1980213-20230822234505726-1052631155.png)

![](https://img2023.cnblogs.com/blog/1980213/202308/1980213-20230822234517226-1494747248.png)

![](https://img2023.cnblogs.com/blog/1980213/202308/1980213-20230822235243146-569261763.png)

### 11. 相关资料

如何远程调试 MAUI blazor / Blazor Hybrid
https://www.cnblogs.com/densen2014/p/16988516.html

到了这里,关于bh003- Blazor hybrid / Maui 使用蓝牙BLE快速教程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信小程序低功耗蓝牙BLE快速开发js

    目的: 1、为了能三分钟快速开发BLE模块,特此做一个笔记,按照笔记的顺序开发,能够简单、快速、规范。 2、如果以后觉得有必要改动的地方就在这里更改。 3、主要是记录BLE连接的步骤。 https://note.youdao.com/ynoteshare/index.html?id=d662c9c1c58121ec28901d78d9aa5e80 比较完整的微信小程

    2024年02月10日
    浏览(74)
  • 在Winform中一分钟入门使用好看性能还好的Blazor Hybrid

    创建完成打开项目文件 WinformDesktop.csproj 文件 打开以后的项目文件,启动项目 这是提供的简单的项目Demo 我们只需要使用masa Blazor提供的模板,一分钟入门使用,你要做的只需要去Masa Blazor组件库去CV代码, 并且Masa Blazor也提供了Blazor在线编辑器去体验Masa Blazor的组件 MASA Try

    2024年02月05日
    浏览(39)
  • Blazor HyBrid 授权讲解

    本文介绍 ASP.NET Core 对 Blazor Hybrid 应用中的安全配置和管理及 ASP.NET Core Identity 的支持。 Blazor Hybrid 应用中的身份验证由本机平台库处理,因为后者提供了浏览器沙盒无法给予的经过增强的安全保证。 本机应用的身份验证使用特定于操作系统的机制或通过联合协议,如 OpenID

    2024年02月07日
    浏览(34)
  • 006.合宙ESP32-C3+蓝牙调试器通过BLE发送接收数据教程

    在平衡小车制作过程中,需要对KP/KD/KSP/KSI等PID系数进行调试,而平衡小车无法通过USB等进行有线调试,而ESP32-C3自带蓝牙+WIFI,使用WIFI比较吃算力,故选择通过蓝牙进行调参,同时能够将Angle/Encoder/PWM等数据回传至手机端进行查看。 前期通过查找资料,发现合宙ESP32-C3自带蓝

    2024年02月03日
    浏览(58)
  • 在winform blazor hybrid中绘图

    前几天跟大家介绍了在winform中使用blazor hybrid,而且还说配上blazor的ui可以让我们的winform程序设计的更加好看,接下来我想以一个在winform blazor hybrid中绘图的例子来进行说明,希望对你有所帮助。 在开始之前,先给大家演示一下效果,如下所示: 如果你对具体实现感兴趣,可

    2024年02月05日
    浏览(60)
  • [MAUI]深入了解.NET MAUI Blazor与Vue的混合开发

    .NET MAUI结合Vue的混合开发可以使用更加熟悉的Vue的语法代替Blazor语法,你现有项目不必重写。之前写过一篇 [MAUI] 在.NET MAUI中结合Vue实现混合开发 ,其中介绍了如何创建一个vue应用并将其打包至MAUI项目,这种方式依赖vue-cli创建和打包静态站点,好处是可以使用Node.js 的构建但

    2024年02月08日
    浏览(43)
  • MAUI+Blazor混合应用开发示例

    笔者之前在公司搭建过一套生产管理系统,该系统要求能和硬件进行串口通信,同时又要方便后台进行信息查询。笔者给出的解决方案就是: MAUI + Blazor ,这样只需要提供一套UI,就能满足桌面端、移动端和Web端三种不同应用场景。今天要介绍的是基于桌面端的开发实现(实

    2024年02月11日
    浏览(34)
  • MAUI+Blazor:windows 打包踩坑

    最近打算研究一下MAUI+Blazor,争取在今年年底之前彻底搞懂MAUI+Blazor的安装模式, Windows 4种安装程序格式MSI,EXE、AppX和MSIX优缺点对比以及后缀为 .msixbundle的文件怎么安装? 我们windows一般用exe文件进行安装,exe是最普遍的安装文件格式,原因是exe对于开发者具有最高的自定义

    2024年02月13日
    浏览(29)
  • ESP32经典蓝牙和BLE的使用 (基于Arduino)

    经典蓝牙串口通信 该程序效果如下 ESP32完成初始化后生成一个蓝牙信号 手机通过蓝牙串口发送字符 B ,LED点亮 手机通过蓝牙串口发送字符 A ,LED熄灭 低功耗蓝牙 BLE (常用) BLE GATT协议 GATT全称Generic Attribute Profile, GATT 代表通用属性,它定义了暴露给连接的BLE设备的分层数据结

    2024年02月01日
    浏览(48)
  • Blazor HyBrid在香橙派(Ubuntu Arm)运行的效果

    准备香橙派一块!当前教程使用的是香橙派5 4G开发板 准备.NET环境 安装.NET Core依赖 下载.NET 7 SDK 创建dotnet文件夹并解压 创建软连接 查看版本 如果需要使用 https 请使用 一下是一个 Masa Blazor 可以用于在 Arm 设备运行的程序 项目开源地址: 239573049/MasaLinuxDesktop (github.com) 然后在

    2024年02月06日
    浏览(140)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包