用上网卡转发短信


发布于

|

分类

在V站上上了个SIM卡的车。但长时间带着俩手机不方便。于是就想办法将短信和电话从备用手机实时转到主力机上。试了IFTTT,不稳定。然后就想用树莓+SMS开发版来做这个事儿。偶然间发现其实上网卡里面也藏着短信功能,就买了个上网卡开始鼓捣。

25块钱,深水鱼二手,包邮到家。

物理

我买来的是华为E303s。一个12年左右的3G上网卡,可以插一个大SIM卡和一个MicroSD卡。

插上Win电脑,会识别出来一个USB光盘。自动安装驱动,弹出192.168.1.1的控制页面。赶快取消自动拨号、断线重连、漫游。反正是把能关的都关了。信号选自动。

插上Linux电脑,毛事情都没发生?

  • lsusb看一下,发现一个Bus 001 Device 011: ID 12d1:14db Huawei Technologies Co., Ltd.。注意这里的12d1:14db。后面会用到。
  • dmesg可以看到,识别了一个USB Mass Storage,还有一个网卡设备。
  • ip a可以看到,多了一个网卡。
  • ls /dev | grep ttyUSB,什么都没有。

查资料(都是些13年左右的帖子……好老了……毕竟买的是3G上网卡,也都是12、13年的东西了 )发现,它有好多工作模式:一种是U盘模式,一种是HiLink模式,一种是Debug模式,最后还有个序列设备模式。下面我们用两种方法来用它。

方法一 使用内置WebAPI

这个3G上网卡里面有一套WebUI给用户使用的。由于是前后端分离的写法,API可以比较容易地找到,一个Chrome F12就可以找出来大多数API。我们可以用找到的这些API来做一些事情,比如状态监测、短信收发。

说简单也简单,说难也难,毕竟是第一次在完全没有文档和说明的情况下扒API来用。另外是测试比较费钱……

说一下几个坑的点:

  • 最最关键的,会多出一块网卡。后果是访问某些网站的时候会被带到上网卡的WebUI上,而不是从树莓派的有线网链接到Internet。虽然代码很方便,但不太推荐。
  • 首先是,它是通过XML交互的,但也不完全。
  • 其次是,所有参数都是有顺序的,只能用OrderedDict进行序列化。
  • 最后是,不需要找着网上的教程去拿Header、拿Token、登录。直接暴力request解决问题即可。

大体思路是这样的:

  1. 看一下统计信息,如果有未读信息,就处理
  2. 从收件箱里面取出短信
  3. 对于每一条短信,该转发就转发,该Push就Push
  4. 删除这条消息
  5. 收尾,清空发件箱

在用函数调试通过之后,封装成了类,便于使用。整个文件见这里。除了没写注释之外,代码风格还算过得去吧?

加入crontab豪华套餐,给手机卡充好值,开始享受「双卡」吧。

方法二 使用AT指令

这种方式,我们可以用比较低层的命令直接操控。好处是不会因为多一个网卡而出现很多奇奇怪怪的事情。缺点嘛……比较麻烦。

将上网卡转到ttyUSB模式

上面做了那么多测试,说明这个上网卡工作在HiLink模式。对于一般使用者来说,免驱动即插即用,是极好的;但对于我来说……我要通过tty和AT指令来读短信啊。所以就需要把模式切换到ttyUSB模式。

IDlsusb namemode
12d1:1f01Huawei Technologies Co., Ltd.USB Mass Storage
12d1:14dbHuawei Technologies Co., Ltd.HiLink
12d1:14dcHuawei Technologies Co., Ltd.HiLink
12d1:1001Huawei Technologies Co., Ltd. E169/E620/E800 HSDPA ModemModem
12d1:1c05Huawei Technologies Co., Ltd. Broadband stick (modem on) 

这个过程比较波折一些。资料中提到很多种方法,下面是我觉得成功率最高、最简单的。

方法一(确认成功)

新建文件/etc/usb_modeswitch.d/12d1:1f01,输入内容

# Huawei E303s - switch to other mode instead of HiLink CDC-Ether mode
#DefaultVendor=  0x12d1
#DefaultProduct= 0x14db
TargetVendor=0x12d1
TargetProduct=0x1f01

# switch to E169/E620/E800 HSDPA Modem
MessageContent="55534243000000000000000000000011060000000000000000000000000000"

# switch to USB Mass Storage mode
#MessageContent="55534243123456780000000000000011062000000100000000000000000000"

# Unknown
#MessageContent="55534243123456780000000000000a11062000000000000100000000000000"

# Unknown
#MessageContent="55534243123456780000000000000011062000000101000100000000000000"

然后重启。lsusb可以按到已经工作在了Modem模式下。再用ls /dev | grep ttyUSB就可以看到三个ttyUSB设备了。

按说此时就能直接用了。不过为了避免以后麻烦,我们再多做一点东西。

我们可以使用screen /dev/ttyUSB2来进行控制。如果screen之后发现怎么敲键盘都没反应就说明不是ttyUSB2,就换其他的。

输入

AT^U2DIAG?

查看当前模式,最好能记录下来。然后再输入

AT^U2DIAG=0

就可以让网卡以后都工作在这个序列设备模式上。当然,如果想切换回来,也很简单,输入

AT^U2DIAG=375

就好了。其中最后的375是第一步记录下来的数字。

之后删除前面创建的/etc/usb_modeswitch.d/12d1:1f01文件。

拔下上网卡,插到其他Linux电脑上——是不是发现出现了ttyUSB设备了呢?这时候再用lsusb看设备,会发已经变成了最后一个模式——能用就行了呗。

方法二(没有继续试下去)

工作在HiLink模式下,看ip a,会多出来个eth1网卡。然后就有人找到了方法开启调试(debug)模式:

curl -X POST -d '<?xml version="1.0" encoding="UTF-8"?><request><mode>0</mode></request>' http://192.168.1.1/api/device/mode

会出现两个ttyUSB设备。想办法连接上去,然后用前面的AT指令弄成个永久的ttyUSB模式——我没有做继续尝试。tty一直都是黑屏,可能是波特率设置不太对的原因吧。

测试发短信

我们就不亲自用AT指令来发短信了,找现成工具代劳吧。

sudo apt-get install gammu

然后进行一下配置

gammu-config

Port 选我们能用的那个ttyUSB设备。 Connection可以在这里找到。我选择了at19200。其他保持默认。

最后,确认一下信息

$ gammu --identify
Device               : /dev/ttyUSB2
Manufacturer         : Huawei
Model                : E303 (E303)
Firmware             : 22.157.39.00.112
IMEI                 : XXXXXXXXXXXXXXX
SIM IMSI             : XXXXXXXXXXXXXXX

发个短信试试

$ echo "HelloWorld" | gammu sendsms TEXT 18XXXXXXXXX
If you want break, press Ctrl+C...
Sending SMS 1/1....waiting for network answer..OK, message reference=67

获取和转发短信

在收到短信后,上网卡会通过内部私有指令第一时间将短信读出来、给网络发ACK消息、存储到内部Inbox里。所以直接用AT指令是获取不到短信的!这里我暂时没搞定。


没搞定的话……就又在深水鱼上20元包邮了个华为E220。这个东西插上去就直接有两个ttyUSB,而且ttyUSB1是我们需要的接口。省事很多。

方案一: 使用gammu-systemd

我们的逻辑是这样的: 使用 gammu-smsd 服务获取短信,存储在sqlite里面。写一个Python,定时查看sqlite内容,找到没处理的短信,进行转发。这样的好处是有完整的记录,万一转漏了,之后也能再把短信找到。

所以第一步是安装一些东西:

sudo apt install libgammu-dev python3-gammu gammu-smsd libdbd-sqlite3 libsqlite3-dev sqlite3

这里安装了gamu-smsd和python的接口,并且还有sqlite及其接口。

如果使用Conda来安装的话,可以这样玩:

sudo apt install gammu-smsd libgammu-dev
conda create --name pisms python=3 sqlite 
source activate pisms
pip install python-gammu

安装后,编辑/etc/gammu-smsdrc文件:

[gammu]
port = /dev/ttyUSB1
connection = at19200
[smsd]
service = sql 
logfile = syslog 
debuglevel = 0 
driver = sqlite3 
dbdir = /home/pi 
database = smsd.db 

最后是创建一个smsd.db的sqlite数据库。我们找到/usr/share/doc/gammu/examples/sql,这里面有例子。

OK,准备工作做完了,这样新来短信会直接被存储到这个sqlite数据库中。

我们使用Python代码来完成短信转发这件事儿。代码见这里

同样,加入Crontab豪华套餐,开始享受短信转发。

方案二: 直接使用gammu

这个不想写了。大致思路是,只使用gammu,不使用gammu-smsd。每次直接从sim卡中手动获取短信,然后进行转发,并删除已经转发过的短信。应该和上面的代码差不多。

总结

不难,就是Debug比较费钱。Debug过程总共浪费了30多条短信

我们还可以再转发之前加一层过滤,避免转发垃圾短信——嗯,搞个SVM分类器?反正文本都已经拿到了,怎么玩就随意了吧?

同样的,我们还可以将短信推送到Telegram上、Wechat上、邮件上,甚至微博和Twitter上。甚至可以搞一个自动展示短信的网站——随意啦。

参考资料


评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注