⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdugenerator.java

📁 发送短信 接收短信 多种接口com/net/modem 开发库
💻 JAVA
📖 第 1 页 / 共 2 页
字号:

package org.ajwcc.pduUtils.gsm3040;

import java.io.*;
import java.util.*;
import org.ajwcc.pduUtils.gsm3040.ie.*;

//PduUtils Library - A Java library for generating GSM 3040 Protocol Data Units (PDUs)
//
//Copyright (C) 2008, Ateneo Java Wireless Competency Center/Blueblade Technologies, Philippines.
//PduUtils is distributed under the terms of the Apache License version 2.0
//
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//
//http://www.apache.org/licenses/LICENSE-2.0
//
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
public class PduGenerator
{
	private ByteArrayOutputStream baos;

	private int firstOctetPosition = -1;

	private boolean updateFirstOctet = false;

	protected void writeSmscInfo(Pdu pdu) throws Exception
	{
		if (pdu.getSmscAddress() != null)
		{
			writeBCDAddress(pdu.getSmscAddress(), pdu.getSmscAddressType(), pdu.getSmscInfoLength());
		}
		else
		{
			writeByte(0);
		}
	}

	protected void writeFirstOctet(Pdu pdu)
	{
		// store the position in case it will need to be updated later
		firstOctetPosition = pdu.getSmscInfoLength() + 1;
		writeByte(pdu.getFirstOctet());
	}

	// validity period conversion from hours to the proper integer
	protected void writeValidityPeriodInteger(int validityPeriod)
	{
		if (validityPeriod == -1)
		{
			baos.write(0xFF);
		}
		else
		{
			int validityInt;
			if (validityPeriod <= 12) validityInt = (validityPeriod * 12) - 1;
			else if (validityPeriod <= 24) validityInt = (((validityPeriod - 12) * 2) + 143);
			else if (validityPeriod <= 720) validityInt = (validityPeriod / 24) + 166;
			else validityInt = (validityPeriod / 168) + 192;
			baos.write(validityInt);
		}
	}

