在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解决问题即可。
大体思路是这样的:
- 看一下统计信息,如果有未读信息,就处理
- 从收件箱里面取出短信
- 对于每一条短信,该转发就转发,该Push就Push
- 删除这条消息
- 收尾,清空发件箱
在用函数调试通过之后,封装成了类,便于使用。整个文件见这里。除了没写注释之外,代码风格还算过得去吧?
加入crontab豪华套餐,给手机卡充好值,开始享受「双卡」吧。
方法二 使用AT指令
这种方式,我们可以用比较低层的命令直接操控。好处是不会因为多一个网卡而出现很多奇奇怪怪的事情。缺点嘛……比较麻烦。
将上网卡转到ttyUSB模式
上面做了那么多测试,说明这个上网卡工作在HiLink模式。对于一般使用者来说,免驱动即插即用,是极好的;但对于我来说……我要通过tty和AT指令来读短信啊。所以就需要把模式切换到ttyUSB模式。
ID | lsusb name | mode |
---|---|---|
12d1:1f01 | Huawei Technologies Co., Ltd. | USB Mass Storage |
12d1:14db | Huawei Technologies Co., Ltd. | HiLink |
12d1:14dc | Huawei Technologies Co., Ltd. | HiLink |
12d1:1001 | Huawei Technologies Co., Ltd. E169/E620/E800 HSDPA Modem | Modem |
12d1:1c05 | Huawei 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上。甚至可以搞一个自动展示短信的网站——随意啦。
发表回复