2020年6月19日金曜日

Raspberry pi4でBLE ScanのPythonプログラムを作成する

目的

Raspberry Pi 4を用いて、BleAdvertiseのScanを行うまで

見つけた問題点

hcitool lescanを用いるようだが、
コマンドを実施すると、下記のエラーが出た

$ sudo hcitool lescan
Set scan parameters failed: Input/output error
Scanning for BLE devices on Raspberry Pi 4 Model Bを参照すると、
解決方法でデバイスのdown/upをするとあるが、投稿者同等直らなかった

ライブラリとPythonスクリプト

おそらく下記はやらなくてもいいが、上を解決しようと試行錯誤した後。。
Raspberry Pi4はデフォルトではbluezは5.50 (2020/06/19時点)

$ bluetoothctl version
Version 5.50

bluezのアップデート

BlueZ 5.54に置き換える

$ wget http://www.kernel.org/pub/linux/bluetooth/bluez-5.54.tar.xz
$ tar xvf bluez-5.54.tar.xz
$ cd bluez-5.54
$ ./configure --prefix=/usr --mandir=/usr/share/man  --sysconfdir=/etc --localstatedir=/var
$ make
$ make install
一応再起動した方が良い?

バージョンの確認とお試しとしてtestフォルダにあるble advertiseを実行してみる

$ bluetoothctl version
Version 5.54
$ python3 example-advertisement
example-advertisement:201: PyGIDeprecationWarning: GObject.MainLoop is deprecated; use GLib.MainLoop instead
  mainloop = GObject.MainLoop()
Advertising forever...
GetAll
returning props
Advertisement registered

他の端末(例としてMac上のXcode付属のBluetooth Explorerから見ると以下のように出る

Manufacturer Data : {length = 7, bytes = 0xffff0001020304}
kCBAdvDataChannel : 37
Service UUIDs : (
    "Heart Rate",
    Battery
)
Service Data : {
    9999 = {length = 5, bytes = 0x0001020304};
}
Local Name : TestAdvertisement
kCBAdvDataIsConnectable : 0

C言語などや他のライブラリが使うことを考えて
BlueZ 5.50のdev用ヘッダファイルたちを5.54に置き換えておく
バックアップも取っておく

$ sudo cp -ipr lib/ /usr/include/bluetooth.5.54
$ cd /usr/include
$ sudo mv bluetooth bluetooth.5.50
$ sudo ln -s bluetooth.5.54/ bluetooth

bluepyのインストール

bluepyを参照
なお、本ライブラリはルート権限が必要 (デバイスの操作がルートのみ)

$cat ble_rpi.py
from bluepy import btle
scanner = btle.Scanner(0)
devices = scanner.scan(3.0)
for device in devices:
    print("Macアドレス:" + device.addr)
    print("アドレスタイプ:" + device.addrType)
    print("RSSI:" + str(device.rssi))
    print("アドバタイシングデータ:")
    for adTypeCode, description, valueText in device.getScanData():
        print(" " + description + ":" + valueText)
$ sudo python3 ble_rpi.py
Macアドレス:2f:05:xx:xx:xx:xx
アドレスタイプ:random
RSSI:-47
アドバタイシングデータ:
    Flags:1a
    Complete 16b Services:0000fd6f-0000-1000-8000-00805f9b34fb
    16b Service Data:6ffd341691188f76e34f8635f1177c1cadaf86eb405f
Macアドレス:4d:xx:xx:xx:xx:xx
アドレスタイプ:random
RSSI:-52
アドバタイシングデータ:
    Flags:1a
    Tx Power:0c
    Manufacturer:4c001005021cf71772

という感じで表示される。

参考ページ

2020年6月14日日曜日

Python Markdownで独自のタグを使う

目的

Bloggerの投稿をmarkdownでやりたい


やり方

方法は色々あると思うが、markdownをhtml形式に変換するのが手っ取り早かった

Qiita:Pythonでmarkdownをhtmlにコンバートする

こちらにmarkdownの使い方はまとまっていたので上記記事を参照した

ただし、私のbloggerではcodeタグではなく、<pre class="prettyprint"></p>で行っている

デフォルトのままでは```はcodeに変換されてしまう。。

その為、このタグを上書きして独自のタグを使うためのextensionを作成した


コード

import markdown
from markdown.inlinepatterns import Pattern
from markdown.extensions import Extension
import xml.etree.ElementTree as etree

BACKTICK_RE = r'([```]{3})(.*?)\2'

