using Godot; using System; using System.Globalization; 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,1000")] 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 = "请输入正确的端口号"; } } } timer = new Timer(); timer.Interval = interval; timer.Elapsed += OnTimerElapsed; timer.AutoReset = true; timer.Start(); } public override void _ExitTree() { timer.Stop(); } private void UpdatePortAndIP() { _modbus.Dispose(); _modbus = ModbusMaster.TCP(ip, port); } private async void OnTimerElapsed(object sender, ElapsedEventArgs e) { SetHints( "正在获取温湿度数据..."+DateTime.Now); _CancellationTokenSource.Cancel(); await UniTask.SwitchToTaskPool(); try { _CancellationTokenSource.Token.ThrowIfCancellationRequested(); var vs = _modbus.ReadInputRegisters(1, 0, 2); _CancellationTokenSource.Token.ThrowIfCancellationRequested(); if (vs is not { Length: 2 }) { SetHints(hintsLabel.Text = $"获取温湿度数据失败:数据长度为:{vs.Length}"+DateTime.Now); return; } temperature = vs[0] / 10.0; humidity = vs[1] / 10.0; SetHints("已获取到温湿度数据:"+DateTime.Now); temperatureContaier.Text = temperature.ToString(CultureInfo.InvariantCulture); humidityContainer.Text = humidity.ToString(CultureInfo.InvariantCulture); } catch (OperationCanceledException) { //SetHints("连接超时:"+DateTime.Now); } catch (Exception ex) { SetHints(ex.Message); GD.Print("ex:" + ex); } } private async void SetHints(string hints) { await UniTask.SwitchToSynchronizationContext(BITApp.SynchronizationContext); hintsLabel.Text = hints; } }