/// <summary> /// 用户数据编码 /// </summary> /// <param name="UDC">短信内容</param> /// <param name="UDH">用户数据头</param> /// <param name="DCS">编码方案</param> /// <returns>编码后的字符串</returns> /// <remarks> /// L:用户数据长度,长度1 /// M:用户数据,长度0~140 /// </remarks> private static String UDEncoding(Object UDC, PDUUDH[] UDH = null, EnumDCS DCS = EnumDCS.UCS2) { // 用户数据头编码 Int32 UDHL; String Header = UDHEncoding(UDH, out UDHL); // 用户数据内容编码 Int32 UDCL; String Body; if (UDC is String) { // 7-Bit编码或UCS2编码 Body = UDCEncoding(UDC as String, out UDCL, UDHL, DCS); } else { // 8-Bit编码 Body = UDCEncoding(UDC as Byte[], out UDCL); } // 用户数据区长度 Int32 UDL; if (DCS == EnumDCS.BIT7) { // 7-Bit编码 UDL = (UDHL * 8 + 6) / 7 + UDCL; // 字符数 } else { // UCS2编码或者8-Bit编码 UDL = UDHL + UDCL; // 字节数 } return(UDL.ToString("X2") + Header + Body); }
/// <summary> /// 数据编码方案 /// </summary> /// <param name="UDC">用户数据</param> /// <param name="DCS">编码字符集</param> /// <returns>编码字符串</returns> private static String DCSEncoding(Object UDC, EnumDCS DCS = EnumDCS.UCS2) { if (UDC is String) { if (DCS == EnumDCS.BIT7) { // 7-Bit编码 return("00"); } else { // UCS2编码 return("08"); } } else { // 8-Bit编码 return("04"); } }
/// <summary> /// 用户数据内容拆分 /// </summary> /// <param name="UDC">用户数据内容</param> /// <param name="UDH">用户数据头</param> /// <param name="DCS">编码方案</param> /// <returns>拆分内容列表</returns> private List <String> UDCSplit(String UDC, PDUUDH[] UDH = null, EnumDCS DCS = EnumDCS.UCS2) { // 统计用户数据头长度 Int32 UDHL = GetUDHL(UDH); if (DCS == EnumDCS.BIT7) { // 7-Bit编码 // 计算剩余房间数 Int32 Room = (Int32)EnumUDL.BIT7UDL - (UDHL * 8 + 6) / 7; if (Room < 1) { if (String.IsNullOrEmpty(UDC)) { return new List <String>() { UDC } } ; else { return(null); // 超出范围 } } if (SeptetsLength(UDC) <= Room) { return(new List <String>() { UDC }); } else { // 需要拆分成多条短信 if (UDHL == 0) { UDHL++; } if (mCSMIEI == EnumCSMIEI.BIT8) { UDHL += 5; // 1字节消息参考号 } else { UDHL += 6; // 2字节消息参考号 } // 更新剩余房间数 Room = (Int32)EnumUDL.BIT7UDL - (UDHL * 8 + 6) / 7; if (Room < 1) { return(null); // 超出范围 } List <String> CSM = new List <String>(); Int32 i = 0; while (i < UDC.Length) { Int32 Step = SeptetsToChars(UDC, i, Room); if (i + Step < UDC.Length) { CSM.Add(UDC.Substring(i, Step)); } else { CSM.Add(UDC.Substring(i)); } i += Step; } return(CSM); } } else { // UCS2编码 // 计算剩余房间数 Int32 Room = ((Int32)EnumUDL.BIT8UDL - UDHL) >> 1; if (Room < 1) { if (String.IsNullOrEmpty(UDC)) { return new List <String>() { UDC } } ; else { return(null); // 超出范围 } } if (UDC == null || UDC.Length <= Room) { return(new List <String>() { UDC }); } else { // 需要拆分成多条短信 if (UDHL == 0) { UDHL++; } if (mCSMIEI == EnumCSMIEI.BIT8) { UDHL += 5; // 1字节消息参考号 } else { UDHL += 6; // 2字节消息参考号 } // 更新剩余房间数 Room = ((Int32)EnumUDL.BIT8UDL - UDHL) >> 1; if (Room < 1) { return(null); // 超出范围 } List <String> CSM = new List <String>(); for (Int32 i = 0; i < UDC.Length; i += Room) { if (i + Room < UDC.Length) { CSM.Add(UDC.Substring(i, Room)); } else { CSM.Add(UDC.Substring(i)); } } return(CSM); } } }
/// <summary> /// 用户数据解码 /// </summary> /// <param name="data">编码字符串</param> /// <param name="Index">起始索引号</param> /// <param name="UDHI">用户数据头标识</param> /// <param name="DCS">编码方案</param> /// <returns> /// String类型:文本内容 /// Byte[]类型:二进制内容 /// </returns> private static Object UserDataDecoding(String data, Int32 Index, Boolean UDHI = false, EnumDCS DCS = EnumDCS.UCS2) { // 用户数据区长度 Int32 UDL = Convert.ToInt32(data.Substring(Index, 2), 16); Index += 2; // 跳过用户数据头 Int32 UDHL = 0; if (UDHI) { // 用户数据头长度 UDHL = Convert.ToInt32(data.Substring(Index, 2), 16); UDHL++; Index += UDHL << 1; } // 获取用户数据 if (DCS == EnumDCS.UCS2) { // 获取字符个数 Int32 CharNumber = (UDL - UDHL) >> 1; StringBuilder sb = new StringBuilder(CharNumber); for (Int32 i = 0; i < CharNumber; i++) { sb.Append(Convert.ToChar(Convert.ToInt32(data.Substring((i << 2) + Index, 4), 16))); } return(sb); } else if (DCS == EnumDCS.BIT7) { Int32 Septets = UDL - (UDHL * 8 + 6) / 7; // 7-Bit编码字符数 Int32 FillBits = (UDHL * 8 + 6) / 7 * 7 - UDHL * 8; // 填充位数 return(BIT7Decoding(BIT7Unpack(data, Index, Septets, FillBits))); } else { // 8Bit编码 // 获取数据长度 UDL -= UDHL; Byte[] Binary = new Byte[UDL]; for (Int32 i = 0; i < UDL; i++) { Binary[i] = Convert.ToByte(data.Substring((i << 1) + Index, 2), 16); } return(Binary); } }
/// <summary> /// 长短信编码 /// </summary> /// <param name="SCA">服务中心地址</param> /// <param name="DA">接收方地址</param> /// <param name="UDC">用户数据内容</param> /// <param name="UDH">用户数据头</param> /// <param name="DCS">编码方案</param> /// <returns>长短信编码序列</returns> /// <remarks>长短信自动拆分</remarks> public String[] PDUEncoding(String SCA, String DA, Object UDC, PDUUDH[] UDH = null, EnumDCS DCS = EnumDCS.UCS2) { // 短信拆分 if (UDC is String) { List <String> CSMUDC = UDCSplit(UDC as String, UDH, DCS); if (CSMUDC == null) { return(null); } if (CSMUDC.Count > 1) { // 长短信 Int32 CSMMR = _mCSMMR; if (++_mCSMMR > 0xFFFF) { _mCSMMR = 0; } // 生成短信编码序列 String[] CSMSeries = new String[CSMUDC.Count]; for (Int32 i = 0; i < CSMUDC.Count; i++) { // 更新用户数据头 PDUUDH[] CSMUDH = UpdateUDH(UDH, CSMMR, CSMUDC.Count, i); CSMSeries[i] = SoloPDUEncoding(SCA, DA, CSMUDC[i], CSMUDH, DCS); } return(CSMSeries); } else { // 单条短信 return(new String[1] { SoloPDUEncoding(SCA, DA, UDC, UDH, DCS) }); } } else if (UDC is Byte[]) { List <Byte[]> CSMUDC = UDCSplit(UDC as Byte[], UDH); if (CSMUDC == null) { return(null); } if (CSMUDC.Count > 1) { // 长短信 Int32 CSMMR = _mCSMMR; if (++_mCSMMR > 0xFFFF) { _mCSMMR = 0; } // 生成短信编码序列 String[] CSMSeries = new String[CSMUDC.Count]; for (Int32 i = 0; i < CSMUDC.Count; i++) { // 更新用户数据头 PDUUDH[] CSMUDH = UpdateUDH(UDH, CSMMR, CSMUDC.Count, i); CSMSeries[i] = SoloPDUEncoding(SCA, DA, CSMUDC[i], CSMUDH, DCS); } return(CSMSeries); } else { // 单条短信 return(new String[1] { SoloPDUEncoding(SCA, DA, UDC, UDH, DCS) }); } } else { return(null); } }
/// <summary> /// 单条短信编码 /// </summary> /// <param name="SCA">服务中心地址,如果为null,则表示使用SIM卡设置</param> /// <param name="DA">接收方地址</param> /// <param name="UDC">用户数据内容</param> /// <param name="UDH">用户数据头</param> /// <param name="DCS">编码方案</param> /// <returns>编码后的字符串</returns> /// <remarks> /// 发送方PDU格式(SMS-SUBMIT-PDU) /// SCA(Service Center Adress):短信中心,长度1-12 /// PDU-Type(Protocol Data Unit Type):协议数据单元类型,长度1 /// MR(Message Reference):消息参考值,为0~255。长度1 /// DA(Destination Adress):接收方SME的地址,长度2-12 /// PID(Protocol Identifier):协议标识,长度1 /// DCS(Data Coding Scheme):编码方案,长度1 /// VP(Validity Period):有效期,长度为1(相对)或者7(绝对或增强) /// UDL(User Data Length):用户数据段长度,长度1 /// UD(User Data):用户数据,长度0-140 /// </remarks> private String SoloPDUEncoding(String SCA, String DA, Object UDC, PDUUDH[] UDH = null, EnumDCS DCS = EnumDCS.UCS2) { StringBuilder sb = new StringBuilder(400); // 短信中心 sb.Append(SCAEncoding(SCA)); // 协议数据单元类型 if (UDH == null || UDH.Length == 0) { sb.Append(PDUTypeEncoding(false)); } else { sb.Append(PDUTypeEncoding(true)); } // 消息参考值 sb.Append(MREncoding()); // 接收方SME地址 sb.Append(DAEncoding(DA)); // 协议标识 sb.Append(PIDEncoding()); // 编码方案 sb.Append(DCSEncoding(UDC, DCS)); // 有效期 sb.Append(_mVP); // 用户数据长度及内容 sb.Append(UDEncoding(UDC as String, UDH, DCS)); return(sb.ToString()); }
/// <summary> /// 用户数据内容编码 /// </summary> /// <param name="UDC">用户数据内容</param> /// <param name="UDCL">输出:UCS2编码字节数或7-Bit编码字符数</param> /// <param name="UDHL">用户数据头长度,7-Bit编码时需要参考</param> /// <param name="DCS">编码方案</param> /// <returns>编码字符串</returns> private static String UDCEncoding(String UDC, out Int32 UDCL, Int32 UDHL = 0, EnumDCS DCS = EnumDCS.UCS2) { if (String.IsNullOrEmpty(UDC)) { UDCL = 0; return(String.Empty); } if (DCS == EnumDCS.BIT7) { // 7-Bit编码,需要参考用户数据头长度,已保证7-Bit边界对齐 return(BIT7Pack(BIT7Encoding(UDC, out UDCL), UDHL)); } else { // UCS2编码 UDCL = UDC.Length << 1; // 字节数 StringBuilder sb = new StringBuilder(UDCL << 1); foreach (Char Letter in UDC) { sb.Append(Convert.ToInt32(Letter).ToString("X4")); } return(sb.ToString()); } }