SmsToolset是一个用C#编写的.NET库,旨在帮助创建发送和接收PDU格式文本消息的应用程序。它通过GSM网络进行通信。这个库的核心概念是PDU配置文件,这是一个确定传输PDU数据包结构的对象。PDU配置文件的基本部分是由文本文件驱动的设置对象,该文件以众所周知的JSON格式编写。JSON文件中定义的配置文件参数加载到设置对象中,从而初始化PDU配置文件对象。配置文件的主要任务是创建PDU数据包。库的另一个重要部分是PDU配置文件管理器,它有助于创建和管理许多不同的配置文件。
总体而言,该库由三个主要部分组成,分别负责:
此外,库还包含一些基本工具的实现,这些工具有助于执行以下任务:
该库的结构由三个命名空间组成。第一个命名空间SmsTools.PduProfile
是库的核心。这里有两个主要接口:IPduProfile
和IPduProfileSettings
,以及PduProfileManager
类。IPduProfileSettings
代表从JSON文件加载的设置对象,然后初始化实现IPduProfile
接口的配置文件对象。PduProfileManager
类的实例用于管理配置文件。在库中,分别实现了这些接口:PduDefaultProfileSettings
负责配置设置,以及PduDefaultProfile
类,负责创建配置文件。这些类之所以重要,是因为这个配置文件对象负责创建将通过GSM网络发送的PDU包。PDU包的结构和内容定义了IPduProfileSettings
合同和相关的JSON文件。因此,应用给定的设置对象决定了包的形式及其元素:
另一个命名空间是SmsTools.Commands
,其中包含代表通信设备(DCE:GSM调制解调器)理解的AT命令的接口。代表AT命令的对象的主要任务是形成传递给DCE的字符串,特别是PDU包,并解释从DCE收到的响应。为了实现这个概念,使用了IATCommand
和ICommandParameter
接口,分别代表命令及其参数。命令的实现被分为三个部分:
SimpleATCommand
类负责创建不接受任何参数的命令。ParamATCommand
允许创建接受单个参数的命令。StepwiseATCommand
用于在传递上一个参数的结果取决于传递多个参数的情况下。发送文本消息的命令就是这样一个例子。最后一个命名空间SmsTools.Operations
包含代表DCE及其实现的接口。其主要且唯一目的是向DCE发送命令并接收响应。IPortPlug
对象被命令用于其执行DCE。
所有上述概念都在Authentication
、ServiceCenter
和PduSms
类中实现。Authentication
用于通过PIN验证用户。使用ServiceCenter
类可以读取和设置服务中心号码。PduSms
允许以PDU包的形式发送文本消息。
让看看使用内置默认设置和默认配置文件发送SMS的最简单的示例。
使用PduSms
类时,内置默认PDU配置文件的默认设置如下:
var ports = SerialPortPlug.AvailablePorts();
if (ports.Any())
{
var config = SerialPortConfig.CreateDefault();
config.Name = ports.First();
using (var modem = new SerialPortPlug(config))
{
if (!modem.IsOpen)
return;
var destination = 888123456;
var message = "hello";
var sms = new PduSms();
bool isSent = await sms.Send(modem, destination, message);
}
}
如何通过PIN验证用户:
var auth = new Authentication();
bool isAuthenticated = await auth.IsAuthenticated(modem);
if (!isAuthenticated)
{
isAuthenticated = await auth.Authenticate(modem, 1234);
}
如果愿意,可以这样设置服务中心号码:
var sca = new ServiceCenter();
var defined = await sca.IsDefined(modem);
if (defined)
{
bool international = await sca.HasInternationalFormat(modem);
var address = await sca.GetAddress(modem);
}
else
{
bool success = await sca.SetAddress(modem, 48601000310, true);
}
现在,让以稍微复杂一点的方式做同样的事情。首先,创建一个包含配置文件设置的JSON文件。设置如下:
JSON文件的内容:
{
"sca": {
"type": 145,
"value": 48601000310
},
"pdu-header": {
"value": 17
},
"mr": {
"value": 0
},
"da": {
"type": 145,
"value": 0
},
"pid": {
"value": 0
},
"dcs": {
"value": 8
},
"vp": {
"value": 255
},
"ud": {
"value": ""
}
}
与JSON文件结构匹配的数据合同在PduDefaultProfileSettings
类中定义,因此可以使用这个类创建设置对象,然后根据加载的设置创建配置文件:
var manager = new PduProfileManager();
using (var file = Assembly.GetExecutingAssembly().GetManifestResourceStream("profile.json"))
{
var settings = manager.CreateProfileSettings<PduDefaultProfileSettings>(file);
var profile = manager.CreateDefaultProfile(settings, "my_profile");
}
有了PDU配置文件,可以创建将通过GSM网络发送的PDU包:
int length = 0;
string packet = string.Empty;
long destination = 48888123456;
string message = "华为";
packet = profile.GetPacket(destination, message, out length);
在以PDU包的形式发送消息之前,必须将消息格式设置为PDU:
string commandParameterValue = Constants.MessageFormat.Pdu.ToValueString();
string successfulResponsePattern = Constants.BasicSuccessfulResponse;
var commandParameter = new CommandParameter(commandParameterValue, successfulResponsePattern);
string atCommand = ATCommand.MessageFormat.Command();
var command = new ParamATCommand(atCommand, commandParameter);
await command.ExecuteAsync(modem);
bool succeeded = command.Succeeded();
最后,可以发送消息:
var lengthStep = new CommandParameter($"{length}{Constants.CR}", Constants.ContinueResponse, false);
var packetStep = new CommandParameter($"{packet}{Constants.SUB}", Constants.BasicSuccessfulResponse);
var sendCommand = new StepwiseATCommand(ATCommand.MessageSend.Command(), new ICommandParameter[] { lengthStep, packetStep });
await sendCommand.ExecuteAsync(modem);
bool succeeded = sendCommand.Succeeded();