ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C#——通过webapi读写Modbus设备

2022-03-06 13:31:32  阅读:226  来源: 互联网

标签:webapi Parse string C# ushort cmb private Modbus port


调用webapi控制本地程序读写Modbus RTU设备

例如服务开启后,访问http://192.168.3.252:2000/api/home/ReadMultiCoil?slaveAdd=1&address=99&number=10,可以调用webapi实现读从站地址为1的设备中线圈起始地址为99的共十个线圈的值,返回值是JSON

其中192.168.3.252:2000为服务的HttpServer,ReadMultiCoil为定义的函数

运行的时候需要管理员权限,最好关闭防火墙或者开放端口

应该有更好的方法实现相同功能的,但我太菜了懒得找

Modbus RTU的代码是之前的代码改的,更改了串口关闭后没法重新打开的问题,顺便改了一下抄的代码里Http服务关不掉的问题

 

 1 <Window x:Class="******.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:******"
 7         mc:Ignorable="d"
 8         Title="MainWindow" Height="450" Width="800">
 9     <Grid Loaded="Grid_Loaded">
10         <ComboBox x:Name="cmb_portname" HorizontalAlignment="Left" Margin="92,119,0,0" VerticalAlignment="Top" Width="120" MouseEnter="cmb_portname_MouseEnter"/>
11         <ComboBox x:Name="cmb_baud" HorizontalAlignment="Left" Margin="270,119,0,0" VerticalAlignment="Top" Width="120"/>
12         <ComboBox x:Name="cmb_parity" HorizontalAlignment="Left" Margin="440,119,0,0" VerticalAlignment="Top" Width="120"/>
13         <ComboBox x:Name="cmb_dataBits" HorizontalAlignment="Left" Margin="92,176,0,0" VerticalAlignment="Top" Width="120"/>
14         <ComboBox x:Name="cmb_stopBits" HorizontalAlignment="Left" Margin="270,176,0,0" VerticalAlignment="Top" Width="120"/>
15         <Label Content="串口" HorizontalAlignment="Left" Margin="47,119,0,0" VerticalAlignment="Top"/>
16         <Label Content="波特率" HorizontalAlignment="Left" Margin="224,119,0,0" VerticalAlignment="Top"/>
17         <Label Content="校验" HorizontalAlignment="Left" Margin="401,119,0,0" VerticalAlignment="Top"/>
18         <Label Content="数据位" HorizontalAlignment="Left" Margin="41,176,0,0" VerticalAlignment="Top"/>
19         <Label Content="停止位" HorizontalAlignment="Left" Margin="219,176,0,0" VerticalAlignment="Top"/>
20         <Button x:Name="btn_port" Content="打开串口" HorizontalAlignment="Left" Margin="440,176,0,0" VerticalAlignment="Top" Width="75" Click="btn_port_Click"/>
21         <Button x:Name="btn_StartService" Content="开启服务" HorizontalAlignment="Left" Margin="440,228,0,0" VerticalAlignment="Top" Width="75" Click="btn_start_Click"/>
22         <Button x:Name="btn_StopService" Content="关闭服务" HorizontalAlignment="Left" Margin="559,228,0,0" VerticalAlignment="Top" Width="75" Click="btn_close_Click"/>
23         <TextBox x:Name="tb_serviceIP" HorizontalAlignment="Left" Height="23" Margin="92,228,0,0" TextWrapping="Wrap" Text="192.168.3.252" VerticalAlignment="Top" Width="120"/>
24         <TextBox x:Name="tb_servicePort" HorizontalAlignment="Left" Height="23" Margin="270,228,0,0" TextWrapping="Wrap" Text="2000" VerticalAlignment="Top" Width="120"/>
25         <Label Content="服务IP" HorizontalAlignment="Left" Margin="41,228,0,0" VerticalAlignment="Top"/>
26         <Label Content="服务端口" HorizontalAlignment="Left" Margin="213,228,0,0" VerticalAlignment="Top"/>
27 
28     </Grid>
29 </Window>

 

 

  1 using System;
  2 using System.IO.Ports;
  3 using System.Threading.Tasks;
  4 using System.Web.Http;
  5 using System.Web.Http.SelfHost;
  6 using System.Windows;
  7 using Modbus.Device;
  8 
  9 namespace ******
 10 {
 11     /// <summary>
 12     /// MainWindow.xaml 的交互逻辑
 13     /// </summary>
 14     public partial class MainWindow : Window
 15     {
 16         private static IModbusMaster master;
 17         private static SerialPort port;
 18         //写线圈或写寄存器数组
 19         private bool[] coilsBuffer;
 20         private ushort[] registerBuffer;
 21         //串口参数
 22         private string portName;
 23         private int baudRate;
 24         private Parity parity;
 25         private int dataBits;
 26         private StopBits stopBits;
 27 
 28         private HttpServer httpServer = null;
 29 
 30 
 31         public static MainWindow x;
 32         public MainWindow()
 33         {
 34             InitializeComponent();
 35             x = this;
 36         }
 37 
 38         #region 串口下拉列表刷新
 39         /// <summary>
 40         /// 刷新串口下拉列表显示
 41         /// </summary>
 42         private void GetSerialLstTb1()
 43         {
 44             //清除cmb_portname显示
 45             cmb_portname.SelectedIndex = -1;
 46             cmb_portname.Items.Clear();
 47             string[] serialLst = SerialPort.GetPortNames();
 48             if (serialLst.Length > 0)
 49             {
 50                 //取串口进行排序
 51                 Array.Sort(serialLst);
 52                 //将串口列表输出到cmb_portname
 53                 for (int i = 0; i < serialLst.Length; i++)
 54                 {
 55                     cmb_portname.Items.Add(serialLst[i]);
 56                     cmb_portname.SelectedIndex = 0;
 57                 }
 58             }
 59         }
 60         /// <summary>
 61         /// 鼠标移入串口cmb触发刷新
 62         /// </summary>
 63         /// <param name="sender"></param>
 64         /// <param name="e"></param>
 65         private void cmb_portname_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
 66         {
 67             GetSerialLstTb1();
 68         }
 69 
 70         #endregion
 71 
 72         /// <summary>
 73         /// 界面加载
 74         /// </summary>
 75         /// <param name="sender"></param>
 76         /// <param name="e"></param>
 77         private void Grid_Loaded(object sender, RoutedEventArgs e)
 78         {
 79             GetSerialLstTb1();
 80 
 81             cmb_baud.Items.Add("9600");
 82             cmb_baud.Items.Add("14400");
 83             cmb_baud.Items.Add("19200");
 84 
 85             cmb_parity.Items.Add("奇");
 86             cmb_parity.Items.Add("偶");
 87             cmb_parity.Items.Add("无");
 88 
 89             cmb_dataBits.Items.Add("7");
 90             cmb_dataBits.Items.Add("8");
 91 
 92             cmb_stopBits.Items.Add("1");
 93             cmb_stopBits.Items.Add("2");
 94 
 95             cmb_portname.SelectedIndex = -1;
 96             cmb_baud.SelectedIndex = 0;
 97             cmb_parity.SelectedIndex = 2;
 98             cmb_dataBits.SelectedIndex = 1;
 99             cmb_stopBits.SelectedIndex = 0;
100         }
101         #region 串口配置
102         /// <summary>
103         /// 串口参数获取
104         /// </summary>
105         /// <returns></返回串口配置参数>
106         private SerialPort InitSerialPortParameter()
107         {
108             if (cmb_portname.SelectedIndex < 0 || cmb_baud.SelectedIndex < 0 || cmb_parity.SelectedIndex < 0 || cmb_dataBits.SelectedIndex < 0 || cmb_stopBits.SelectedIndex < 0)
109             {
110                 MessageBox.Show("请选择串口参数");
111                 return null;
112             }
113             else
114             {
115                 portName = cmb_portname.SelectedItem.ToString();
116                 baudRate = int.Parse(cmb_baud.SelectedItem.ToString());
117 
118                 switch (cmb_parity.SelectedItem.ToString())
119                 {
120                     case "奇":
121                         parity = Parity.Odd;
122                         break;
123                     case "偶":
124                         parity = Parity.Even;
125                         break;
126                     case "无":
127                         parity = Parity.None;
128                         break;
129                     default:
130                         break;
131                 }
132                 dataBits = int.Parse(cmb_dataBits.SelectedItem.ToString());
133                 switch (cmb_stopBits.SelectedItem.ToString())
134                 {
135                     case "1":
136                         stopBits = StopBits.One;
137                         break;
138                     case "2":
139                         stopBits = StopBits.Two;
140                         break;
141                     default:
142                         break;
143                 }
144 
145                 port = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
146                 return port;
147 
148             }
149         }
150         #endregion
151         /// <summary>
152         /// 开闭端口
153         /// </summary>
154         /// <param name="sender"></param>
155         /// <param name="e"></param>
156         private void btn_port_Click(object sender, RoutedEventArgs e)
157         {
158             if (cmb_portname.Items.Count != 0)
159             {
160                 try
161                 {
162                     if ((string)btn_port.Content == "关闭串口")
163                     {
164                         btn_port.Content = "打开串口";
165                         port.Close();
166                     }
167                     else
168                     {
169                         InitSerialPortParameter();
170                         port.PortName = cmb_portname.SelectedItem.ToString();
171                         port.BaudRate = int.Parse(cmb_baud.SelectedValue.ToString());
172                         port.Open();
173                         btn_port.Content = "关闭串口";
174                     }
175                 }
176                 catch (Exception ex)
177                 {
178                     MessageBox.Show(ex.GetType().ToString());
179                     MessageBox.Show("端口被占用\n请选择正确的端口", "错误");
180                 }
181             }
182             else
183             {
184                 MessageBox.Show("请选择正确的端口", "错误");
185             }
186         }
187 
188         public class HttpServer
189         {
190             private HttpSelfHostServer server;
191 
192             public HttpServer(string ip, int port)
193             {
194                 var config = new HttpSelfHostConfiguration($"http:\\{ip}:{port}");
195                 config.MapHttpAttributeRoutes();
196                 config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{action}");
197                 server = new HttpSelfHostServer(config);
198             }
199 
200             public Task StartHttpServer()
201             {
202                 return server.OpenAsync();
203             }
204             public Task CloseHttpServer()
205             {
206                 return server.CloseAsync();
207             }
208         }
209 
210         private async void btn_start_Click(object sender, RoutedEventArgs e)
211         {
212             try
213             {
214                 httpServer = new HttpServer("\\" + tb_serviceIP.Text, int.Parse(tb_servicePort.Text));
215                 await httpServer.StartHttpServer();
216                 MessageBox.Show("服务开启");
217             }
218             catch (Exception ex)
219             {
220                 MessageBox.Show("服务开启失败" + ex.Message);
221             }
222         }
223 
224         private async void btn_close_Click(object sender, RoutedEventArgs e)
225         {
226             try
227             {
228                 //httpServer = new HttpServer("\\" + tb_serviceIP.Text, int.Parse(tb_servicePort.Text));
229                 await httpServer.CloseHttpServer();
230                 MessageBox.Show("服务关闭");
231             }
232             catch (Exception ex)
233             {
234                 MessageBox.Show("服务关闭失败" + ex.Message);
235             }
236         }
237 
238 
239         public class HomeController : ApiController
240         {
241             /// <summary>
242             /// 读多个寄存器
243             /// http://192.168.3.252:2000/api/home/ReadKeepReg?slaveAdd=1&address=99&number=10
244             /// </summary>
245             /// <param name="slaveAdd">从站地址</param>
246             /// <param name="address">寄存器首地址</param>>
247             /// <param name="number">寄存器数量</param>
248             /// <returns></returns>
249             [HttpGet]
250             public IHttpActionResult ReadKeepReg(string slaveAdd, string address, string number)
251             {
252                 master = ModbusSerialMaster.CreateRtu(port);
253 
254                 string message = "";
255                 byte slaveAddress = byte.Parse(slaveAdd);
256                 ushort startAddress = ushort.Parse(address);
257                 ushort numberOfPoints = ushort.Parse(number);
258                 try
259                 {
260                     x.registerBuffer = master.ReadHoldingRegisters(slaveAddress, startAddress, numberOfPoints);
261                 }
262                 catch (Exception e)
263                 {
264                     MessageBox.Show(e.Message);
265                 }
266                 for (int i = 0; i < x.registerBuffer.Length; i++)
267                 {
268                     message = message + x.registerBuffer[i].ToString("X4") + " ";
269                 }
270                 //MessageBox.Show(message);
271                 return Json(message);
272             }
273             /// <summary>
274             /// 写多个寄存器
275             /// http://192.168.3.252:2000/api/home/WriteKeepReg?slaveAdd=1&address=99&message=1234%201235%201236%201237
276             /// </summary>
277             /// <param name="slaveAdd">从站地址</param>
278             /// <param name="address">寄存器首地址</param>
279             /// <param name="message">信息,以空格分开。例1111 2222,就是写两个寄存器</param>
280             [HttpGet]
281             public void WriteKeepReg(string slaveAdd, string address, string message)
282             {
283                 master = ModbusSerialMaster.CreateRtu(port);
284                 byte slaveAddress = byte.Parse(slaveAdd);
285                 ushort startAddress = ushort.Parse(address);
286 
287                 slaveAddress = byte.Parse(slaveAdd);
288                 startAddress = ushort.Parse(address);
289 
290                 //转化ushort数组
291                 string[] strarr = message.Split(' ');
292                 x.registerBuffer = new ushort[strarr.Length];
293                 for (int i = 0; i < strarr.Length; i++)
294                 {
295                     x.registerBuffer[i] = ushort.Parse(strarr[i], System.Globalization.NumberStyles.HexNumber);
296                 }
297                 master.WriteMultipleRegisters(slaveAddress, startAddress, x.registerBuffer);
298                 return;
299             }
300             /// <summary>
301             /// 读多个线圈
302             /// http://192.168.3.252:2000/api/home/ReadMultiCoil?slaveAdd=1&address=99&number=10
303             /// </summary>
304             /// <param name="slaveAdd">从站地址</param>
305             /// <param name="address">线圈首地址</param>
306             /// <param name="number">线圈数量</param>
307             /// <returns></returns>
308             [HttpGet]
309             public IHttpActionResult ReadMultiCoil(string slaveAdd, string address, string number)
310             {
311                 master = ModbusSerialMaster.CreateRtu(port);
312 
313                 string message = ""; 
314                 byte slaveAddress = byte.Parse(slaveAdd);
315                 ushort startAddress = ushort.Parse(address);
316                 ushort numberOfPoints = ushort.Parse(number);
317                 try
318                 {
319                     x.coilsBuffer = master.ReadCoils(slaveAddress, startAddress, numberOfPoints);
320                 }
321                 catch (Exception e)
322                 {
323                     MessageBox.Show(e.Message);
324                 }
325                 for (int i = 0; i < x.coilsBuffer.Length; i++)
326                 {
327                     message = message + x.coilsBuffer[i] + " ";
328                 }
329                 //MessageBox.Show(message);
330                 return Json(message);
331             }
332             /// <summary>
333             /// 写多个线圈
334             /// http://192.168.3.252:2000/api/home/WriteMultiCoil?slaveAdd=1&address=99&message=1%200%200%200%201%201%201%201
335             /// </summary>
336             /// <param name="slaveAdd">从站地址</param>
337             /// <param name="address">线圈首地址</param>
338             /// <param name="message">信息,空格分开</param>
339             [HttpGet]
340             public void WriteMultiCoil(string slaveAdd, string address, string message)
341             {
342                 master = ModbusSerialMaster.CreateRtu(port);
343                 byte slaveAddress = byte.Parse(slaveAdd);
344                 ushort startAddress = ushort.Parse(address);
345 
346                 slaveAddress = byte.Parse(slaveAdd);
347                 startAddress = ushort.Parse(address);
348 
349                 //转化ushort数组
350                 string[] strarr = message.Split(' ');
351                 x.coilsBuffer = new bool[strarr.Length];
352                 for (int i = 0; i < strarr.Length; i++)
353                 {
354                     if (strarr[i] == "0")
355                     {
356                         x.coilsBuffer[i] = false;
357                     }
358                     else
359                     {
360                         x.coilsBuffer[i] = true;
361                     }
362                 }
363                 master.WriteMultipleCoilsAsync(slaveAddress, startAddress, x.coilsBuffer);
364                 return;
365 
366             }
367         }
368     }
369 }

 

标签:webapi,Parse,string,C#,ushort,cmb,private,Modbus,port
来源: https://www.cnblogs.com/junk-code-of-bo/p/15971456.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有