class CodePattern(Pattern):
    def handleMatch(self, m):
        if m.group(2) == '```':
            tag = 'pre'
            el = etree.Element(tag)
            el.text = m.group(3)
            el.set('class', "prettyprint")
            return el
        pass

class CodeExtension(Extension):
    def extendMarkdown(self, md):
        # Delete the old patterns
        md.inlinePatterns.deregister('backtick')

        # Add our new MultiPattern
        multi = CodePattern(BACKTICK_RE)
        md.inlinePatterns.register(multi, 'backtick', 100)


sample_text = '''
※今回の箇所はここ※
```
まさかコードも入れられるんですか?
if (!lie) {
    return true;
}
```
'''

md = markdown.Markdown(extensions=['tables', CodeExtension()])
print(md.convert(sample_text))

これを行うと、
<p>※今回の箇所はここ※
<pre class="prettyprint">
まさかコードも入れられるんですか?
if (!lie) {
    return true;
}
</pre>
</p>

と出力されるので、これをbloggerに貼り付ければHTMLを書くのがかなり楽になる。

参考

Tutorial: Writing-Extensions-for-Python-Markdown

2020年6月13日土曜日

Matplotlibで日本語が表示されないからフォントを追加

目的

Matplotlibの初期フォントでは日本語を表示すると豆腐になるため、それを修正する方法


準備

IPAフォント

ここからIPAexゴシックをダウンロード

中身にあるipaexg.ttfをRaspberry piに持っていく


インストール

下記で行っていることは、フォントをダウンロードして来たものに置き換える

その後に設定ファイルをローカルにコピーして、その設定ファイルのフォントをダウンロードしたものを使用するように書き換える

最後に、cacheを削除して、フォント定義をリセットする

 $ cp ipaexg.ttf /home/pi/.local/lib/python3.7/site-packages/matplotlib/mpl-data/fonts/ttf/
$ cp /home/pi/.local/lib/python3.7/site-packages/matplotlib/mpl-data/matplotlibrc /home/pi/.config/matplotlib/
$ vim /home/pi/.config/matplotlib/matplotlibrc
#font.family : sans-serif
font.family : IPAexGothic
$ rm -rf /home/pi/.cache/matplotlib/

その他

設定ファイルがどこにあるかわからない場合はpython上で確認する

python3
Python 3.7.3 (default, Dec 20 2019, 18:57:59) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import matplotlib
>>> matplotlib.get_configdir()
'/home/pi/.config/matplotlib'
>>> import matplotlib
>>> matplotlib.matplotlib_fname()
'/home/pi/.config/matplotlib/matplotlibrc'

2020年6月12日金曜日

公開鍵認証を用いてRaspberry PiにSSH接続する

目的

Raspberry Piにssh接続はできるが、パスワード認証だと万が一外につながった時に踏み台にされたり燃やされたりと心配なので鍵認証に変更する


以下は全てMacからパスワード認証でSSH接続をして行った

鍵を生成する

ssh-keygenと打ち、保存場所とパスワードを入れることで生成される

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/pi/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/pi/.ssh/id_rsa.
Your public key has been saved in /home/pi/.ssh/id_rsa.pub.
The key fingerprint is:
********
+----[SHA256]-----+

鍵を保存する

適当な箇所に鍵を保存する

今回は、.ssh以下にrpiフォルダを作成した

$ mkdir .ssh/rpi
$ mv id_rsa.pub .ssh/rpi/
$ mv id_rsa .ssh/rpi/

Macに秘密鍵(id_rsa)をコピーする

Macでもう一つターミナルを開く

scp 欲しいファイル ダウンロード先

$ scp pi@IPアドレス:~/.ssh/id_rsa ~/Desktop

SSH設定を変更する

ここで失敗するとSSH接続ができなくなるが、そうなった場合はRaspberry pi側本体側で操作して修正をする

sudo vim /etc/ssh/sshd_config

PermitRootLogin no
PubkeyAuthentication yes
RSAAuthentication yes
AuthorizedKeysFile %h/.ssh/rpi/id_rsa.pub
PasswordAuthentication no

上記を変更・追加をする

PermitRootLogin: ルートログインの禁止

PubkeyAuthentication: 公開鍵認証を許可

RSAAuthentication: RSA認証を許可

AuthorizedKeysFile: 公開鍵の保存場所指定

PasswordAuthentication: パスワードログインの禁止

余裕があればPasswordAuthenticationはyesのまま一回秘密鍵でのログインを実施した方が良い

設定に失敗していても、パスワードでのログインができるので


設定の有効化

$ sudo /etc/init.d/ssh restart
[ ok ] Restarting ssh (via systemctl): ssh.service

問題がなければOKと出る


接続元での確認

macのターミナルを開き、秘密鍵を指定してログインをする。

秘密鍵生成時のパスワードを聞かれるので入力すると接続される

$ ssh -i ~/Desktop/id_rsa -p 22 pi@RpiのIPアドレス
Enter passphrase for key '/Users/***/Desktop/id_rsa':
Linux raspberrypi 4.19.118-v7l+ #1311 SMP Mon Apr 27 14:26:42 BST 2020 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Jun 12 11:41:31 2020 from 192.168.1.2
pi@raspberrypi:~ $

また、パスワード認証形式で弾かれることも確かめておく

ssh pi@RPiのIPアドレス
pi@****: Permission denied (publickey).

macのSSH configファイルに設定を書いておく

デスクトップにあるRaspberry pi向けsshの秘密鍵をmacの何処かに保存する(以下では~/.ssh/rpi/)

下記のようにconfigファイルに設定を書く

$ mv ~/Desktop/id_rsa ~/.ssh/rpi
$ cat ~/.ssh/config

Host rpi
    HostName 192.168.1.29
    IdentityFile ~/.ssh/rpi/id_rsa
    User pi

$ ssh-add ~/.ssh/rpi/id_rsa
$ ssh rpi

Linux raspberrypi 4.19.118-v7l+ #1311 SMP Mon Apr 27 14:26:42 BST 2020 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Jun 12 12:52:06 2020 from 192.168.1.2
pi@raspberrypi:~ $ 

最後に

ポートスキャン対策でPort番号もデフォルトの22から他にした方が良いとされる。

しかし今回は、ローカルネットワークでの使用のみでルータで22番へのアクセスは禁止しているので変更はしない

2020年6月11日木曜日

Systemdを使用して起動時にpythonスクリプトを起動する

目的

起動時にPythonスクリプトを実行させる

Systemdの設定

cat /etc/systemd/system/sample.service

[Unit]
Description=Run Python Script

[Service]
ExecStart=/usr/bin/python3 /home/pi/Desktop/Python/sample.py
WorkingDirectory=/home/pi/Desktop/Python/
User=pi
Group=pi

[Install]
WantedBy=multi-user.target

WorkingDirectoryを設定しておけば、そのフォルダが実行時のカレントディレクトリとなる

サービスの自動起動登録

sudo systemctl enable sample.service

サービスの起動

sudo systemctl restart stocknews.service

もしも下記のエラーが出たら、systemctl daemon-reloadとする

Warning: The unit file, source configuration file or drop-ins of sample.service changed on disk. Run 'systemctl daemon-reload' to reload units

期待通りの働きをしないとき

ログが出るので確認をする

systemctl status sample.service

Raspberry PIでSeleniumを使ってスクレイピング

目的

