签到有奖
消息提醒
运维工程师专区
官方商城
扫码分享好友 任选多种周边
在WINCC组态中,我们有时会遇到需要发送短信的场合
WinCC可以通过VBS脚本写串口通讯利用短信模块发送短信,单存在一些问题
中文短信乱码,需要重新编码。
短信频率高的时候会造成UI线程阻塞、卡顿
访问串口过快会使短信发送不成功。
针对如上问题,我开发了一个WinCC控件,组态时只需将控件放入画面中,在发送短信时调用控件的函数发送;在控件内部使用了多线程、队列,不管短信频率多高都不会影响画面运行,也不会造成串口繁忙而使短信发送失败,支持中文,现将核心代码分享给大家:
在WinCC中添加控件,并根据实际情况设置如下属性:
需要发送短信的时候使用如下脚本:
试用控件地址:
https://www.ad.siemens.com.cn/club/bbs/post.aspx?a_id=1441984&b_id=5&b_sid=&s_id=17&pno=0
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
帖子链接:https://www.ad.siemens.com.cn/club/bbs/post.aspx?a_id=1438632&b_id=5&s_id=17&num=6
补下中文编码的代码:
public class PDUEncoder
{
/// <summary>
/// 服务中心地址编码(SCA = Service Center Adress)
/// </summary>
/// <param name="SCA">服务中心地址</param>
/// <returns>编码后的字符串</returns>
/// <remarks>
/// SCA组成:1~12个八位位组
/// A:服务中心地址长度,长度1,其值为B+C字节数
/// B:服务中心地址类型,长度0~1
/// C:服务中心地址,长度0~10。
/// </remarks>
private static string SCAEncoding(string SCA)
if (string.IsNullOrEmpty(SCA))
{ // 表示使用SIM卡内部的设置值,该值通过AT+CSCA指令设置
return "00";
}
StringBuilder sb = new StringBuilder(SCA.Length + 5);
int Index = 0;
if (SCA.StartsWith("+"))
{ // 国际号码
sb.Append((SCA.Length / 2 + 1).ToString("X2")); // SCA长度编码
sb.Append("91"); // SCA类型编码
Index = 1;
else
{ // 国内号码
sb.Append(((SCA.Length + 1) / 2 + 1).ToString("X2")); // SCA长度编码
sb.Append("81"); // SCA类型编码
// SCA地址编码
for (; Index < SCA.Length; Index += 2)
{ // 号码部分奇偶位对调
if (Index == SCA.Length - 1)
sb.Append(SCA[Index]);
sb.Append(SCA[Index + 1]);
return sb.ToString();
/// 接收方地址编码
/// <param name="DA">接收方地址</param>
/// DA组成:2~12个八位位组
/// F:地址长度,长度1。注意:其值是接收方地址长度,而非字节数
/// G:地址类型,长度1,取值同B。
/// H:地址,长度0~10。
private static string DAEncoding(string DA)
if (string.IsNullOrEmpty(DA))
{ // 地址长度0,地址类型未知
return "0080";
StringBuilder sb = new StringBuilder(DA.Length + 5);
sb.Append("1100");
if (DA.StartsWith("+"))
sb.Append((DA.Length - 1).ToString("X2")); // 地址长度编码
sb.Append("91"); // 地址类型
sb.Append(DA.Length.ToString("X2")); // 地址长度编码
sb.Append("81"); // 地址类型
for (; Index < DA.Length; Index += 2)
if (Index == DA.Length - 1)
sb.Append("F"); // 补“F”凑成偶数个
sb.Append(DA[Index + 1]);
sb.Append(DA[Index]);
/// 用户数据内容编码
/// <param name="UDC">用户数据内容</param>
/// <param name="UDCL">输出:UCS2编码字节数或7-Bit编码字符数</param>
/// <returns>编码字符串</returns>
private static string UDCEncoding(string UDC, out int UDCL)
if (string.IsNullOrEmpty(UDC))
UDCL = 0;
return string.Empty;
// UCS2编码
UDCL = UDC.Length; // 字节数
StringBuilder sb = new StringBuilder(UDCL << 1);
foreach (char Letter in UDC)
sb.Append(Convert.ToInt32(Letter).ToString("X4"));
/// 获取PDU
/// <param name="DA">短信发送地址</param>
/// <param name="msg">短信内容</param>
/// <param name="DALen">数据长度</param>
/// <returns></returns>
public static string GetPDU(string SCA, string DA, string msg,out int DALen)
string SCAPdu = SCAEncoding(SCA);
string DAPdu = DAEncoding(DA);
int len = 0;
string UDCPdu = UDCEncoding(msg, out len);
StringBuilder sb = new StringBuilder();
sb.Append(SCAPdu).Append(DAPdu).Append(len.ToString("X2")).Append(UDCPdu);
DALen = (sb.Length - SCAPdu.Length) / 2;
赞成版主的说法,能把控件上传上来就牛逼了!
楼主,你的这个代码是写在哪里才可以呢?c?vs?wincc的c脚本?还是其他的什么?
写的wincc的全局脚本吗?
你好,代码用C#封装成控件就可以了。在WinCC里面只需要一条VBS脚本调用就可以。
你好,代码用C#封装成控件就可以了。在WinCC里面只需要一条VBS脚本调用就可以。WinCC没法做这么复杂的程序的。
有意思,我也试试!
欢迎探讨~
强帖必须得火啊!
厉害了伙计
分享
扫码分享好友 任选多种好礼
收藏
有帮助
欢迎您访问支持中心!
丰富的视频,全方位的文档,大量的网友交流精华……
为了更好的完善这些内容,我们诚邀您在浏览结束后,花20秒左右的时间,完成一个用户在线调查!
感谢您的支持!
密码至少8位,包含大、小写字母,数字和符号至少三种。
允许邮箱和手机接收来自支持中心网站的信息
我已同意《支持中心网站注册协议和隐私政策》
微信登录扫码一键登录
验证码登录
密码登录
二维码失效点击重试
打开微信扫一扫,快速登录/注册
未注册手机验证后自动登录,注册即代表同意《支持中心网站注册协议和隐私政策》
三日内免验证登录
短信登录
登录