GSM MODEM java发送短信开发

本文记录了使用短信猫进行短信服务开发的过程,包括环境配置、依赖管理、短信客户端配置、服务启动与停止、发送短信的实现。开发中遇到的问题如驱动适配、设备测试以及解决办法也进行了分享。主要涉及Java环境配置、SMSLib库的使用以及数据库监控触发短信发送的逻辑。
摘要由CSDN通过智能技术生成

短信猫开发记录

准备

GSM MODEM
天线(没有天线,可能没有信号)
java相关开发环境(jar包,驱动,配置文件)
超级终端(用于检测设备是否正常)
SIM卡

  1. 配置环境:
    把RXTXcomm.jar文件放在\jdk\jre\lib\ext目录下
    把rxtxSerial.dll和rxtxParallel.dll文件放在\jdk\jre\bin目录下

  2. 搭建项目
    maven依赖

<dependency>
	<groupId>org.smslib</groupId>
	<artifactId>smslib</artifactId>
	<version>3.5.3</version>
</dependency>
  1. 开发需求:监听数据库某表的变化,有数据插入,发送短信到某表保存的联系人信息。
    思路:项目初始化时保存总量和最大时间到redis中,定时任务每分钟去查询一次和redis中数据比较,总量不同则对联系人发送短信。

  2. 短信客户端配置

@Configuration
@Slf4j
public class SmsServerConfig {
    @Value("${sms.portName}")
    private String portName;
    @Value("${sms.baud}")
    private int baudIndex;
    @Value("${sms.pin:0000}")
    private String pin;
    @Value("${sms.puer.ip:}")
    private String prIp;
    @Value("${sms.puer.username:}")
    private String prUserName;
    @Value("${sms.puer.password:}")
    private String prPassword;
    @Value("${sms.type:}")
    private String type;
    /**
     * 签名编码
     */
    @Value("${sms.mas.sign:}")
    private String sign;
    /**
     * url
     */
    @Value("${sms.mas.url:}")
    private String url;
    /**
     * 账号
     */
    @Value("${sms.mas.userAccount:}")
    private String userAccount;
    /**
     * 密码
     */
    @Value("${sms.mas.password:}")
    private String password;
    /**
     * 企业名称
     */
    @Value("${sms.mas.ecname:}")
    private String ecname;

    @Bean
    public SmsExecuter smsServer(){
        return new SmsServer(portName,baudIndex,pin);
    }
}

短信服务的方法,包括配置,初始化,启动服务,发送短信等方法。

/**
 * 短信服务
 */
@Slf4j
public class SmsServer implements SmsExecuter {
    private static Service  service;
    static int bauds[] = {9600,14400,19200,28800,33600,38400,56000,57600,115200};
    private boolean init=false;
    private boolean start=false;

    public SmsServer(String portName,int baudIndex,String pin){

        //波特率
        int baud=bauds[baudIndex];

        SerialModemGateway gateway = new SerialModemGateway("modem."+portName,portName,baud,"SIEMENS","null");
        //设置收件箱绑定
        gateway.setInbound(true);
        //设置发件箱绑定
        gateway.setOutbound(true);
        //获取实例
        service = Service.getInstance();
        //加入轮询 支持linux
        service.S.SERIAL_POLLING=true;

        try {
            service.addGateway(gateway);
            init=true;
            log.info("初始化成功");
        } catch (GatewayException e) {
            log.error("初始化失败",e);
            e.printStackTrace();
        }
    }

    /**
     * 消息发送
     * @param msg 消息对象
     * @return 是否发送成功
     */
    private boolean sendSMS(OutboundMessage msg){
        msg.setEncoding(Message.MessageEncodings.ENCUCS2);
        try {
            return  service.sendMessage(msg);
        } catch (Exception e) {
            log.error("消息发送失败",e);
        }
        return false;
    }

    /**
     * 开启服务
     */
    @Override
    public void start(){
        if(!init){
            throw new RuntimeException("初始化出错,无法启动服务");
        }
        try {
            service.startService();
            start=true;
        } catch (Exception e) {
            log.error("启动短信服务失败",e);
        }
    }

    /**
     * 停止短信服务
     */
    public void stop(){
        if(start){
            try {
                service.stopService();
                start=false;
            } catch (Exception e) {
                log.error("停止短信服务失败",e);
            }
        }
    }

    @Override
    public boolean send(String phone, String content) {
        OutboundMessage outboundMessage=new OutboundMessage(phone,content);
        return this.sendSMS(outboundMessage);
    }

    @Override
    public boolean send(List<String> phones, String content) throws SendErrorException {
    	//TODO:本来通过OutboundMessage[]群发短信,发现中文没有展示,时间有限,测试短信花的自己的钱,就省事用这种方式发送群发短信 
        int res = 0;
        for (String phone : phones) {
            boolean send = send(phone, content);
            if (send){
                res++;
            }
        }
        return res==phones.size();
    }
}

