Toggle navigation
首页
(current)
问答
文章
话题
商城
登录
注册
稀饭放姜 iRTU 学习日记 (3):PC电脑通过UDP与iRTU通讯的一个小例子
C#
UDP
iRTU
透传
UPWS服务器
通过开源的C#客户端(UPWs_CS)和iRTU的485端口建立透传连接,可以互相透明传输文本或者二进制数据。
Openluat Air720D 4G DTU主控板 是由合宙开源社区技术专家“稀饭放姜”设计,上海合宙物联网公司推出的一款移动2G/4G 双模DTU产品。今天的学习日记里面,我将尝试使用iRTU配合另一个开源C#客户端UPWs_CS实现PC电脑上用C#客户端与iRTU双向传输数据。 ## 基本功能: ## 通过开源的C#客户端(UPWs_CS)和iRTU的485端口建立透传连接,可以互相透明传输文本或者二进制数据。 ![](/static/editormd/php/../uploads/5_66104.jpg) ## 实现原理 ## ![](/static/editormd/php/../uploads/5_70204.jpg) 1) iRTU通过UDP端口连接到远程的UPWS服务器,并发送上线消息 服务地址为 udp://box.miuser.net:7101 2)PC客户端通过UPWs_CS C#客户端 连接到UPWS服务器,并发送上线消息,连接地址同上为: 服务地址为 udp://box.miuser.net:7101 3)电脑客户端接一个USB转UART串口的连接线,再转接一个UART转RS485的连接板连接到iRTU上,并使用串口调试工具打开USB串口 4)通过电脑客户端可以和LLCOM串口调试工具建立起双向的文本命令传输,传输支持中文和英文。 硬件连接方式及IRTU配置方式请参考上一篇文章《稀饭放姜 iRTU 学习日记 (2):实现最基本的一个应用-RS485透传》 文章链接为 https://oldask.openluat.com/article/988 ## iRTU 使用 C#客户端 透传使用方法 ## 运行文末附带的C#连接功能包的执行文件:UPWS_CS.exe 源码为文件包中的UPWS_CS.rar 输入连接地址:box.miuser.net 输入端口号:7101 输入任意10位数字作为ID 输入任意16位数字或英文字母作为密码 ID与MM设置需要与iRTU设置保持一致 ![](/static/editormd/php/../uploads/5_19715.jpg) 点击"打开连接",即可收到iRTU上行的心跳数据包了 发送方式可以是字符串,或者是二进制数据,通过单选框“字符发送”与“Hex发送”进行选择 举个栗子,比如Hex模式下发送的343536,等效于字符发送模式系下发送“456” 因为ASCII码表中0x34,对应字符“4” 接收的原理相同,您可以通过选择“字符显示功能”,决定以字符串或二进制方式显示接收到的数据包 ![](/static/editormd/php/../uploads/5_17246.jpg) 例子中为了演示清晰,心跳包内容也都做了展示。 您可以通过判断包头类型方式来过滤心跳包显示,源码中有相关的内容叙述。 ## 关键性代码展示 ## 下面我选取部分有趣的代码,并加以简单的原理介绍,文末的文件包中提供完整的C#源码,在VS2019环境中编译使用。 打开连接部分: private void btn_ConnectUDP_Click(object sender, EventArgs e) { if (!isRunning) { isRunning = true; //获取服务器地址 s_server = txt_server.Text; //获取服务器端口 s_port = txt_port.Text; //对域名进行解析 IPHostEntry hostEntry = Dns.GetHostEntry((s_server)); //取得解析得到的IP地址 client.ep = new IPEndPoint(hostEntry.AddressList[hostEntry.AddressList.Length - 1], Convert.ToInt32(s_port)); //开始侦听 client.Listening(); //挂载接收消息的处理函数 client.Received += new UdpEventHandler(client_Received); //判断显示模式,二进制或字符串显示 if (rbnHex.Checked) { isHexRead = true; } else { isHexRead = false; } //打开心跳发送时钟 tmr_heartbeat_Tick(sender,e); } } 数据包拼接: public class package { public string str; //生成一个数据包 public package(string ID = "0000000000", string MM = "0000000000000000",string content="",string type="") { //数据包头的模板 if (type == "") { str = "004932A08"; }else { str = "004932" + type + "08"; } //添加ID和MM字段 str = str + ID; str = str + MM; //添加1234为正文引导 str = str + "1234"; //添加要发送的正文 str = str + content; //添加数据尾05 str = str + "05"; //计算发送包总长,并转化为字符串 int len = str.Length; string s_len = ("00" + len.ToString()).Substring(0, 4); //用计算出来的长度替换数据头模板中的长度数据 str = s_len + str.Substring(4, str.Length - 4); } } 发送数据部分: //发送数据 private void btnSend_Click(object sender, EventArgs e) { //根据用户选择决定是发送二进制还是文本 if (rad_AscSend.Checked) isHexWrite = false; else isHexWrite = true; //UDP连接 if (isRunning) { //生成一个包 if (!isHexWrite) { List
lbuff = new List
(); lbuff = StringToBytes(txt_send.Text).ToList(); //组包 package pkg = new package(txt_ID.Text, txt_MM.Text, BytesToString(lbuff.ToArray())); string s_out = pkg.str.ToString(); //将要发送的字符串转为字节数据 byte[] bt = Encoding.GetEncoding("GB2312").GetBytes(s_out); //发送 client.Send(bt, client.ep); }else { List
lbuff = new List
(); //将字符表示的16进制数转化成为字节数据 lbuff = strToToHexByte(txt_send.Text).ToList(); //将字节数据转变成字符串,并组包 package pkg = new package(txt_ID.Text, txt_MM.Text, BytesToString(lbuff.ToArray())); string s_out = pkg.str.ToString(); //将要发送的字符串转为字节数据 byte[] bt = Encoding.GetEncoding("GB2312").GetBytes(s_out); client.Send(bt, client.ep); } } else { MessageBox.Show("数据传输端口未打开", "错误提示"); return; } if (!CheckSendData()) { MessageBox.Show("请输入要发送的数据!", "错误提示"); return; } 接收数据部分: //UDP收到消息后的回调函数 void client_Received(object sender, UdpEventArgs e) { IPEndPoint ep = e.Remote as IPEndPoint; string tmpReceived = Encoding.Default.GetString(e.Received); //在主线程更新显示信息 this.BeginInvoke(new Action(() => { //决定是否显示发送心跳包的回声 //if (tmpReceived.Substring(6,1)=="C") { string content = tmpReceived.Substring(39, tmpReceived.Length - 41); if (isHexRead == false) { //显示接收的数据 txt_rsv.Text += content + "\r\n"; txt_rsv.Select(txt_rsv.TextLength, 0); txt_rsv.ScrollToCaret(); } else { //以二进制方式显示接收的数据 string RecvDataText = ""; Byte[] ReceivedData = StringToBytes(content); for (int i = 0; i < ReceivedData.Length; i++) { RecvDataText += (ReceivedData[i].ToString("X2") + " "); } RecvDataText += "\r\n"; txt_rsv.Text += RecvDataText; txt_rsv.Select(txt_rsv.TextLength, 0); txt_rsv.ScrollToCaret(); } } //显示原始发送数据 rtb_rsv.Text = rtb_rsv.Text+ "[" +DateTime.Now.ToLongTimeString()+"]" +tmpReceived+ "\r\n" ; })); } # 常见故障排除 ## 1 程序无法编译,请检查VS版本是否为最新的VS2019 2 发送接收数据不全,错误,请检查ID和MM长度是否正确 3 无接收,无法送,请检查iRTU的ID和MM设置是否完全一致 ## 参考资料 ## 本文所提及的文档及工具资料包: https://pan.baidu.com/s/15QICk163bI5NCB8M0SSDpA 提取码:a610 本文参考资料如下: 1 iRTU项目开源地址 https://github.com/hotdll/iRTU 2 UPWS服务器项目开源地址 https://github.com/miuser00/UdpPlugWebsocket 3 LLC能跑Lua脚本的串口调试工具项目开源地址 https://github.com/chenxuuu/llcom ## 技术咨询方式 ## 合宙Luat(稀饭放姜iRTU) QQ群:952343033 ## 本文所述iRTU系列 DTU主控板购买链接 ## http://m.openluat.com/product/724 ![](/static/editormd/php/../uploads/5_11419.jpg) 谢谢您阅读本文,并祝您开发一切顺利
发表于 2019-12-02 14:47
阅读 ( 2193 )
分类:
默认分类
0 推荐
收藏
你可能感兴趣的文章
9、RDA8910CSDK二次开发:趁热打铁干脆顺带把UDP通讯也给撸了吧
1844 浏览
稀饭放姜 iRTU 学习日记 (5):用电脑采集Modbus温湿度传感器数据
3045 浏览
稀饭放姜 iRTU 学习日记 (4):Websokcet手机客户端通过iRTU控制Modbus继电器
2526 浏览
稀饭放姜 iRTU 学习日记 (0)入手iRTU固件的开发板
3365 浏览
稀饭放姜 iRTU 学习日记 (2):实现最基本的一个应用-RS485透传
3516 浏览
相关问题
0 条评论
请先
登录
后评论
miuser
工程师
21 篇文章
作家榜
»
技术销售Delectate
43 文章
陈夏
26 文章
国梁
24 文章
miuser
21 文章
晨旭
20 文章
朱天华
19 文章
金艺
19 文章
杨奉武
18 文章
×
发送私信
发给:
内容:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!