WaveCom 短信猫C#开发,有问题的进来讨论下----(先占个位子)
2009-08-31 17:23 kwjlk 阅读(1970) 评论(5) 编辑 收藏 举报悲剧了那,呵呵。这边http://www.cnblogs.com/engin/archive/2010/11/23/1885907.html有个具体的,我这个就当自己做过写点感触了。
最近在开发应用级的短信发送东东。不说别的了,下面就是咱的家伙:
短信猫为:USB wavecom Q2406A的GSM(据说GSM的只能发短信,Gprs的能发短信也猛发彩信)短信猫。
按照卖家给的说明书和网上搜集来的资料,在自己的百般(也许没这么多)下终于发出了第一条短信:
第一条短信是利用微软的超级终端(在开始->程序->附件->通讯里面的)连接短信猫,然后使用at指令进行的短信文本格式发送。
at命令:
atz 初始化短信猫
at + cmgf=1 选择文本格式发送短信,注意,文本格式下发送短信只能发送abcd的字母。
at + cmgs=13469273621 接收短信的人的号码,
> 输入字母内容,输入后不要回车 直接按住Ctrl + Z组合键 就可以发送了
--------------------------------------------------------------------------------------------------------------------------------------
但是,真正的应用去需要发送中文。而且还遇到了长、短短信的问题。即汉字输入下的七十个字符算作一条短信。七十个字以内的短信可以做一条发送,
接收者看到的也是一条短信。如果,字符量超过了七十个那就要自己分条发送了。但这是就出现了一个最优的要求:分条可以,但是我总得可以让接收者
当作一条看吧。不用看完一条再看一条,有时候还会因为断章取义出现误会。这时候,我只找到了一种答案:使用PDU编码发送短信。
一、发送短短信。
相关文章链接:
有点儿关于超级终端使用的东西
http://www.ccidcom.com/blog/?uid-11541-action-viewspace-itemid-52809
讲解PDU编码协议的
http://blog.21ic.com/user1/4641/archives/2008/45476.html
超级终端在这里
点确定后
选择你的短信猫使用的端口
点还原为默认后
确定后就可以使用了
使用PDU编码发送长短短信
短信猫的操作命令为
AT + CMGF=0
AT+CMGS=发送内容长度
>内容Ctrl+Z发送
将一条短信所有内容进行PDU编码的代码如下:
using System;
using System.Collections.Generic;
using System.Text;
namespace SMS.Service
{
/// <summary>
/// 针对国内短信编码(USC2)
/// </summary>
public class PDUdecoding
{
public readonly static int MAX_CHAR_COUNT = 70;//最长可发送汉字个数
/// <summary>
/// 获取单条短信最大发送字符个数
/// </summary>
/// <returns></returns>
public static int GetMaxEncodeCharCount()
{
return PDUdecoding.MAX_CHAR_COUNT * 2 - 6;
}
/// <summary>
/// 短信内容编码
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
/// <remarks>
/// 采用Big-Endian 字节顺序的 Unicode 格式编码,将高低位互换
/// 将转换后的短信内容存进字节数组
/// 去掉在进行Unicode格式编码中,两个字节中的"-",例如:00-21,变成0021
/// 将整条短信内容的长度除2,保留两位16进制数
/// </remarks>
public static string Encoding(string value)
{
Encoding encoding = System.Text.Encoding.BigEndianUnicode;
string result = string.Empty;
byte[] bytes = encoding.GetBytes(value);
for (int i = 0; i < bytes.Length; i++)
{
result += BitConverter.ToString(bytes, i, 1);
}
return result;
}
/// <summary>
/// 奇偶互换并补F
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private static string ParityChange(string value)
{
string result = string.Empty;
int length = value.Length;
for (int i = 1; i < length; i += 2)//奇偶互换
{
result += value[i];
result += value[i - 1];
}
if (!(length % 2 == 0))//不是偶数则加上F,与最后一位互换
{
result += 'F';
result += value[length - 1];
}
return result;
}
/// <summary>
/// 接收短信手机号码编码
/// </summary>
/// <param name="phone"></param>
/// <returns></returns>
public static string DecodingPhone(string phone)
{
string result = string.Empty;
if (null == phone || 0 == phone.Length)
{
return result;
}
if ('+' == phone[0])
{
phone = phone.TrimStart('+');
}
if (!(phone.Substring(0, 2) == "86"))//补86
{
phone = String.Format("86{0}", phone);
}
return ParityChange(phone);
}
#region 尚不使用
/// <summary>
/// 短信中心号码编码
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string DecodingCenter(string phone)
{
string result = string.Empty;
result = ParityChange(phone);
result = String.Format("91{0}", result);//加上91
result = String.Format("{0:X2}{1}", result.Length / 2, result);
return result;
}
#endregion
/// <summary>
/// 编码短信的发送内容
/// </summary>
/// <param name="content">短信的发送内容</param>
/// <returns></returns>
public static string EncodingContent(string content)
{
string result = string.Empty;
byte[] bytes = System.Text.Encoding.BigEndianUnicode.GetBytes(content);
//for (int i = 0; i < bytes.Length; i++)
//{
// if (0x80 == (bytes[i] & 0x80))//汉字 6c49 108 73
// {
// result = string.Format("{0}{1:X2}", result, bytes[i]);
// result = string.Format("{0}{1:X2}", result, bytes[++i]);
// }
// else
// {
// result = string.Format("{0}00{1:X2}", result, bytes[i]);
// }
//}
foreach (char item in content)
{
bytes = System.Text.Encoding.BigEndianUnicode.GetBytes(new char[1] { item });
if (bytes.Length < 2)
continue;
//
if (0x80 == (Asc(item) & 0x80))//汉字
{
result = string.Format("{0}{1:X2}", result, bytes[0]);
result = string.Format("{0}{1:X2}", result, bytes[1]);
}
else
{
result = string.Format("{0}00{1:X2}", result, bytes[1]);
}
}
return result;
}
/// <summary>
/// 将发送内容同时在前面补上短信内容长度进行编码,
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string EncodeingAddLength(string value)
{
//对短信内容进行编码
string result = Encoding(value);
//补上内容长度 ,组合。
return String.Format("{0:X2}{1}", result.Length / 2, result);
}
/// <summary>
/// 短短信的PDU编码
/// </summary>
/// <param name="center">短信中心号码</param>
/// <param name="phone">接收者手机号码</param>
/// <param name="content">发送内容</param>
/// <param name="length">要发送内容的长度,由两部分组成,接收手机号加上要发送的内容</param>
/// <returns>编码</returns>
public static string EncodingSMS(string center, string phone, string content, out string length)
{
//center = DecodingCenter(center);
string result = String.Format("{0}11000D91{1}000800{2}", center, DecodingPhone(phone), EncodeingAddLength(content));
length = String.Format("{0:D2}", result.Length / 2 - center.Length / 2);//获取发送编码的长度==计算除去短信服务中心号码后的编码长度 除以 二
return result;
}
//// <summary>
/// 发送超长短信
/// </summary>
/// <param name="center">短信中心号码</param>
/// <param name="phone">接收者号码</param>
/// <param name="count">短信分条总数</param>
/// <param name="index">短信分条索引</param>
/// <param name="content">已编码短信内容</param>
/// <param name="length">当前分条的长度</param>
/// <returns>当前分条短信的内容</returns>
public static string EncodingSMS(string center, string phone, int count, int index, string content, out string length)
{
content = EncodingContent(content);
string message = string.Empty;
int msgcount = PDUdecoding.GetMaxEncodeCharCount() * 2;//固定
if (index == count)
{
message = content.Substring((index - 1) * msgcount); //共可发送134个编码
}
else
{
message = content.Substring((index - 1) * msgcount, msgcount);
}
//加密消息中心号码
//center = DecodingCenter(center);
//string result = string.Format("005100{0}{1}0008A7{2:X2}05000304{3:D2}{4:D2}{5}",
// center,
// DecodingPhone(phone),
// (message.Length + 12) / 2,
// count,
// i,
// message);
//length = String.Format("{0:D2}", result.Length / 2 - center.Length / 2);//获取短信内容加上手机号码长度
/**/
////string ph = phone;
////phone = DecodingPhone(phone).Substring(2);
////string result = string.Format("005100{0}{1}0008A7{2:X2}05000304{3:D2}{4:D2}{5}",
//// string.Format("{0:X2}A1", ph.Length),
//// phone,
//// (message.Length + 12) / 2,
//// count,
//// i,
//// message);
string result = String.Format("{0}51000D91{1}000800{2:X2}05000304{4:D2}{5:D2}{3}",
center,
DecodingPhone(phone),
message.Length / 2 + 6,
message,
count,
index
);
length = String.Format("{0:D2}", result.Length / 2 - center.Length / 2);//获取短信内容加上手机号码长度
return result;
}
#region 不能正常使用
/// <summary>
/// 超长短信
/// </summary>
/// <param name="center">短信息中心号码</param>
/// <param name="phone">接收者手机号码</param>
/// <param name="content">消息内容</param>
/// <param name="count">消息分条总数量</param>
/// <param name="index">获取第几条分条</param>
/// <param name="length">当前分条长度</param>
/// <returns>当前消息分条内容</returns>
//public static string EncodingSMS(string center, string phone, string content, int count, int index, out string length)
//{
// if (content.Length <= PDUdecoding.MAX_CHAR_COUNT)
// {
// return PDUdecoding.EncodingSMS(center, phone, content, out length);
// }
// else
// {
// if (count - 1 == index)
// {
// content = content.Substring(index * (PDUdecoding.MAX_CHAR_COUNT - 6));
// }
// else
// {
// content = content.Substring(index * (PDUdecoding.MAX_CHAR_COUNT - 6), PDUdecoding.MAX_CHAR_COUNT - 6);
// }
// center = DecodingCenter(center);
// content = Encoding(content);
// string result = "";
// DateTime tm = DateTime.Now;
// //result = string.Format("{0}44000D91{1}0008{2}{3:X2}05000304{4:D2}{5:D2}{6}",
// // center,
// // DecodingPhone(phone),
// // ParityChange(string.Format("{0:X2}{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}08", tm.Year - 2000, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second)),
// // (content.Length + 12) / 2,
// // count,
// // i + 1,
// // content
// // );
// result = string.Format("005100{0}{1}0008A7{2:X2}05000304{3:D2}{4:D2}{5}",
// center,
// DecodingPhone(phone),
// (content.Length + 12) / 2,
// count,
// index + 1,
// content);
// length = String.Format("{0:D2}", result.Length / 2 - center.Length / 2);//获取短信内容加上手机号码长度
// return result;
// }
//}
#endregion
private static int Asc(char item)
{
byte[] bytes = System.Text.Encoding.Default.GetBytes(new char[1] { item });
if (bytes.Length < 2)
return bytes[0];
return bytes[0] * 256 + bytes[1] - 65535;
}
}
}
用C#中的SerialPort 进行COM端口操作
#region
/// <summary>
/// 发送短信(长/短)
/// </summary>
/// <param name="sp">GSM短信猫SerialPort端口对象</param>
/// <param name="serviceCenterAddress">短信中心号码</param>
/// <param name="text">内容</param>
/// <param name="phonenumber">接收者号码</param>
/// <param name="count">短信分条总量</param>
/// <param name="index">当前第几条</param>
public static void GSMModemSMSsend(
SerialPort sp,
string serviceCenterAddress,
string text,
string phonenumber,
int count,
int index
)
{
try
{
if (sp.IsOpen)
{
sp.Close();
}
sp.Open();
string length = "";
if (count == 1)
{
string smsTemp = PDUdecoding.EncodingSMS("00", phonenumber, text, out length);
#region Short SMS Send
sp.WriteLine("atz"); //短信猫初始化命令
sp.WriteLine("at + cmgf=0"); //以PDU编码格式发送短信
sp.WriteLine(String.Format("at + cmgs={0}", length)); //设置通信内容长度
sp.Write(smsTemp); //写入PDU编码的通信内容
sp.WriteLine("\x01a"); //Ctrl + Z 发送短信
#endregion
}
else
{
#region Long SMS Send
string smsTemp = PDUdecoding.EncodingSMS(serviceCenterAddress, phonenumber, count, index, text, out length);
sp.WriteLine("atz"); //短信猫初始化命令
sp.WriteLine("at + cmgf=0"); //以PDU编码格式发送短信
sp.WriteLine(String.Format("at + cmgs={0}", length)); //设置通信内容长度
sp.Write(smsTemp); //写入PDU编码的通信内容
sp.WriteLine("\x01a"); //Ctrl + Z 发送短信
#endregion
}
}
catch (Exception ex)
{
throw ex;
}
#region 获取端口的命令写入写出部分情况 调试时使用
//byte[] buffer = new byte[sp.ReadBufferSize];
//sp.Read(buffer, 0, buffer.Length);
//string response = Encoding.ASCII.GetString(buffer);
#endregion
}
#endregion
第一次写出来时 短信猫发送短信的时间间隔竟然是二十秒左右,不然会出现部分文字丢失的情况。老板相当不能容忍,于是又翻回来左看右看
终于发现点还算有价值的东西,现在写在这里为大家参考。
第一,使用PDU编码发送短信 正常长度为151
为什么说是正常长度? 这个正常长度指的是出去在短信PDU通信协议中的其他固定成分外的用户内容的大小。注意:太大的长度则会产生
较长的发送时间。
第二、我得出的短信发送时间间隔值
PDU编码长度为17或21(短短信一个字,长短信一个字)的发送时间间隔为5秒
长度为151的发送时间间隔为 8.5秒
所以,上面的代码还是要进行修改的