.NET库SmsToolset:PDU格式短信发送与接收

SmsToolset是一个用C#编写的.NET库,旨在帮助创建发送和接收PDU格式文本消息的应用程序。它通过GSM网络进行通信。这个库的核心概念是PDU配置文件,这是一个确定传输PDU数据包结构的对象。PDU配置文件的基本部分是由文本文件驱动的设置对象,该文件以众所周知的JSON格式编写。JSON文件中定义的配置文件参数加载到设置对象中,从而初始化PDU配置文件对象。配置文件的主要任务是创建PDU数据包。库的另一个重要部分是PDU配置文件管理器,它有助于创建和管理许多不同的配置文件。

总体而言,该库由三个主要部分组成,分别负责:

  • 创建和管理PDU配置文件
  • 为通信设备(GSM调制解调器)创建命令
  • 向通信设备发送命令并接收响应

此外,库还包含一些基本工具的实现,这些工具有助于执行以下任务:

  • 通过PIN进行身份验证
  • 处理服务中心号码
  • 发送和读取文本消息

该库的结构由三个命名空间组成。第一个命名空间SmsTools.PduProfile是库的核心。这里有两个主要接口:IPduProfileIPduProfileSettings,以及PduProfileManager类。IPduProfileSettings代表从JSON文件加载的设置对象,然后初始化实现IPduProfile接口的配置文件对象。PduProfileManager类的实例用于管理配置文件。在库中,分别实现了这些接口:PduDefaultProfileSettings负责配置设置,以及PduDefaultProfile类,负责创建配置文件。这些类之所以重要,是因为这个配置文件对象负责创建将通过GSM网络发送的PDU包。PDU包的结构和内容定义了IPduProfileSettings合同和相关的JSON文件。因此,应用给定的设置对象决定了包的形式及其元素:

  • 服务中心的数量
  • 目的号码
  • 使用的协议
  • 数据编码方案
  • 包的有效期限
  • 包头信息,如回复路径、用户头、状态报告、有效格式、重复拒绝和消息类型

另一个命名空间是SmsTools.Commands,其中包含代表通信设备(DCE:GSM调制解调器)理解的AT命令的接口。代表AT命令的对象的主要任务是形成传递给DCE的字符串,特别是PDU包,并解释从DCE收到的响应。为了实现这个概念,使用了IATCommandICommandParameter接口,分别代表命令及其参数。命令的实现被分为三个部分:

  • SimpleATCommand类负责创建不接受任何参数的命令。
  • ParamATCommand允许创建接受单个参数的命令。
  • StepwiseATCommand用于在传递上一个参数的结果取决于传递多个参数的情况下。发送文本消息的命令就是这样一个例子。

最后一个命名空间SmsTools.Operations包含代表DCE及其实现的接口。其主要且唯一目的是向DCE发送命令并接收响应。IPortPlug对象被命令用于其执行DCE。

所有上述概念都在AuthenticationServiceCenterPduSms类中实现。Authentication用于通过PIN验证用户。使用ServiceCenter类可以读取和设置服务中心号码。PduSms允许以PDU包的形式发送文本消息。

使用代码

让看看使用内置默认设置和默认配置文件发送SMS的最简单的示例。

使用PduSms类时,内置默认PDU配置文件的默认设置如下:

  • 服务中心号码类型:未设置
  • 服务中心号码:未设置
  • PDU头:0x11,意味着:
    • 回复路径:无设置
    • 用户数据段仅包含消息内容
    • 不需要状态报告
    • 有效期限字段有效,格式为相对
    • 不拒绝重复
    • 消息类型:SMS-SUBMIT
  • 目的号码类型:默认(不需要前缀)
  • 目的号码:未设置
  • 协议标识符:sms
  • 数据编码方案:UCS2
  • 有效期限:0xFF(最大)
  • 消息:未设置
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文件。设置如下:

  • 服务中心号码类型:国际
  • 服务中心号码:+48 601 000 310
  • PDU头:0x11,意味着:
    • 回复路径:无设置
    • 用户数据段仅包含消息内容
    • 不需要状态报告
    • 有效期限字段有效,格式为相对
    • 不拒绝重复
    • 消息类型:SMS-SUBMIT
  • 目的号码类型:国际
  • 目的号码:未设置
  • 协议标识符:sms
  • 数据编码方案:UCS2
  • 有效期限:0xFF(最大)
  • 消息:未设置

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();
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485