gpt4 book ai didi

java - 使用 2 个线程从 gsm 调制解调器获取短信

转载 作者:行者123 更新时间:2023-12-02 11:56:46 35 4
gpt4 key购买 nike

尝试执行一个应用程序,每隔一段时间从 gsm 调制解调器读取短信。

思考这个解决方案:

我的应用程序中有 2 个线程。

T1)- GSMModemHandler,它是串行通信的处理程序。T2)- SMSPicker,每个时间段都会请求短信并对其执行一些字符串算法。

我希望我的应用程序这样做:

A)- T2 使用 GSMModemHandler 类的方法 readAllMessages() 请求短信,然后保持阻塞状态。

B)- T1 有一个 SerialEventListener,因此它监听对 GSM-Modem 发送的请求的响应,并将其发送回 T2。

C)- 一旦 T2 类的列表中提供了响应,T2 就会恢复其有关字符串算法的任务,然后在等待一定时间后再次执行 A 中的相同操作。

我尝试编写代码,当我启动应用程序时,它会工作一段时间然后阻塞,我猜问题来自于两个线程之间的误解,但找不到问题出在哪里以及如何解决。

这是我的代码和结果:

public class GSMModemHandler extends SerialPort implements 
SerialPortEventListener{

private static final String
COMMAND_REMISE_A_ZERO = "ATZ",
COMMAND_SMS_MODE_TEXT = "AT+CMGF=1",
COMMAND_DETAILED_ERRORS = "AT+CMEE=1",
COMMAND_SET_UP_MEMORIES = "AT+CPMS=\"MT\",\"MT\",\"MT\"",

COMMAND_LIST_SUPPORTED_STORAGE_MODES = "AT+CPMS=?",

COMMAND_ENVOIE_SMS = "AT+CMGS=",

COMMAND_GET_ALL_SMS = "AT+CMGL=\"ALL\"",
COMMAND_GET_NEW_SMS = "AT+CMGL=\"REC UNREAD\"",

COMMAND_DELETE_ALL_MESSAGES = "AT+CMGD=0[,4]",
COMMAND_DELETE_READ_MESSAGES = "AT+CMGD=0[,1]";

private SMSPicker smsPicker = null;
private String response = "";

public GSMModemHandler(String port) throws SerialPortException{
super(port);
this.openPort();
this.setParams(9600,SerialPort.DATABITS_8,SerialPort.STOPBITS_1,SerialPort.PARITY_NONE);
this.addEventListener(this);
this.startGsm();
}

public void startGsm() throws SerialPortException{
this.writeString(GSMModemHandler.COMMAND_REMISE_A_ZERO + "\r\n");
this.writeString(GSMModemHandler.COMMAND_SMS_MODE_TEXT + "\r\n");
this.writeString(GSMModemHandler.COMMAND_DETAILED_ERRORS + "\r\n");
this.writeString(GSMModemHandler.COMMAND_SET_UP_MEMORIES + "\r\n");
}

public void sendMessage(SMS sms){
try{
if(this.isOpened()){
this.writeString(GSMModemHandler.COMMAND_ENVOIE_SMS + "\"" + sms.getCorrespondantSms() + "\"\r\n");
this.writeString(sms.getContenuSms() + '\032');
}
}
catch(SerialPortException exp){
exp.printStackTrace();
}
}

public void readAllMessages(){
try{
if(this.isOpened())
this.writeString(GSMModemHandler.COMMAND_GET_ALL_SMS + "\r\n");

}
catch(SerialPortException exp){
exp.printStackTrace();
}
}

public void readUnreadMessages(){
try{
if(this.isOpened())
this.writeString(GSMModemHandler.COMMAND_GET_NEW_SMS + "\r\n");
}
catch(SerialPortException exp){
exp.printStackTrace();
}
}

public void deleteAllMessages(){
try{
if(this.isOpened())
this.writeString(GSMModemHandler.COMMAND_DELETE_ALL_MESSAGES + "\r\n");
}
catch(SerialPortException exp){
exp.printStackTrace();
}
}

public void deleteReadMessages(){
try{
if(this.isOpened())
this.writeString(GSMModemHandler.COMMAND_DELETE_READ_MESSAGES + "\r\n");
}
catch(SerialPortException exp){
exp.printStackTrace();
}
}

public synchronized void fermerConnexion(){
try{
this.closePort();
}
catch(SerialPortException exp){
exp.printStackTrace();
}
}

AtomicBoolean nextResponseIsSms = new AtomicBoolean(false);

@Override
public void serialEvent(SerialPortEvent spe) {
try {
String reponse = this.readString();

System.out.println("GSM response = " + reponse);

// If the next response contains the wanted sms
if(reponse != null && reponse.contains("AT+CMGL=")){
this.nextResponseIsSms.set(true);
System.out.println("nextResponseIsSms = true");
}

// if the response contains sms
else if(this.nextResponseIsSms.get()){

this.smsPicker.getResponse().add(reponse);

System.out.println("response sent !");

this.deleteAllMessages(); // deleting the sms in the gsm modem

System.out.println("messages deleted");

this.nextResponseIsSms.set(false);

System.out.println("nextResponseIsSms = false");

// gives the SMSPicker the hand to treat the response
synchronized(this.smsPicker){ this.smsPicker.notify(); }

System.out.println("smsPicker notified");
}

} catch (SerialPortException ex) {
Logger.getLogger(GSMModemHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* @return the smsPicker
*/
public SMSPicker getSmsPicker() {
return smsPicker;
}

/**
* @param smsPicker the smsPicker to set
*/
public void setSmsPicker(SMSPicker smsPicker) {
this.smsPicker = smsPicker;
}

}

public class SMSPicker extends ControlledThread{

private GSMModemHandler modemGsm;
private SMSQueueToDatabase smsQueueHandler;
private volatile Queue<String> responses = new LinkedList<String>();

public SMSPicker(double frequency, GSMModemHandler gsmModem){
super(frequency);
this.modemGsm = gsmModem;
this.modemGsm.setSmsPicker(this);
this.smsQueueHandler = new SMSQueueToDatabase(frequency);
}

@Override
public void whatToDoBeforeTheLoop(){
this.smsQueueHandler.start();

try {
this.wait(2 * this.waitingPeriod.get());
} catch (InterruptedException ex) {
Logger.getLogger(SMSPicker.class.getName()).log(Level.SEVERE, null, ex);
}
}

@Override
public void whatToDoDuringTheLoop() throws NullPointerException{
synchronized(this){
try {
System.out.println("I'm going to launch the request !");

// Sending the sms read request to the gsm modem
this.modemGsm.readAllMessages();

System.out.println("i'm going to be stopped!");

// wait till we get the answer
this.wait();

System.out.println("I've been stopped and now resuming");
}
catch (InterruptedException ex) {
Logger.getLogger(SMSPicker.class.getName()).log(Level.SEVERE, null, ex);
}
}

// Treating the response in order to extract sms from it
while(!this.responses.isEmpty()){
String longMessage = this.responses.poll();

if(longMessage != null){
String[] shortMessages = null;
shortMessages = longMessage.split("\\+CMGL: [0-9]*,\"");

if(shortMessages == null) continue;

for(String shortMessage: shortMessages){
int indexLastOK = shortMessage.lastIndexOf("OK");

if(indexLastOK != -1 && shortMessage.contains("+"))
this.smsQueueHandler.getSmsFifo().add(this.fromStringToSms(shortMessage
.substring(0,shortMessage.lastIndexOf("OK") - 2))); // if it is the last sms
else if(shortMessage.contains("REC")) // if it is not the last one
this.smsQueueHandler.getSmsFifo().add(this.fromStringToSms(shortMessage));
}
}
}
}

private SMS fromStringToSms(String stringSms){
String[] smsParts = stringSms.split(",");

String correspondantSms = smsParts[1].replaceAll("\"", "");
String dateSms = smsParts[3].replace("\"","").replaceAll("/", "-");
String heureSms = smsParts[4].substring(0,smsParts[4].lastIndexOf("\"")).substring(0, 8);
String contenuSms = stringSms.substring(stringSms.lastIndexOf("\"") + 3);

LocalDateTime momentSms = LocalDateTime.parse("20" + dateSms + "T" + heureSms);

return new SMS(correspondantSms,contenuSms,momentSms);
}

@Override
public void whatToDoAfterTheLoop() {
}

/**
* @return the modemGsm
*/
public GSMModemHandler getModemGsm() {
return modemGsm;
}

/**
* @param modemGsm the modemGsm to set
*/
public void setModemGsm(GSMModemHandler modemGsm) {
this.modemGsm = modemGsm;
}

/**
* @return the smsQueueHandler
*/
public SMSQueueToDatabase getSmsQueueHandler() {
return smsQueueHandler;
}

/**
* @param smsQueueHandler the smsQueueHandler to set
*/
public void setSmsQueueHandler(SMSQueueToDatabase smsQueueHandler) {
this.smsQueueHandler = smsQueueHandler;
}

/**
* @return the response
*/
public Queue<String> getResponse() {
return responses;
}

/**
* @param response the response to set
*/
public void setResponse(Queue<String> responses) {
this.responses = responses;
}

}

public abstract class ControlledThread extends Thread{

protected AtomicBoolean workable = null;
protected AtomicLong waitingPeriod = null;

public ControlledThread(double frequency){
super();
this.workable = new AtomicBoolean(true);
this.waitingPeriod = new AtomicLong(((long)(1000 / frequency)));
}

@Override
public synchronized void run() {
this.whatToDoBeforeTheLoop();
while(this.workable.get()){
try{
this.whatToDoDuringTheLoop();
this.wait(this.waitingPeriod.get());
}
catch(InterruptedException exp){
exp.printStackTrace();
}
}
this.whatToDoAfterTheLoop();
}

public void stopWorking(){
this.workable.set(false);
}

public synchronized boolean isWorking(){
return this.workable.get();
}

public abstract void whatToDoBeforeTheLoop();
public abstract void whatToDoDuringTheLoop();
public abstract void whatToDoAfterTheLoop();
}

结果: enter image description here

注意:阻塞状态发生在红线处(BUILD STOPPED 只是我通过杀死停止应用程序的结果)

提前致谢!

最佳答案

很可能,您遇到了错过的信号:您开始等待已经发生的 notify()

这是因为你开始无条件等待。但是,您应该始终在检查其等待条件的循环内等待。

就您的情况而言,继续等待的理由可能是直到提供答案为止。

所以:

while (!hasAnswer()) {
this.wait();
}

您还必须确保同步的监视器(在您的情况下为 SMSPicker)正确保护确定条件的状态。由于您似乎只是暴露了响应队列,因此它认为情况可能并非如此,但我错过了太多细节,无法确定。

有关更详细的说明,请查看 here .

关于java - 使用 2 个线程从 gsm 调制解调器获取短信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47555566/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com