用树莓派搭建基于Pushover的短信转发平台
- 151 次检阅

因为要去英国上学,最近开始考虑手机卡的问题。各种服务都绑在国内的手机卡上,更换起来太麻烦。估计需要保留国内手机卡,但这样的话就有不停倒腾手机卡的问题。恰巧最近购进树莓派4b。emm...那么来吧。

首先确定用料。查找资料后找到了几个比较理想的方案:

  • 1.基于GSM模块一类连GPIO通信
  • 2.基于现有的3G上网卡直接连USB

基于成本和实用性考虑的话,GPIO通信需要单独安装驱动且占用GPIO口,我用了berryboot多系统(见另一篇文章)所以必须在pi上连屏幕,基本都占了...且体积偏大无保护外壳,在运输和使用过程中可能出问题。其次,开发板价格多在百元以上,功能多一些,考虑到国外的漫游费用就不设计通话类的功能了,我们的需求只是接收短信。而3g网卡可能四五十就能买到,况且大厂的硬件质量可能会更好一些,毕竟要用三四年的样子,综合考虑选择方案二。

上网卡的种类多样,我用的华为E173免驱,诸如此类免驱网卡应该都是可以直接识别的。另一方面就是要考虑频率,在国内用联通卡,联通在英国用EE和O2的网络,查资料后发现GSM1900MHz和国内是通用的。所以如果有国外使用需求,买网卡的时候记得要确定购买的上网卡是否支持合作运营商的频段。

食材有了炊具也是个问题,debian系统所以理论上可以用gammu或者直接用AT指令,当然也有很多其他的选择,可以根据个人口味自行决定。我这里用gammu,以稳定方便为主。

步骤

连接网卡,使用lsusb指令查看usb信息确保设备被识别。

使用sudo apt-get install gammu安装gammu平台,安装完成后sudo gammu-config进行配置

配置如图,port的话ls /dev/ttyUSB*可以看一下连接信息,不确定的话就...挨个试试吧。配置完成后使用sudo gammu --identify查看sim卡imei信息,可能有报错,只要不是 Can not access SIM card 就说明成功了。

因为要接收短信,所以下面要配置一下smsd,通过sudo apt-get install gammu-smsd安装。打开/etc/gammu-smsdrc进行配置。详细文档可以到https://wammu.eu/docs/manual/smsd看一下,我这里只讲我用到的。

配置完成后sudo gammu-smsd --config /etc/gammu-smsdrc --pid /var/run/gammu-smsd.pid --daemon --user gammu --group gammu启动。

在这里遇到了很多坑,因为gammu有很多存储方式,默认的是用文件也就是files。但是!!接收是实现了,收到短信内容如图:

虽说一看就是编码问题,但好像并没有可以设置编码的地方??总之费尽周折后读了下官方文档,发现可以用mysql储存。navicat读了下以为万事大吉,于是开始写脚本做转发。

需要注意的是mysql表需要手动导入,直接贴sql到这里。

