• 欢迎大家分享资料!前往留言板评论即可!

稀饭放姜 iRTU 学习日记 (3):PC电脑通过UDP与iRTU通讯的一个小例子

合宙 模组资料网 2年前 (2021-05-15) 336次浏览 0个评论 扫描二维码
文章目录[隐藏]

Openluat Air720D 4G DTU主控板 是由合宙开源社区技术专家“稀饭放姜”设计,上海合宙物联网公司推出的一款移动2G/4G 双模DTU产品。今天的学习日记里面,我将尝试使用iRTU配合另一个开源C#客户端UPWs_CS实现PC电脑上用C#客户端与iRTU双向传输数据。

基本功能:

通过开源的C#客户端(UPWs_CS)和iRTU的485端口建立透传连接,可以互相透明传输文本或者二进制数据。

稀饭放姜 iRTU 学习日记 (3):PC电脑通过UDP与iRTU通讯的一个小例子

实现原理

稀饭放姜 iRTU 学习日记 (3):PC电脑通过UDP与iRTU通讯的一个小例子

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透传》

文章链接为 http://doc.openluat.com/article/647/0

iRTU 使用 C#客户端 透传使用方法

运行文末附带的C#连接功能包的执行文件:UPWS_CS.exe

源码为文件包中的UPWS_CS.rar

输入连接地址:box.miuser.net

输入端口号:7101

输入任意10位数字作为ID

输入任意16位数字或英文字母作为密码

ID与MM设置需要与iRTU设置保持一致

稀饭放姜 iRTU 学习日记 (3):PC电脑通过UDP与iRTU通讯的一个小例子

点击”打开连接”,即可收到iRTU上行的心跳数据包了

发送方式可以是字符串,或者是二进制数据,通过单选框“字符发送”与“Hex发送”进行选择

举个栗子,比如Hex模式下发送的343536,等效于字符发送模式系下发送“456” 因为ASCII码表中0x34,对应字符“4”

接收的原理相同,您可以通过选择“字符显示功能”,决定以字符串或二进制方式显示接收到的数据包

稀饭放姜 iRTU 学习日记 (3):PC电脑通过UDP与iRTU通讯的一个小例子

例子中为了演示清晰,心跳包内容也都做了展示。 您可以通过判断包头类型方式来过滤心跳包显示,源码中有相关的内容叙述。

关键性代码展示

下面我选取部分有趣的代码,并加以简单的原理介绍,文末的文件包中提供完整的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<byte> lbuff = new List<byte>();
                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<byte> lbuff = new List<byte>();
                //将字符表示的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

稀饭放姜 iRTU 学习日记 (3):PC电脑通过UDP与iRTU通讯的一个小例子

谢谢您阅读本文,并祝您开发一切顺利


喜欢 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址