pythonで起動させたスレッドを殺す

pythonでサブプロセスから起動させた子を停止させて殺します。
色々調べた結果、呼んだ時のIDを指定して止めることにしました。

環境

Ubuntu 16.04
python 3.5.2

プログラム

[thread_test.py]

# -*- coding:utf8 -*-
import  time
import subprocess
from subprocess import Popen
import os
import signal

cmd = "python thread_test_child.py"
proc = subprocess.Popen("exec " + cmd, stdout=subprocess.PIPE, shell=True)
print( "process id = %s" % proc.pid )
print(proc.stdout.readline())
os.killpg(os.getpgid(proc.pid), signal.SIGTERM)

呼び出す子プロセス

[thread_test_child.py]

print("====")

↓結果↓

process id = 22818
b'====\n'
Terminated

終わり

raspberrypi3のbluetoothライブラリを最新にする

(2019/3/1時点での記事です)
ラスベリーパイ3でbluetoothの通信をしている時にちょっと不具合等が起きたので、最新のライブラリに更新しました。
使っているのはblueZになります。

環境

Raspberrypi3B raspbian 4.14.79-v7+
 

ライブラリダウンロード

ここから最新ver.確認してダウンロード
www.bluez.org

(2019/3/1時点での最新は5.50)

解凍からインストールまで

tar xvf bluez-5.50.tar.xz
cd bluez-5.50
sudo apt update
sudo apt install -y libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev
./configure --prefix=/usr --mandir=/usr/share/man --sysconfdir=/etc --localstatedir=/var --enable-experimental --enable-midi 
make
sudo make install
sudo reboot
sudo cp /usr/libexec/bluetooth/bluetoothd /usr/lib/bluetooth
 
bluetoothctl -v
bluetoothd --version

下2つのコマンドを打つと5.50のバージョンが出てくると思います。

終わり

pythonでスレッドを再起動させる

pythonでマルチスレッドを使っている時にスレッドがエラーで停止したときに再起動させて復活させる。

環境

python 3.5.2

プログラム

 サブスレッドで÷0をして意図的にエラーをして、それをメインが監視して落ちていたら再起動
 ここでは監視としてメインとスレッドの時間を比較して監視する

import threading, time

global_lock = threading.Lock()   # LOCK OBJECT
global_time = 0
            
