首页 > 编程语言 >Xamarin.Forms-手机串口调试程序开发文档

Xamarin.Forms-手机串口调试程序开发文档

时间:2024-11-13 09:57:27浏览次数:1  
标签:Xamarin ObservableProperty 串口 SerialPortHelper 调试程序 new using public string

Xamarin.Forms 手机串口调试程序开发文档
1.开发背景:
因工作性质特殊,需要通过手持设备与电力设备进行报文通讯,达到设备状态、地址码等数据的下发及查询功能。但因为后期手持设备厂家停产,维护不及时,造成设备稀缺,无法满足正常工作需要,特制作此手机APP,通过串口驱动连接串口转红外设备,使之发送与接收来自终端的报文信息,达到数据交互的目的,以下是软件主界面:

2.开发框架:

开发工具:VisualStudio2022,框架采用Maui框架进行开发。
3.开发所用设备及接口:
开发过程中,引用Android.UsbSerial 程序集;设备采用Type_C 转USB转换器与USB红外设备进行连接,根据设备类型在程序集中匹配合适驱动,通过报文的编码逻辑组织报文,以达到数据发送和接收的目的。
4.界面功能设计:
界面共设计两个,第一个是设备搜寻页面及安全提示内容,插入串口设备后,如果驱动合适,则会显示设备的详细信息,包括设备型号、驱动信息、生产厂家等。如果驱动不合适,则不会显示设备的详细信息等内容。
第二个页面则是数据功能页面,包括端口号、波特率、起止位、校验位的设置,以及相关的操作选项设置等。通过设置相关的参数及功能,将报文进行重组,发送报文到终端设备,终端设备根据报文的内容进行动作。
5.主要技术问题:
本软件开发过程中遇到的主要问题,还是对串口驱动的应用知识方面了解太少;第一次做Maui方面的开发,不太熟练;手机APP相关软件的开发涉及的项目太少,经验不足。
6.部分代码:
using Android.Icu.Text;
using Android.Telephony.Euicc;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Hoho.Android.UsbSerial.Driver;
using MauiUsbSerialForAndroid.Converter;
using MauiUsbSerialForAndroid.Helper;
using MauiUsbSerialForAndroid.Model;
using Microsoft.Maui.Controls.Compatibility.Platform.Android;
using System.Collections.ObjectModel;
using System.Text;
using System.Text.RegularExpressions;

namespace MauiUsbSerialForAndroid.ViewModel
{
[ObservableObject]
public partial class SerialDataViewModel : IQueryAttributable
{
[ObservableProperty]
bool isOpen = false;
public UsbDeviceInfo DeviceInfo { get; set; }
public string[] AllEncoding { get; } = new string[] { "HEX", "ASCII", "UTF-8", "GBK", "GB2312", "Unicode" };
public int[] AllBaudRate { get; } = new[] { 300, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 43000, 57600, 76800, 115200, 128000, 230400, 256000, 460800, 921600, 1382400 };
public int[] AllDataBits { get; } = new[] { 5, 6, 7, 8 };
public string[] AllParity { get; } = Enum.GetNames(typeof(Parity));
public string[] AllStopBits { get; } = Enum.GetNames(typeof(StopBits));