短信方法的执行者

/**
 * 短信执行者
 */
public interface SmsExecuter {
    /**
     * 短信发送
     * @param phone
     * @param content
     * @return
     */
    boolean send(String phone, String content) throws SendErrorException;

    /**
     * 短信群发
     * @param phones
     * @param content
     * @return
     * @throws SendErrorException
     */
    boolean send(List<String> phones, String content) throws SendErrorException;

    void start();
}

具体过程:

/**
 * @author Mingwentao
 * @date 2022年03月02日 14:39
 * <p>
 * 启动短信服务初始化
 * <p>
 * 初始化向redis中缓存数据
 */
@Component
@Slf4j
@Order(0)
public class InitRedisDataTask implements CommandLineRunner {


    @Autowired
    RedisUtil redisUtil;

    @Autowired
    SmsExecuter smsExecuter;

    @Resource
    MethodMapper methodMapper;


    @Override
    public void run(String... strings) {
        //启动短信服务
        smsExecuter.start();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //1. 获取当前告警信息表的总量
        int tCount = methodMapper.selectCount(null);
        //2. 获取当前告警信息表的最大时间
        LambdaQueryWrapper<AlertInfo> wapper = Wrappers.lambdaQuery();
        wapper.orderByDesc(AlertInfo::getFCjsj);
        List<AlertInfo> alertInfos = methodMapper.selectList(wapper);
        //3. 存入redis
        if (alertInfos != null && alertInfos.size() > 0 && tCount != 0) {
            redisUtil.set(MAX_COUNT_KEY, String.valueOf(tCount));
            redisUtil.set(MAX_GJ_TIME_KEY, sdf.format(alertInfos.get(0).getFCjsj()));
        }
    }

    /**
     * redisUtil.set("t_gjxx_max_time","2022-03-11 02:18:21");
     * redisUtil.set("t_gjxx_count","8");
     */
}
/**
 * @author Mingwentao
 * @date 2022年03月02日 15:29
 */
@Component
@EnableScheduling
@Slf4j
public class ScheduleTask {

    @Autowired
    RedisUtil redisUtil;

    @Resource
    MethodMapper methodMapper;

    @Autowired
    SmsExecuter smsExecuter;

    @Resource
    PhoneMapper phoneMapper;

    @Scheduled(cron = "${taskTime}")
    public void sendSmsInfo() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //1. 获取redis中的count量
        int rCount = Integer.parseInt(redisUtil.get(MAX_COUNT_KEY));
        //2. 获取表中的count量
        int tCount = methodMapper.selectCount(null);
        //3. 有数据变动才发送短信
        if (rCount != tCount) {
            String time = redisUtil.get(MAX_GJ_TIME_KEY);
            LambdaQueryWrapper<AlertInfo> wapper = Wrappers.lambdaQuery();
            wapper.gt(AlertInfo::getFCjsj, time);
            wapper.orderByDesc(AlertInfo::getFCjsj);
            //告警信息
            List<AlertInfo> alertInfos = methodMapper.selectList(wapper);
            if (alertInfos != null && alertInfos.size() > 0) {
                QueryWrapper<TelePhoneInfo> query = new QueryWrapper<>();
                query.select("phone");
                List<Object> phoneLists = phoneMapper.selectObjs(query);
                if (phoneLists != null && phoneLists.size() > 0) {
                    //TODO:群发短信
                    sendSms(phoneLists, alertInfos);
                }
                //更新redis中数据
                redisUtil.set(MAX_COUNT_KEY, String.valueOf(tCount));
                redisUtil.set(MAX_GJ_TIME_KEY, sdf.format(alertInfos.get(0).getFCjsj()));
            }
        }
    }

    /**
     * 调用短信服务发送短信
     *
     * @param phone
     * @param alertInfos
     */
    private void sendSms(List<Object> phone, List<AlertInfo> alertInfos) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<String> strs = new ArrayList<>();
        for (Object o : phone) {
            strs.add(String.valueOf(o));
        }
        StringBuilder sb = new StringBuilder();
        for (AlertInfo alertInfo : alertInfos) {
            String content = sb.append(CONTENT_PREFIX).append(alertInfo.getFXw()).append(" ").append(sdf.format(alertInfo.getFCjsj())).toString();
            try {
                smsExecuter.send(strs, content);
            } catch (SendErrorException e) {
                log.error("发送短信失败");
            }
        }
    }
}

踩坑

  1. 短信猫驱动建议找厂商直接要,网上下的驱动很多不适用
  2. 一定要先用终端软件测试设备,用at指令测下设备功能,大部分原因可能是设备问题,比如我中间一直无法发送短信,就是因为设备是2g信号的,已经过时了,更换4g信号的设备后,就正常使用了。

at指令

硬件开发过程和指令

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值