	protected void writeTimeStampStringForDate(Date timestamp)
	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(timestamp);
		int year = cal.get(Calendar.YEAR) - 2000;
		int month = cal.get(Calendar.MONTH) + 1;
		int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
		int hourOfDay = cal.get(Calendar.HOUR_OF_DAY);
		int minute = cal.get(Calendar.MINUTE);
		int sec = cal.get(Calendar.SECOND);
		TimeZone tz = cal.getTimeZone();
		int offset = tz.getOffset(timestamp.getTime());
		int minOffset = offset / 60000;
		int tzValue = minOffset / 15;
		// for negative offsets, add 128 to the absolute value
		if (tzValue < 0)
		{
			tzValue = 128 - tzValue;
		}
		// note: the nibbles are written as BCD style
		baos.write(PduUtils.createSwappedBCD(year));
		baos.write(PduUtils.createSwappedBCD(month));
		baos.write(PduUtils.createSwappedBCD(dayOfMonth));
		baos.write(PduUtils.createSwappedBCD(hourOfDay));
		baos.write(PduUtils.createSwappedBCD(minute));
		baos.write(PduUtils.createSwappedBCD(sec));
		baos.write(PduUtils.createSwappedBCD(tzValue));
	}

	protected void writeAddress(String address, int addressType, int addressLength) throws Exception
	{
		switch (PduUtils.extractAddressType(addressType))
		{
			case PduUtils.ADDRESS_TYPE_ALPHANUMERIC:
				byte[] textSeptets = PduUtils.stringToUnencodedSeptets(address);
				byte[] alphaNumBytes = PduUtils.encode7bitUserData(null, textSeptets);
				// ADDRESS LENGTH - should be the semi-octet count
				//                - this type is not used for SMSCInfo
				baos.write(alphaNumBytes.length * 2);
				// ADDRESS TYPE
				baos.write(addressType);
				// ADDRESS TEXT
				baos.write(alphaNumBytes);
				break;
			default:
				// BCD-style
				writeBCDAddress(address, addressType, addressLength);
		}
	}

	protected void writeBCDAddress(String address, int addressType, int addressLength) throws Exception
	{
		// BCD-style
		// ADDRESS LENGTH - either an octet count or semi-octet count
		baos.write(addressLength);
		// ADDRESS TYPE
		baos.write(addressType);
		// ADDRESS NUMBERS
		// if address.length is not even, pad the string an with F at the end
		if (address.length() % 2 == 1)
		{
			address = address + "F";
		}
		int digit = 0;
		for (int i = 0; i < address.length(); i++)
		{
			char c = address.charAt(i);
			if (i % 2 == 1)
			{
				digit |= ((Integer.parseInt(Character.toString(c), 16)) << 4);
				baos.write(digit);
				// clear it
				digit = 0;
			}
			else
			{
				digit |= (Integer.parseInt(Character.toString(c), 16) & 0x0F);
			}
		}
	}

	protected void writeUDData(Pdu pdu, int mpRefNo, int partNo)
	{
		int dcs = pdu.getDataCodingScheme();
		try
		{
			switch (PduUtils.extractDcsEncoding(dcs))
			{
				case PduUtils.DCS_ENCODING_7BIT:
					writeUDData7bit(pdu, mpRefNo, partNo);
					break;
				case PduUtils.DCS_ENCODING_8BIT:
					writeUDData8bit(pdu, mpRefNo, partNo);
					break;
				case PduUtils.DCS_ENCODING_UCS2:
					writeUDDataUCS2(pdu, mpRefNo, partNo);
					break;
				default:
					throw new RuntimeException("Invalid DCS encoding: " + PduUtils.extractDcsEncoding(dcs));
			}
		}
		catch (Exception e)
		{
			throw new RuntimeException(e);
		}
	}

	protected void writeUDH(Pdu pdu) throws IOException
	{
		// stream directly into the internal baos
		writeUDH(pdu, baos);
	}

	protected void writeUDH(Pdu pdu, ByteArrayOutputStream udhBaos) throws IOException
	{
		// need to insure that proper concat info is inserted
		// before writing if needed
		// i.e. the reference number, maxseq and seq have to be set from
		// outside (OutboundMessage)
		udhBaos.write(pdu.getUDHLength());
		for (Iterator<InformationElement> ieIterator = pdu.getInformationElements(); ieIterator.hasNext();)
		{
			InformationElement ie = ieIterator.next();
			udhBaos.write(ie.getIdentifier());
			udhBaos.write(ie.getLength());
			udhBaos.write(ie.getData());
		}
	}

	protected int computeOffset(Pdu pdu, int maxMessageLength, int partNo)
	{
		// computes offset to which part of the string is to be encoded into the PDU
		// also sets the MpMaxNo field of the concatInfo if message is multi-part
		int offset;
		int maxParts = 1;
		if (!pdu.isBinary())
		{
			maxParts = pdu.getDecodedText().length() / maxMessageLength + 1;
		}
		else
		{
			maxParts = pdu.getDataBytes().length / maxMessageLength + 1;
		}
		if (pdu.hasTpUdhi())
		{
			if (pdu.getConcatInfo() != null)
			{
				if (partNo > 0)
				{
					pdu.getConcatInfo().setMpMaxNo(maxParts);
				}
			}
		}
		if ((maxParts > 1) && (partNo > 0))
		{
			//      - if partNo > maxParts
			//          - error
			if (partNo > maxParts) { throw new RuntimeException("Invalid partNo: " + partNo + ", maxParts=" + maxParts); }
			offset = ((partNo - 1) * maxMessageLength);
		}
		else
		{
			// just get from the start
			offset = 0;
		}
		return offset;
	}

	protected void checkForConcat(Pdu pdu, int lengthOfText, int maxLength, int maxLengthWithUdh, int mpRefNo, int partNo)
	{
		if ((lengthOfText <= maxLengthWithUdh) || ((lengthOfText > maxLengthWithUdh) && (lengthOfText <= maxLength)))
		{
			// nothing needed
		}
		else
		{
			// need concat
			if (pdu.getConcatInfo() != null)
			{
				// if concatInfo is already present then just replace the values with the supplied
				pdu.getConcatInfo().setMpRefNo(mpRefNo);
				pdu.getConcatInfo().setMpSeqNo(partNo);
			}
			else
			{
				// add concat info with the specified mpRefNo, bogus maxSeqNo, and partNo
				// bogus maxSeqNo will be replaced once it is known in the later steps
				// this just needs to be added since its presence is needed to compute
				// the UDH length
				ConcatInformationElement concatInfo = InformationElementFactory.generateConcatInfo(mpRefNo, partNo);
				pdu.addInformationElement(concatInfo);
				updateFirstOctet = true;
			}
		}
	}

	protected int computePotentialUdhLength(Pdu pdu)
	{
		int currentUdhLength = pdu.getTotalUDHLength();
		if (currentUdhLength == 0)
		{
			// add 1 for the UDH Length field
			return ConcatInformationElement.getDefaultConcatLength() + 1;
		}
		else
		{
			// this already has the UDH Length field, no need to add 1
			return currentUdhLength + ConcatInformationElement.getDefaultConcatLength();
		}
	}

	protected void writeUDData7bit(Pdu pdu, int mpRefNo, int partNo) throws Exception
	{
		String decodedText = pdu.getDecodedText();
		// partNo states what part of the unencoded text will be used
		//      - max length is based on the size of the UDH
		//        for 7bit => maxLength = 160 - total UDH septets
		// check if this message needs a concat
		byte[] textSeptetsForDecodedText = PduUtils.stringToUnencodedSeptets(decodedText);
		int potentialUdhLength = PduUtils.getNumSeptetsForOctets(computePotentialUdhLength(pdu));

		checkForConcat(pdu, 
                       textSeptetsForDecodedText.length, 
                       160 - PduUtils.getNumSeptetsForOctets(pdu.getTotalUDHLength()), // CHANGED
                       160 - potentialUdhLength, 
                       mpRefNo, 
                       partNo);		
		

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -