Skip to content

Instantly share code, notes, and snippets.

@wwin3286tw
Last active July 14, 2020 03:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wwin3286tw/ae7ef8149e474475b14fde89b7c8783c to your computer and use it in GitHub Desktop.
Save wwin3286tw/ae7ef8149e474475b14fde89b7c8783c to your computer and use it in GitHub Desktop.
Python Bluetooth Classic Serial Port Communication

Python Bluetooth Classic Serial Port Communication

Copyright © 2018-09 by Yi,Jia-Ye Partition Rights Reserved

程式碼包含使用第三方著作(https://github.com/0-1-0/lightblue-0.4)

  1. 必須公布原始碼,不得作為專有軟體
  2. 僅能收取傳送與提供上必要的工本費用
  3. 不能阻止他人針對軟體做任何逆向工程
  4. 可執行程式必須附帶原始碼
  5. 不得作為專有軟體及任何商業用途

WARNING: DEPRECATED, THIS GIST WILL NO LONGER ABLE TO MAINTAIN.

警告:腳本已經廢棄,不再做任何維護!

THIS SCRIPTS COMES WITH ABSOLUTELY NO WARRANTY, USE AT YOUR OWN RISK.

這些腳本並沒有任何承諾,使用者風險自負!

版本更新記錄

  1. 將資料格式化
  2. 字串和二進位資料使用不同通道
  3. 增加Wifi模式
  4. 考慮統一function命名風格

專案議題(Project issue)

  1. 都寫在程式的開頭(Code Summary)了,請前往查看

建議的機台平台與軟體相依性

  1. Linux(Ubuntu 16.04 tested)
  2. Python2 only
  3. Lightblue module(only on python2)

機台硬體需求

  1. Single Board Computer(Ex: Raspberry)
  2. Linux Base PC with WIFI and BT

客戶端硬體需求

  1. Android Phone(tested)
  2. Support bluetooth classic Serial Port Profile(SPP) Devices

描述

  1. Can communication With Bluetooth Device(PC、RaspberryPI) using Android or support SPP device.
  2. 能夠用Android與藍芽裝置(單板電腦、電腦)
  3. Built-in File Transport Protocol.
  4. 內建檔案傳輸功能
  5. Camera Control, Take picture.
  6. 相機控制,拍張照吧!
  7. Waiting you to add more function.
  8. 等你加入更多功能
  9. WIFI file trasnfer
  10. WIFI檔案傳輸功能

專案參考

安裝

手動安裝參考

#sudo nmcli dev wifi connect ? password ? ifname wlan0
sudo nmcli dev wifi connect Kaiwood password 0660006000 ifname wlan0;wait
sudo cp /usr/share/zoneinfo/Asia/Taipei /etc/localtime
sudo apt-get update;wait
sudo apt-get -y install software-properties-common ntpdate
sudo ntpdate tick.stdtime.gov.tw
sudo add-apt-repository ppa:apt-fast/stable -y;wait
sudo apt-get update
sudo apt-get -y install apt-fast;wait
sudo apt-fast -y install build-essential cmake pkg-config cmake automake autoconf autotools-dev fswebcam unzip p7zip-full locate libbluetooth-dev libopenobex* python-pip libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev;wait
#sudo apt-fast install -y libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev
git clone https://github.com/0-1-0/lightblue-0.4.git
cd lightblue-0.4
sudo -H python setup.py install
cd ~
#sudo nano /etc/systemd/system/dbus-org.bluez.service
#ExecStart=/usr/lib/bluetooth/bluetoothd -C
#add ExecStartPost=/usr/bin/sdptool add sp
#sudo sed -i '9s/.*/ExecStart=\/usr\/lib\/bluetooth\/bluetoothd -C/' /etc/systemd/system/dbus-org.bluez.service #replace string and save in one-line(已廢棄,複製比較快,幹)
###!!!RUN THE NORMAL SCRIPT!!!###
sudo cp dbus-org.bluez.service /etc/systemd/system/dbus-org.bluez.service # 如果你很不幸的rekt了bluez的設定檔,請再次執行本行、以及以下兩行 ##
sudo systemctl daemon-reload
sudo systemctl restart bluetooth
sudo -H python -m pip install pybluez
bluetoothctl
power on
scan on
pair ?
#remove ?
sudo hciconfig hci up #<class 'lightblue._lightbluecommon.BluetoothError'>, A_BT-ftp-server.py, 102, Cannot access local device: no available bluetoot devices
#sudo /usr/bin/sdptool add sp
sdptool add --channel=0 SP
sudo chmod 777 /var/run/sdp

sudo nano /etc/systemd/system/bluetooth.target.wants/bluetooth.service
#應該可以跑伺服器了 #Now, you can run the BT server.
sudo ./A_BT-ftp-server.py
#sudo apt-get install -y bluez-tools 
#sudo btmon #監聽藍芽封包

手動

sudo nmcli dev wifi connect Kaiwood password 0660006000 ifname wlan0;wait
git config --global http.sslverify false
cd ~;
git clone https://gist.github.com/wwin3286tw/ae7ef8149e474475b14fde89b7c8783c ~/blueServer;
cd blueServer;
chmod 755 *.py;
chmod 755 *.sh;
./run.sh;

快速安裝

sudo nmcli dev wifi connect Kaiwood password 0660006000 ifname wlan0;wait;
bash <(wget -qO- https://gist.githubusercontent.com/wwin3286tw/ae7ef8149e474475b14fde89b7c8783c/raw/cd63385fe16dff2e98b4d8bc795ab5e947e8c1f6/quick.sh);
cd ~/blueServer

解除安裝

cd ~
rm -rf blueServer/

Debugging Reinstall(如果你更新了程式,只是想重新安裝,請執行以下命令)

cd ~
rm -rf blueServer/
git clone https://gist.github.com/wwin3286tw/ae7ef8149e474475b14fde89b7c8783c ~/blueServer;
cd blueServer;
chmod 755 *.py;
chmod 755 *.sh;
#!/usr/bin/python2
# -*- coding: UTF-8 -*-
'''
###Code Summary###
作者: Jack
電子信箱: wwin3286tw
手機:xxxxxxxxxx
日期: 2018-09-26
時間: 09:16:20 GMT+8
描述: BlueTooth classic Serial port ccFTP(Control & Communication& File Transfer Protocol) Server
讀我:
1. 使用類似Android的R資源檔
2. 如果你遭遇到腳本的 ^M 錯誤,請使用 sed -i -e 's/\r$//' 腳本名稱.sh
3. 享受吧
版本更新資訊:
1. 程式碼已經重構
2. 命名改進
3. 增加除錯模式,開啟以顯示錯誤
4. 程式碼比以前乾淨數十倍。
5. 增加中文註解、翻譯英文註解
問題(issue):
1. 可以考慮格式化命令與回應(formatting request command and respone data)
TODO:
1. 可以考慮新增LOG寫入到檔案功能
2. 考慮使用 命令後回應流程,移除人類可讀的描述資訊,進而簡化
例如:一個命令對應一個回應
###Code Summary###
'''
import BlueServerLib as bsl #自己寫的外部程式庫,模組化並加速開發
import os
import sys
import base64
import time
import glob
import time
import json
import subprocess
import os.path
from datetime import datetime
import lightblue
import sys
debugMode=True #是否開啟除錯模式,不開啟將無法看到錯誤訊息
# sys.setdefaultencoding() does not exist, here!
reload(sys) # Reload does the trick! #來自stackoverflow的答案 #https://stackoverflow.com/questions/2276200/changing-default-encoding-of-python
sys.setdefaultencoding('UTF8') #設定預設編碼,不再使用ASCII編碼,避免不必要的編碼錯誤
cam_path='/dev/video1' #設定攝影機位置 #TODO: 偵測正確的相機位置
ResourceFile="resource.json" #資源檔位置
R=bsl.GetResource(ResourceFile) #讀取資源檔
Default_FileName="sample.png" #預設試紙照片儲存檔名
cam0=bsl.camera(cam_path) #建立相機物件
#TransferMethod=1 #廢棄,請在Android端使用,xget 命令來啟動httpd伺服器,然後使用提供的網址進行下載
#使用過xget命令後,httpd伺服器將會一直在線上,除非使用killall命令
#啟動httpd前,務必確認該port無程式占用
#BT=0, WIFI=1
def WriteDefaultResource(): #可能廢棄,若遭遇到資源檔消失的問題,可使用此命令寫回
resource='{"server_msg":{"error":{"server_encountered_error":"伺服器遭遇錯誤","address_or_port_in_use":"位置或連接口正在被使用中","cam_not_exist":"相機不存在","wifi_not_exist":"WiFi不存在","bt_not_exist":"藍芽不存在","ble_not_exist":"低功耗藍芽不存在","other_devices_fail":"其他裝置啟動失敗,無法啟動","other_devices_not_exist":"其他裝置不存在,無法啟動"},"info":{"restart_server":"伺服器正在重新啟動","user_disconnect":"使用者離線","server_restart_success":"伺服器成功重啟","user_interrupt":"伺服器收到使用者中斷","user_interrupt_and_going_offine":"伺服器收到使用者中斷,準備離線","operaction_done":"操作已經完成","operacting":"操作進行中","new_connection":"[新連線] 來自: {}","brocasting":"廣播並聆聽第{}頻道..."},"warning":{"server_encountered_fixable_error":"伺服器遭遇到可處理的錯誤","server_fixing_error":"伺服器正在嘗試修復錯誤"}},"file_msg":{"file_exist":"檔案存在","folder_exist":"資料夾存在","object_path_exist":"檔案路徑存在","file_not_exist":"檔案不存在","folder_not_exist":"資料夾不存在","object_path_not_exist":"檔案路徑不存在","resource_busy":"資源忙碌中,暫時不可用"},"msg_level":{"info":{"text":"訊息","color":"green"},"warning":{"text":"警告","color":"yellow"},"error":{"text":"錯誤","color":"red"},"debug":{"text":"除錯","color":"white"},"verbose":{"text":"詳細","color":"blue"},"dipshit":{"text":"幹話","color":"gary"}},"msg_direction":{"TX":"送出","RX":"收到"},"local_msg":{"permission_denied":"請以root權限執行本程式","connection_refused":"連線被拒,請使用sudo hciconfig檢查","path_not_found_error":"請檢查設定檔 /etc/systemd/system/dbus-org.bluez.service,是否設定正確","bt_not_available":"請檢查藍芽裝置是否啟動"}}'
#TODO: 寫回檔案的指令
def doing1(conn,cmd): #只有一個命令(argc=1)的往這裡送 #conn為藍芽連線通道,若有需要,本程式將可支援多連線 #data為命令
if (cmd=="get"): #取得預設檔名檔案,預設值為sample.png #鬆散的命令方法,不建議使用
pass
#bsl.server().SendText(conn,"DEFAULT,-") #廢棄
#conn.send(bsl.ReadFile(Default_FileName))
#bsl.server().SendText(conn,"DEFAULT,+")
elif cmd=="close": #關閉藍芽連線,程式將結束
flag=False #設定旗標,設定為false程式將不再等待,來自手機藍芽的命令
#elif cmd=="filelen": #Deprecated, Use ls to get file info.
# bsl.server().SendText(conn,bsl.getFileLen(Default_FileName))
elif cmd=="ok": #echo 測試,藉由來回發送ok,測試藍芽連線是否正常
bsl.server().SendText(conn,"ok") #送回ok給手機端
elif cmd=="ls": #以json格式送回檔案清單
bsl.server().SendText(conn,bsl.GetFileList()) #使用library取得檔案清單
elif cmd=="shot": #拍照命令
bsl.server().SendText(conn,R.server_msg.info.operacting) #拍照中請稍後
cam0.take_photo(Default_FileName) #將拍攝檔案儲存為sample.png
bsl.server().SendText(conn,R.server_msg.info.operaction_done) #拍攝完成
elif cmd=="camchk": #檢查相機是否存在 #TODO: 檢查是否為特定廠牌的相機,或者就保持寫死video1路徑
if cam0.exists(): #檢查相機是否存在
bsl.server().SendText(conn,R.file_msg.object_path_exist) #相機物件"在"路徑上 #無法使用檔案的檢測方法
else:
bsl.server().SendText(conn,R.file_msg.object_path_not_exist) #相機物件"不在"路徑上 #無法使用檔案的檢測方法
elif cmd=="reboot": #重開機,當機台遇到不想解決的問題時,可以使用此命令
bsl.server().SendText(conn,'rebooting...') #重啟中
os.system('reboot')
elif cmd=="bye": #廢棄,為close命令的前身
pass #填充用的空語句,保持縮排結構完整性
#bsl.server().SendText(conn,'shuting down!')
elif cmd=="xget": #這裡採用busybox的httpd applet,簡化設定
bsl.service().stop_bhttpd_service() #不管有沒有,先送httpd終止命令
bsl.server().SendText(conn,R.service.bhttpd.starting) #伺服器被啟動了
bsl.service().start_bhttpd_service(80,".") #開始服務
# TO DO: 確認服務是否真的被啟動成功
bsl.server().SendText(conn,R.service.bhttpd.started) #伺服器已經被啟動
elif cmd=="geturl": #獲取檔案位置
bsl.server().SendText(conn,"http://{}/sample.png".format(bsl.common().GetIP())) #告知檔案位置。手機即可透過該位置下載檔案
def doing2(conn,data): #argc=2的命令丟這邊
bsl.server().log(R.msg_level.info,data) #伺服器紀錄
isfile=os.path.isfile(data.split(' ')[1]) #檢查檔案是否存在 #命令:data.split(' ')[0] #檔名:data.split(' ')[1]
cmd=data.split()[0]
if cmd=="get": #藍芽傳送命令,實際上可以傳送任何檔案,檔案接收必須在
if(isfile): #檔案存在
#title_start="{},{},{}".format(R.file_msg.file_exist,x,'+') #廢棄,作為檔案開頭,切換模式字串
#title_end="{},{},{}".format(R.file_msg.file_exist,x,'-') #廢棄,作為檔案結尾,切換模式字串
bsl.server().SendText(conn,R.protocol.start_png_mode) #送出檔案開始字串
bsl.server().SendData(conn,bsl.GetBase64Encode(bsl.ReadFile(data.split()[1]))) #送出檔案經過base64編碼的字串
bsl.server().SendText(conn,R.protocol.end_png_mode) #送出檔案開始字串
if (not(isfile)):#檔案不存在
bsl.server().SendText(conn,R.file_msg.file_not_exist) #檔案不存在
def command_selector(conn,cmd): #命令選擇器,根據命令大小,丟給FUNCTION
if (bsl.common().argc(cmd)==1):
doing1(conn,cmd)
elif(bsl.common().argc(cmd)==2):
doing2(conn,cmd)
def main(restart): #主程式 (是否重啟)
try: #避免錯誤,捕抓意外情況
bsl.server().copyleft_declaration()
sock = lightblue.socket() #產生socket物件
sock.bind(("", 1)) #綁定通道,若通道被占用,綁定通道將出錯
sock.listen(1) #聆聽RFCOMM通道1
lightblue.advertise("EchoService", sock, lightblue.RFCOMM) #開始廣播服務
if (restart):#如果重啟旗標為真
bsl.server().log(R.msg_level.info,R.server_msg.info.server_restart_success) #伺服器重啟成功
bsl.server().log(R.msg_level.info,R.server_msg.info.brocasting.format(sock.getsockname()[1])) #告知手機綁定通道
conn, addr = sock.accept() #新連線
bsl.server().log(R.msg_level.info,R.server_msg.info.new_connection.format(addr[0]))
flag=True
while(flag):
data = conn.recv(1024).rstrip()
#print(data)
bsl.server().log(R.msg_level.info,"{} {}".format(R.msg_direction.RX,data))
command_selector(conn,data)
except KeyboardInterrupt:
print
bsl.server().log(R.msg_level.info,R.server_msg.info.user_interrupt)
exit();
except Exception as exception: #捕抓到錯誤
exceptionString=str(exception) #錯誤原因字串
if (debugMode): #除錯模式?
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print("{}, {}, {}, {}".format(exc_type, fname, exc_tb.tb_lineno,exceptionString))
error_code=bsl.common().GetErrorCode(exceptionString)
#print('error_code: {}'.format(error_code))
if (error_code=='98'): #端口正在被使用中例外
bsl.server().log(R.msg_level.error,R.server_msg.error.address_or_port_in_use)
terminated = True
elif (error_code=='104'):#使用者離線例外
bsl.server().log(R.msg_level.info,R.server_msg.info.user_disconnect)
bsl.server().log(R.msg_level.info,R.server_msg.warning.server_encountered_fixable_error)
bsl.server().log(R.msg_level.info,R.server_msg.warning.server_fixing_error)
conn.close()
sock.close()
bsl.server().log(R.msg_level.info,R.server_msg.info.restart_server)
main(True)
elif (error_code=='13'): #權限不足例外
bsl.server().log(R.msg_level.error,R.local_msg.permission_denied)
terminated = True
elif (error_code=='111'): #連線被拒例外
bsl.server().log(R.msg_level.error,R.local_msg.connection_refused)
if __name__ == '__main__': #避免程式被誤引入,當作library使用
main(False)
#!/usr/bin/python2
# -*- coding: UTF-8 -*-
'''
###Code Summary###
Author: Jack
E-Mail: wwin3286tw@yahoo.com.tw
Tested Date: 2018-09-14 11:39:15 GMT+8
Description: BlueTooth classic Serial port ccFTP(Control & Communication& Fuck Trust Pig) Server support library
ReadMe:
1. Using Java like R Resource File.
2. #sed -i -e 's/\r$//' scriptname.sh #If you have DAMN ^M problem, try this shit.
3. Enjoy fucking salary.
Version Change info:
1. Code Refactoried.
2. Naming improved.
3. Add debug mode, Enable to show exception.
4. Code more clear than before. Although cannot see the older code.
###Code Summary###
'''
##最常用的方法,為了減少複雜性,不使用class
##Most frequently access method, so I do not use fucking class.
from datetime import datetime
import io
import sys
import os
import json
import glob
import re
import base64
import socket
import subprocess
from datetime import datetime
from termcolor import colored
LocalhostName="Server_Localhost"
def ReadFile(filename): #讀取檔案(檔名) #I:檔名, O:二進位資料
bin= open(filename,"rb").read()
return bin
def GetBase64Encode(bin): #將二進位資料轉成Base64字串 #I: 二進位資料, O:Base64編碼後字串
return base64.b64encode(bin)
def GetBase64Decode(bin): #將Base64字串資料轉成二進位 #I:Base64編碼後字串, O:二進位資料
return base64.b64decode(bin)
def ReadAllText(filename): #讀取檔案所有資料 #I:檔案名稱, 字串資料
all_text=""
with io.open(filename, mode='r', encoding='utf-8') as f:
all_text=f.read()
return all_text
def LoadResource(ResourceFile): #讀取資源檔 #I:資源檔名稱, O:資源檔全部內容,JSON字串
return ReadAllText(ResourceFile) #調用讀取全部文字function
def GetResource(ResourceFile): #將JSON轉成好用的物件格式,可以使用"."點存取資源檔(feed Google dog: JSON to Python object)
from collections import namedtuple
return json.loads(LoadResource(ResourceFile),object_hook=lambda d: namedtuple('X', d.keys())(*d.values()))
def GetFileLen(filename): #取得檔案大小
return str(os.path.getsize(filename))
def ListFilesWithExt(ext): #取得經過副檔名 篩選後的檔案清單
return glob.glob("*." + ext )
def GetFileList(): #取得檔案清單
list="[";files=ListFilesWithExt('png');fileCount=len(files);count=0;
for file in files:
count+=1;
if (count<=fileCount-1):
list+= json.dumps({'name':file,'size':GetFileLen(file)},separators=(',',':')) + ","
else:
list+= json.dumps({'name':file,'size':GetFileLen(file)},separators=(',',':'))
list+="]"
return list
##Most frequently use
class service: #服務
def start_bhttpd_service(self,port,dir): #啟動busybox_httpd服務
os.system("sudo busybox httpd -p {0} -h {1}".format(port,dir)) #
def stop_bhttpd_service(self): #停止busybox_httpd服務
os.system("sudo killall busybox") #把busybox殺掉就可以停止服務
class device: #外部裝置(外設)
#sudo udevadm info --query=all /dev/video1 | grep 'VENDOR_ID\|MODEL_ID\|SERIAL_SHORT'
def usb_info(self): #尚未使用,但未廢棄,可以返回USB資訊清單,供確認是否使用正確的USB相機 #參考:https://stackoverflow.com/questions/8110310/simple-way-to-query-connected-usb-devices-info-in-python
device_re = re.compile("Bus\s+(?P<bus>\d+)\s+Device\s+(?P<device>\d+).+ID\s(?P<id>\w+:\w+)\s(?P<tag>.+)$", re.I) #神奇又萬用的正規表達式
df = subprocess.check_output("lsusb") #這裡都是狗吐給我的,所以不解釋囉~
devices = []
for i in df.split('\n'):
if i:
info = device_re.match(i)
if info:
dinfo = info.groupdict()
dinfo['device'] = '/dev/bus/usb/%s/%s' % (dinfo.pop('bus'), dinfo.pop('device'))
devices.append(dinfo)
return devices
class camera: #相機物件
#這裡務必宣告成物件在使用相機 #支援多相機操營養
def __init__(self,camPath): #初始化相機物件
self.CamPath=camPath
def take_photo(self,Filename): #拍一張照片 #TODO: 如果需要設定更多選項,可以變動下面的指令參數,請餵狗:fswebcam
os.system("sudo fswebcam -d {0} -r 800x600 --no-title --no-timestamp --no-subtitle --no-shadow --no-banner {1} --png 9".format(self.CamPath,Filename));
def exists(self): #確認相機是否存在
return os.path.exists(self.CamPath);
class server: #伺服器
def log(self,level,info): #伺服器紀錄器,主要會顯示在機台上
now=datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")
print("{} [{}] - [{}] {}".format(now,LocalhostName,colored(level.text,level.color),info)) #紀錄會依層級給予不同的顏色 [資訊]、[警告]、[錯誤]
sys.stdout.flush()#立刻顯示,不拖延,python有個懶惰的特性,print資料不會是即時,需要用命令讓他立刻顯示
def SendText(self,conn,val):
import lightblue
self.log(R.msg_level.info,"{} {}".format(R.msg_direction.TX,val))
conn.send(val+'\n')
def SendData(self,conn,val):
import lightblue
#self.log(R.msg_level.info,"{} {}".format(R.msg_direction.TX,val))
conn.send(val+'\n')
def copyleft_declaration(self):
print("=========================================")
print("| BlueServer |")
print("| Version:2018-09-28_fix-170 |")
print("| 本著作,包含使用GPL v3授權之衍生作品 |")
print("| 不得用於專有軟體及任何商業用途 |")
print("| author: wwin3286tw@yahoo.com.tw |")
print("=========================================")
class common:
def argc(self,arg_array): #計算命令的長度,有幾個空格分開
return len(arg_array.split(' '))
def GetErrorCode(self,s):
if s.endswith(")") and s.startswith("("):
s = s[:-1]
s = s[1:]
error_code=s.split(',')[0]
else:
error_code=s
return error_code
def GetIP(self): #獲得機台IP位置
return [l for l in ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1], [[(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0]
#參考:https://stackoverflow.com/questions/166506/finding-local-ip-addresses-using-pythons-stdlib
ResourceFile="resource.json"
R=GetResource(ResourceFile)
##圖書館遊樂場(Library Playground)##
#可以在這裡除錯,隨你玩。
#print(R.services.bhttpd.starting)
#server().log(R.msg_level.info,R.file_msg.folder_exist)
#cam0=camera('/dev/video0')
#print(cam0.exists())
[Unit]
Description=Bluetooth service
Documentation=man:bluetoothd(8)
ConditionPathIsDirectory=/sys/class/bluetooth
[Service]
Type=dbus
BusName=org.bluez
ExecStart=/usr/lib/bluetooth/bluetoothd -C
NotifyAccess=main
#WatchdogSec=10
#Restart=on-failure
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
LimitNPROC=1
ExecStartPost=/usr/bin/sdptool add sp
[Install]
WantedBy=bluetooth.target
Alias=dbus-org.bluez.service
[Unit]
Description=Bluetooth service
Documentation=man:bluetoothd(8)
ConditionPathIsDirectory=/sys/class/bluetooth
[Service]
Type=dbus
BusName=org.bluez
ExecStart=/usr/lib/bluetooth/bluetoothd
NotifyAccess=main
#WatchdogSec=10
#Restart=on-failure
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
LimitNPROC=1
[Install]
WantedBy=bluetooth.target
Alias=dbus-org.bluez.service
source-directory /etc/network/interfaces.d
auto lo
iface lo inet loopback
auto wlan0
iface wlan0 inet static
address 192.168.0.130
netmask 255.255.255.0
gateway 192.168.0.1
wpa-essid Kaiwood
wpa-psk 0660006000
git config --global http.sslverify false
cd ~;
git clone https://gist.github.com/wwin3286tw/ae7ef8149e474475b14fde89b7c8783c ~/blueServer;
cd blueServer;
chmod 755 *.py;
chmod 755 *.sh;
./run.sh;
{
"server_msg": {
"error": {
"server_encountered_error": "伺服器遭遇錯誤",
"address_or_port_in_use": "位置或連接口正在被使用中",
"cam_not_exist": "相機不存在",
"wifi_not_exist": "WiFi不存在",
"bt_not_exist": "藍芽不存在",
"ble_not_exist": "低功耗藍芽不存在",
"other_devices_fail": "其他裝置啟動失敗,無法啟動",
"other_devices_not_exist": "其他裝置不存在,無法啟動"
},
"info": {
"restart_server": "伺服器正在重新啟動",
"user_disconnect": "使用者離線",
"server_restart_success": "伺服器成功重啟",
"user_interrupt": "伺服器收到使用者中斷",
"user_interrupt_and_going_offine": "伺服器收到使用者中斷,準備離線",
"operaction_done": "操作已經完成",
"operacting": "操作進行中",
"new_connection": "[新連線] 來自: {}",
"brocasting": "廣播並聆聽第{}頻道..."
},
"warning": {
"server_encountered_fixable_error": "伺服器遭遇到可處理的錯誤",
"server_fixing_error": "伺服器正在嘗試修復錯誤"
}
},
"file_msg": {
"file_exist": "檔案存在",
"folder_exist": "資料夾存在",
"object_path_exist": "檔案路徑存在",
"file_not_exist": "檔案不存在",
"folder_not_exist": "資料夾不存在",
"object_path_not_exist": "檔案路徑不存在",
"resource_busy": "資源忙碌中,暫時不可用"
},
"msg_level": {
"info": {"text":"訊息","color":"green"},
"warning": {"text":"警告","color":"yellow"},
"error": {"text":"錯誤","color":"red"},
"debug": {"text":"除錯","color":"white"},
"verbose": {"text":"詳細","color":"blue"},
"dipshit": {"text":"幹話","color":"gary"}
},
"msg_direction": {
"TX": "送出",
"RX": "收到"
},
"local_msg": {
"permission_denied": "請以root權限執行本程式",
"connection_refused": "連線被拒,請使用sudo hciconfig檢查",
"path_not_found_error": "請檢查設定檔 /etc/systemd/system/dbus-org.bluez.service,是否設定正確",
"bt_not_available": "請檢查藍芽裝置是否啟動"
},
"protocol":{
"start_png_mode":"BEG_PNG",
"end_png_mode":"END_PNG"
},
"service":{
"bhttpd":{
"starting":"正在啟動檔案傳輸服務...",
"stopped":"檔案傳輸服務已經停止",
"stopping":"正在嘗試停止檔案傳輸服務...",
"started":"檔案傳輸服務已經啟動"
}
}
}
#!/bin/bash
log() {
now="`date '+%Y-%m-%d %H:%M:%S.%3N'`";
printf -v now "[%s %s]" $now
echo "${now} ${@}"
}
cd ~/blueServer
log "複製dbus-org.bluez.service設定檔"
sudo cp dbus-org.bluez.service /etc/systemd/system/dbus-org.bluez.service
log "將時區更新為 /亞洲/台北"
sudo cp /usr/share/zoneinfo/Asia/Taipei /etc/localtime
log "取得最新軟體清單"
sudo apt-get update;wait
log "安裝基本組件"
sudo apt-get -y install ntpdate curl
sudo ntpdate tick.stdtime.gov.tw;wait
log "快速安裝 apt-fast..."
/bin/bash -c "$(curl -sL https://git.io/vokNn)"
log "apt-fast 安裝完成"
log "開始安裝主要元件,這需費時較久,請稍後。"
sudo apt-fast -y install build-essential cmake pkg-config cmake automake autoconf autotools-dev fswebcam unzip p7zip-full locate libbluetooth-dev libopenobex* python-pip libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev bluez-tools python-termcolor;wait
log "主要元件安裝完成"
log "開始克隆必要的python程式庫"
cd ~/
git clone https://github.com/0-1-0/lightblue-0.4.git ~/lightblue-0.4;wait
cd ~/lightblue-0.4
sudo -H python setup.py install;wait
log "重啟藍芽服務中"
sudo sed -i 's/^#IdleTimeout=.*/IdleTimeout=0/' /etc/bluetooth/input.conf
sudo systemctl daemon-reload
sudo systemctl restart bluetooth
log "重啟藍芽裝置"
sudo hciconfig hci0 up
log "藍芽重啟成功"
log "變更Service Discovery Protocol(SDP)執行權限"
sudo chmod 777 /var/run/sdp
log "開始使用pip安裝必要的python程式庫"
sudo -H python -m pip install pybluez
#sudo /usr/bin/sdptool add sp
log "設定藍芽可被偵測、配對"
sudo bluetoothctl <<EOF
power on
discoverable on
pairable on
agent NoInputNoOutput
default-agent
EOF
log "可以跑該死的藍芽序列伺服器了"
#!/bin/bash
log() {
now="`date '+%Y-%m-%d %H:%M:%S.%3N'`";
printf -v now "[%s %s]" $now
echo "${now} ${@}"
}
cd ~
wget https://w1.fi/cgit/hostap/plain/hostapd/hostapd.conf
sudo cp hostapd.conf /etc/hostapd/hostapd.conf
sudo systemctl restart hostapd
rm hostapd.conf
cd ~/blueServer
log "複製dbus-org.bluez.service設定檔"
sudo cp dbus-org.bluez.service /etc/systemd/system/dbus-org.bluez.service
log "將時區更新為 /亞洲/台北"
sudo cp /usr/share/zoneinfo/Asia/Taipei /etc/localtime
log "取得最新軟體清單"
sudo apt-get update;wait
log "安裝基本組件"
sudo apt-get -y install ntpdate curl software-properties-common
sudo ntpdate tick.stdtime.gov.tw;wait
log "安裝 apt-fast..."
sudo add-apt-repository ppa:apt-fast/stable -y;wait
sudo apt-get update
sudo apt-get -y install apt-fast;wait
log "apt-fast 安裝完成"
log "開始安裝主要元件,這需費時較久,請稍後。"
sudo apt-fast -y install build-essential cmake pkg-config cmake automake autoconf autotools-dev fswebcam unzip p7zip-full locate libbluetooth-dev libopenobex* python-pip libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev bluez-tools;wait
log "主要元件安裝完成"
log "開始克隆必要的python程式庫"
cd ~/
git clone https://github.com/0-1-0/lightblue-0.4.git ~/lightblue-0.4;wait
cd ~/lightblue-0.4
sudo -H python setup.py install;wait
log "重啟藍芽服務中"
sudo sed -i 's/^#IdleTimeout=.*/IdleTimeout=0/' /etc/bluetooth/input.conf
sudo systemctl daemon-reload
sudo systemctl restart bluetooth
log "重啟藍芽裝置"
sudo hciconfig hci0 up
log "藍芽重啟成功"
log "變更Service Discovery Protocol(SDP)執行權限"
sudo chmod 777 /var/run/sdp
log "開始使用pip安裝必要的python程式庫"
sudo -H python -m pip install pybluez
#sudo /usr/bin/sdptool add sp
log "設定藍芽可被偵測、配對"
sudo bluetoothctl <<EOF
power on
discoverable on
pairable on
agent NoInputNoOutput
default-agent
EOF
log "可以跑該死的藍芽序列伺服器了"
<mxfile userAgent="Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36" version="9.1.8" editor="www.draw.io" type="device"><diagram id="01ff5919-39d3-1365-7166-ba8096f9b469" name="Page-1">3Vpbs9o2EP41es3YutjSow2mzUw6kxke0j76gIJpDWKMCIf++qxkGWNb9JD2xEDzkJHX0kpeffvt5YDIZPP6S5Xvit/UUpYIB8tXRKYIY0EI/G8Ep1pAGa4Fq2q9rEVhK5iv/5ZOGDjpYb2U+85ErVSp17uucKG2W7nQHVleVerYnfZVld1dd/lKDgTzRV4OpV/WS13UUo7jVv6rXK+KZucwEvWbl3zx16pSh63bD2Hy1f6rX2/yRpf70H2RL9XxQkQyRCaVUroebV4nsjSmbcxWr5tdeXs+dyW3+pYF7oO+5eVBNie259KnxhZyCaZxj6rShVqpbV5mrTS13yuNxgCeCr0pYRjC8E+p9cndbn7QCkSthk9K7dy8ek+z0dXPCM/GAcxJtZG6OsGUSpa5Xn/rrsvd7a/O885LP6s1aMSBAyqJ3T04nIYk6KrYq0O1kG7VpR3fUHRGcqNI59VK6oEiGFx8Tyuy13TljgPPnUUl2Cnd7/ItjFdmjDKK0ilKZyiLkaAo4SjjiAeIM5QJxEOUgiRCgiAeNwpg744OJ36p+pLuTgxxjFJiNkgnVi+xO4XNBlN3GjExEjhKEppVMJnPru7dx2FZgvsbvB2LtZbzXb4wb45AQF3UOfPISsvXH8VTc51h9zqZezy2ZBA2LlxcEAEPriOwc+X/dL/P5ZNwLusjTsQcW1u4O1n0H333ZsuxoeWGUB8CEOYkNVoFElOUDO3dteb4+Ds7/VsAjN4BgNhHME8DwMgDQD4SADH9n1kOk7Es53Hdp7ZcKMYivchDej8S+slsSHeF2rwc9uNQHelSHfFQHf9JofbJ0t8e6rjHX0cLtfzGUMtBmNqYC7F1lnz2pJQGm7yJzGaWTShnKA0sflOUUqs7QAm5e2QOaQ+ueMTITMJnxqsY4pUEfmO/P17FTXi9oEsR27IFgJkYMn08JFJxRyRijz2fBomYeJhztByReJAI9UhmMOhhwAty7HKpj0mZqbANfmEA4X5i9QR2VYzSCKXYLs9QymySYNF9byD3ix0ajQhkyt4Tt/DF1el3J7cPf5iHD+znY9qTg1I8FqZ9OegAr6a6jqwE0MnqbOBqN6iLanAEHs/nH6cXnSWGkhnikUE2VOyw2LPScnVd4cMSnvmIXTQKY+MVSeRxQk8b7MHSEErG9JlnLnOxJ20ez1F8afPQUbh1iqnFOMSFxJ82W/42eO34BzgWNszv9aOex7SN21uc4MHCBGP0AxsP9MTTFTNXMDMtQ3OHE2u/K/wC+aIxLSSRyRtxu99JP0dpLwA6Vb7BsztJbN+mKKFW59TqtDeZ+Cj23nfbz2XpmP1O+tBV1SV3UezhLnKzsd+dzprz9Kuqt2KuB8sAYWEpSbR/OQJO5Lby4kBJsQfa94Ztn5KiUTPXZ25eUU8JRsdqXlFfCeZyUsuSKYwLrXdL2xqYWBTWYvGA5NlHYczYmIGRPnMrgPrKprFaAdRXNrlkziZgiYnrZhCaJkAd72tGhAFkhjVZQkph6BNCO/N1CR4MnXxUjrwt3/aFLHhluiXntgkzeR731YKGGoTjiDQzc1zSlro0Dt62CgfX+viEIm79+cO/uDJ4bH/tVP8apv1FGcm+Aw==</diagram></mxfile>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment