Linux 将串口映射为TCP服务+无线热点(树莓派)

起因

最近在做一个Android控制APP,本来想使用蓝牙BLE的串口透传模块,但是因为项目中使用的串口数据包比较长,通信比较频繁,买了个透传模块一次多大(MTU)只有20个字节,也不支持修改,而且写入过程需要有Thread.sleep(23),就很蛋疼了,数据量一大通信延迟特别严重,而且控制的设备对实时性要求较高,这个方案显然不能满足要求,放弃。

手里刚好有一块树莓派3B+,放着吃灰,想着是不是可以用树莓派建WIFI热点,把串口用网络转发出来。树莓派自带的串口,网上说有些小问题,再有项目中需要控制多个串口,树莓派最多自带2个,不走弯路直接上usb转串口,插到rspi的USB上,试了几个常用模块,都可以识别,美滋滋。插上之后在/dev/ttyUSB*上,可以用echo 123 > /dev/ttyUSB0去尝试发送。

第一步将串口映射为TCP服务,双向转发。

首先当然是想自己写代码转发,网上搜了下,嗯~~,好像都是简单demo,要写成产品级别的估计要下点功夫。看有没有现成的工具,学过几天信安,转发当然是nc(netcat),奈何好像脚本挺负载的,最后在国外某论坛上找到了一个一条命令搞定的好玩意,socat,完美解决问题

socat TCP-LISTEN:4161,fork,reuseaddr FILE:/dev/ttyUSB0,b57600,raw,echo=0”
#4161是TCP服务的端口号
#/dev/ttyUSB0就是对应的USB转的串口
#最后加echo=0,不加的话树莓派会给串口回写,也就是外部设备向串口写什么,串口会原样向串口返回同样的数据

测试使用sscom串口调试工具使用网络“TCPClient”连接测试,通信顺畅,测试一小时连接正常,大问题解决

第二步将TCP服务设为自启动,不需要也不可能每次都要人工启动。

确定串口设备的名称

首先要解决的问题是usb转串口每次插入时设备名不确定的问题,由于是多个串口,不能确定是哪一个,这就要求设置usb串口名称固定

/etc/udev/rules.d/99-input.rules(也有可能不一样),中添加一行:

SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523",ATTRS{serial}=="123456", SYMLINK+="userilaMoto"

这些信息可以使用命令 udevadmin info -a -n /dev/ttyUSB0 中查找idVendor,idProduct,serial,可以添加更多只要能区分出不同设备即可

最后SYMLINK就是设置完成后在/dev中要出现的名称,当然不能与现有的重名。

可是有些串口设备没有serial号,呵呵,如果买了几个相同的usb转串口根本没法区分。

最后在/dev/serial目录下有两个目录 by-id 和 by-path,在by-path下不管是什么模块插上只要物理USB端口一样,名字就不会变,这就方便多了,哈哈。

串口名称形如/dev/serial/by-path/platform-3f980000.usb-0:1.2:0-port0

设置编写服务脚本

在/etc/init.d/下建立一个脚本文件取名netserial,名字可以自己起

在/etc/init.d/下有很多服务脚本,可以参考编写,注意下面脚本中echo和log*mes使用service或systemctl命令都不会显示,不写无妨,只是在自己测试脚本的时候比较方便而已

/etc/init.d/netserial

#!/bin/sh
#
### BEGIN INIT INFO
# Provides:          netserial
# Required-Start:    
# Required-Stop:     
# Should-Start: 
# Should-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: serial port via network
# Description:
### END INIT INFO

PATH=/sbin:/bin:/usr/sbin:/usr/bin
. /lib/lsb/init-functions

start(){
    pcount=$(ps -aux | grep TCP-LISTEN:5961 | grep socat | wc -l)
    if [ $pcount -eq 0 ] 
    then 
        nohup socat -lu -d -d -d TCP-LISTEN:5961,fork,reuseaddr FILE:'/dev/serial/by-path/platform-3f980000.usb-usb-0\:1.3\:1.0-port0',b57600,raw,echo=0 > /var/logs/socat5961.log &
        log_success_msg "\033[32msocat TCP:5961 <----> RightTop USB Serial Port@57600 Started  \033[0m"
    else
        log_warning_msg "\033[35msocat TCP:5961 <----> RightTop USB Serial Port@57600 has Started last time  \033[0m"
    fi

    pcount=$(ps -aux | grep TCP-LISTEN:5962 | grep socat | wc -l)
    if [ $pcount -eq 0 ] 
    then 
        nohup socat -lu -d -d -d TCP-LISTEN:5962,fork,reuseaddr FILE:'/dev/serial/by-path/platform-3f980000.usb-usb-0\:1.2\:1.0-port0',b38400,raw,echo=0 > /var/logs/socat5962.log &
        log_success_msg "\033[32msocat TCP:5962 <----> RightBottom USB Serial Port@38400 Started  \033[0m"
    else 
        log_warning_msg "\033[35msocat TCP:5962 <----> RightBottom USB Serial Port@38400 has Started last time  \033[0m"
    fi

    pcount=$(ps -aux | grep TCP-LISTEN:5963| grep socat | wc -l)
    if [ $pcount -eq 0 ] 
    then 
        nohup socat -lu -d -d -d TCP-LISTEN:5963,fork,reuseaddr FILE:'/dev/serial/by-path/platform-3f980000.usb-usb-0\:1.1.3\:1.0-port0',b9600,raw,echo=0 > /var/logs/socat5963.log &
        log_success_msg "\033[32msocat TCP:5963 <----> LeftBottom USB Serial Port@9600  Started \033[0m"
    else
        log_warning_msg "\033[35msocat TCP:5963 <----> LeftBottom USB Serial Port@9600  has Started last time \033[0m"
    fi
}

stop(){
    pcount=$(ps -aux | grep TCP-LISTEN:5961 | grep socat | wc -l)
    if [ $pcount -gt 0 ] 
    then 
        ps -aux | grep TCP-LISTEN:5961 | grep socat | awk '{print $2}' | xargs kill
        log_success_msg "\033[31msocat TCP:5961 <----> RightTop USB Serial Port Stop\033[0m" 
    fi

    pcount=$(ps -aux | grep TCP-LISTEN:5962| grep socat | wc -l)
    if [ $pcount -gt 0 ] 
    then 
        ps -aux | grep TCP-LISTEN:5962| grep socat | awk '{print $2}' | xargs kill
        log_success_msg "\033[31msocat TCP:5962 <----> RightBottom USB Serial Port Stop\033[0m" 
    fi

    pcount=$(ps -aux | grep TCP-LISTEN:5963 | grep socat | wc -l)
    if [ $pcount -gt 0 ] 
    then 
        ps -aux | grep TCP-LISTEN:5963 | grep socat | awk '{print $2}' | xargs kill
        log_success_msg "\033[31msocat TCP:5963 <----> LeftBottom USB Serial Port Stop\033[0m" 
    fi
    
}

status(){
    pcount=$(ps -aux | grep TCP-LISTEN:5961 | grep socat | wc -l)
    if [ $pcount -gt 0 ] 
    then 
        log_progress_msg "\033[32msocat TCP:5961 <----> RightTop USB Serial Port @57600 active\033[0m \n"
    else 
        echo "\033[31msocat TCP:5961 <----> RightTop USB Serial Port @57600 inactive\033[0m \n"
        #cat /var/logs/socat5961.log  | grep  -v transferred | tail -n 20 
    fi
    log_progress_msg "see log in /var/logs/socat5961.log \n"

    pcount=$(ps -aux | grep TCP-LISTEN:5962| grep socat | wc -l)
    if [ $pcount -gt 0 ] 
    then 
        echo "\033[32msocat TCP:5962 <----> RightBottom USB Serial Port @38400  active\033[0m"
    else 
        echo "\033[31msocat TCP:5962 <----> RightBottom USB Serial Port @38400 inactive\033[0m"
    fi
    log_progress_msg "see log in /var/logs/socat5962.log \n"

    pcount=$(ps -aux | grep TCP-LISTEN:5963 | grep socat | wc -l)
    if [ $pcount -gt 0 ] 
    then 
        echo "\033[32msocat TCP:5963 <----> LeftBottom USB Serial Port @9600 active\033[0m"
    else 
        echo "\033[31msocat TCP:5963 <----> LeftBottom USB Serial Port @9600 inactive\033[0m"
    fi
    log_progress_msg "see log in /var/logs/socat5963.log \n"
}

case "$1" in
start)
    start
        ;;
stop)
    stop
    ;;
restart)
    stop
    start
        ;;
status)
        status
        ;;
*)
        log_failure_msg "Usage: /etc/init.d/netserial {start|stop|restart|status}"
    exit 1
        ;;
esac

设置开机启动

cd /etc/init.d
#脚本权限
chmod 775 netserial
#安装启动脚本,96是启动序号,因为需要使用网络,和usb硬件,设置到靠后,多个串口可以分别安装
update-rc.d netserial defaults 96
#卸载启动脚本,先写到这里,以免后期需要卸载
# update-rc.d -f netserial remove

# 同样可以使用 service或者systemctl start/stop/restart/status 控制服务 

无线热点

由于不可能每次都要手动在设备上连接无线网络,需要无线网络自动连接,有两种方案可选:

  1. 手机/平板创建热点,树莓派自动连接,缺点,移动设备热点不会自动开启,长时间不连接会关闭,如果热点名字改了密码变了,就再连接不上了,而且支持特定设备。

  2. 树莓派创建热点,移动设备自动连接,缺点实现有点难度,但使用方便。

3.使用自动化工具完成 [更新]
主要有两种一个是create_ap,另一个是 raspap-webgui
推荐使用raspap-webgui一个命令自动安装,还带web管理端,非常方便。
使用方法参见其github,我就不多嘴了。https://github.com/billz/raspap-webgui

wget -q https://git.io/voEUQ -O /tmp/raspap && bash /tmp/raspap

更新:以下方式太麻烦(不推荐)

下面采用法案2搭建热点,就当给自己做笔记,一面以后再填坑。

以下内容大部分参考 Simpreative文章 https://www.jianshu.com/p/0ecd8b734204

使用hostapd dnsmasq 搭建

sudo apt-get install dnsmasq hostapd

# 修改 /etc/dhcpcd.conf
interface wlan0
static ip_address=192.168.0.1/24

# 创建 sudo nano /etc/hostapd/hostapd.conf
interface=wlan0
driver=nl80211
ssid=RaspberryPi
hw_mode=g
channel=7
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=12345678
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP

# 修改/etc/default/hostapd
DAEMON_CONF="/etc/hostapd/hostapd.conf"

#配置DNSMASQ
sudo mv /etc/dnsmasq.conf /etc/bak_dnsmasq.conf

#重新创建 /etc/dnsmasq.conf,并写入
interface=wlan0
dhcp-range=192.168.0.2,192.168.0.20,255.255.255.0,24h

# 还有net转发,当然这里不涉及数据转发问题

到此为止好像结束了,但是hostapd 起不来,查看状态,提示

 Loaded: masked (/dev/null; bad)

需要使用命令"unmask"

sudo systemctl unmask hostapd.service
sudo systemctl enable hostapd.service

但是开机之后还是没有无线热点,但是 service hostapd status 提示启动了呀,并且重启服务就可以正常连接,好坑呀。

最后查看状态有一个日志提示

random: Cannot readfrom /dev/random: Try again
random: Only 0/20bytes of strong random data available from /dev/random
random: Not enoughentropy pool available for secure operations

表示随机数不够,查了一下是因为/dev/random 生成速度太慢,改成/dev/urandom 就好了
网上有说是将random 备份然后软链接urandom->random,但是每次重启后就没有了...

没办法只有源码改造了

#下载源码
wget http://w1.fi/releases/hostapd-2.9.tar.gz
tar -xzvf hostapd-2.6.tar.gz
#配置文件
cd hostapd-2.6/hostapd
cp defconfig .config
#修改源码
hostapd-2.6/src/crypto/random.c :(不止1处)
由    fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
改为  fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK);
#安装依赖,使用工具搜索缺失的依赖
sudo apt install apt-file
apt-file search xx/xx/xx.h

#编译,如果出现错误安装对应的依赖
cd hostapd-2.9/hostapd
make
#将编译好的hostapd覆盖原来的文件
sudo cp hostapd /usr/sbin/
sudo cp hostapd_cli /usr/sbin/

嗯....,提示信息是没了,但是还是不能开机启动,手启可以,没办法了,最后在netserial脚本上加了一句

start(){
...
#暂停10秒
sleep 10
#重启hostapd服务
service hostapd restart
}

不算完美,功能实现了,不想折腾了...

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容

  • 树莓派的串口默认为串口终端调试使用,如要正常使用串口则需要修改树莓派设置。关闭串口终端调试功能后则不能再通过串口登...
    coolwriter阅读 6,278评论 2 6
  • 1、串口连接 这种方式在我树莓派的第一篇博客有讲,这里我简单介绍。 连接树莓派,树莓派GPIO串口的GND,txd...
    麦牛2013阅读 1,850评论 0 0
  • USB设备驱动程序用来驱动相应的USB设备,USB设备驱动用usb_driver表示,它主要用来将USB设备挂接到...
    Joe_HUST阅读 6,251评论 1 5
  • 太痛苦了 分开以后的每个晚上 都痛苦万分
    6dd7b4d13cb9阅读 61评论 0 0
  • 如果我们当初不添加好友, 现在也不会有那么多故事, 喜欢的时候,再多看一眼...
    潇然梦_阅读 110评论 0 0