    [ObservableProperty]
    string encodingSend = "HEX";
    [ObservableProperty]
    string encodingReceive = "HEX";
    [ObservableProperty]
    int intervalReceive = 50;
    [ObservableProperty]
    int intervalSend = 1000;
    [ObservableProperty]
    bool cycleToSend = false;
    [ObservableProperty]
    bool showTimeStamp = true;
    [ObservableProperty]
    bool autoScroll = true;
    [ObservableProperty]
    string sendData = "";
    [ObservableProperty]
    SerialOption serialOption = new SerialOption();
    [ObservableProperty]
    string softName = "";
    // 终端地址;
    [ObservableProperty]
    string terminalAddr = "20785593";
    //终端操作;
    [ObservableProperty]
    string terminalOperation = "";
    //测量点操作;
    [ObservableProperty]
    string pointOperation = "";
    //测量点编号;
    [ObservableProperty]
    string pointIndex = "";
    //终端操作;
    [ObservableProperty]
    bool terminalChecked = true;
    //测量点操作;
    [ObservableProperty]
    bool pointChecked;
    //信息操作;
    [ObservableProperty]
    bool msgChecked;
    public ObservableCollection<SerialLog> Datas { get; } = new();
    System.Timers.Timer timerSend;
    [ObservableProperty]
    string receivedText;
    public SerialDataViewModel()
    {
        SerialPortHelper.WhenDataReceived().Subscribe(data =>
        {
            ReceivedText = SerialPortHelper.GetData(data, EncodingReceive);
            //Shell.Current.DisplayAlert("TooFast", ReceivedText, "ok");
            if (receivedText.Length > 0)
            {
                AddLog(new SerialLog($"{TerminalAddr}: {TerminalOperation} 成功", false));
            }
            else
            {
                AddLog(new SerialLog($"{TerminalAddr}: {TerminalOperation} 失败", false));
            }
            //AddLog(new SerialLog($"终端地址:{convertedText}", false));
            //AddLog(new SerialLog($"终端地址:{convertedText}", false));
        });
        timerSend = new System.Timers.Timer(intervalSend);
        timerSend.Elapsed += TimerSend_Elapsed;
        timerSend.Enabled = false;

        SerialPortHelper.WhenUsbDeviceAttached((usbDevice) =>
        {
            if (usbDevice.DeviceId == DeviceInfo.Device.DeviceId)
            {
                AddLog(new SerialLog("Usb device attached", false));
                Open();
            }
        });

        SerialPortHelper.WhenUsbDeviceDetached((usbDevice) =>
        {
            if (usbDevice.DeviceId == DeviceInfo.Device.DeviceId)
            {
                AddLog(new SerialLog("Usb device detached", false));
                Close();
            }
        });
    }
    private void TimerSend_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        Send();
    }
    partial void OnIntervalReceiveChanged(int value)
    {
        SerialPortHelper.IntervalChange(value);
    }
    async partial void OnIntervalSendChanged(int value)
    {
        if (value < 5)
        {
            await Shell.Current.DisplayAlert("TooFast", "Set at least 5 milliseconds", "ok");
            IntervalSend = 5;
        }
        timerSend.Interval = IntervalSend;
    }
    partial void OnCycleToSendChanged(bool value)
    {
        timerSend.Enabled = value;
    }
    Regex regHexRemove = new Regex("[^a-fA-F0-9 ]");
    partial void OnSendDataChanged(string value)
    {
        if (EncodingSend == "HEX")
        {
            string temp = regHexRemove.Replace(value, "");
            if (SendData != temp)
            {
                Shell.Current.DisplayAlert("Only hex", "Only HEX characters can be entered", "Ok");
                SendData = temp;
            }
        }
    }
    public void ApplyQueryAttributes(IDictionary<string, object> query)
    {
        if (query.ContainsKey("Serial"))
        {
            DeviceInfo = (UsbDeviceInfo)query["Serial"];
            Open();
        }
    }
    [RelayCommand]
    public void Toggle()
    {
        if (IsOpen)
        {
            Close();
        }
        else
        {
            Open();
        }
    }
    [RelayCommand]
    public async void Open()
    {
        if (!IsOpen)
        {
            string r = await SerialPortHelper.RequestPermissionAsync(DeviceInfo);
            if (SerialPortHelper.CheckError(r, showDialog: false))
            {
                r = SerialPortHelper.Open(DeviceInfo, SerialOption);
                if (SerialPortHelper.CheckError(r, showDialog: false))
                {
                    IsOpen = true;
                }
                else
                {
                    AddLog(new SerialLog(r, false));
                }
            }
            else
            {
                AddLog(new SerialLog(r, false));
            }
        }
    }
    [RelayCommand]
    public void Close()
    {
        try
        {
            SerialPortHelper.Close();
            CycleToSend = false;
            IsOpen = false;
        }
        catch (Exception)
        {
        }
    }
    [RelayCommand]
    public void Clear()
    {
        Datas.Clear();
    }
    /// <summary>
    /// 发送信息,先判断是何种操作;
    /// </summary>
    [RelayCommand]
    public void Send()
    {
        if (SoftName.Length == 0)
        {
            Shell.Current.DisplayAlert("Choose right softname", "请选择合适的操作软件!", "Ok");
        }
        else
        {
            if ("二层集抄".Equals(SoftName))
            {
                EcjcConverter ecjc = new EcjcConverter();
                if (terminalChecked is true) //如果是终端操作;
                {
                    if (TerminalOperation.Equals("读终端地址"))
                    {
                        SendData = ecjc.ReadAddressMethod(TerminalAddr);
                       
                    }
                    else if ("写终端地址".Equals(TerminalOperation))
                    {
                        SendData=ecjc.WriteAddressMethod(TerminalAddr);
                      
                    }
                    else if ("硬件初始化".Equals(TerminalOperation))
                    {
                        SendData = ecjc.HardwareFormatingMethod(TerminalAddr);
                     
                    }
                    else if ("数据区初始化".Equals(TerminalOperation))
                    {
                        SendData = ecjc.DataAreaFormatingMethod(TerminalAddr);
                       
                    }
                }
            }
           // 不是二层集抄
            else if ("GW376".Equals(SoftName))
            {
                Gw376Converter gw376 = new Gw376Converter();
                if (terminalChecked is true) //如果是终端操作;
                {
                    if (TerminalOperation.Equals("读终端地址"))
                    {
                       SendData=gw376.ReadAddressMethod(TerminalAddr);
                       
                    }
                    else if ("写终端地址".Equals(TerminalOperation))
                    {
                       SendData=gw376.WriteAddressMethod(this.terminalAddr);
                       
                    }
                    else if ("硬件初始化".Equals(TerminalOperation))
                    {
                        SendData = gw376.HardwareFormatingMethod(TerminalAddr);
                       
                    }
                    else if ("数据区初始化".Equals(TerminalOperation))
                    {
                        SendData=gw376.DataAreaFormatingMethod(TerminalAddr);
                    }
                }
            }
            byte[] send = SerialPortHelper.GetBytes(SendData, EncodingSend);
            if (send.Length == 0)
            {
                return;
            }
            string s = SerialPortHelper.Write(send);

            if (SerialPortHelper.CheckError(s))
            {
                if (EncodingSend == "HEX")
                {
                    //AddLog(new SerialLog(SendData.ToUpper(), true));
                    AddLog(new SerialLog($"{terminalOperation}:{TerminalAddr}", true));
                }
                else
                {
                    AddLog(new SerialLog(SendData, true));
                }
            }
            else
            {
                AddLog(new SerialLog(s, true));
            }
        }
    }
    [RelayCommand]
    public async void Back()
    {
        Close();
        await Shell.Current.GoToAsync("..");
    }
    void AddLog(SerialLog serialLog)
    {
        Datas.Add(serialLog);

        //fix VirtualView cannot be null here
        Task.Delay(50);
    }
    [RelayCommand]
    void SerialOptionChange()
    {
        SerialPortHelper.SetOption(serialOption);
    }
}

}
using CommunityToolkit.Mvvm.ComponentModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MauiUsbSerialForAndroid.Helper;
using System.Collections.ObjectModel;
using Hoho.Android.UsbSerial.Driver;
using Android.Hardware.Usb;
using CommunityToolkit.Mvvm.Input;
using MauiUsbSerialForAndroid.Model;
using MauiUsbSerialForAndroid.View;
using Android.OS;
using Android.Content;
using Android.Util;