class sub_while(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        global global_time
        time_cnt=0
        
        while True:
            global_lock.acquire()
            time_cnt = time_cnt+1
            global_time = int(time.time())
            global_lock.release()
            
            print("sub_thread:",int(time.time()))
            
            if(time_cnt >= 5):
                #error
                val = 100/0
            time.sleep(1)
    
if __name__ == "__main__": 
    global global_time
    
    thread1 = sub_while()
    thread1.start()

    #再起動閾値時間
    threshold_time =5
    while True:
        print("main_time:",int(time.time()))
        print("diff_time:",int(time.time()) - global_time)

        global_lock.acquire()
        #スレッド監視
        if(int(time.time()) - global_time > threshold_time):
            print("-- thread restart --")
            thread1 = sub_while()
            thread1.start()
        global_lock.release()

        time.sleep(1)        

結果

sub_thread: 1543545253
main_time: 1543545253
diff_time: 0
main_time: 1543545254
sub_thread: 1543545254
diff_time: 0
main_time: 1543545255
sub_thread: 1543545255
diff_time: 0
main_time: 1543545256
sub_thread: 1543545256
diff_time: 0
main_time: 1543545257
diff_time: 0
sub_thread: 1543545257
Exception in thread Thread-1:
Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "threadtest2.py", line 27, in run
    val = 100/0
ZeroDivisionError: division by zero

main_time: 1543545258
diff_time: 1
main_time: 1543545259
diff_time: 2
main_time: 1543545260
diff_time: 3
main_time: 1543545261
diff_time: 4
main_time: 1543545262
diff_time: 5
main_time: 1543545263
diff_time: 6
-- thread restart --
sub_thread: 1543545263
main_time: 1543545264
diff_time: 0
sub_thread: 1543545264
main_time: 1543545265
diff_time: 1
sub_thread: 1543545265
main_time: 1543545266
diff_time: 1
sub_thread: 1543545266
main_time: 1543545267
diff_time: 1
sub_thread: 1543545267
Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
    self.run()
  File "threadtest2.py", line 27, in run
    val = 100/0
ZeroDivisionError: division by zero

main_time: 1543545268
diff_time: 1
main_time: 1543545269
diff_time: 2

 
以上。

ubuntuでpythonのbluetooth開発環境を構築3

bluepyでプログラムを作っていましたがDelegateやNotificationの部分できちんと動作しなかったところがあるので、またライブラリを変更します

今回使ったのはこちら
github.com

環境

ubuntu16.04
python2.7

RaspberryPi3 B+ でも確認
(Linux raspberrypi.local 4.14.71-v7+ #1145 SMP Fri Sep 21 15:38:35 BST 2018 armv7l GNU/Linux)(STRETCH)

pythonは2系で動かします

Adafruit_Python_BluefruitLEインストール

sudo apt-get update
sudo apt-get -y install libusb-dev libdbus-1-dev libglib2.0-dev libudev-dev libical-dev libreadline-dev
git clone https://github.com/adafruit/Adafruit_Python_BluefruitLE
cd Adafruit_Python_BluefruitLE/
sudo python2 setup.py install

ここまでは公式通りにインストール
しかし、ここからbluez-5.33を公式通りにインストールしたらエラーが出たため5.37を入れます

cd ~
wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.37.tar.xz
tar xvf bluez-5.37.tar.xz
cd bluez-5.37
./configure
make
sudo make install
sudo systemctl start bluetooth
sudo systemctl enable bluetooth

lowEnergy有効化

sudo nano /lib/systemd/system/bluetooth.service
9行目を
ExecStart=/usr/local/libexec/bluetooth/bluetoothd  
から
ExecStart=/usr/local/libexec/bluetooth/bluetoothd    --experimental  
に修正
sudo systemctl daemon-reload
sudo systemctl restart bluetooth

そしたらサンプルプログラムを動かします。
手持ちが前回同様blenano2なのでそれを使いました。
(プログラムはこちら
blenano2は電源入れておいて、
examples/low_level.pyを編集します

# Example of low level interaction with a BLE UART device that has an RX and TX
# characteristic for receiving and sending data.  This doesn't use any service
# implementation and instead just manipulates the services and characteristics
# on a device.  See the uart_service.py example for a simpler UART service
# example that uses a high level service implementation.
# Author: Tony DiCola
import logging
import time
import uuid
import struct
import binascii
import Adafruit_BluefruitLE


# Enable debug output.
#logging.basicConfig(level=logging.DEBUG)

# Define service and characteristic UUIDs used by the UART service.
UART_SERVICE_UUID = uuid.UUID('713d0000-503e-4c75-ba94-3148f18d941e')
#TX_CHAR_UUID      = uuid.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E')
RX_CHAR_UUID      = uuid.UUID('713d0001-503e-4c75-ba94-3148f18d941e')

# Get the BLE provider for the current platform.
ble = Adafruit_BluefruitLE.get_provider()


# Main function implements the program logic so it can run in a background
# thread.  Most platforms require the main thread to handle GUI events and other
# asyncronous events like BLE actions.  All of the threading logic is taken care
# of automatically though and you just need to provide a main function that uses
# the BLE provider.
def main():
    # Clear any cached data because both bluez and CoreBluetooth have issues with
    # caching data and it going stale.
    ble.clear_cached_data()

    # Get the first available BLE network adapter and make sure it's powered on.
    adapter = ble.get_default_adapter()
    adapter.power_on()
    print('Using adapter: {0}'.format(adapter.name))

    # Disconnect any currently connected UART devices.  Good for cleaning up and
    # starting from a fresh state.
    print('Disconnecting any connected UART devices...')
    ble.disconnect_devices([UART_SERVICE_UUID])

    # Scan for UART devices.
    print('Searching for UART device...')
    try:
        adapter.start_scan()
        # Search for the first UART device found (will time out after 60 seconds
        # but you can specify an optional timeout_sec parameter to change it).
        device = ble.find_device(service_uuids=[UART_SERVICE_UUID])
        if device is None:
            raise RuntimeError('Failed to find UART device!')
    finally:
        # Make sure scanning is stopped before exiting.
        adapter.stop_scan()

    print('Connecting to device...')
    device.connect()  # Will time out after 60 seconds, specify timeout_sec parameter
                      # to change the timeout.

    # Once connected do everything else in a try/finally to make sure the device
    # is disconnected when done.
    try:
        # Wait for service discovery to complete for at least the specified
        # service and characteristic UUID lists.  Will time out after 60 seconds
        # (specify timeout_sec parameter to override).
        print('Discovering services...')
        device.discover([UART_SERVICE_UUID], [ RX_CHAR_UUID])#TX_CHAR_UUID

        # Find the UART service and its characteristics.
        uart = device.find_service(UART_SERVICE_UUID)
        rx = uart.find_characteristic(RX_CHAR_UUID)
        #tx = uart.find_characteristic(TX_CHAR_UUID)

        # Write a string to the TX characteristic.
        #print('Sending message to device...')
        #tx.write_value('Hello world!\r\n')

        # Function to receive RX characteristic changes.  Note that this will
        # be called on a different thread so be careful to make sure state that
        # the function changes is thread safe.  Use queue or other thread-safe
        # primitives to send data to other threads.
        def received(data):
            #print('Received: {0}'.format((data)))
            print(binascii.b2a_hex(data))

        # Turn on notification of RX characteristics using the callback above.
        print('Subscribing to RX characteristic changes...')
        rx.start_notify(received)

        # Now just wait for 30 seconds to receive data.
        print('Waiting 60 seconds to receive data from the device...')
        time.sleep(60)
    finally:
        # Make sure device is disconnected on exit.
        device.disconnect()


# Initialize the BLE system.  MUST be called before other BLE calls!
ble.initialize()

# Start the mainloop to process BLE events, and run the provided function in
# a background thread.  When the provided main function stops running, returns
# an integer status code, or throws an error the program will exit.
ble.run_mainloop_with(main)

python2で実行すると

Using adapter: astina-System-Product-Name
Disconnecting any connected UART devices...
Searching for UART device...
Connecting to device...
Discovering services...
Subscribing to RX characteristic changes...
Waiting 60 seconds to receive data from the device...
0102030000
0102030000
0102030000

みたいな感じでbluetooth経由で受信したデータが表示されます。(表示した受信データはblenano2のプログラムをちょっといじったので違います)

ちなみにDiscovering services...で止まってしまう場合は内部のbluetooth設定とかで止まっている可能性があります。
その場合は手動でbluetoothをオンオフしたりPCを再起動させたほうがいいです。
またRaspberryPi3 B+でも確認できました。

以上です。

ubuntu16でpythonのbluetooth開発環境を構築2

前回やったのはその後エラーで大変だったので、ちょっとやり直し。

環境

ubuntu16.04
python3.5.2

bluepyインストール

bluepy · PyPI
↑まず、ここからダウンロードしておく
2018/10/26現在最新は1.2.0

cd
sudo apt-get install libglib2.0-dev
tar -xzvf IanHarvey-bluepy-v-1.1.4-0-g117ac3d.tar.gz
cd IanHarvey-bluepy-117ac3d/
sudo python3 setup.py build
sudo python3 setup.py install

・インストール成功しているか確認

cd IanHarvey-bluepy-v-1.1.4-0-g117ac3d/bluepy
python scanner.py 
  Traceback (most recent call last):
    File "scanner.py", line 18, in <module>
      scanner.scan(10.0, passive=True)
    File "/usr/local/lib/python3.5/dist-packages/bluepy-1.1.4-py3.5.egg/bluepy/btle.py", line 679, in scan
      self.start(passive=passive)
    File "/usr/local/lib/python3.5/dist-packages/bluepy-1.1.4-py3.5.egg/bluepy/btle.py", line 617, in start
      self._mgmtCmd("le on")
    File "/usr/local/lib/python3.5/dist-packages/bluepy-1.1.4-py3.5.egg/bluepy/btle.py", line 276, in _mgmtCmd
      "Failed to execute mgmt cmd '%s'" % (cmd))
  bluepy.btle.BTLEException: Failed to execute mgmt cmd 'le on'

エラーが出る(今になって思うとこの時bluetoothドングル挿してなかったかも...)
また、2行目のfrom __future__ import print_functionは消しておく

bluetoothの確認
(ドングルさして確認)

sudo /usr/local/bin/blescan -i=0
Scanning for devices...
    Device (new): **:**:**:**:**:** (random), -62 dBm (not connectable)
	Complete 16b Services: <****>
	16b Service Data: <****0000000000000000000000000000000000000000>
	Manufacturer: <***********>

確認できた

・権限付与
また、調べてるとbluepy-helperでエラーが出てる人が多かったのでこちらも対処

sudo setcap 'cap_net_raw,cap_net_admin+eip' bluepy-helper

・bluepyが使えるか確認

python scanner.py 
Scanning for devices...
    Device (new): d2:18:5c:a9:20:33 (random), -43 dBm 
	Flags: <06>
	Complete Local Name: 'MyBlePeripheral'
	Complete 128b Services: <1e948df1483194ba754c3e5000003d71>

ちなみに見つかったのはredbearのblenano2(プログラムはこちら

以上。pythonbluetoothを使えるようになりました。


ubuntu16でpythonのbluetooth開発環境を構築

ーー追記ーー
 
この記事の内容はすぐやめたので、ライブラリ変わってもいいならbluepyで構築した記事があるので飛んでください
ubuntu16でpythonのbluetooth開発環境を構築2 - ロボット、電子工作、IoT、AIなどの開発記録
 
ーーーーーー

今回はpyBluezとgattlibを入れました。
python2.7と3.4の人はすぐインストールができるけど、それ以外の人はちょっと面倒な感じでした。

環境

ubuntu16.04
python3.5.2

pyBlueZインストール

sudo apt install python3-dev libbluetooth3-dev

low Energyの人は

sudo pip install  pybluez\[ble\]

そうじゃない人は

pip install pybluez

pyBlueZインストール

依存関係インストール

sudo apt install libglib2.0 libboost-python-dev libboost-thread-dev

次に”リポジトリをダウンロードする”をクリックしてzipで保存する
OscarAcena / pygattlib / Downloads — Bitbucket

以下手順
・解凍
・setup.pyを開き、22行目boost_python-py34を自分の環境に合わせる(今回は35)
・src/Makefileを開き12行目のboost_python-py34を自分の環境に合わせる(今回は35)
・端末で make PYTHON_VER=3
・続いて sudo python3 setup.py install
・一応確認  sudo pip3 install gattlib

以上です

参考

ありがとうございます
python-gattlibのインストール方法 - Qiita