streamlitを試す

streamlitはpythonコードだけで、Webブラウザーからアクセスできるアプリを公開できる優れものです。磁気センサーのオフセット可視化で試してみました。jupyterのコードへ多少手を加えるだけでOK。デバッグはjupyterで動作確認を行い、完成したら必要に応じてstreamlit化するのが良さそう。streamlitはコマンドラインから次のように実行し、表示されたurlをブラウザーでアクセスします。

$ treamlit run mag-offset.py

  You can now view your Streamlit app in your browser.

  Network URL: http://192.168.68.122:8501
  External URL: http://203.165.226.42:8501

ブラウザーでアクセスした様子

mag-offset.py

import matplotlib

import os
import pandas as pd
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import math
import numpy as np

import streamlit as st
st.title('Magnetic compass offset plot')
### データの読み込み
df = pd.read_csv('BMX055/data4.csv')
#print(df)
a_x=np.average(df['Mag_x'])
a_y=np.average(df['Mag_y'])
a_z=np.average(df['Mag_z'])
#print(round(a_x,2),round(a_y,2),round(a_z,2))
# ここからグラフ描画

# グラフの入れ物を用意する。
fig = plt.figure()
#ax = Axes3D(fig)     <--- warningとなるので、次の行に書き換え
ax = fig.add_subplot(111, projection='3d')
# 軸のラベルを設定する。
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
st.table(pd.DataFrame({
    'Center X': [a_x],
    'Center Y': [a_y],
    'Center Z': [a_z]
}))
# グラフを表示する。
ax.scatter3D(df['Mag_x'],df['Mag_y'],df['Mag_z'],color="blue")
ax.scatter3D(a_x,a_y,a_z,color="red")
#plt.show()       <--- plt.show()を st.write(fig)へ置き換える。
st.write(fig)

磁気コンパス補正データの可視化

9軸センサーBMX055の磁気コンパスのデータ(x,y,z)を取得して可視化してみました。センサーはi2cでRaspberry Piに接続しています。

jupyter notebookで3Dプロットした様子

赤の点は、x,y,zのそれぞれの平均値を示す。

BMX055からデータを取得

 -*- coding: utf-8 -*-
#
# https://taku-info.com/bmx055howtouse-mag/
#

from smbus import SMBus
import time
import math
import datetime
import csv

# I2C
ACCL_ADDR = 0x19
ACCL_R_ADDR = 0x02
GYRO_ADDR = 0x69
GYRO_R_ADDR = 0x02
MAG_ADDR = 0x13
MAG_R_ADDR = 0x42

i2c = SMBus(1)

def bmx_setup():
    # acc_data_setup : 加速度の値をセットアップ
    i2c.write_byte_data(ACCL_ADDR, 0x0F, 0x03)
    i2c.write_byte_data(ACCL_ADDR, 0x10, 0x08)
    i2c.write_byte_data(ACCL_ADDR, 0x11, 0x00)
    time.sleep(0.5)

    # gyr_data_setup : ジャイロ値をセットアップ
    i2c.write_byte_data(GYRO_ADDR, 0x0F, 0x04)
    i2c.write_byte_data(GYRO_ADDR, 0x10, 0x07)
    i2c.write_byte_data(GYRO_ADDR, 0x11, 0x00)
    time.sleep(0.5)

    # mag_data_setup : 地磁気値をセットアップ
    data = i2c.read_byte_data(MAG_ADDR, 0x4B)
    if(data == 0):
        i2c.write_byte_data(MAG_ADDR, 0x4B, 0x83)
        time.sleep(0.5)
    i2c.write_byte_data(MAG_ADDR, 0x4B, 0x01)
    i2c.write_byte_data(MAG_ADDR, 0x4C, 0x00)
    i2c.write_byte_data(MAG_ADDR, 0x4E, 0x84)
    i2c.write_byte_data(MAG_ADDR, 0x51, 0x04)
    i2c.write_byte_data(MAG_ADDR, 0x52, 0x16)
    time.sleep(0.5)

def acc_value():
    data = [0, 0, 0, 0, 0, 0]
    acc_data = [0.0, 0.0, 0.0]

    try:
        for i in range(6):
            data[i] = i2c.read_byte_data(ACCL_ADDR, ACCL_R_ADDR + i)

        for i in range(3):
            acc_data[i] = ((data[2*i + 1] * 256) + int(data[2*i] & 0xF0)) / 16
            if acc_data[i] > 2047:
                acc_data[i] -= 4096
            acc_data[i] *= 0.0098

    except IOError as e:
        print("I/O error({0}): {1}".format(e.errno, e.strerror))

    return acc_data

def gyro_value():
    data = [0, 0, 0, 0, 0, 0]
    gyro_data = [0.0, 0.0, 0.0]

    try:
        for i in range(6):
            data[i] = i2c.read_byte_data(GYRO_ADDR, GYRO_R_ADDR + i)

        for i in range(3):
            gyro_data[i] = (data[2*i + 1] * 256) + data[2*i]
            if gyro_data[i] > 32767:
                gyro_data[i] -= 65536
            gyro_data[i] *= 0.0038

    except IOError as e:
        print("I/O error({0}): {1}".format(e.errno, e.strerror))

    return gyro_data

def mag_value():
    data = [0, 0, 0, 0, 0, 0, 0, 0]
    mag_data = [0.0, 0.0, 0.0]

    try:
        for i in range(8):
            data[i] = i2c.read_byte_data(MAG_ADDR, MAG_R_ADDR + i)

        for i in range(3):
            if i != 2:
                mag_data[i] = ((data[2*i + 1] * 256) + (data[2*i] & 0xF8)) / 8
                if mag_data[i] > 4095:
                    mag_data[i] -= 8192
            else:
                mag_data[i] = ((data[2*i + 1] * 256) + (data[2*i] & 0xFE)) / 2
                if mag_data[i] > 16383:
                    mag_data[i] -= 32768

    except IOError as e:
        print("I/O error({0}): {1}".format(e.errno, e.strerror))

    return mag_data

if __name__ == "__main__":

    bmx_setup()
    time.sleep(0.1)
    now_time = datetime.datetime.now()
    filename = 'test_' + now_time.strftime('%Y%m%d_%H%M%S') + '.csv'
    # ファイル,1行目(カラム)の作成
    with open(filename, 'a') as f:
        writer = csv.writer(f)
        writer.writerow(['Mag_x', 'Mag_y', 'Mag_z'])
    while True:
        #acc = acc_value()
        #gyro= gyro_value()
        mag = mag_value()
        theta = math.atan2(mag[1],mag[0]) * 180.0 / 3.141592
        if ( theta < 0 ):
            theta = theta + 360.0
        '''
        theta = 360.0 - theta
        print("Accl -> x:{}, y:{}, z: {}".format(acc[0], acc[1], acc[2]))
        print("Gyro -> x:{}, y:{}, z: {}".format(gyro[0], gyro[1], gyro[2]))
        print("Mag -> x:{}, y:{}, z: {}".format(mag[0], mag[1], mag[2]))
        '''
        print(theta)
        time.sleep(0.02)
        with open(filename, 'a', newline="") as f:
            writer = csv.writer(f)
            writer.writerow([mag[0], mag[1], mag[2]])

取得したデータをjupyter notebookで可視化

%matplotlib nbagg

import os
import pandas as pd
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import math
import numpy as np

### データの読み込み
df = pd.read_csv('BMX055/data4.csv')
print(df)
a_x=np.average(df['Mag_x'])
a_y=np.average(df['Mag_y'])
a_z=np.average(df['Mag_z'])
print(round(a_x,2),round(a_y,2),round(a_z,2))
# ここからグラフ描画
 
# グラフの入れ物を用意する。
fig = plt.figure()
#ax = Axes3D(fig)    <--- warning対策
ax = fig.add_subplot(111, projection='3d') 
# 軸のラベルを設定する。
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')

# グラフを表示する。
ax.scatter3D(df['Mag_x'],df['Mag_y'],df['Mag_z'],color="blue")
ax.scatter3D(a_x,a_y,a_z,color="red")
plt.show()

RPA (Robotic Process Automation)

Webスクレイピング超入門】2時間で基礎を完全マスター!PythonによるWebスクレイピング入門 連結版
https://www.youtube.com/watch?v=VRFfAeW30qE

【初学者必見】Pythonで実データの需要予測を実装したい人がはじめに見る動画
https://www.youtube.com/watch?v=uKq_dgEUVfA&list=RDCMUC0xRMqPOyRNPTaL6BxhbCnQ&index=11

Python×自動化】PyAutoGUIを用いてPC操作の自動化方法を40分でわかりやすく解説!
https://www.youtube.com/watch?v=zmrbS98KXyo&list=RDCMUC0xRMqPOyRNPTaL6BxhbCnQ&index=10