CREATE TABLE `gammu` (
  `Version` integer NOT NULL default '0' PRIMARY KEY
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
CREATE TABLE `inbox` (
  `UpdatedInDB` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `ReceivingDateTime` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `Text` text NOT NULL,
  `SenderNumber` varchar(20) NOT NULL default '',
  `Coding` enum('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression') NOT NULL default 'Default_No_Compression',
  `UDH` text NOT NULL,
  `SMSCNumber` varchar(20) NOT NULL default '',
  `Class` integer NOT NULL default '-1',
  `TextDecoded` text NOT NULL,
  `ID` integer unsigned NOT NULL auto_increment,
  `RecipientID` text NOT NULL,
  `Processed` enum('false','true') NOT NULL default 'false',
  `Status` integer NOT NULL default '-1',
  PRIMARY KEY `ID` (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ;
CREATE TABLE `outbox` (
  `UpdatedInDB` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `InsertIntoDB` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `SendingDateTime` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `SendBefore` time NOT NULL DEFAULT '23:59:59',
  `SendAfter` time NOT NULL DEFAULT '00:00:00',
  `Text` text,
  `DestinationNumber` varchar(20) NOT NULL default '',
  `Coding` enum('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression') NOT NULL default 'Default_No_Compression',
  `UDH` text,
  `Class` integer default '-1',
  `TextDecoded` text NOT NULL,
  `ID` integer unsigned NOT NULL auto_increment,
  `MultiPart` enum('false','true') default 'false',
  `RelativeValidity` integer default '-1',
  `SenderID` varchar(255),
  `SendingTimeOut` timestamp NULL default CURRENT_TIMESTAMP,
  `DeliveryReport` enum('default','yes','no') default 'default',
  `CreatorID` text NOT NULL,
  `Retries` int(3) default 0,
  `Priority` integer default 0,
  `Status` enum('SendingOK','SendingOKNoReport','SendingError','DeliveryOK','DeliveryFailed','DeliveryPending','DeliveryUnknown','Error','Reserved') NOT NULL default 'Reserved',
  `StatusCode` integer NOT NULL default '-1',
  PRIMARY KEY `ID` (`ID`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;

CREATE INDEX outbox_date ON outbox(SendingDateTime, SendingTimeOut);
CREATE INDEX outbox_sender ON outbox(SenderID(250));
CREATE TABLE `outbox_multipart` (
  `Text` text,
  `Coding` enum('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression') NOT NULL default 'Default_No_Compression',
  `UDH` text,
  `Class` integer default '-1',
  `TextDecoded` text,
  `ID` integer unsigned NOT NULL default '0',
  `SequencePosition` integer NOT NULL default '1',
  `Status` enum('SendingOK','SendingOKNoReport','SendingError','DeliveryOK','DeliveryFailed','DeliveryPending','DeliveryUnknown','Error','Reserved') NOT NULL default 'Reserved',
  `StatusCode` integer NOT NULL default '-1',
  PRIMARY KEY (`ID`, `SequencePosition`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
CREATE TABLE `phones` (
  `ID` text NOT NULL,
  `UpdatedInDB` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `InsertIntoDB` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `TimeOut` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `Send` enum('yes','no') NOT NULL default 'no',
  `Receive` enum('yes','no') NOT NULL default 'no',
  `IMEI` varchar(35) NOT NULL,
  `IMSI` varchar(35) NOT NULL,
  `NetCode` varchar(10) default 'ERROR',
  `NetName` varchar(35) default 'ERROR',
  `Client` text NOT NULL,
  `Battery` integer NOT NULL DEFAULT -1,
  `Signal` integer NOT NULL DEFAULT -1,
  `Sent` int NOT NULL DEFAULT 0,
  `Received` int NOT NULL DEFAULT 0,
  PRIMARY KEY (`IMEI`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
CREATE TABLE `sentitems` (
  `UpdatedInDB` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  `InsertIntoDB` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `SendingDateTime` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `DeliveryDateTime` timestamp NULL,
  `Text` text NOT NULL,
  `DestinationNumber` varchar(20) NOT NULL default '',
  `Coding` enum('Default_No_Compression','Unicode_No_Compression','8bit','Default_Compression','Unicode_Compression') NOT NULL default 'Default_No_Compression',
  `UDH` text NOT NULL,
  `SMSCNumber` varchar(20) NOT NULL default '',
  `Class` integer NOT NULL default '-1',
  `TextDecoded` text NOT NULL,
  `ID` integer unsigned NOT NULL default '0',
  `SenderID` varchar(255) NOT NULL,
  `SequencePosition` integer NOT NULL default '1',
  `Status` enum('SendingOK','SendingOKNoReport','SendingError','DeliveryOK','DeliveryFailed','DeliveryPending','DeliveryUnknown','Error') NOT NULL default 'SendingOK',
  `StatusError` integer NOT NULL default '-1',
  `TPMR` integer NOT NULL default '-1',
  `RelativeValidity` integer NOT NULL default '-1',
  `CreatorID` text NOT NULL,
  `StatusCode` integer NOT NULL default '-1',
  PRIMARY KEY (`ID`, `SequencePosition`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;

CREATE INDEX sentitems_date ON sentitems(DeliveryDateTime);
CREATE INDEX sentitems_tpmr ON sentitems(TPMR);
CREATE INDEX sentitems_dest ON sentitems(DestinationNumber);
CREATE INDEX sentitems_sender ON sentitems(SenderID(250));

因为希望能尽可能达到原生的短信效果,对比了一下几种方案:telegrambot - 国内用不了测试太麻烦。邮件的话iphone自带客户端用轮询,要手动刷新,时效性太低。所以比较可行的就是捷径和pushover,但捷径只支持ios且需要穿透后直连,做中转速度势必有影响,所以综合考虑推荐pushover,支持推送提醒、历史查询,有多系统客户端,完美。

首先要在官网申请一个api,传送门:https://pushover.net/apps/build,具体的说明也在官网,参数有这么几个,post提交到 api.pushover.net/1/messages.json 简单看一下就可以开始做了。

gammu自带run on receive参数,也就是在收到短信后可以执行特定脚本,python分分钟搞定。(忽略为了省事直接写的post)

#!/usr/bin/python
# -
- coding: UTF-8 --
#encoding:utf8
import MySQLdb
import requests,json
import sys
import urllib
reload(sys)
sys.setdefaultencoding('utf8')
db = MySQLdb.connect("127.0.0.1", "sms", "****", "sms")
cursor = db.cursor()
sql = "SELECT * FROM inbox WHERE ID = (SELECT max(ID) FROM inbox);"
try:
cursor.execute(sql)
results = cursor.fetchall()
for row in results:
msg=row[8]
print row
url = 'https://api.pushover.net/1/messages.json'
r = requests.post(url,'token=asaii1urpt7wgnovdihiz2agvejws6&user=uc4qb4j94x8pi11yp3uqm7bwh8vx5w&sound=pushover&device=iPhone&title=From '+row[6]+'&message='+msg)
except:
print "Error: unable to fecth data"
db.close()

但是在这一步折腾了大概一整天。知道是编码问题,但刚开始无论怎么decode始终是不能转换成中文输出,sys.setdefaultencoding('utf8') 也试过但不管怎么就是不行,最后随手把 MySQLdb.connect("127.0.0.1", "sms", "***", "sms","utf-8") 输入时候的编码声明去掉,结果竟然就可以了???可能是因为数据库用的是utf8mb4_general_ci而mysqldb转换成的是utf8mb4,没有实现Unicode排序规则所以导致的问题?不过好在最后还是解决了。

成品如图,运行稳定。

最后是设置开机启动,直接加到rc.local,在这里需要注意的是添加到rc.local时不能加sudo,因为在这里本身就是root执行,如果添加sudo的话脚本是不能运行的,也就是不能进行推送。

最后来一张成品图。

分享到:
, ,

这篇文章还没有评论

发表评论