namespace MauiUsbSerialForAndroid.ViewModel
{
[ObservableObject]
public partial class SerialPortViewModel : IQueryAttributable
{

    bool openIng = false;
    public ObservableCollection<UsbDeviceInfo> UsbDevices { get; } = new();
    public SerialPortViewModel()
    {
        SerialPortHelper.WhenUsbDeviceAttached((usbDevice) =>
        {
            GetUsbDevices();
        });

        SerialPortHelper.WhenUsbDeviceDetached((usbDevice) =>
        {
            GetUsbDevices();
        });
    }
    public void ApplyQueryAttributes(IDictionary<string, object> query)
    {
        GetUsbDevices();
    }
    [RelayCommand]
    public async Task GetUsbDevices()
    {
        UsbDevices.Clear();
        var list = SerialPortHelper.GetUsbDevices();
        foreach (var item in list)
        {
            UsbDevices.Add(item);
            //fix VirtualView cannot be null here
            await Task.Delay(50);
        }
    }
    [RelayCommand]
    async Task Open(UsbDeviceInfo usbDeviceInfo)
    {
        if (openIng) { return; }
        openIng = true;
        await Shell.Current.GoToAsync(nameof(SerialDataPage), new Dictionary<string, object> {
                { "Serial",usbDeviceInfo}
            });
        openIng = false;
    }

}

}