今話題のPythonライブラリStreamlitを用いて、顔検出アプリの作成から公開までの流れをわかりやすく解説
https://www.youtube.com/watch?v=zpBjbK6jic0

rock pi4へraspiの手順でKubernetesをインストールしてみる

インストール手順の参照元:ラズパイでKubernetesクラスタを構築する

インストール先の環境

  • rock pi4 4GB RAM
  • Linux rock 4.4.154-110-rockchip-gcef30e88a9f5 #1 SMP Mon Jun 22 07:37:10 UTC 2020 aarch64 aarch64 aarch64 GNU/Linux
  • 18.04.5 LTS (Bionic Beaver)

次の手順でkubelet kubeadm kubectlをインストール

$ sudo -s
# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt    -key add -
OK
# cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
> deb https://apt.kubernetes.io/ kubernetes-xenial main
> EOF
# apt-get update
# apt-get install -y kubelet kubeadm kubectl
#  kubeadm version -o yaml
clientVersion:
  buildDate: "2021-06-16T12:57:56Z"
  compiler: gc
  gitCommit: 092fbfbf53427de67cac1e9fa54aaa09a28371d7
  gitTreeState: clean
  gitVersion: v1.21.2
  goVersion: go1.16.5
  major: "1"
  minor: "21"
  platform: linux/arm64
#  cat /proc/sys/net/bridge/bridge-nf-call-iptables
1
$ kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.2", GitC    ommit:"092fbfbf53427de67cac1e9fa54aaa09a28371d7", GitTreeState:"clean", BuildDat    e:"2021-06-16T12:57:56Z", GoVersion:"go1.16.5", Compiler:"gc", Platform:"linux/a    rm64"}
# swapoff -a
# kubeadm init --pod-network-cidr=10.244.0.0/16
[init] Using Kubernetes version: v1.21.2
{中略}
Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.68.111:6443 --token iuzu6k.j2arujghto188qq1 \
        --discovery-token-ca-cert-hash sha256:bed560334a382d997a48491083e569dbaaac8b1a6d8804c9b917b8596d36b255
$ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$ sudo chown $(id -u):$(id -g) $HOME/.kube/config

$  kubectl get node
The connection to the server 127.0.0.1:16443 was refused - did you specify the right host or port?


helmでインストールしたwordpressのphpスクリプトの場所を特定

/var/snap/microk8s/common/ 以下に置かれているようだ。

$ sudo find / -name wp-login.php 2>/dev/null
/var/snap/microk8s/common/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/179/fs/opt/bitnami/wordpress/wp-login.php
/var/snap/microk8s/common/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/170/fs/opt/bitnami/wordpress/wp-login.php
/var/snap/microk8s/common/run/containerd/io.containerd.runtime.v2.task/k8s.io/6f704f341ec11315ce29fc36f1a4d4c4e7c88b55d460fa0249c7e268b20be2ed/rootfs/opt/bitnami/wordpress/wp-login.php

k8sのサービスへ別マシンから接続

k8sのサービスへ別マシンから接続するには、ポートフォワーディングを設定します。例えばk8sのdashbordをアクセスする場合には、設定に必要な情報を次の手順で取得

$ microk8s kubectl get all --all-namespaces | grep dashboard | grep TCP
kube-system          service/kubernetes-dashboard        ClusterIP      10.152.183.19    <none>        443/TCP

必要な部分は太字の箇所

kube-system service/kubernetes-dashboard ClusterIP 10.152.183.19 443/TCP

外部からアクセスする場合のポートを10443とした場合のportforward設定の例;10443が既に使われていた場合はエラーとなるので、別のポートを指定する。

microk8s.kubectl port-forward --address 0.0.0.0 -n kube-system service/kubernetes-dashboard 10443:443 &

wordpressをアクセスする場合;外部マシンからhttp://xxx.xxx.xxx.xxx:20443/をアクセス

(xxx.xxx.xxx.xxxはk8sマシンのIPアドレス)

microk8s kubectl get all --all-namespaces | grep wordpress | grep TCP
helm-test            service/test-wordpress              LoadBalancer   10.152.183.226   <pending>     80:30034/TCP,443:30311/TC
microk8s.kubectl port-forward --address 0.0.0.0 -n helm-test service/test-wordpress 20443:443 &
Forwarding from 0.0.0.0:20443 -> 8443