Node-RED の Grove Base HAT ノードが動かなくなっていたので、ひとまず手元で動くように修正したメモ
Node-RED の Grove Base HAT ノードが動かなくなっていたので、ひとまず手元で動くように修正したメモです。
この記事は Seeed UG Advent Calendar 2022 の 16 日目の記事です。
背景
私が作った node-red-contrib-grove-base-hat ノードが、
- 2022/8 ごろのバージョンの Raspberry Pi OS
- 2022/11 ごろのバージョンの grove.py
の組み合わせで動かなくなっていたことに、最近イチからセットアップしたら気づきました。
以前の私のリリースから長い時間が経過しているので、どれがクリティカルな原因か分からないのですが、以前のバージョンはひとまず固定して、
Release v0.0.10 · 1ft-seabass/node-red-contrib-grove-base-hat
手元で動くようにして方針が見えたら次のバージョンで修正してみます。
以前のコード
まず、 Node-RED ノードの仕組み。grove-led を例に。
var path = require('path');
module.exports = function(RED) {
function GroveLedNode(config) {
// console.log(path.join(__dirname , 'grove-led.py'));
// console.log("__dirname " , __dirname );
RED.nodes.createNode(this,config);
this.port_number = config.port_number;
this.port_name = "D" + this.port_number;
this.status({fill:"blue",shape:"dot",text:this.port_name});
var node = this;
node.on('input', function(msg) {
// msg.payload = msg.payload.toLowerCase();
const gpio_pin = this.port_number;
const exec = require('child_process').exec;
this.status({fill:"yellow",shape:"ring",text:this.port_name + " connecting"});
exec('python -u ' + path.join( __dirname , 'grove-led.py') + ' ' + gpio_pin + ' ' + msg.payload, (err, stdout, stderr) => {
if (err) { console.log(err); }
// console.log(stdout);
this.status({fill:"green",shape:"dot",text:this.port_name + " connected"});
});
// node.send(msg);
});
}
RED.nodes.registerType("grove-led",GroveLedNode);
}
いたってシンプル。ここは問題なく動いてました。grove.py を参考にして作った後述する grove-led.py という python コードを実行するものです。
以下は grove-led.py の v0.0.10 での中身です。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# The MIT License (MIT)
#
# Grove Base Hat for the Raspberry Pi, used to connect grove sensors.
# Copyright (C) 2018 Seeed Technology Co.,Ltd.
'''
This is the code for
- `Grove - Red LED <https://www.seeedstudio.com/Grove-Red-LED-p-1142.html>`_
- `Grove - Green LED <https://www.seeedstudio.com/Grove-Green-LED-p-1144.html>`_
- `Grove - Purple LED <https://www.seeedstudio.com/Grove-Purple-LED-3m-p-1143.html>`_
- `Grove - White LED <https://www.seeedstudio.com/Grove-White-LED-p-1140.html>`_
Examples:
.. code-block:: python
import time
from grove.grove_led import GroveLed
# connect to pin 5(slot D5)
PIN = 5
led = GroveLed(PIN)
while True:
led.on()
time.sleep(1)
led.off()
time.sleep(1)
'''
import time
import os # add for node-red
import json # add for node-red
import sys #add for node-red
from grove.gpio import GPIO
__all__ = ['GroveLed', 'GPIO']
class GroveLed(GPIO):
'''
Class for Grove - XXXX Led
Args:
pin(int): number of digital pin the led connected.
'''
def __init__(self, pin):
super(GroveLed, self).__init__(pin, GPIO.OUT)
def on(self):
'''
light on the led
'''
self.write(1)
def off(self):
'''
light off the led
'''
self.write(0)
Grove = GroveLed
def main():
# print disable
sys.stdout = open(os.devnull, 'w')
from grove.helper import SlotHelper
sh = SlotHelper(SlotHelper.GPIO)
pin = sh.argv2pin()
argvs = sys.argv #add for node-red
led = GroveLed(pin)
# print enable
sys.stdout = sys.__stdout__
control = argvs[2]
# print (control == "1")
if (control == "1"):
led.on()
if (control == "0"):
led.off()
if __name__ == '__main__':
main()
Node-RED から出された指示を実行してるんですが、2 年くらい前の grove.py の LED を動かすソースコードを、そのままコピーで持って来て使ってたんです。
これが、どうも最新の grove.py がある状態だと、うまく動かない様子。
アプローチ変更したら成功
grove.py を良く読んでいると、どうも、grove.py 自体はライブラリとして使って、自分の書いたコードで呼び出す使い方が良いようです。
ということで、grove-led.py の内容を以下のように変えてみました。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
import os # add for node-red
import json # add for node-red
import sys #add for node-red
from grove.grove_led import GroveLed
def main():
# print disable
# sys.stdout = open(os.devnull, 'w')
argvs = sys.argv #add for node-red
pin = int(argvs[1])
led = GroveLed(pin)
# print enable
# sys.stdout = sys.__stdout__
control = argvs[2]
# print (control == "1")
if (control == "1"):
led.on()
if (control == "0"):
led.off()
if __name__ == '__main__':
main()
こうしてみたところ、Node-RED からこの python への指示を出す部分は一切変更せずに、LED が光るのが復活しました!
他でも同じように修正してみたらうまくいった
超音波距離センサーとボタンについても、同じように grove.py 自体はライブラリとして使って、自分の書いたコードで呼び出す方式で試してみたところ、うまく動きました。
ライブラリとしての使い方を、ちゃんとドキュメント読み込まないといけないのはありましたが、今後も grove.py が更新されても、ライブラリとして呼ぶ形で動作を保つと思うので、今回のやりかたのほうが、ちゃんと動く強度がありそうです。
たしかに、前回のやり方は、今思うと、そのときのライブラリの仕組みをコピーして持ってくるので、ライブラリ自体が更新されると不都合が起きそうな建付けですね。勉強になりました。
近々、もう少し念入りに動作確認をしつつ Grove Base HAT ノードを修正してアップデートしてみます!