以上代码,仅作参考,QQ:1009714648

标签:Xamarin,ObservableProperty,串口,SerialPortHelper,调试程序,new,using,public,string
From: https://www.cnblogs.com/lyqfs/p/18543253

相关文章

  • HarmonyOS蓝牙串口协议(SPP)详解:实现设备间可靠数据交换
    本文旨在深入探讨华为鸿蒙HarmonyOSNext系统(截止目前API12)的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。在智能设备互联互通的世界里,蓝牙技术扮......
  • 基于ESP32的桌面小屏幕实战[3]:硬件设计之主控模块、墨水屏和TP、USB转串口、蜂鸣器、
    1.主控模块主控用的是ESP32-S。在立创商城搜索它,找到ESP32-S,复制编号。回到嘉立创EDA,用编号搜原件。把原件放置在原理图中。按照之前的外设接口说明接线。注意,给引脚命名的时候,要单击鼠标右键,点击属性,在名称处编辑。打开这个芯片的数据手册,找到外围设计原理图。参......
  • 广州大彩串口屏输入密码后加入加载中画面
    众所周知,我们在使用大型设备或者玩游戏的时候点击开始或者运行时总会有一个加载中的界面出现,这不仅提供了缓冲时间供给cpu进行加载,而且使得我们的设备显得更加的完整,变得更加的高级。但是网上对于输入密码后加入加载中界面的文章寥寥无几,许多学者想要设置相关的内容,但是却对此......
  • ubuntu串口权限修改
    文章目录一、确认串口设备名称二、修改串口权限方法一:临时修改权限方法二:永久修改权限(推荐)三、通过udev规则修改权限(高级)ubuntu串口权限修改一、确认串口设备名称首先,我们需要确认串口设备的名称。在Ubuntu系统中,串口设备通常位于/dev/ttyS*或/dev/ttyUSB*目录下......
  • FPGA实现串口升级及MultiBoot(六)ICAPE2原语实例讲解
    本文目录索引一个指令和三种方式通过ICAPE2原语添加ICAPE2IP构建Golden位流工程MultiBoot位流工程验证example2总结代码缩略词索引:K7:Kintex7V7:Vertex7A7:Artix7MB:MicroBlaze上一篇文章种总结了MultiBoot关键技术,分为:一个指令、二种......
  • 【2】GD32H7xx 串口Idle + DMA接收不定长数据
    目录1.IDLE中断相关介绍2.D-Cache与DMA同时使用2.1I-Cache与D-Cache2.2D-Cache与DMA同时使用时的数据一致性问题2.2.1CPU读取DMA写入到SRAM的数据2.2.2DMA读取CPU写入到SRAM的数据3.UartIdle+DMA收发程序4.程序测试1.IDLE中断相关介绍在GD32H7xxMCU......
  • 查找串口
    查询串口fromserial.tools.list_portsimportcomports(fromserial.tools.list_ports_windowsimportcomports)print(comports())[<serial.tools.list_ports_common.ListPortInfoobjectat0x0000014FD6B0A8C0>,<serial.tools.list_ports_common.ListPortInfo......
  • 学习记录:STM32G431CBU6的多通道ADC采样串口打印(HAL库)
    一配置  二代码uint16_tGet_adc(){//启动ADC1HAL_ADC_Start(&hadc1);//等待ADC转换完成,超时为100msHAL_ADC_PollForConversion(&hadc1,100);//判断ADC是否转换成功if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC)......
  • STM32 第20章 USART--串口通信3
    时间:2024.10.30参考资料:《零死角玩转STM32》“USART--串口通信”章节 一、学习内容1、串口2345代码移植实现控制串口2-->将串口1的宏修改成串口2的即可1.1串口的宏串口1://为了方便移植,定义的宏//串口1-USART#defineDEBUG_USARTxUSART1#d......
  • STM32 第20章 USART--串口通信2
    时间:2024.10.29参考资料:《零死角玩转STM32》“USART--串口通信”章节编程是从GPIO输出-使用固件库点亮LED灯的基础上开始一、学习内容1、STM32串口初始化结构体和固件库1.1USART初始化结构体 /***@briefUSARTInitStructuredefinition*/typedef......