📄 modemgateway.java
字号:
// SMSLib for Java v3
// A Java API library for sending and receiving SMS via a GSM modem
// or other supported gateways.
// Web Site: http://www.smslib.org
//
// Copyright (C) 2002-2008, Thanasis Delenikas, Athens/GREECE.
// SMSLib 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.
package org.smslib.modem;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Collection;
import java.util.Random;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.ajwcc.pduUtils.gsm3040.*;
import org.smslib.*;
import org.smslib.InboundMessage.MessageClasses;
import org.smslib.OutboundMessage.MessageStatuses;
import org.smslib.modem.athandler.AATHandler;
/**
* Class representing GSM modems or phones. Extends AGateway with modem specific
* operations.
*/
public class ModemGateway extends AGateway
{
/**
* Class representing different types of GSM modems / phones.
*/
public enum ModemTypes
{
/**
* Serially connected modem. These modems are connected via a serial
* port, either physical or emulated (i.e. USB, IrDA, etc).
*/
SERIAL,
/**
* IP connected modem.
*/
IP
}
private AModemDriver driver;
private AATHandler atHandler;
private String modemDevice;
private int modemParms;
private String manufacturer;
private String model;
private String simPin, simPin2;
private int outMpRefNo;
private List<List<InboundMessage>> mpMsgList;
private String smscNumber;
ModemGateway(ModemTypes type, String id, String myModemDevice, int myModemParms, String myManufacturer, String myModel)
{
super(id);
this.modemDevice = myModemDevice;
this.modemParms = myModemParms;
this.manufacturer = myManufacturer;
this.model = myModel;
setAttributes(AGateway.GatewayAttributes.SEND | AGateway.GatewayAttributes.RECEIVE | AGateway.GatewayAttributes.BIGMESSAGES | AGateway.GatewayAttributes.WAPSI | AGateway.GatewayAttributes.PORTADDRESSING | AGateway.GatewayAttributes.FLASHSMS | AGateway.GatewayAttributes.DELIVERYREPORTS);
if (type == ModemTypes.SERIAL) this.driver = new SerialModemDriver(this, this.modemDevice + ":" + this.modemParms);
else this.driver = new IPModemDriver(this, this.modemDevice + ":" + this.modemParms);
this.atHandler = AATHandler.load(this, this.manufacturer, this.model);
this.simPin = "";
this.simPin2 = "";
this.outMpRefNo = new Random().nextInt();
if (this.outMpRefNo < 0) this.outMpRefNo *= -1;
this.outMpRefNo %= 65536;
this.mpMsgList = new ArrayList<List<InboundMessage>>();
this.smscNumber = "";
}
@Override
public void startGateway() throws TimeoutException, GatewayException, IOException, InterruptedException
{
getService().getLogger().logInfo("Starting gateway, using " + getATHandler().getDescription() + " AT Handler.", null, getGatewayId());
this.driver.connect();
super.startGateway();
getService().getLogger().logInfo("Gateway started.", null, getGatewayId());
}
@Override
public void stopGateway() throws TimeoutException, GatewayException, IOException, InterruptedException
{
getService().getLogger().logInfo("Stopping gateway...", null, getGatewayId());
getATHandler().done();
super.stopGateway();
this.driver.disconnect();
getService().getLogger().logInfo("Gateway stopped.", null, getGatewayId());
}
@Override
public void readMessages(Collection<InboundMessage> msgList, MessageClasses msgClass) throws TimeoutException, GatewayException, IOException, InterruptedException
{
if (getGatewayStatus() != GatewayStatuses.RUNNING) return;
synchronized (this.driver.SYNC_Commander)
{
if (getProtocol() == Protocols.PDU) readMessagesPDU(msgList, msgClass, 0);
else if (getProtocol() == Protocols.TEXT) readMessagesTEXT(msgList, msgClass, 0);
}
}
@Override
public InboundMessage readMessage(String memLoc, int memIndex) throws TimeoutException, GatewayException, IOException, InterruptedException
{
Collection<InboundMessage> msgList;
if (getGatewayStatus() != GatewayStatuses.RUNNING) return null;
synchronized (this.driver.SYNC_Commander)
{
msgList = new ArrayList<InboundMessage>();
readMessages(msgList, MessageClasses.ALL);
for (InboundMessage msg : msgList)
if ((msg.getMemIndex() == memIndex) && (msg.getMemLocation().equals(memLoc))) return msg;
return null;
}
}
@Override
public boolean sendMessage(OutboundMessage msg) throws TimeoutException, GatewayException, IOException, InterruptedException
{
if (getGatewayStatus() != GatewayStatuses.RUNNING) return false;
synchronized (this.driver.SYNC_Commander)
{
if (getProtocol() == Protocols.PDU) return sendMessagePDU(msg);
else if (getProtocol() == Protocols.TEXT) return sendMessageTEXT(msg);
else return false;
}
}
@Override
public boolean deleteMessage(InboundMessage msg) throws TimeoutException, GatewayException, IOException, InterruptedException
{
if (getGatewayStatus() != GatewayStatuses.RUNNING) return false;
synchronized (this.driver.SYNC_Commander)
{
if (msg.getMemIndex() >= 0) return deleteMessage(msg.getMemIndex(), msg.getMemLocation());
else if ((msg.getMemIndex() == -1) && (msg.getMpMemIndex().length() != 0))
{
StringTokenizer tokens = new StringTokenizer(msg.getMpMemIndex(), ",");
while (tokens.hasMoreTokens())
deleteMessage(Integer.parseInt(tokens.nextToken()), msg.getMemLocation());
}
return true;
}
}
private boolean deleteMessage(int memIndex, String memLocation) throws TimeoutException, GatewayException, IOException, InterruptedException
{
return getATHandler().deleteMessage(memIndex, memLocation);
}
private boolean sendMessageTEXT(OutboundMessage msg) throws TimeoutException, GatewayException, IOException, InterruptedException
{
int refNo;
boolean ok = false;
refNo = getATHandler().sendMessage(0, "", msg.getRecipient(), msg.getText());
if (refNo >= 0)
{
msg.setGatewayId(getGatewayId());
msg.setRefNo("" + refNo);
msg.setDispatchDate(new Date());
msg.setMessageStatus(MessageStatuses.SENT);
incOutboundMessageCount();
ok = true;
}
else
{
msg.setRefNo(null);
msg.setDispatchDate(null);
msg.setMessageStatus(MessageStatuses.FAILED);
}
return ok;
}
private void readMessagesTEXT(Collection<InboundMessage> msgList, MessageClasses msgClass, int myLimit) throws TimeoutException, GatewayException, IOException, InterruptedException
{
int i, j, memIndex;
int limit = (myLimit < 0 ? 0 : myLimit);
String response, line, msgText, originator, dateStr, refNo;
BufferedReader reader;
StringTokenizer tokens;
InboundMessage msg;
Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
for (int ml = 0; ml < (getATHandler().getStorageLocations().length() / 2); ml++)
{
if (getATHandler().switchStorageLocation(getATHandler().getStorageLocations().substring((ml * 2), (ml * 2) + 2)))
{
response = getATHandler().listMessages(msgClass);
response = response.replaceAll("\\s+OK\\s+", "\nOK");
reader = new BufferedReader(new StringReader(response));
for (;;)
{
line = reader.readLine().trim();
if (line == null) break;
line = line.trim();
if (line.length() > 0) break;
}
while (true)
{
if (line == null) break;
line = line.trim();
if (line.length() <= 0 || line.equalsIgnoreCase("OK")) break;
i = line.indexOf(':');
j = line.indexOf(',');
memIndex = Integer.parseInt(line.substring(i + 1, j).trim());
tokens = new StringTokenizer(line, ",");
tokens.nextToken();
tokens.nextToken();
if (Character.isDigit(tokens.nextToken().trim().charAt(0)))
{
line = line.replaceAll(",,", ", ,");
tokens = new StringTokenizer(line, ",");
tokens.nextToken();
tokens.nextToken();
tokens.nextToken();
refNo = tokens.nextToken();
tokens.nextToken();
dateStr = tokens.nextToken().replaceAll("\"", "");
cal1.set(Calendar.YEAR, 2000 + Integer.parseInt(dateStr.substring(0, 2)));
cal1.set(Calendar.MONTH, Integer.parseInt(dateStr.substring(3, 5)) - 1);
cal1.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateStr.substring(6, 8)));
dateStr = tokens.nextToken().replaceAll("\"", "");
cal1.set(Calendar.HOUR_OF_DAY, Integer.parseInt(dateStr.substring(0, 2)));
cal1.set(Calendar.MINUTE, Integer.parseInt(dateStr.substring(3, 5)));
cal1.set(Calendar.SECOND, Integer.parseInt(dateStr.substring(6, 8)));
dateStr = tokens.nextToken().replaceAll("\"", "");
cal2.set(Calendar.YEAR, 2000 + Integer.parseInt(dateStr.substring(0, 2)));
cal2.set(Calendar.MONTH, Integer.parseInt(dateStr.substring(3, 5)) - 1);
cal2.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateStr.substring(6, 8)));
dateStr = tokens.nextToken().replaceAll("\"", "");
cal2.set(Calendar.HOUR_OF_DAY, Integer.parseInt(dateStr.substring(0, 2)));
cal2.set(Calendar.MINUTE, Integer.parseInt(dateStr.substring(3, 5)));
cal2.set(Calendar.SECOND, Integer.parseInt(dateStr.substring(6, 8)));
msg = new StatusReportMessage(refNo, memIndex, getATHandler().getStorageLocations().substring((ml * 2), (ml * 2) + 2), cal1.getTime(), cal2.getTime());
msg.setGatewayId(getGatewayId());
getService().getLogger().logDebug("IN-DTLS: MI:" + msg.getMemIndex(), null, getGatewayId());
msgList.add(msg);
incInboundMessageCount();
}
else
{
line = line.replaceAll(",,", ", ,");
tokens = new StringTokenizer(line, ",");
tokens.nextToken();
tokens.nextToken();
originator = tokens.nextToken().replaceAll("\"", "");
tokens.nextToken();
dateStr = tokens.nextToken().replaceAll("\"", "");
cal1.set(Calendar.YEAR, 2000 + Integer.parseInt(dateStr.substring(0, 2)));
cal1.set(Calendar.MONTH, Integer.parseInt(dateStr.substring(3, 5)) - 1);
cal1.set(Calendar.DAY_OF_MONTH, Integer.parseInt(dateStr.substring(6, 8)));
dateStr = tokens.nextToken().replaceAll("\"", "");
cal1.set(Calendar.HOUR_OF_DAY, Integer.parseInt(dateStr.substring(0, 2)));
cal1.set(Calendar.MINUTE, Integer.parseInt(dateStr.substring(3, 5)));
cal1.set(Calendar.SECOND, Integer.parseInt(dateStr.substring(6, 8)));
msgText = reader.readLine().trim();
msg = new InboundMessage(cal1.getTime(), originator, msgText, memIndex, getATHandler().getStorageLocations().substring((ml * 2), (ml * 2) + 2));
msg.setGatewayId(getGatewayId());
getService().getLogger().logDebug("IN-DTLS: MI:" + msg.getMemIndex(), null, getGatewayId());
msgList.add(msg);
incInboundMessageCount();
}
line = reader.readLine().trim();
while (line.length() == 0)
line = reader.readLine().trim();
if ((limit > 0) && (msgList.size() == limit)) break;
}
reader.close();
}
}
}
private boolean sendMessagePDU(OutboundMessage msg) throws TimeoutException, GatewayException, IOException, InterruptedException
{
boolean ok = false;
List<String> pdus = msg.getPdus(this.smscNumber, this.outMpRefNo);
for (String pdu : pdus)
{
Pdu newPdu = new PduParser().parsePdu(pdu);
getService().getLogger().logDebug(newPdu.toString(), null, getGatewayId());
int j = pdu.length() / 2;
if (this.smscNumber == null)
{
// Do nothing on purpose!
}
else if (this.smscNumber.length() == 0) j--;
else
{
int smscNumberLen = this.smscNumber.length();
if (this.smscNumber.charAt(0) == '+') smscNumberLen--;
if (smscNumberLen % 2 != 0) smscNumberLen++;
int smscLen = (2 + smscNumberLen) / 2;
j = j - smscLen - 1;
}
getService().getLogger().logDebug("Sending Pdu: " + pdu, null, getGatewayId());
int refNo = getATHandler().sendMessage(j, pdu, null, null);
if (refNo >= 0)
{
msg.setGatewayId(getGatewayId());
msg.setRefNo(String.valueOf(refNo));
msg.setDispatchDate(new Date());
msg.setMessageStatus(MessageStatuses.SENT);
incOutboundMessageCount();
ok = true;
}
else
{
msg.setRefNo(null);
msg.setDispatchDate(null);
msg.setMessageStatus(MessageStatuses.FAILED);
ok = false;
}
}
if (pdus.size() > 1)
{
this.outMpRefNo = (this.outMpRefNo + 1) % 65536;
}
return ok;
}
private void readMessagesPDU(Collection<InboundMessage> msgList, MessageClasses messageClass, int myLimit) throws TimeoutException, GatewayException, IOException, InterruptedException
{
int i, j, memIndex;
String response, line, pduString;
BufferedReader reader;
int limit = (myLimit < 0 ? 0 : myLimit);
for (int ml = 0; ml < (getATHandler().getStorageLocations().length() / 2); ml++)
{
if (getATHandler().switchStorageLocation(getATHandler().getStorageLocations().substring((ml * 2), (ml * 2) + 2)))
{
response = getATHandler().listMessages(messageClass);
response = response.replaceAll("\\s+OK\\s+", "\nOK");
reader = new BufferedReader(new StringReader(response));
for (;;)
{
line = reader.readLine().trim();
if (line == null) break;
line = line.trim();
if (line.length() > 0) break;
}
// use the parser to determine the message type
PduParser parser = new PduParser();
while (true)
{
if (line == null) break;
line = line.trim();
if (line.length() <= 0 || line.equalsIgnoreCase("OK")) break;
i = line.indexOf(':');
j = line.indexOf(',');
memIndex = Integer.parseInt(line.substring(i + 1, j).trim());
pduString = reader.readLine().trim();
try
{
getService().getLogger().logDebug("READ PDU: " + pduString, null, getGatewayId());
// this will throw an exception for PDUs
// it can't classify
Pdu pdu = parser.parsePdu(pduString);
if (pdu instanceof SmsDeliveryPdu)
{
getService().getLogger().logDebug(pdu.toString(), null, getGatewayId());
InboundMessage msg;
if (pdu.isBinary())
{
msg = new InboundBinaryMessage((SmsDeliveryPdu) pdu, memIndex, getATHandler().getStorageLocations().substring((ml * 2), (ml * 2) + 2));
}
else
{
msg = new InboundMessage((SmsDeliveryPdu) pdu, memIndex, getATHandler().getStorageLocations().substring((ml * 2), (ml * 2) + 2));
}
msg.setGatewayId(getGatewayId());
getService().getLogger().logDebug("IN-DTLS: MI:" + msg.getMemIndex() + " REF:" + msg.getMpRefNo() + " MAX:" + msg.getMpMaxNo() + " SEQ:" + msg.getMpSeqNo(), null, getGatewayId());
if (msg.getMpRefNo() == 0)
{
// single message
msgList.add(msg);
incInboundMessageCount();
}
else
{
// multi-part message
int k, l;
List<InboundMessage> tmpList;
InboundMessage listMsg;
boolean found, duplicate;
found = false;
for (k = 0; k < this.mpMsgList.size(); k++)
{
// List of List<InboundMessage>
tmpList = this.mpMsgList.get(k);
listMsg = tmpList.get(0);
// check if current message list is for this message
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -