1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Wiki Bot in Python 202503 (ページ変更機能とページ挿入機能)

Last updated at Posted at 2025-06-30

はじめに

「Wiki IoT/Bot Computing」 というのを開発中です。これは一種の並列計算機構で、「Wiki Bot」と名付けた、IoTのエッジ端末がこの計算機構の演算装置群であり、インターネット上に分散配置されたWikiのページをこの計算機構の記憶装置として使おうとするものです。

従来、Wiki Bot はJavaを中心にして作っていましたが、従来のWiki Botの機能を、今回の、ページ変更機能とページ挿入機能の追加により、ほぼ、Python に移し替えました。

なお、前回以下の記事で、Java版にはなかった、画像などのファイルをuploadする機能を加えています。

これにより、以下のように、毎時ごとにその時間のデータを、その時間のページ(合計24ページ)に書き込むとともに、毎日、その日のデータを、その日のページ(合計31ページ)に書き込むシステムを実現することができます。また、このとき、毎時ごとに行う処理のスクリプトを1つのページにまとめて書いておき、それを毎時ごとのページに挿入することができます。同じように、毎日行う処理のスクリプトを1つのページにまとめて書いておき、それを日々のページに挿入することができます。

wiki_iot_bot_setpage_include_01.png

Wiki Bot

エッジ端末がWikiのページの記述で遠隔操作されるBot となります。これをWiki Botと呼んでいます。

wiki-bot-20250102-01.png

ページ変更

IoTシステムでは、エッジシステムにおいて獲得したデータを、毎時ごと、または毎日ごと、に保存して、あとから参照したい場合があります。今回の機能追加により Wiki IoT/Bot Computer で、あらかじめ、毎時ごとに、または毎日ごとに、データとスクリプトを格納するWikiページ(これをobject ページと呼ぶことにします)を作っておき、Botが、時間が変わるたびに、または日が変わるたびに、そのBotが読み書きするobject ページを変更することができます。これは、Object ページのスクリプトに、

 command: set pageName="<次に実行されるページ>"

を書き加えることにより、実現することができます。<次に実行されるページ> には

<hour>

または

<day>

を含むことができ、<hour>には、そのときの時間の時、<day>にはその日の日が置き換わります。例えば以下のコマンド

command: set pageName="ex01_h<hour>"

がスクリプトに書かれていて、これが18時に実行されると、
実行されたときの時間が<hour>と置き換わり、従って、

"ex01_h<hour>"

は、

"ex01_h18"

になり、Wiki Botが次にこのページを読むとき、前と同じWiki サーバの、
ex01_h18 のページを読むことになります。

なお、このとき、あらかじめ
"ex01_h00", "ex01_h01", ..., "ex01_h23" の24枚のページすべてに、実行すべきスクリプトを書いておく必要があります。

例えば、ex01_h06 は、以下のようになります。

object_page http://192.168.1.37/pukiwiki/?ex01_h06 or http://192.168.1.37/pukiwiki/?ex01_h06
device yama_bot_0000_0000_0000_0001 or yama_bot_0000_0000_0000_0001 start after no write for 10 min.
command: set read_interval=60000
command: set exec_interval=0
command: set report_length=400
command: py test
py: import time
py: v=self.ex_pico("ex self.sensing.get_motion()")
py: line="device=motion, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_lx()")
py: line="device=lx, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_co2()")
py: if v.startswith("Traceback"):
py:     v=0
py: line="device=co2, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_pressure()")
py: line="device=pressure, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_humidity()")
py: line="device=humidity, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_temperature()")
py: line="device=temp, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: self.send_result()
command: end test
command: run test
command: set pageName="ex01_h<hour>"
result:
device=temp, Date=2025-02-07 00:14:58.634112, v=13.69C
device=motion, Date=2025-02-06 23:53:43.508638, v=0
device=lx, Date=2025-02-06 23:53:45.542352, v=0
device=pressure, Date=2025-02-06 23:53:47.585749, v=1016.75hPa
device=humidity, Date=2025-02-06 23:53:49.641112, v=47.11%
device=temp, Date=2025-02-06 23:53:51.726429, v=16.34C
device=motion, Date=2025-02-06 23:54:43.955486, v=0
...
current_device="yama_bot_0000_0000_0000_0001". Date=2025-02-07 00:00:55.012417

また、ex01_h07 は以下のようになります。

object_page http://192.168.1.37/pukiwiki/?ex01_h07 or http://192.168.1.37/pukiwiki/?ex01_h07
device yama_bot_0000_0000_0000_0001 or yama_bot_0000_0000_0000_0001 start after no write for 10 min.
command: set read_interval=60000
command: set exec_interval=0
command: set report_length=400
command: py test
py: import time
py: v=self.ex_pico("ex self.sensing.get_motion()")
py: line="device=motion, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_lx()")
py: line="device=lx, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_co2()")
py: if v.startswith("Traceback"):
py:     v=0
py: line="device=co2, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_pressure()")
py: line="device=pressure, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_humidity()")
py: line="device=humidity, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_temperature()")
py: line="device=temp, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: self.send_result()
command: end test
command: run test
command: set pageName="ex01_h<hour>"
result:
device=temp, Date=2025-02-07 00:14:58.634112, v=13.69C
device=motion, Date=2025-02-06 23:53:43.508638, v=0
device=lx, Date=2025-02-06 23:53:45.542352, v=0
device=pressure, Date=2025-02-06 23:53:47.585749, v=1016.75hPa
device=humidity, Date=2025-02-06 23:53:49.641112, v=47.11%
device=temp, Date=2025-02-06 23:53:51.726429, v=16.34C
device=motion, Date=2025-02-06 23:54:43.955486, v=0
...
current_device="yama_bot_0000_0000_0000_0001". Date=2025-02-07 00:00:55.012417

ページ挿入

上の例で、それぞれの時間のobjectページで、同じ処理を行うスクリプトを、それぞれのobjectページに書くのは面倒です。そこで、今回の機能拡張により、別のページに処理だけを書いておき、それをobjectページに挿入することも可能になっています。この、挿入されるスクリプトを記述したページを class ページと呼ぶことにします。

例えば、以下の class ページ

command: set read_interval=60000
command: set exec_interval=0
command: set report_length=360
command: py test
py: import time
py: v=self.ex_pico("ex self.sensing.get_motion()")
py: line="device=motion, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_lx()")
py: line="device=lx, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_co2()")
py: if v.startswith("Traceback"):
py:     v=0
py: line="device=co2, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_pressure()")
py: line="device=pressure, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_humidity()")
py: line="device=humidity, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: v=self.ex_pico("ex self.sensing.get_temperature()")
py: line="device=temp, Date="+self.Pico_Time.get_now()+", v="+str(v)
py: self.write_line(line)
py: self.send_result()
command: end test
command: run test
command: set pageName="ex01_h<hour>"

を、http://192.168.1.37/pukiwiki/?class_ex01_h に書いておき、objectページ、ex01_h06 とex01_h07 の、それぞれのページのスクリプトの部分を、以下のinclude 文

include http://192.168.1.37/pukiwiki/?class_ex01_h or http://192.168.1.37/pukiwiki/?class_ex01_h

に書き換えることで、いままでそれぞれのページに同じスクリプトを書いていたものを一つのclass ページにまとめて書くことができます。
ここで、object ページ ex01_h06 は以下のようになります。

object_page http://192.168.1.37/pukiwiki/?ex01_h06 or http://192.168.1.37/pukiwiki/?ex01_h06
device yama_bot_0000_0000_0000_0001 or yama_bot_0000_0000_0000_0001 start after no write for 10 min.
include http://192.168.1.37/pukiwiki/?class_ex01_h or http://192.168.1.37/pukiwiki/?class_ex01_h
result:
device=motion, Date=2025-02-17 06:01:44.025406, v=0
device=lx, Date=2025-02-17 06:01:46.058132, v=272
device=co2, Date=2025-02-17 06:01:48.090722, v=40191
...

object ページ ex01_h07 は以下のようになります。

object_page http://192.168.1.37/pukiwiki/?ex01_h07 or http://192.168.1.37/pukiwiki/?ex01_h07
device yama_bot_0000_0000_0000_0001 or yama_bot_0000_0000_0000_0001 start after no write for 10 min.
include http://192.168.1.37/pukiwiki/?class_ex01_h or http://192.168.1.37/pukiwiki/?class_ex01_h
result:
device=motion, Date=2025-02-17 07:01:47.333278, v=0
device=lx, Date=2025-02-17 07:01:49.363504, v=256
device=co2, Date=2025-02-17 07:01:51.403447, v=35583

ページ変更機能とページ挿入機能を追加したWiki Bot のpython プログラム

以下のリンク先のpython のプログラム wiki_bot_07.py が、ページ変更機能とページ挿入機能を加えた Wiki Bot のプログラムです。これを、Raspberry Pi で動かします。

上のプログラムをダウンロードして、 Raspberry Pi の /home/pi/pythonの直下に置きます。

python3 の仮想環境の構築と使用するパッケージの install

このプログラムは requests_toolbelt パッケージの、MultipartEncoder クラスやpyserialパッケージを利用しているのですが、最近のRaspberry Pi OSでは、pip3コマンドが使えないので、

$ sudo apt install virtualenv python3-virtualenv -y
$ virtualenv -p /usr/bin/python3 testpip

を実行して、python3の仮想環境が使えるようにします。

$ source testpip/bin/activate

を実行して、仮想環境に入ります。

pip3 install requests_toolbelt
pip3 install pyserial

を実行して、 requests_toolbelt と pyserial を install しておきます。

参考:

毎日自動起動するように設定

Wiki bot のプログラムは文字列処理を行いますが、python は文字列処理を行うとゴミが溜まっていき、そのうちメモリが足りなくなることがあります。この問題を緩和するため、以下の設定を行って、毎日、定時に再起動し、自動的にwiki bot が起動されるようにします。

systemd の設定

/etc/systemd/system 直下に、(テキスト)ファイル reboot.service を作成し、エディタで中身を以下のようにします。

[Unit]
Description = Reboot
RefuseManualStart = true
RefuseManualStop = true
 
[Service]
ExecStart = /sbin/reboot

同じく、/etc/systemd/system 直下に、(テキスト)ファイル reboot.timer を作成し、エディタで中身を以下のようにします。このようにした場合は毎朝午前 10:05分に再起動が行われます。

[Unit]
Description = Weekly Reboot Timer
 
[Timer]
OnCalendar=*-*-* 10:05:00
 
[Install]
WantedBy = timers.target

以下を実行して、reboot.timer を有効にし、毎時再起動するタイマーを開始します。

sudo systemctl enable reboot.timer
sudo systemctl start reboot.timer

同じく、/etc/systemd/system 直下に、再起動後に、wiki bot を自動起動するため、(テキスト)ファイル wiki_bot.service を作成し、エディタで中身を以下のようにします。

[Unit]
Description=wiki_bot
After=network.target
 
[Service]
User=pi
Type=simple
WorkingDirectory=/home/pi/python
ExecStart=/home/pi/python/start_wiki_bot.sh
 
[Install]
WantedBy=multi-user.target

以下を実行して、実行を有効にします。

sudo systemctl enable wiki_bot.service

reboot後に自動起動されるbash スクリプト, start_wiki_bot.sh を作成

/home/pi/python ディレクトリ直下に、systemd でreboot後に自動起動される以下のスクリプト、start_wiki_bot.sh を作ります。

#!/usr/bin/bash
sleep 120
xhost +
export DISPLAY=:0.0
cd /home/pi/python
source testpip/bin/activate
python3 wiki_bot_07.py -s

応用例: 情報処理学会IOT研究会
山之上卓, "IoTのためのWiki Bot in Python", 2025-IOT-068

場所を知ることができる Wiki Bot

Wiki Botを動かすRaspberry Pi にGPSデバイスをシリアルインターフェースで接続することで、Wiki Botの場所を知ることができるようになります。これを実現するための Wiki Bot を以下のリンク先に置いています。

また、このWiki Botを使って、場所によって表示を変える、着る電光掲示板を作成しました。

https://protopedia.net/prototype/6774
参考:

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?