Raspberry Pi上でSeleniumでのスクレイピングをする環境準備まで

準備

chromium-chromedriverのインストール

https://launchpad.net/ubuntu/trusty/+package/chromium-chromedriver

chromium-chromedriver 65.0.3325.181-0ubuntu0.14.04.1 in armhf (Updates)を選択し、ダウンロード

インストールにはapt-get installを使う

$sudo apt-get install chromium-chromedriver_65.0.3325.181-0ubuntu0.14.04.1_armhf.deb

Seleniumのインストール

素直に apt-getで

$sudo apt-get install selenium

これで完了です

おまけ

現在のDriverとchromiumのバージョンを調べる

$/usr/lib/chromium-browser/chromedriver -v
ChromeDriver 2.35 (0)
$chromium-browser --version
 --disable-quic --enable-tcp-fast-open --ppapi-flash-path=/usr/lib/chromium-browser/libpepflashplayer.so --ppapi-flash-args=enable_stagevideo_auto=0 --ppapi-flash-version=
Chromium 78.0.3904.108 Built on Raspbian , running on Raspbian 10

Headlessだとダウンロードされない

現状のChromeDriverのバージョンではセキュリティの関係でダウンロードができないようだ

Downloading with chrome headless and selenium

コードに下記に示した例を追加したらダウンロードが行える

def enable_download_in_headless_chrome(driver, download_dir):
    # add missing support for chrome "send_command"  to selenium webdriver
    driver.command_executor._commands["send_command"] = ("POST", '/session/$sessionId/chromium/send_command')

    params = {'cmd': 'Page.setDownloadBehavior', 'params': {'behavior': 'allow', 'downloadPath': download_dir}}
    command_result = driver.execute("send_command", params)


browser = webdriver.Chrome(driverpos, chrome_options=options, service_log_path='/dev/null')
enable_download_in_headless_chrome(browser, os.getcwd() + "/data")

Raspberry piからgithubへssh

目的

Raspberry pi 4の8G版を購入した

コードをRaspberry pi上で書こうとは思わないので、メインPCで書いてgithub経由でRPIに届けたい


SSHを有効にする

sudo raspi-config

5 Interfacing Options  Configure connections to peripherals

P2 SSH         Enable/Disable remote command line access to your Pi using SSH

と進んでYesを押すと有効となる

SSHのキーを作成する

ssh-keygen

Githubに登録

下記で出てきたものをgithubの設定のSSH keys New SSH keyに登録

cat id_rsa.pub

Raspberry piのSSH configに登録

生成した秘密鍵(id_rsa)をsshフォルダ(.ssh/github/)に移す

設定ファイルに記載する

pi@raspberrypi:~/Desktop $ cat ~/.ssh/config 
Host github.com
    HostName github.com
    IdentityFile ~/.ssh/github/id_rsa
    User git

確認

ssh github.comと打ち込み問題なくSSH接続することを確認


PTY allocation request failed on channel 0
Hi ****! You've successfully authenticated, but GitHub does not provide shell access.
Connection to github.com closed.

キーの追加

githubに接続する際に暗号化キーのパスワードを毎回聞かれる

ssh-addでキーを登録する

ssh-add ~/.ssh/id_rsa
ssh-add -l

エラーが出た場合

下記のエラーが出ることがあるので下記を打つことで解決される

Could not open a connection to your authentication agent

$ ssh-agent
$ eval `ssh-agent`

2020年6月10日水曜日

久しぶりの投稿

前回の投稿は2019年6月のようだ。

一年間、全く投稿をしていなかった。

維持療法の方は現状問題なくこなしている。

現在は、6回目の維持療法中で絶賛頭痛がしている。

この頭痛もあと2回で解放されると考えると、考え深いものがある。。。
と思うはずもなく、早く解放されたい。

仕事の方はCovit-19の影響でまだ在宅ワークである。

これで3月から在宅ワークを続けているので、もう3ヶ月目後半である。

新型コロナに感染することもなく、このまま元気にやっていきたいと思います。