using Godot; using System; using System.Collections.Generic; using System.Globalization; using System.Net.Mime; using System.Runtime.InteropServices; using System.Threading; using System.Timers; using BITKit; using Cysharp.Threading.Tasks; using SharpModbus; using Timer = System.Timers.Timer; namespace BITFactory; public partial class 温湿度Reader : Node { [ExportCategory("参数")] [Export(PropertyHint.Range,"100,2000")] private int interval=500; [ExportCategory("网络设置")] [Export] private string ip="192.168.3.7"; [Export] private int port=502; [ExportCategory("运行时")] [Export]public double humidity = 50.0; [Export]public double temperature = 26.0; [ExportCategory("UI 绑定")] [Export] private UXContainer temperatureContaier; [Export] private UXContainer humidityContainer; [Export] private LineEdit ipEdit; [Export] private LineEdit portEdit; [Export] private RichTextLabel hintsLabel; private ModbusMaster _modbus; private System.Timers.Timer timer; private CancellationTokenSource _CancellationTokenSource; public override void _Ready() { _CancellationTokenSource = new CancellationTokenSource(); try { _modbus = ModbusMaster.TCP(ip, port); } catch (Exception e) { hintsLabel.Text = e.Message; } if (ipEdit is not null) { ipEdit.TextChanged += s => ip = s; ipEdit.TextSubmitted +=s=> UpdatePortAndIP(); } if(portEdit is not null) { portEdit.TextSubmitted += OnPortChanged; void OnPortChanged(string s) { UpdatePortAndIP(); if (int.TryParse(s,out var newPort)) { } else { portEdit.Text=string.Empty; portEdit.PlaceholderText = "请输入正确的端口号"; } } } UpdatePortAndIP(); timer = new Timer(); timer.Interval = interval; timer.Elapsed += OnTimerElapsed; timer.AutoReset = false; timer.Start(); } public override void _ExitTree() { _CancellationTokenSource.Cancel(); timer.Stop(); } /// /// 内部方法,用于更新IP和端口 /// private void UpdatePortAndIP() { _modbus?.Dispose(); try { _modbus = ModbusMaster.TCP(ip, port); } catch (Exception e) { BIT4Log.Log<温湿度Reader>(e.Message); } } /// /// 内部方法,定时器回调用于读取Modbus /// /// /// private async void OnTimerElapsed(object sender, ElapsedEventArgs e) { await UniTask.SwitchToTaskPool(); try { if (_modbus is null) { hintsLabel.SetTextAsync("Modbus未初始化"); return; } _CancellationTokenSource.Token.ThrowIfCancellationRequested(); hintsLabel.SetTextAsync( "正在读取温湿度数据..."+DateTime.Now); var vs = _modbus.ReadInputRegisters(1, 0, 2); _CancellationTokenSource.Token.ThrowIfCancellationRequested(); hintsLabel.SetTextAsync( "已采集到数据,正在解析..."+DateTime.Now); if (vs is not { Length: 2 }) { hintsLabel.SetTextAsync(hintsLabel.Text = $"获取温湿度数据失败:数据长度为:{vs.Length}"+DateTime.Now); return; } temperature = vs[0] / 10.0; humidity = vs[1] / 10.0; hintsLabel.SetTextAsync("已获取到温湿度数据:"+DateTime.Now); temperatureContaier.label.SetTextAsync(temperature.ToString(CultureInfo.InvariantCulture)); ; humidityContainer.label.SetTextAsync(humidity.ToString(CultureInfo.InvariantCulture)); timer.Start(); } catch (OperationCanceledException) { BIT4Log.Log<温湿度Reader>($"Modbus读取任务已取消"); } catch (Exception ex) { hintsLabel.SetTextAsync(ex.Message); timer.Start(); } } }