Switchbot温度計とラズパイで快適IoTライフ
Switchbot温度計をフル活用するためラズパイで測定値を取得することを試みます。意外と情報が少なく苦戦したため記録しておきます。
Switchbot温湿度計
ボタンプッシュロボットでおなじみのWonderlabs IncによるIoT温湿度計です。電源も電池駆動なので使い勝手が良く、スマートハウス利用には無限の可能性を感じます。
同社が発売中のHubを利用すればAlexaやその他の家電と連携させることも可能です。私はHubが必要と知らずに1年前に買ってショックを受けました…。単体でもBluetoothでスマホアプリと連携可能ですが、アプリの出来があんまり良くないです。私は
うまくいかなかったコード
検索すると一番にヒットするこちらの記事の方法は、私の環境では上手く行きませんでした・・・。少しコードをいじったりしてみたのですが、小手先の修正では動かず・・・。原因が分かったら報告します。
qiita.com
実行結果
$ sudo python3 switchbot_meter.py ^CTraceback (most recent call last): File "switchbot_meter.py", line 48, in <module> scanner.scan( 0 ) File "/usr/local/lib/python3.5/dist-packages/bluepy/btle.py", line 853, in scan self.process(timeout) File "/usr/local/lib/python3.5/dist-packages/bluepy/btle.py", line 821, in process resp = self._waitResp(['scan', 'stat'], remain) File "/usr/local/lib/python3.5/dist-packages/bluepy/btle.py", line 347, in _waitResp rv = self._helper.stdout.readline() KeyboardInterrupt
実行すると固まってしまいますので、キーボードインタラプトしてます。スキャンのタイムアウトが無効になっているため、いつまでもスキャンを続けてるみたいです。デバイスはラズパイからは見えているのに、なんでスキャンが終わらないんだろう。
結局ギブアップして、別の方法を探しました。
とりあえず動いたコード
諦め掛けていたのですが、スイッチボット開発元のWonderLabsが公開しているpython-hostというライブラリの中にそれっぽいのを見つけました。
GitHub - OpenWonderLabs/python-host: The python code running on Raspberry Pi or other Linux based boards to control SwitchBot.
インストール方法はリンク先のgithubに詳しく書いてあります。このライブラリは、ボタンタイプのスイッチボットでも使えるやつなので、私はすでにインストールしてました。
インストールが済んだら早速ディレクトリに移動し、 switchbot_meter.pyを実行してみます。MACアドレスを入れる所がないのですが、とりあえず実行。
~$ cd python-host ~/python-host $ sudo python switchbot_meter.py
結果
Usage: "sudo python switchbot.py [mac_addr cmd]" or "sudo python switchbot.py" Start scanning... 22 16b Service Data 000d5410d6089a40 16 scan timeout (0, [u'XX:XX:XX:XX:XX:XX', "Humiture:26.8'C 64%"]) Input the device number to control:
おお、温度と湿度が取得できました。私のスイッチボットの表示温度、MACアドレスの値が表示されてます!ちなみにpython3のコード(switchbot_meter_py3.py)を実行する際には、pip3でpexpectのインストールが必要でした(No module named 'pexpect’ というエラーが出る)。
「Input the device number to control:」の表示でデバイスナンバーの入力を求められましたので、0を入れると、処理が先に進みました。
Input the device number to control:0 Preparing to connect. Connection successful. Traceback (most recent call last): File "switchbot_meter.py", line 232, in <module> main() File "switchbot_meter.py", line 222, in main trigger_device(bluetooth_adr) File "switchbot_meter.py", line 167, in trigger_device tempFra = int(data[3], 16) / 10.0 IndexError: string index out of range
コネクション成功、その後よくわからないエラーで止まってしまいました。デバイスナンバーに関してはおそらく複数台のスイッチボットを一括で管理することを想定しているのではないでしょうか。今回は1台ですので、0以上の数字はレンジアウトとなります。
とりあえず温度と湿度をラズパイで取得する、という目的はこれで達せられそうです。返り値がシンプルになるようにコードを書き換えます。
とりあえず動いたコードを修正
やっつけではありますがシンプルに温度と湿度とアドレスだけ返してくれるように修正しました。ライブラリが揃っていればpython2でも3でも動くと思います。
#!/usr/bin/env python3 import pexpect import sys from bluepy.btle import Scanner, DefaultDelegate import binascii class ScanDelegate(DefaultDelegate): def __init__(self): DefaultDelegate.__init__(self) class DevScanner(DefaultDelegate): def __init__( self ): DefaultDelegate.__init__(self) #print("Scanner inited") def dongle_start(self): self.con = pexpect.spawn('hciconfig hci0 up') time.sleep(1) def dongle_restart(self): print("restart bluetooth dongle") self.con = pexpect.spawn('hciconfig hci0 down') time.sleep(3) self.con = pexpect.spawn('hciconfig hci0 up') time.sleep(3) def scan_loop(self): # service_uuid = '1bc5d5a50200b89fe6114d22000da2cb' service_uuid = 'cba20d00-224d-11e6-9fb8-0002a5d5c51b' menufacturer_id = '5900f46d2c8a5f31' dev_list =[] bot_list =[] enc_list =[] link_list =[] meter_list=[] self.con = pexpect.spawn('hciconfig') pnum = self.con.expect(["hci0",pexpect.EOF,pexpect.TIMEOUT]) if pnum==0: self.con = pexpect.spawn('hcitool lescan') #self.con.expect('LE Scan ...', timeout=5) scanner = Scanner().withDelegate(DevScanner()) devices = scanner.scan(10.0) print("Start scanning...") else: raise Error("no bluetooth error") for dev in devices: mac = 0 for (adtype, desc, value) in dev.getScanData(): # print(adtype,desc,value) if desc == '16b Service Data': model = binascii.a2b_hex(value[4:6]) mode = binascii.a2b_hex(value[6:8]) if len(value) == 16: # print(adtype,desc,value,len(value)) # celsius tempFra = int(value[11:12].encode('utf-8'), 16) / 10.0 tempInt = int(value[12:14].encode('utf-8'), 16) if tempInt < 128: tempInt *= -1 tempFra *= -1 else: tempInt -= 128 meterTemp = tempInt + tempFra meterHumi = int(value[14:16].encode('utf-8'), 16) % 128 # print("meter:", meterTemp, meterHumi) else: meterTemp = 0 meterHumi = 0 elif desc == 'Local name': if value == "WoHand": mac = dev.addr model = 'H' mode = 0 elif value == "WoMeter": mac = dev.addr model = 'T' mode = 0 elif desc == 'Complete 128b Services' and value == service_uuid : mac = dev.addr if mac != 0 : #print(binascii.b2a_hex(model),binascii.b2a_hex(mode)) dev_list.append([mac, model.decode('utf-8'), mode, meterTemp, meterHumi]) # print(dev_list) for (mac, dev_type,mode,meterTemp, meterHumi) in dev_list: if dev_type == 'L': link_list.append(mac) if dev_type == 'H' or ord(dev_type) == ord('L') + 128: #print(int(binascii.b2a_hex(mode),16)) if int(binascii.b2a_hex(mode),16) > 127 : bot_list.append([mac,"Turn On"]) bot_list.append([mac,"Turn Off"]) bot_list.append([mac,"Up"]) bot_list.append([mac,"Down"]) else : bot_list.append([mac,"Press"]) elif dev_type == 'T': meter_list.append([mac, meterTemp, meterHumi]) # meter_list = {"a":"1", "b":meterHumi} if ord(dev_type) == ord('L') + 128: enc_list.append([mac,"Press"]) # print(bot_list) #print("Scan timeout.") return bot_list + meter_list pass def register_cb( self, fn ): self.cb=fn return def close(self): #self.con.sendcontrol('c') self.con.close(force=True) def main(): #Check bluetooth dongle #print('Usage: "sudo python switchbot.py [mac_addr cmd]" or "sudo python switchbot.py"') connect = pexpect.spawn('hciconfig') pnum = connect.expect(["hci0",pexpect.EOF,pexpect.TIMEOUT]) if pnum!=0: print('No bluetooth hardware, exit now') sys.exit() connect = pexpect.spawn('hciconfig hci0 up') if len(sys.argv) == 3 or len(sys.argv) == 4: dev = sys.argv[1] act = sys.argv[2] if len(sys.argv) < 4 else ('Turn ' + sys.argv[3] ) #trigger_device([dev,act]) elif len(sys.argv) == 1: #Start scanning... scan = DevScanner() dev_list = scan.scan_loop() print(dev_list) dev = sys.argv[1] if len(sys.argv) > 1 else None dev_number = None if not dev_list: print("No SwitchBot nearby, exit") sys.exit() else : print('wrong cmd.') print('Usage: "sudo python switchbot_meter_py3.py [mac_addr cmd]" or "sudo python switchbot_meter_py3.py"') #connect = pexpect.spawn('hciconfig') return(dev_list) #sys.exit() if __name__ == "__main__": main()
実行結果
~/python-host $ sudo python3 SBHumiture.py Start scanning... [['XX:XX:XX:XX:XX:XX', 27.0, 65]]
色々余分なコードも残ってそうですが、とりあえず所望の値が帰ってきました。スキャンに失敗した際は"No SwitchBot nearby, exit"と表示されます。
毎回スキャンするのではなくアドレス指定でコマンドした方がシンプルだし省エネのような気がしますが、そこまでは出来ませんでした・・・。もし出来たら載せます!
ESP32-WROOM-32DでDS18B20のアドレスを取得する
DS18B20はi-wire通信でデータを取得できる温度センサーです。防水プローブを入手したので、早速ESP32ボードで遊んでみたいと思います。アドレスの取得は必須ではありませんが、後々センサーの並列動作などに必要になるのでやっておきましょう!
こちらの方法を参考にします。Arduinoでのチュートリアルになってますが、ESP32ボードでも流用できました。
henrysbench.capnfatz.com
センサー入手
AmazonのVKLSVANなる出品者から399円で購入しました。レビューがないのが気になりますし、単価がもう少し安いのもありましたが、とりあえず単品で安いのが欲しかったのでこちらで購入。
防水性はなかなかしっかりしてそうです。Amazonではホワイト(DATA / MCU )と書いてますが、実際は黄色のようです。配線
以下の表のように配線しました。データ線は33pinに繋いでます(26pinでは何故かだめでした)。DATAケーブルとVCCケーブルの間に4.7kΩの抵抗を挿入しました。
DS18B20側 | ESP32側 |
---|---|
GND |
GND |
DATA(黄色ケーブル)) |
33番ピン(IO21) |
VCC(赤ケーブル) |
5Vピン |
※pin nameとNo.の関係はこちらに詳しいです。
写真も載せておきます。
コード
pin番号部分(3行目)を33に変更。後は完全に参考リンクのまんまで動きました。
#include <OneWire.h> OneWire ds(33); // This is where DQ of your DS18B20 will connect. void setup(void) { Serial.begin(9600); getDeviceAddress(); } void getDeviceAddress(void) { byte i; byte addr[8]; Serial.println("Getting the address...\n\r"); /* initiate a search for the OneWire object we created and read its value into addr array we declared above*/ //http://henrysbench.capnfatz.com/henrys-bench/arduino-temperature-measurements/ds18b20-arduino-user-manual-introduction-and-contents/ds18b20-user-manual-part-2-getting-the-device-address/ while(ds.search(addr)) { Serial.print("The address is:\t"); //read each byte in the address array for( i = 0; i < 8; i++) { Serial.print("0x"); if (addr[i] < 16) { Serial.print('0'); } // print each byte in the address array in hex format Serial.print(addr[i], HEX); if (i < 7) { Serial.print(", "); } } // a check to make sure that what we read is correct. if ( OneWire::crc8( addr, 7) != addr[7]) { Serial.print("CRC is not valid!\n"); return; } } ds.reset_search(); return; } void loop(void) { // do nothing }
結果
アドレスが表示されました!この固体に関しては0x28, 0x7E, 0x98, 0x79, 0xA2, 0x01, 0x03, 0xB8がアドレスとなります。
ESP-WROOM-32D開発ボードでSwitchbotを動作させる
ESP-WROOM-32D開発ボードとSwitchbotを動かしてみたいと思います。
前回のコードからM5StickC関係の部分を削除するだけで動作しました。
並列処理はまだ使い方が分からないので、スライドスイッチを利用してPIN 25がONであればスイッチボットが10秒に一回動作するように設定します。
配線
ESP-WROOM-32D開発ボードの25番ピンとGNDを接続すると、PIN25=ONと判断されスイッチボットが動作するようにします。なのでこの間にスライドスイッチを差し込んでおきます。
スライドスイッチがONである間は、10秒に一回スイッチボットへ動作指令が飛ぶようなプログラムになってます。
部品
スライドスイッチはブレッドボード専用ではないですが、一応使えてます。ブレッドボードはこの開発ボードには6穴のほうが良いと思います
・ESP32−DevKitC ESP−WROOM−32開発ボード: 無線、高周波関連商品 秋月電子通商-電子部品・ネット通販
・小型スライドスイッチ 1回路2接点 SS12D01G4: パーツ一般 秋月電子通商-電子部品・ネット通販
・ブレッドボード BB−801: パーツ一般 秋月電子通商-電子部品・ネット通販
コード
static String MAC_SWITCHBOT = "xx:xx:xx:xx:xx:xx";のxxの部分にスイッチボットのMACアドレスを入力してください。
//#include <M5StickC.h> #include <driver/i2s.h> #include "BLEDevice.h" //追加 #define BTN_A_PIN 34 #define BTN_B_PIN 18 #define LED_PIN 10 // このLEDは、GPIO10の電位を下げることで発光するタイプ #define LED_ON LOW #define LED_OFF HIGH // INPUT_PULLUPが有効かは不明だが、有効という前提で定義 #define BTN_ON LOW #define BTN_OFF HIGH uint8_t prev_btn_a = BTN_OFF; uint8_t btn_a = BTN_OFF; // このLEDは、GPIO10の電位を下げることで発光するタイプ #define LED_ON LOW #define LED_OFF HIGH // INPUT_PULLUPが有効かは不明だが、有効という前提で定義 #define BTN_ON LOW #define BTN_OFF HIGH // 手元のSwitchBotのMACアドレス static String MAC_SWITCHBOT = "C3:8D:26:47:8A:55"; // SwitchBotのBLE情報 static BLEUUID SERV_SWITCHBOT("cba20d00-224d-11e6-9fb8-0002a5d5c51b"); static BLEUUID CHAR_SWITCHBOT("cba20002-224d-11e6-9fb8-0002a5d5c51b"); // SwitchBot へ送信するコマンド // アームを倒し、引く動作の場合 {0x57, 0x01, 0x00} // 以下2つはスマートフォンアプリでモードを変える必要あり // アームを倒す動作の場合 {0x57, 0x01, 0x01} // アームを引く動作の場合 {0x57, 0x01, 0x02} static uint8_t cmdPress[3] = {0x57, 0x01, 0x01}; #define PIN_CLK 0 #define PIN_DATA 34 #define READ_LEN (2 * 1024) #define SAMPLING_FREQUENCY 44100 uint8_t BUFFER[READ_LEN] = {0}; uint16_t *adcBuffer = NULL; //const uint16_t FFTsamples = 256; // サンプル数は2のべき乗//消去 //double vReal[FFTsamples]; // vReal[]にサンプリングしたデーターを入れる//消去 //double vImag[FFTsamples];//消去 //arduinoFFT FFT = arduinoFFT(vReal, vImag, FFTsamples, SAMPLING_FREQUENCY); // FFTオブジェクトを作る//消去 bool doScan = true; BLEScan* pBLEScan; static BLEAddress *pGattServerAddress; static BLEAdvertisedDevice* myDevice; static BLERemoteCharacteristic* pRemoteCharacteristic; static BLEClient* pClient = NULL; unsigned int sampling_period_us; float dmax = 10000.0; bool doDetection = false; bool sendFlg = false; bool cas = false; //int printCount = 0; void log(String s) { Serial.println(s); } // BLEへの接続 コールバック class MyClientCallback : public BLEClientCallbacks { void onConnect(BLEClient* pclient) { Serial.println("onConnect"); // log("cc conn"); } void onDisconnect(BLEClient* pclient) { Serial.println("onDisconnect"); // log("dis"); // doScan = true; // doDetection = false; if (cas) { esp_restart(); } } }; // アドバタイズ検出時のコールバック class advdCallback: public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advertisedDevice) { Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str()); if (advertisedDevice.haveServiceUUID()) { String addr = advertisedDevice.getAddress().toString().c_str(); Serial.printf("It have service addr: %s \n", advertisedDevice.getAddress().toString().c_str()); if (addr.equalsIgnoreCase(MAC_SWITCHBOT)) { // SwitchBot を発見 // if (advertisedDevice.getServiceUUID().equals(SERV_SWITCHBOT)) { log("found"); advertisedDevice.getScan()->stop(); pGattServerAddress = new BLEAddress(advertisedDevice.getAddress()); myDevice = new BLEAdvertisedDevice(advertisedDevice); doScan = false; doDetection = true; // m5LED(500, 2); } } } }; void setup() { Serial.begin(115200); pinMode(BTN_A_PIN, INPUT_PULLUP);//追加 log("Start"); // BLE 初期化 BLEDevice::init(""); // デバイスからのアドバタイズをスキャン pBLEScan = BLEDevice::getScan(); pBLEScan->setAdvertisedDeviceCallbacks(new advdCallback()); pBLEScan->setActiveScan(true); pBLEScan->setInterval(100); pBLEScan->setWindow(99); // less or equal setInterval value } void loop() { btn_a = digitalRead(BTN_A_PIN);//追加 if((btn_a == BTN_ON)){//追加 if (doScan) { log("Scan"); pBLEScan->start(5, false); } if(doScan == false){ digitalWrite(LED_PIN, LED_ON); //digitalWrite(LED_PIN, LED_OFF); if (connectAndSendCommand(*pGattServerAddress)) { log("Done!"); sendFlg = false; doScan = false; delay(10000); } else { log("Failed."); doScan = true; delay(3000); } } } vTaskDelay(500 / portTICK_RATE_MS); } // SwitchBot の GATT サーバへ接続 ~ Press コマンド送信 static bool connectAndSendCommand(BLEAddress pAddress) { cas = true; try { pClient = BLEDevice::createClient(); pClient->setClientCallbacks(new MyClientCallback()); log("Connecting"); while (!pClient->connect(myDevice)) { log("reconnect"); delay(1000); } // 対象サービスを得る BLERemoteService* pRemoteService = pClient->getService(SERV_SWITCHBOT); if (pRemoteService == nullptr) { log("e:service not found"); return false; } // 対象キャラクタリスティックを得る pRemoteCharacteristic = pRemoteService->getCharacteristic(CHAR_SWITCHBOT); if (pRemoteCharacteristic == nullptr) { log("e:characteristic not found"); return false; } // キャラクタリスティックに Press コマンドを書き込む pRemoteCharacteristic->writeValue(cmdPress, sizeof(cmdPress), false); // pRemoteCharacteristic->writeValue("test", true); log("Send"); cas = false; delay(3000); pClient->disconnect(); pClient = NULL; delay(1000); } catch (...) { log("error"); if (pClient) { pClient->disconnect(); pClient = NULL; } return false; } return true; }
動作
ESP32開発モジュールでスイッチボット動いた。スライドスイッチがオンの間は10秒に一回プレスする仕様。 pic.twitter.com/vVZdUCxLL8
— タラオ (@chem_phys_elec) June 1, 2020
M5StickCのボタンでSwitchbotを操作する
M5StickCのLチカに昨日成功ばかりの新参者ですが、本来の目的であるSwitchbotの操作に取り掛かって行きます。
M5StickC(ESP32チップ)でSwitchbotを操作しようと検索し、以下の2件を発見できました。
qiita.com
dsas.blog.klab.org
一件目はなんとか動作しました。しかし不安定というか、動作したりしなかったり、数十秒止まったりしてしまうようでした。
二件目は使い方が間違っているのかまったく動作しませんでした。シリアルモニタを見ると、文字化けしたテキストが延々吐き出されていました…。
コードを見比べるとキモ(スイッチボット操作)の部分は似通っており、二件目のコードをベースに一件目は作成されたようした。
接続に関する改良が図られているようなので、その点が効いていたのかもしれません。
しかし音をトリガーにするのではなく純粋にスイッチボットをON/OFFするコードがまず必要でしたので、動作した一件目をベースに改造することにしました。
私はC言語の経験と知識がほとんどなかったのでだいぶハードルが高かったのですが、
前述一件目のコードと以下のコードをかなり雑に合体させてとりあえず所望の動作を得ることが出来たので、記録しておきます。
M5StickCであそぶ 〜ボタンとLEDを使う〜 | MUDAなことをしよう。
コード①
M5ボタンを押すと(つまりPIN 37がON)スイッチボットが1回動作するようになってます。
static String MAC_SWITCHBOT = "xx:xx:xx:xx:xx:xx";のxxの部分にMACアドレスを入力してください。
#include <M5StickC.h> #include <driver/i2s.h> #include "BLEDevice.h" //追加 #define BTN_A_PIN 37 #define BTN_B_PIN 39 #define LED_PIN 10 // このLEDは、GPIO10の電位を下げることで発光するタイプ #define LED_ON LOW #define LED_OFF HIGH // INPUT_PULLUPが有効かは不明だが、有効という前提で定義 #define BTN_ON LOW #define BTN_OFF HIGH uint8_t prev_btn_a = BTN_OFF; uint8_t btn_a = BTN_OFF; uint8_t prev_btn_b = BTN_OFF; uint8_t btn_b = BTN_OFF; // このLEDは、GPIO10の電位を下げることで発光するタイプ #define LED_ON LOW #define LED_OFF HIGH // INPUT_PULLUPが有効かは不明だが、有効という前提で定義 #define BTN_ON LOW #define BTN_OFF HIGH // 手元のSwitchBotのMACアドレス static String MAC_SWITCHBOT = "xx:xx:xx:xx:xx:xx"; // SwitchBotのBLE情報 static BLEUUID SERV_SWITCHBOT("cba20d00-224d-11e6-9fb8-0002a5d5c51b"); static BLEUUID CHAR_SWITCHBOT("cba20002-224d-11e6-9fb8-0002a5d5c51b"); // SwitchBot へ送信するコマンド // アームを倒し、引く動作の場合 {0x57, 0x01, 0x00} // 以下2つはスマートフォンアプリでモードを変える必要あり // アームを倒す動作の場合 {0x57, 0x01, 0x01} // アームを引く動作の場合 {0x57, 0x01, 0x02} static uint8_t cmdPress[3] = {0x57, 0x01, 0x01}; #define PIN_CLK 0 #define PIN_DATA 34 #define READ_LEN (2 * 1024) #define SAMPLING_FREQUENCY 44100 uint8_t BUFFER[READ_LEN] = {0}; uint16_t *adcBuffer = NULL; //const uint16_t FFTsamples = 256; // サンプル数は2のべき乗//消去 //double vReal[FFTsamples]; // vReal[]にサンプリングしたデーターを入れる//消去 //double vImag[FFTsamples];//消去 //arduinoFFT FFT = arduinoFFT(vReal, vImag, FFTsamples, SAMPLING_FREQUENCY); // FFTオブジェクトを作る//消去 bool doScan = true; BLEScan* pBLEScan; static BLEAddress *pGattServerAddress; static BLEAdvertisedDevice* myDevice; static BLERemoteCharacteristic* pRemoteCharacteristic; static BLEClient* pClient = NULL; unsigned int sampling_period_us; float dmax = 10000.0; bool doDetection = false; bool sendFlg = false; bool cas = false; //int printCount = 0; void log(String s) { Serial.println(s); M5.Lcd.println(s); } // BLEへの接続 コールバック class MyClientCallback : public BLEClientCallbacks { void onConnect(BLEClient* pclient) { Serial.println("onConnect"); // log("cc conn"); } void onDisconnect(BLEClient* pclient) { Serial.println("onDisconnect"); // log("dis"); // doScan = true; // doDetection = false; if (cas) { esp_restart(); } } }; // アドバタイズ検出時のコールバック class advdCallback: public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advertisedDevice) { Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str()); if (advertisedDevice.haveServiceUUID()) { String addr = advertisedDevice.getAddress().toString().c_str(); Serial.printf("It have service addr: %s \n", advertisedDevice.getAddress().toString().c_str()); if (addr.equalsIgnoreCase(MAC_SWITCHBOT)) { // SwitchBot を発見 // if (advertisedDevice.getServiceUUID().equals(SERV_SWITCHBOT)) { log("found"); advertisedDevice.getScan()->stop(); pGattServerAddress = new BLEAddress(advertisedDevice.getAddress()); myDevice = new BLEAdvertisedDevice(advertisedDevice); doScan = false; doDetection = true; // m5LED(500, 2); } } } }; void setup() { Serial.begin(115200); M5.begin(); // i2sInit(); pinMode(BTN_A_PIN, INPUT_PULLUP);//追加 pinMode(BTN_B_PIN, INPUT_PULLUP);//追加 pinMode(LED_PIN, OUTPUT);//追加 digitalWrite(LED_PIN, LED_OFF);//追加 // pinMode(M5_LED, OUTPUT); M5.Axp.ScreenBreath(8); // 画面の輝度を少し下げる M5.Lcd.setTextSize(2); // 画面内文字のサイズを大きく log("Start"); //xTaskCreate(mic_fft_task, "mic_fft_task", 2048, NULL, 1, NULL);//消去 // BLE 初期化 BLEDevice::init(""); // デバイスからのアドバタイズをスキャン pBLEScan = BLEDevice::getScan(); pBLEScan->setAdvertisedDeviceCallbacks(new advdCallback()); pBLEScan->setActiveScan(true); pBLEScan->setInterval(100); pBLEScan->setWindow(99); // less or equal setInterval value } void loop() { btn_a = digitalRead(BTN_A_PIN);//追加 if (doScan) { log("Scan"); pBLEScan->start(5, false); } // if (sendFlg == true && doScan == false) { if(prev_btn_a == BTN_OFF && btn_a == BTN_ON && doScan == false){//追加 // log reset M5.Lcd.fillScreen(BLACK); M5.Lcd.setCursor(0, 0); digitalWrite(LED_PIN, LED_ON); delay(500); digitalWrite(LED_PIN, LED_OFF); //log("Detect Sound"); if (connectAndSendCommand(*pGattServerAddress)) { log("Done!"); sendFlg = false; doScan = false; } else { log("Failed."); doScan = true; delay(3000); } } vTaskDelay(500 / portTICK_RATE_MS); } // SwitchBot の GATT サーバへ接続 ~ Press コマンド送信 static bool connectAndSendCommand(BLEAddress pAddress) { cas = true; try { pClient = BLEDevice::createClient(); pClient->setClientCallbacks(new MyClientCallback()); log("Connecting"); while (!pClient->connect(myDevice)) { log("reconnect"); delay(1000); } // 対象サービスを得る BLERemoteService* pRemoteService = pClient->getService(SERV_SWITCHBOT); if (pRemoteService == nullptr) { log("e:service not found"); return false; } // 対象キャラクタリスティックを得る pRemoteCharacteristic = pRemoteService->getCharacteristic(CHAR_SWITCHBOT); if (pRemoteCharacteristic == nullptr) { log("e:characteristic not found"); return false; } // キャラクタリスティックに Press コマンドを書き込む pRemoteCharacteristic->writeValue(cmdPress, sizeof(cmdPress), false); // pRemoteCharacteristic->writeValue("test", true); log("Send"); cas = false; delay(3000); pClient->disconnect(); pClient = NULL; delay(1000); } catch (...) { log("error"); if (pClient) { pClient->disconnect(); pClient = NULL; } return false; } return true; }
動作
— タラオ (@chem_phys_elec) June 1, 2020
気持ち長押し目で押してやってください。ディレイに入っている間はボタンを押しても受け付けられないためです。
対策としては並列処理にしたり、タイミングを逃さないトグルスイッチを使用することでしょうか。
コード②
M5ボタンを一度押すと、10秒に一回スイッチボットを動作させます。
ループを解除するには側面ボタンを一回押します(PINを39をON)。
#include <M5StickC.h> #include <driver/i2s.h> #include "BLEDevice.h" //追加 #define BTN_A_PIN 37 #define BTN_B_PIN 39 #define LED_PIN 10 // このLEDは、GPIO10の電位を下げることで発光するタイプ #define LED_ON LOW #define LED_OFF HIGH // INPUT_PULLUPが有効かは不明だが、有効という前提で定義 #define BTN_ON LOW #define BTN_OFF HIGH uint8_t prev_btn_a = BTN_ON; uint8_t btn_a = BTN_ON; uint8_t prev_btn_b = BTN_OFF; uint8_t btn_b = BTN_OFF; // このLEDは、GPIO10の電位を下げることで発光するタイプ #define LED_ON LOW #define LED_OFF HIGH // INPUT_PULLUPが有効かは不明だが、有効という前提で定義 #define BTN_ON LOW #define BTN_OFF HIGH // 手元のSwitchBotのMACアドレス static String MAC_SWITCHBOT = "xx:xx:xx:xx:xx:xx"; // SwitchBotのBLE情報 static BLEUUID SERV_SWITCHBOT("cba20d00-224d-11e6-9fb8-0002a5d5c51b"); static BLEUUID CHAR_SWITCHBOT("cba20002-224d-11e6-9fb8-0002a5d5c51b"); // SwitchBot へ送信するコマンド // アームを倒し、引く動作の場合 {0x57, 0x01, 0x00} // 以下2つはスマートフォンアプリでモードを変える必要あり // アームを倒す動作の場合 {0x57, 0x01, 0x01} // アームを引く動作の場合 {0x57, 0x01, 0x02} static uint8_t cmdPress[3] = {0x57, 0x01, 0x01}; #define PIN_CLK 0 #define PIN_DATA 34 #define READ_LEN (2 * 1024) #define SAMPLING_FREQUENCY 44100 uint8_t BUFFER[READ_LEN] = {0}; uint16_t *adcBuffer = NULL; //const uint16_t FFTsamples = 256; // サンプル数は2のべき乗//消去 //double vReal[FFTsamples]; // vReal[]にサンプリングしたデーターを入れる//消去 //double vImag[FFTsamples];//消去 //arduinoFFT FFT = arduinoFFT(vReal, vImag, FFTsamples, SAMPLING_FREQUENCY); // FFTオブジェクトを作る//消去 bool doScan = true; BLEScan* pBLEScan; static BLEAddress *pGattServerAddress; static BLEAdvertisedDevice* myDevice; static BLERemoteCharacteristic* pRemoteCharacteristic; static BLEClient* pClient = NULL; unsigned int sampling_period_us; float dmax = 10000.0; bool doDetection = false; bool sendFlg = false; bool cas = false; //int printCount = 0; void log(String s) { Serial.println(s); M5.Lcd.println(s); } // BLEへの接続 コールバック class MyClientCallback : public BLEClientCallbacks { void onConnect(BLEClient* pclient) { Serial.println("onConnect"); // log("cc conn"); } void onDisconnect(BLEClient* pclient) { Serial.println("onDisconnect"); // log("dis"); // doScan = true; // doDetection = false; if (cas) { esp_restart(); } } }; // アドバタイズ検出時のコールバック class advdCallback: public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advertisedDevice) { Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str()); if (advertisedDevice.haveServiceUUID()) { String addr = advertisedDevice.getAddress().toString().c_str(); Serial.printf("It have service addr: %s \n", advertisedDevice.getAddress().toString().c_str()); if (addr.equalsIgnoreCase(MAC_SWITCHBOT)) { // SwitchBot を発見 // if (advertisedDevice.getServiceUUID().equals(SERV_SWITCHBOT)) { log("found"); advertisedDevice.getScan()->stop(); pGattServerAddress = new BLEAddress(advertisedDevice.getAddress()); myDevice = new BLEAdvertisedDevice(advertisedDevice); doScan = false; doDetection = true; // m5LED(500, 2); } } } }; void setup() { Serial.begin(115200); M5.begin(); // i2sInit(); pinMode(BTN_A_PIN, INPUT_PULLUP);//追加 pinMode(BTN_B_PIN, INPUT_PULLUP);//追加 pinMode(LED_PIN, OUTPUT);//追加 digitalWrite(LED_PIN, LED_OFF);//追加 // pinMode(M5_LED, OUTPUT); M5.Axp.ScreenBreath(8); // 画面の輝度を少し下げる M5.Lcd.setTextSize(2); // 画面内文字のサイズを大きく log("Start"); //xTaskCreate(mic_fft_task, "mic_fft_task", 2048, NULL, 1, NULL);//消去 // BLE 初期化 BLEDevice::init(""); // デバイスからのアドバタイズをスキャン pBLEScan = BLEDevice::getScan(); pBLEScan->setAdvertisedDeviceCallbacks(new advdCallback()); pBLEScan->setActiveScan(true); pBLEScan->setInterval(100); pBLEScan->setWindow(99); // less or equal setInterval value } void loop() { btn_a = digitalRead(BTN_A_PIN);//追加 btn_b = digitalRead(BTN_B_PIN); if (doScan) { log("Scan"); pBLEScan->start(5, false); } // if (sendFlg == true && doScan == false) { if((prev_btn_a == BTN_ON || btn_a == BTN_ON) && doScan == false){//追加 // log reset M5.Lcd.fillScreen(BLACK); M5.Lcd.setCursor(0, 0); digitalWrite(LED_PIN, LED_ON); //digitalWrite(LED_PIN, LED_OFF); prev_btn_a = BTN_ON; prev_btn_b = BTN_OFF; log("Detect Sound"); if (connectAndSendCommand(*pGattServerAddress)) { log("Done!"); sendFlg = false; doScan = false; delay(10000); } else { log("Failed."); doScan = true; delay(3000); } if(prev_btn_b == BTN_ON || btn_b == BTN_ON){ // ボタンBが押されたとき。今回は2回点滅 digitalWrite(LED_PIN, LED_ON); delay(100); digitalWrite(LED_PIN, LED_OFF); delay(100); digitalWrite(LED_PIN, LED_ON); delay(100); digitalWrite(LED_PIN, LED_OFF); prev_btn_a = BTN_OFF; prev_btn_b = BTN_ON; } } vTaskDelay(500 / portTICK_RATE_MS); } // SwitchBot の GATT サーバへ接続 ~ Press コマンド送信 static bool connectAndSendCommand(BLEAddress pAddress) { cas = true; try { pClient = BLEDevice::createClient(); pClient->setClientCallbacks(new MyClientCallback()); log("Connecting"); while (!pClient->connect(myDevice)) { log("reconnect"); delay(1000); } // 対象サービスを得る BLERemoteService* pRemoteService = pClient->getService(SERV_SWITCHBOT); if (pRemoteService == nullptr) { log("e:service not found"); return false; } // 対象キャラクタリスティックを得る pRemoteCharacteristic = pRemoteService->getCharacteristic(CHAR_SWITCHBOT); if (pRemoteCharacteristic == nullptr) { log("e:characteristic not found"); return false; } // キャラクタリスティックに Press コマンドを書き込む pRemoteCharacteristic->writeValue(cmdPress, sizeof(cmdPress), false); // pRemoteCharacteristic->writeValue("test", true); log("Send"); cas = false; delay(3000); pClient->disconnect(); pClient = NULL; delay(1000); } catch (...) { log("error"); if (pClient) { pClient->disconnect(); pClient = NULL; } return false; } return true; }
不用な部分も残ってるかもしれませんが、これでお目当ての動作が得られました。
スイッチボットのトリガーを変更したい場合は、以下の部分をお好みに変化させてください。
if((prev_btn_a == BTN_ON || btn_a == BTN_ON) && doScan == false)
BlynkでRaspberry Pi3+のCO2センサー測定値を取得
Blynkは各種IoTデバイスに対してスマホ等外部のデバイスから相互に通信を行えるシステムのことです。今回はBlynkを利用して、Raspberry Pi3+にアクセスしCO2センサー測定値を取得します。Lチカでも大変お世話になったこちらの記事を参考にし手順を進めました。
blog.livedoor.jp
難易度:☆★★★★
新規性:☆★★★★
有用性:☆☆☆★★
準備
Blynkスマホアプリ側の準備
Blynkアプリをスマホにインストールし、新規プロジェクトを作成しトークンを入手しておきます。
BlynkのRaspberry Piへのインストールに関してはこちらの記事にまとめました。
main.cppの書換え
main.cppはBlynkライブラリに含まれるソースファイルです。vimでmain.cppの中身を書き換えます。cppとはC++固有の拡張子らしいです。
pi@raspberrypi:~ $ cd blynk pi@raspberrypi:~/blynk $ cd blynk-library/linux pi@raspberrypi:~/blynk/blynk-library/linux $ sudo vi main.cpp
この中で次の行を探し出し、
BLYNK_WRITE(V1) { printf("Got a value: %s\n", param[0].asStr()); }
次のコードに置き換えます。参考記事のまんまで使用させて頂いてます。
void blynk_read_exec(int pin) { char command[256] = ""; char buff[256] = ""; FILE *fp; sprintf(command, "/home/pi/blynk/BLYNK_READ_V%d.sh", pin); if((fp=popen(command,"r")) != NULL) { if(fgets(buff, 255, fp) != NULL) strtok(buff, "\n\0"); } pclose(fp); Blynk.virtualWrite(pin, buff); BLYNK_LOG("Command: %s -> %s", command, buff); } void blynk_write_exec(int pin, const BlynkParam& param) { char command[256] = ""; char buff[256] = ""; sprintf(command, "/home/pi/blynk/BLYNK_WRITE_V%d.sh", pin); for (int i=0; i<3; i++) { if(! param[i].isValid()) break; sprintf(buff, " %d", param[i].asInt()); strcat(command, buff); } BLYNK_LOG("Command: %s", command); system(command); } BLYNK_READ(V0) { blynk_read_exec(V0); } BLYNK_READ(V1) { blynk_read_exec(V1); } BLYNK_READ(V2) { blynk_read_exec(V2); } BLYNK_READ(V3) { blynk_read_exec(V3); } BLYNK_READ(V4) { blynk_read_exec(V4); } BLYNK_READ(V5) { blynk_read_exec(V5); } BLYNK_READ(V6) { blynk_read_exec(V6); } BLYNK_READ(V7) { blynk_read_exec(V7); } BLYNK_READ(V8) { blynk_read_exec(V8); } BLYNK_READ(V9) { blynk_read_exec(V9); } BLYNK_WRITE(V10) { blynk_write_exec(V10,param); } BLYNK_WRITE(V11) { blynk_write_exec(V11,param); } BLYNK_WRITE(V12) { blynk_write_exec(V12,param); } BLYNK_WRITE(V13) { blynk_write_exec(V13,param); } BLYNK_WRITE(V14) { blynk_write_exec(V14,param); } BLYNK_WRITE(V15) { blynk_write_exec(V15,param); } BLYNK_WRITE(V16) { blynk_write_exec(V16,param); } BLYNK_WRITE(V17) { blynk_write_exec(V17,param); } BLYNK_WRITE(V18) { blynk_write_exec(V18,param); } BLYNK_WRITE(V19) { blynk_write_exec(V19,param); }
vimへコピペすると先頭行が消えたりしたのですが、テキストエディタ等に一度張り付けてダミーの行を加えてやりました。
この書き換え操作によりBlynkでバーチャルピンのX番をONにした際に、"/home/pi/blynk/BLYNK_WRITE_VX.sh"のシェルスクリプトファイルが実行されることになります。今後新しいバーチャルピンに機能をアサインする際、main.cppを弄る必要がなくなりました。凄い!
もう一つ私にとって大いに助かる点は、間接的にpythonファイルを扱えるようになったということですね。
動作確認
今までの操作に問題がなかったかを確認してみます。参考記事に載っているCPU温度取得を試してみます。
blynkディレクトリにBLYNK_READ_V0.shを作成します。
pi@raspberrypi:~ $ cd blynk pi@raspberrypi:~/blynk $ sudo vi BLYNK_READ_V0.sh
次のように記入し保存します。
#!/bin/sh data=`cat /sys/class/thermal/thermal_zone0/temp | awk '{printf($1/1000)}'` printf "%3.1f" $data
作成したシェルスクリプトファイルに権限を与えます。Linuxでのshファイル実行にはこの操作が必要なようです(参考)。
pi@raspberrypi:~/blynk $ chmod 700 BLYNK_READ_V0.sh
BLYNK_READ_V0.shを作成しましたので、アプリ側でV0ピンをONにすればこのファイルが実行されるはずです。
LXTerminalでBlynkを起動します。
$ cd blynk $ cd blynk-library/linux $ sudo ./blynk --token=<トークン>
スマホのBlynkアプリでプロジェクトを開き、Widget BoxからValue Displayを選択します。
Value Displayのセッティング画面でINPUTをVirtualピンの0番、すなわちV0を選択し、READING RATEを適当な値に設定します。
プロットする場合はSuperChartを選択し、+Add Datastream→INPUTをV0に設定します。
▷ボタンを押せばBlynkサーバーとの通信が始まります。成功すればCPUの温度がスマホで確認できるはずです。
CO2センサーの値を取得する
以前の記事でpythonのスクリプトでCO2センサーの値を取得したので、こちらを流用したいと思います。
co2.pyという名前で、任意の場所に次の内容のファイルを保存します。
import mh_z19 co2 = mh_z19.read_all()["co2"] print(co2)
次にBlynkディレクトリに以下の内容のファイルを保存します。
python3 /home/pi/co2.py
ここではファイル名をBLYNK_READ_V1.shとしました。パス部分はco2.pyの保存場所に合わせて適宜変更してください。
最後に作成したシェルスクリプトに権限を付与します。
pi@raspberrypi:~/blynk $ chmod 700 BLYNK_READ_V1.sh
これで準備は完了です。BlynkアプリでV1ピンをONにすればCO2濃度が取得できます。
BlynkでスマホからRaspberry Pi3+でLチカする
Blynkは各種IoTデバイスに対してスマホ等外部のデバイスから相互に通信を行えるシステムのことです。一つの用途としては、外部ネットからラズパイへのアクセスが考えられます。今回はBlynkからのラズパイLチカを目標に、Blynkの環境構築を試みました。
なお今回はこちらの記事の内容をトレースすることで成功しました。Blynk公式のチュートリアルも試したのですが失敗しました➡失敗編
まず下準備
配線
Raspberry PiのGPIO18ピンとGNDにLEDを接続しました。GPIO18をBlynkアプリでONできれば目標は達成となります。
Blynkのインストール
まずblynkディレクトリを作成し、そこにblynkのライブラリをgit cloneします。
pi@raspberrypi:~ $ cd blynk pi@raspberrypi:~/blynk $ git clone https://github.com/blynkkk/blynk-library.git Cloning into 'blynk-library'... remote: Enumerating objects: 11456, done. remote: Total 11456 (delta 0), reused 0 (delta 0), pack-reused 11456 Receiving objects: 100% (11456/11456), 9.20 MiB | 1.80 MiB/s, done. Resolving deltas: 100% (7204/7204), done.
先ほど生成されたblynk-library/linuxディレクトリに移動し、コンパイル(多分)を行います。
pi@raspberrypi:~/blynk $ cd blynk-library/linux pi@raspberrypi:~/blynk/blynk-library/linux $ make clean all target=raspberry rm main.o ../src/utility/BlynkDebug.o ../src/utility/BlynkHandlers.o ../src/utility/BlynkTimer.o blynk rm: 'main.o' を削除できません: そのようなファイルやディレクトリはありません rm: '../src/utility/BlynkDebug.o' を削除できません: そのようなファイルやディレクトリはありません rm: '../src/utility/BlynkHandlers.o' を削除できません: そのようなファイルやディ レクトリはありません rm: '../src/utility/BlynkTimer.o' を削除できません: そのようなファイルやディレクトリはありません rm: 'blynk' を削除できません: そのようなファイルやディレクトリはありません Makefile:64: ターゲット 'clean' のレシピで失敗しました make: [clean] エラー 1 (無視されました) g++ -I ../src/ -I ./ -DLINUX -c -O3 -w -DRASPBERRY main.cpp -o main.o g++ -I ../src/ -I ./ -DLINUX -c -O3 -w -DRASPBERRY ../src/utility/BlynkDebug.cpp -o ../src/utility/BlynkDebug.o g++ -I ../src/ -I ./ -DLINUX -c -O3 -w -DRASPBERRY ../src/utility/BlynkHandlers.cpp -o ../src/utility/BlynkHandlers.o g++ -I ../src/ -I ./ -DLINUX -c -O3 -w -DRASPBERRY ../src/utility/BlynkTimer.cpp -o ../src/utility/BlynkTimer.o g++ main.o ../src/utility/BlynkDebug.o ../src/utility/BlynkHandlers.o ../src/utility/BlynkTimer.o -lrt -lpthread -s -lwiringPi -o blynk
読み方が良く分かりませんが、main.cppがコンパイルされたんだと思います
Blynk立ち上げとLチカ
次のコマンドでBlynkサーバー立ち上げます。
pi@raspberrypi:~/blynk/blynk-library/linux $ sudo ./blynk --token=<トークン> [0] ___ __ __ / _ )/ /_ _____ / /__ / _ / / // / _ \/ '_/ /____/_/\_, /_//_/_/\_\ /___/ v0.6.1 on Linux [1] Connecting to blynk-cloud.com:80 [468] Ready (ping: 172ms).
無事Blynkが立ち上がりました。
またスマホアプリからのLチカにも応答しました!
【失敗編】BlynkでRaspberry Pi3+とスマホを接続するための環境を構築する
Blynkは各種IoTデバイスに対してスマホ等外部のデバイスから相互に通信を行えるシステムのことです。一つの用途としては、外部ネットからラズパイへのアクセスが考えられます。今回はBlynkからのラズパイLチカを目標に、Blynkの環境構築を試みました。
……が、かなり遠回りしたのでその失敗談を記録として残しておきます。エラー文も全て載せてあるので、同様のエラーに遭遇した方の参考になれば幸いです。十分知識あるの方からすると頭痛のするような内容だと思います。
※この記事は失敗編です。成功した方法は別の記事にまとめてあります。
試したことと結果
・Blynk公式の動画チュートリアルに従って環境構築するも、npmのインストールに躓く。
・npmをアップデートした。
・Blynkのインストールとサーバー立ち上げ、スマホアプリとのコネクションに成功。しかしLチカには失敗。
・結局Blynk公式のチュートリアルとは別な方法でBlynkをインストールし直した結果、Lチカに成功。
まず下準備
配線
Raspberry PiのGPIO18ピンとGNDにLEDを接続しました。GPIO18をBlynkアプリでONできれば目標は達成となります。
公式動画チュートリアルに従って環境構築を試みる
動画はこちら。このチュートリアルを見る限りではとても簡単そうです。
youtu.be
動画の元となるコートと詳細な説明はこちらに載っています。公開はちょうど三年前です。
まずはNode.js.をインストールする前に、過去のバージョンを削除するとのことです。
pi@raspberrypi:~ $ sudo apt-get purge node nodejs node.js -y パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 注意、regex 'node.js' のために 'node-json-localizer' を選択します 注意、regex 'node.js' のために 'node-json-stable-stringify' を選択します 注意、regex 'node.js' のために 'node-jsv' を選択します 注意、regex 'node.js' のために 'node-jsonstream' を選択します 注意、regex 'node.js' のために 'node-jsdom' を選択します 注意、regex 'node.js' のために 'node-jsesc' を選択します 注意、regex 'node.js' のために 'node-json-stringify-safe' を選択します 注意、regex 'node.js' のために 'node-json5' を選択します 注意、regex 'node.js' のために 'node-jscoverage' を選択します 注意、regex 'node.js' のために 'node-js-yaml' を選択します 注意、regex 'node.js' のために 'node-jssip' を選択します 注意、regex 'node.js' のために 'node-jsonminify' を選択します 注意、regex 'node.js' のために 'node-jsonselect' を選択します 注意、regex 'node.js' のために 'node-jsonfile' を選択します 注意、regex 'node.js' のために 'node-jsonparse' を選択します 注意、regex 'node.js' のために 'node-jsonify' を選択します 注意、regex 'node.js' のために 'node-js-tokens' を選択します 注意、regex 'node.js' のために 'node-json-parse-helpfulerror' を選択します 注意、regex 'node.js' のために 'node-jsconfig' を選択します パッケージ 'node-jscoverage' はインストールされていないため削除もされません パッケージ 'node' はインストールされていないため削除もされません パッケージ 'node-js-tokens' はインストールされていないため削除もされません パッケージ 'node-js-yaml' はインストールされていないため削除もされません パッケージ 'node-jsconfig' はインストールされていないため削除もされません パッケージ 'node-jsdom' はインストールされていないため削除もされません パッケージ 'node-jsesc' はインストールされていないため削除もされません パッケージ 'node-json-localizer' はインストールされていないため削除もされません パッケージ 'node-json-parse-helpfulerror' はインストールされていないため削除もされません パッケージ 'node-json-stable-stringify' はインストールされていないため削除もされません パッケージ 'node-json-stringify-safe' はインストールされていないため削除もされません パッケージ 'node-json5' はインストールされていないため削除もされません パッケージ 'node-jsonfile' はインストールされていないため削除もされません パッケージ 'node-jsonify' はインストールされていないため削除もされません パッケージ 'node-jsonminify' はインストールされていないため削除もされません パッケージ 'node-jsonparse' はインストールされていないため削除もされません パッケージ 'node-jsonselect' はインストールされていないため削除もされません パッケージ 'node-jsonstream' はインストールされていないため削除もされません パッケージ 'node-jssip' はインストールされていないため削除もされません パッケージ 'node-jsv' はインストールされていないため削除もされません 以下のパッケージは「削除」されます: nodejs* アップグレード: 0 個、新規インストール: 0 個、削除: 1 個、保留: 0 個。 この操作後に 83.7 MB のディスク容量が解放されます。 (データベースを読み込んでいます ... 現在 126503 個のファイルとディレクトリがインストールされています。) nodejs (12.16.2-1nodesource1) を削除しています ... dpkg: 警告: nodejs の削除中、ディレクトリ '/usr/lib/node_modules/npm/docs' が空でないため削除できませんでした dpkg: 警告: nodejs の削除中、ディレクトリ '/usr/lib/node_modules/npm/node_modules/node-gyp/gyp/pylib/gyp/generator' が空でないため削除できませんでした dpkg: 警告: nodejs の削除中、ディレクトリ '/usr/lib/node_modules/npm/lib' が空でないため削除できませんでした man-db (2.7.6.1-2) のトリガを処理しています ...
インストールされていた古いバージョンが削除されたようです。しかし何やら最後のほうに不穏な警告が出てしまいました。同様の警告はチュートリアルにも出現していますが、問題はないんでしょうか。npmというnodeモジュールがあり、それが削除できなかったということでしょうか。しかし空でないから削除できないというのも私には良く分かりません。現段階では特に成す術がないので先に進みます…。
次のコマンドはautoremoveです。これにより先ほどのpurgeで削除し切れなかった依存パッケージを削除できるそうです(参考①、②)。
pi@raspberrypi:~ $ sudo apt-get autoremove パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 アップグレード: 0 個、新規インストール: 0 個、削除: 0 個、保留: 0 個。
特に削除はありませんでした。
次のコマンドからチュートリアルで言う「Automatic Node.js installation」のセクションに入ります。これはNode.jsのインストールの前準備みたいなものでしょうか。
pi@raspberrypi:~ $ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash - ================================================================================ ================================================================================ DEPRECATION WARNING Node.js 6.x LTS Boron is no longer actively supported! You will not receive security or critical stability updates for this version. You should migrate to a supported version of Node.js as soon as possible. Use the installation script that corresponds to the version of Node.js you wish to install. e.g. * https://deb.nodesource.com/setup_10.x — Node.js 10 LTS "Dubnium" (recommended) * https://deb.nodesource.com/setup_12.x — Node.js 12 LTS "Erbium" Please see https://github.com/nodejs/Release for details about which version may be appropriate for you. The NodeSource Node.js distributions repository contains information both about supported versions of Node.js and supported Linux distributions. To learn more about usage, see the repository: https://github.com/nodesource/distributions ================================================================================ ================================================================================ Continuing in 20 seconds ... ## Installing the NodeSource Node.js 6.x LTS Boron repo... ## Populating apt-get cache... + apt-get update 取得:1 http://archive.raspberrypi.org/debian stretch InRelease [25.4 kB] 取得:2 http://raspbian.raspberrypi.org/raspbian stretch InRelease [15.0 kB] 取得:3 https://deb.nodesource.com/node_12.x stretch InRelease [4,585 B] 取得:4 http://archive.raspberrypi.org/debian stretch/main armhf Packages [220 kB] 取得:5 https://deb.nodesource.com/node_12.x stretch/main armhf Packages [775 B] 取得:6 http://raspbian.raspberrypi.org/raspbian stretch/main armhf Packages [11.7 MB] 11.9 MB を 17秒 で取得しました (667 kB/s) パッケージリストを読み込んでいます... 完了 ## Confirming "stretch" is supported... + curl -sLf -o /dev/null 'https://deb.nodesource.com/node_6.x/dists/stretch/Release' ## Adding the NodeSource signing key to your keyring... + curl -s https://deb.nodesource.com/gpgkey/nodesource.gpg.key | apt-key add - OK ## Creating apt sources list file for the NodeSource Node.js 6.x LTS Boron repo... + echo 'deb https://deb.nodesource.com/node_6.x stretch main' > /etc/apt/sources.list.d/nodesource.list + echo 'deb-src https://deb.nodesource.com/node_6.x stretch main' >> /etc/apt/sources.list.d/nodesource.list ## Running `apt-get update` for you... + apt-get update ヒット:1 http://raspbian.raspberrypi.org/raspbian stretch InRelease ヒット:2 http://archive.raspberrypi.org/debian stretch InRelease 取得:3 https://deb.nodesource.com/node_6.x stretch InRelease [4,608 B] 取得:4 https://deb.nodesource.com/node_6.x stretch/main armhf Packages [1,008 B] 5,616 B を 2秒 で取得しました (2,419 B/s) パッケージリストを読み込んでいます... 完了 ## Run `sudo apt-get install -y nodejs` to install Node.js 6.x LTS Boron and npm ## You may also need development tools to build native addons: sudo apt-get install gcc g++ make ## To install the Yarn package manager, run: curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list sudo apt-get update && sudo apt-get install yarn
Node.js 6.x LTS Boronはサポートされないという注意文が出た後に、NodeSource Node.js 6.x LTS Boron repoなるファイルをインストールし始めました。大丈夫でしょうか(^^;)。
次のコマンドはapt-getのupgradeとupgradeです。
pi@raspberrypi:~ $ sudo apt-get update && sudo apt-get upgrade ヒット:1 http://raspbian.raspberrypi.org/raspbian stretch InRelease ヒット:2 https://deb.nodesource.com/node_6.x stretch InRelease ヒット:3 http://archive.raspberrypi.org/debian stretch InRelease パッケージリストを読み込んでいます... 完了 パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 アップグレードパッケージを検出しています... 完了 以下のパッケージはアップグレードされます: libldap-2.4-2 libldap-common libtiff5 アップグレード: 3 個、新規インストール: 0 個、削除: 0 個、保留: 0 個。 501 kB のアーカイブを取得する必要があります。 この操作後に追加で 3,072 B のディスク容量が消費されます。 続行しますか? [Y/n] y 取得:1 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf libldap-common all 2.4.44+dfsg-5+deb9u4 [85.7 kB] 取得:2 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf libldap-2.4-2 armhf 2.4.44+dfsg-5+deb9u4 [196 kB] 取得:3 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf libtiff5 armhf 4.0.8-2+deb9u5 [220 kB] 501 kB を 2秒 で取得しました (187 kB/s) changelog を読んでいます... 完了 (データベースを読み込んでいます ... 現在 121698 個のファイルとディレクトリがインストールされています。) .../libldap-common_2.4.44+dfsg-5+deb9u4_all.deb を展開する準備をしています ... libldap-common (2.4.44+dfsg-5+deb9u4) で (2.4.44+dfsg-5+deb9u1 に) 上書き展開しています ... .../libldap-2.4-2_2.4.44+dfsg-5+deb9u4_armhf.deb を展開する準備をしています ... libldap-2.4-2:armhf (2.4.44+dfsg-5+deb9u4) で (2.4.44+dfsg-5+deb9u1 に) 上書き展開しています ... .../libtiff5_4.0.8-2+deb9u5_armhf.deb を展開する準備をしています ... libtiff5:armhf (4.0.8-2+deb9u5) で (4.0.8-2+deb9u4 に) 上書き展開しています ... libldap-common (2.4.44+dfsg-5+deb9u4) を設定しています ... libtiff5:armhf (4.0.8-2+deb9u5) を設定しています ... libc-bin (2.24-11+deb9u4) のトリガを処理しています ... libldap-2.4-2:armhf (2.4.44+dfsg-5+deb9u4) を設定しています ... man-db (2.7.6.1-2) のトリガを処理しています ... libc-bin (2.24-11+deb9u4) のトリガを処理しています ...
次のコマンドはnodejsのインストールですね。2個前でインストールしたソースファイル(NodeSource Node.js 6.x LTS Boron repo)を元にインストールされるのではないでしょうか。
pi@raspberrypi:~ $ sudo apt-get install build-essential nodejs -y パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 build-essential はすでに最新バージョン (12.3) です。 以下の追加パッケージがインストールされます: libc-ares2 libhttp-parser2.8 libuv1 nodejs-doc 以下のパッケージが新たにインストールされます: libc-ares2 libhttp-parser2.8 libuv1 nodejs nodejs-doc アップグレード: 0 個、新規インストール: 5 個、削除: 0 個、保留: 0 個。 5,087 kB のアーカイブを取得する必要があります。 この操作後に追加で 22.2 MB のディスク容量が消費されます。 取得:1 http://archive.raspberrypi.org/debian stretch/main armhf libc-ares2 armhf 1.14.0-1~bpo9+1 [80.7 kB] 取得:2 http://archive.raspberrypi.org/debian stretch/main armhf libhttp-parser2.8 armhf 2.8.1-1~bpo9+1 [19.3 kB] 取得:3 http://archive.raspberrypi.org/debian stretch/main armhf libuv1 armhf 1.18.0-3~bpo9+1 [86.3 kB] 取得:4 http://archive.raspberrypi.org/debian stretch/main armhf nodejs armhf 8.11.1~dfsg-2~bpo9+1 [4,126 kB] 取得:5 http://archive.raspberrypi.org/debian stretch/main armhf nodejs-doc all 8.11.1~dfsg-2~bpo9+1 [775 kB] 5,087 kB を 8秒 で取得しました (568 kB/s) 以前に未選択のパッケージ libc-ares2:armhf を選択しています。 (データベースを読み込んでいます ... 現在 121698 個のファイルとディレクトリがインストールされています。) .../libc-ares2_1.14.0-1~bpo9+1_armhf.deb を展開する準備をしています ... libc-ares2:armhf (1.14.0-1~bpo9+1) を展開しています... 以前に未選択のパッケージ libhttp-parser2.8:armhf を選択しています。 .../libhttp-parser2.8_2.8.1-1~bpo9+1_armhf.deb を展開する準備をしています ... libhttp-parser2.8:armhf (2.8.1-1~bpo9+1) を展開しています... 以前に未選択のパッケージ libuv1:armhf を選択しています。 .../libuv1_1.18.0-3~bpo9+1_armhf.deb を展開する準備をしています ... libuv1:armhf (1.18.0-3~bpo9+1) を展開しています... 以前に未選択のパッケージ nodejs を選択しています。 .../nodejs_8.11.1~dfsg-2~bpo9+1_armhf.deb を展開する準備をしています ... nodejs (8.11.1~dfsg-2~bpo9+1) を展開しています... 以前に未選択のパッケージ nodejs-doc を選択しています。 .../nodejs-doc_8.11.1~dfsg-2~bpo9+1_all.deb を展開する準備をしています ... nodejs-doc (8.11.1~dfsg-2~bpo9+1) を展開しています... nodejs-doc (8.11.1~dfsg-2~bpo9+1) を設定しています ... libuv1:armhf (1.18.0-3~bpo9+1) を設定しています ... libc-bin (2.24-11+deb9u4) のトリガを処理しています ... man-db (2.7.6.1-2) のトリガを処理しています ... libc-ares2:armhf (1.14.0-1~bpo9+1) を設定しています ... libhttp-parser2.8:armhf (2.8.1-1~bpo9+1) を設定しています ... nodejs (8.11.1~dfsg-2~bpo9+1) を設定しています ... update-alternatives: /usr/bin/js (js) を提供するために自動モードで /usr/bin/nodejs を使います libc-bin (2.24-11+deb9u4) のトリガを処理しています ...
特にエラーは出ていないようです。インストールがうまく行ったかどうかを確認します。
pi@raspberrypi:~ $ npm -v -bash: npm: コマンドが見つかりません pi@raspberrypi:~ $ node -v v8.11.1
npmが入ってなさそうです(^^;)チュートリアルではnodeはv6.10.12、npmはv3.10.10が入っています。次のコマンドはBlynkのインストールですが、npm不在の状態では失敗するのは明らかでしょう。
そもそもnpmとは何なのか良く分かってませんでしたが、こちらの記事によると開発に必要なパッケージ(ライブラリとか、プラグインとか色々)を管理するためのツールです。全ての人が、全く同じ開発環境を再現するためにとても重要な役割を果たしています。とのことです。この記事の内容を全部理解できるくらいの知識が本当は必要だと思います。
pi@raspberrypi:~ $ sudo npm install blynk-library -g sudo: npm: コマンドが見つかりません
npmの再インストールが必要と思われます。チュートリアル動画のコメント欄を覗いた所、やはり同様の問題が発生した人がいるようでした。
素直にapt-get installでnpmをインストールすればよいようです。
pi@raspberrypi:~ $ sudo apt-get install npm パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 以下の追加パッケージがインストールされます: gyp libjs-inherits libjs-node-uuid libssl-dev libssl-doc libuv1-dev node-abbrev node-ansi node-ansi-color-table node-archy node-async node-balanced-match node-block-stream node-brace-expansion node-builtin-modules node-combined-stream node-concat-map node-cookie-jar node-delayed-stream node-forever-agent node-form-data node-fs.realpath node-fstream node-fstream-ignore node-github-url-from-git node-glob node-graceful-fs node-gyp node-hosted-git-info node-inflight node-inherits node-ini node-is-builtin-module node-isexe node-json-stringify-safe node-lockfile node-lru-cache node-mime node-minimatch node-mkdirp node-mute-stream node-node-uuid node-nopt node-normalize-package-data node-npmlog node-once node-osenv node-path-is-absolute node-pseudomap node-qs node-read node-read-package-json node-request node-retry node-rimraf node-semver node-sha node-slide node-spdx-correct node-spdx-expression-parse node-spdx-license-ids node-tar node-tunnel-agent node-underscore node-validate-npm-package-license node-which node-wrappy node-yallist nodejs-dev 提案パッケージ: node-hawk node-aws-sign node-oauth-sign node-http-signature debhelper 以下のパッケージが新たにインストールされます: gyp libjs-inherits libjs-node-uuid libssl-dev libssl-doc libuv1-dev node-abbrev node-ansi node-ansi-color-table node-archy node-async node-balanced-match node-block-stream node-brace-expansion node-builtin-modules node-combined-stream node-concat-map node-cookie-jar node-delayed-stream node-forever-agent node-form-data node-fs.realpath node-fstream node-fstream-ignore node-github-url-from-git node-glob node-graceful-fs node-gyp node-hosted-git-info node-inflight node-inherits node-ini node-is-builtin-module node-isexe node-json-stringify-safe node-lockfile node-lru-cache node-mime node-minimatch node-mkdirp node-mute-stream node-node-uuid node-nopt node-normalize-package-data node-npmlog node-once node-osenv node-path-is-absolute node-pseudomap node-qs node-read node-read-package-json node-request node-retry node-rimraf node-semver node-sha node-slide node-spdx-correct node-spdx-expression-parse node-spdx-license-ids node-tar node-tunnel-agent node-underscore node-validate-npm-package-license node-which node-wrappy node-yallist nodejs-dev npm アップグレード: 0 個、新規インストール: 70 個、削除: 0 個、保留: 0 個。 4,438 kB のアーカイブを取得する必要があります。 この操作後に追加で 17.3 MB のディスク容量が消費されます。 続行しますか? [Y/n] y 取得:1 http://archive.raspberrypi.org/debian stretch/main armhf libuv1-dev armhf 1.18.0-3~bpo9+1 [102 kB] 取得:2 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf gyp all 0.1+20150913git1f374df9-1 [266 kB] 取得:3 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf libjs-node-uuid all 1.4.0-1 [12.6 kB] 取得:4 http://archive.raspberrypi.org/debian stretch/main armhf nodejs-dev armhf 8.11.1~dfsg-2~bpo9+1 [353 kB] 取得:5 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf libssl-dev armhf 1.1.0l-1~deb9u1 [1,387 kB] 取得:6 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf libssl-doc all 1.1.0l-1~deb9u1 [1,480 kB] 取得:7 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-async all 0.8.0-1 [24.6 kB] 取得:8 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-builtin-modules all 1.1.1-1 [3,298 B] 取得:9 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-fs.realpath all 1.0.0-1 [5,522 B] 取得:10 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-hosted-git-info all 2.1.5-1 [5,696 B] 取得:11 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-wrappy all 1.0.2-1 [3,114 B] 取得:12 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-once all 1.4.0-2 [3,356 B] 取得:13 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-inflight all 1.0.6-1 [3,334 B] 取得:14 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-is-builtin-module all 1.0.0-1 [2,860 B] 取得:15 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-isexe all 1.1.2-1 [3,948 B] 取得:16 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-node-uuid all 1.4.0-1 [9,194 B] 取得:17 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-path-is-absolute all 1.0.0-1 [3,266 B] 取得:18 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-pseudomap all 1.0.2-1 [3,504 B] 取得:19 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-spdx-license-ids all 1.2.2-1 [4,754 B] 取得:20 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-spdx-correct all 1.0.2-1 [3,678 B] 取得:21 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-spdx-expression-parse all 1.0.4-1 [12.1 kB] 取得:22 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-underscore all 1.8.3~dfsg-1 [37.6 kB] 取得:23 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-validate-npm-package-license all 3.0.1-1 [3,442 B] 取得:24 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-yallist all 2.0.0-1 [5,362 B] 取得:25 http://ftp.tsukuba.wide.ad.jp/Linux/raspbian/raspbian stretch/main armhf libjs-inherits all 2.0.3-1 [2,762 B] 取得:26 http://ftp.tsukuba.wide.ad.jp/Linux/raspbian/raspbian stretch/main armhf node-abbrev all 1.0.9-1 [3,668 B] 取得:27 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-ansi all 0.3.0-2 [8,608 B] 取得:28 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-ansi-color-table all 1.0.0-1 [4,408 B] 取得:29 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-archy all 1.0.0-1 [4,052 B] 取得:30 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-balanced-match all 0.4.2-1 [3,982 B] 取得:31 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-inherits all 2.0.3-1 [3,744 B] 取得:32 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-block-stream all 0.0.9-1 [4,488 B] 取得:33 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-concat-map all 0.0.1-1 [3,462 B] 取得:34 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-brace-expansion all 1.1.6-1+deb9u1 [5,788 B] 取得:35 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-delayed-stream all 0.0.5-1 [4,482 B] 取得:36 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-combined-stream all 0.0.5-1 [4,918 B] 取得:37 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-cookie-jar all 0.3.1-1 [3,570 B] 取得:38 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-forever-agent all 0.5.1-1 [3,066 B] 取得:39 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-mime all 1.3.4-1 [11.8 kB] 取得:40 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-form-data all 0.1.0-1 [6,084 B] 取得:41 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-minimatch all 3.0.3-1 [12.8 kB] 取得:42 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-glob all 7.1.1-1 [18.4 kB] 取得:43 http://ftp.tsukuba.wide.ad.jp/Linux/raspbian/raspbian stretch/main armhf node-rimraf all 2.5.4-2 [7,482 B] 取得:44 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-mkdirp all 0.5.0-1 [4,634 B] 取得:45 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-graceful-fs all 4.1.11-1 [10.8 kB] 取得:46 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-fstream all 1.0.10-1+deb9u1 [18.2 kB] 取得:47 http://ftp.tsukuba.wide.ad.jp/Linux/raspbian/raspbian stretch/main armhf node-fstream-ignore all 0.0.6-2 [5,536 B] 取得:48 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-github-url-from-git all 1.4.0-1 [3,730 B] 取得:49 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-nopt all 3.0.6-3 [9,538 B] 取得:50 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-npmlog all 0.0.4-1 [5,516 B] 取得:51 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-osenv all 0.1.0-1 [3,734 B] 取得:52 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-tunnel-agent all 0.3.1-1 [3,840 B] 取得:53 http://ftp.tsukuba.wide.ad.jp/Linux/raspbian/raspbian stretch/main armhf node-json-stringify-safe all 5.0.0-1 [3,356 B] 取得:54 http://ftp.tsukuba.wide.ad.jp/Linux/raspbian/raspbian stretch/main armhf node-qs all 2.2.4-1 [8,474 B] 取得:55 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-request all 2.26.1-1 [15.7 kB] 取得:56 http://ftp.tsukuba.wide.ad.jp/Linux/raspbian/raspbian stretch/main armhf node-semver all 5.3.0-1 [21.9 kB] 取得:57 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-tar all 2.2.1-1 [17.6 kB] 取得:58 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-which all 1.2.11-1 [4,946 B] 取得:59 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-gyp all 3.4.0-1 [28.9 kB] 取得:60 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-ini all 1.1.0-1 [4,720 B] 取得:61 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-lockfile all 0.4.1-1 [5,150 B] 取得:62 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-lru-cache all 4.0.2-1 [7,412 B] 取得:63 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-mute-stream all 0.0.7-1 [4,344 B] 取得:64 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-normalize-package-data all 2.3.5-2 [10.5 kB] 取得:65 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-read all 1.0.7-1 [4,540 B] 取得:66 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-read-package-json all 1.2.4-1 [7,740 B] 取得:67 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-retry all 0.6.0-1 [6,124 B] 取得:68 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-sha all 1.2.3-1 [4,064 B] 取得:69 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf node-slide all 1.1.4-1 [6,078 B] 取得:70 http://ftp.jaist.ac.jp/pub/Linux/raspbian-archive/raspbian stretch/main armhf npm all 1.4.21+ds-2 [354 kB] 4,438 kB を 48秒 で取得しました (91.3 kB/s) パッケージからテンプレートを展開しています: 100% 以前に未選択のパッケージ gyp を選択しています。 (データベースを読み込んでいます ... 現在 121846 個のファイルとディレクトリがインストールされています。) .../00-gyp_0.1+20150913git1f374df9-1_all.deb を展開する準備をしています ... gyp (0.1+20150913git1f374df9-1) を展開しています... 以前に未選択のパッケージ libjs-node-uuid を選択しています。 .../01-libjs-node-uuid_1.4.0-1_all.deb を展開する準備をしています ... libjs-node-uuid (1.4.0-1) を展開しています... 以前に未選択のパッケージ libssl-dev:armhf を選択しています。 .../02-libssl-dev_1.1.0l-1~deb9u1_armhf.deb を展開する準備をしています ... libssl-dev:armhf (1.1.0l-1~deb9u1) を展開しています... 以前に未選択のパッケージ libssl-doc を選択しています。 .../03-libssl-doc_1.1.0l-1~deb9u1_all.deb を展開する準備をしています ... libssl-doc (1.1.0l-1~deb9u1) を展開しています... 以前に未選択のパッケージ libuv1-dev:armhf を選択しています。 .../04-libuv1-dev_1.18.0-3~bpo9+1_armhf.deb を展開する準備をしています ... libuv1-dev:armhf (1.18.0-3~bpo9+1) を展開しています... 以前に未選択のパッケージ node-async を選択しています。 .../05-node-async_0.8.0-1_all.deb を展開する準備をしています ... node-async (0.8.0-1) を展開しています... 以前に未選択のパッケージ node-builtin-modules を選択しています。 .../06-node-builtin-modules_1.1.1-1_all.deb を展開する準備をしています ... node-builtin-modules (1.1.1-1) を展開しています... 以前に未選択のパッケージ node-fs.realpath を選択しています。 .../07-node-fs.realpath_1.0.0-1_all.deb を展開する準備をしています ... node-fs.realpath (1.0.0-1) を展開しています... 以前に未選択のパッケージ node-hosted-git-info を選択しています。 .../08-node-hosted-git-info_2.1.5-1_all.deb を展開する準備をしています ... node-hosted-git-info (2.1.5-1) を展開しています... 以前に未選択のパッケージ node-wrappy を選択しています。 .../09-node-wrappy_1.0.2-1_all.deb を展開する準備をしています ... node-wrappy (1.0.2-1) を展開しています... 以前に未選択のパッケージ node-once を選択しています。 .../10-node-once_1.4.0-2_all.deb を展開する準備をしています ... node-once (1.4.0-2) を展開しています... 以前に未選択のパッケージ node-inflight を選択しています。 .../11-node-inflight_1.0.6-1_all.deb を展開する準備をしています ... node-inflight (1.0.6-1) を展開しています... 以前に未選択のパッケージ node-is-builtin-module を選択しています。 .../12-node-is-builtin-module_1.0.0-1_all.deb を展開する準備をしています ... node-is-builtin-module (1.0.0-1) を展開しています... 以前に未選択のパッケージ node-isexe を選択しています。 .../13-node-isexe_1.1.2-1_all.deb を展開する準備をしています ... node-isexe (1.1.2-1) を展開しています... 以前に未選択のパッケージ node-node-uuid を選択しています。 .../14-node-node-uuid_1.4.0-1_all.deb を展開する準備をしています ... node-node-uuid (1.4.0-1) を展開しています... 以前に未選択のパッケージ node-path-is-absolute を選択しています。 .../15-node-path-is-absolute_1.0.0-1_all.deb を展開する準備をしています ... node-path-is-absolute (1.0.0-1) を展開しています... 以前に未選択のパッケージ node-pseudomap を選択しています。 .../16-node-pseudomap_1.0.2-1_all.deb を展開する準備をしています ... node-pseudomap (1.0.2-1) を展開しています... 以前に未選択のパッケージ node-spdx-license-ids を選択しています。 .../17-node-spdx-license-ids_1.2.2-1_all.deb を展開する準備をしています ... node-spdx-license-ids (1.2.2-1) を展開しています... 以前に未選択のパッケージ node-spdx-correct を選択しています。 .../18-node-spdx-correct_1.0.2-1_all.deb を展開する準備をしています ... node-spdx-correct (1.0.2-1) を展開しています... 以前に未選択のパッケージ node-spdx-expression-parse を選択しています。 .../19-node-spdx-expression-parse_1.0.4-1_all.deb を展開する準備をしています ... node-spdx-expression-parse (1.0.4-1) を展開しています... 以前に未選択のパッケージ node-underscore を選択しています。 .../20-node-underscore_1.8.3~dfsg-1_all.deb を展開する準備をしています ... node-underscore (1.8.3~dfsg-1) を展開しています... 以前に未選択のパッケージ node-validate-npm-package-license を選択しています。 .../21-node-validate-npm-package-license_3.0.1-1_all.deb を展開する準備をしています ... node-validate-npm-package-license (3.0.1-1) を展開しています... 以前に未選択のパッケージ node-yallist を選択しています。 .../22-node-yallist_2.0.0-1_all.deb を展開する準備をしています ... node-yallist (2.0.0-1) を展開しています... 以前に未選択のパッケージ nodejs-dev を選択しています。 .../23-nodejs-dev_8.11.1~dfsg-2~bpo9+1_armhf.deb を展開する準備をしています ... nodejs-dev (8.11.1~dfsg-2~bpo9+1) を展開しています... 以前に未選択のパッケージ libjs-inherits を選択しています。 .../24-libjs-inherits_2.0.3-1_all.deb を展開する準備をしています ... libjs-inherits (2.0.3-1) を展開しています... 以前に未選択のパッケージ node-abbrev を選択しています。 .../25-node-abbrev_1.0.9-1_all.deb を展開する準備をしています ... node-abbrev (1.0.9-1) を展開しています... 以前に未選択のパッケージ node-ansi を選択しています。 .../26-node-ansi_0.3.0-2_all.deb を展開する準備をしています ... node-ansi (0.3.0-2) を展開しています... 以前に未選択のパッケージ node-ansi-color-table を選択しています。 .../27-node-ansi-color-table_1.0.0-1_all.deb を展開する準備をしています ... node-ansi-color-table (1.0.0-1) を展開しています... 以前に未選択のパッケージ node-archy を選択しています。 .../28-node-archy_1.0.0-1_all.deb を展開する準備をしています ... node-archy (1.0.0-1) を展開しています... 以前に未選択のパッケージ node-balanced-match を選択しています。 .../29-node-balanced-match_0.4.2-1_all.deb を展開する準備をしています ... node-balanced-match (0.4.2-1) を展開しています... 以前に未選択のパッケージ node-inherits を選択しています。 .../30-node-inherits_2.0.3-1_all.deb を展開する準備をしています ... node-inherits (2.0.3-1) を展開しています... 以前に未選択のパッケージ node-block-stream を選択しています。 .../31-node-block-stream_0.0.9-1_all.deb を展開する準備をしています ... node-block-stream (0.0.9-1) を展開しています... 以前に未選択のパッケージ node-concat-map を選択しています。 .../32-node-concat-map_0.0.1-1_all.deb を展開する準備をしています ... node-concat-map (0.0.1-1) を展開しています... 以前に未選択のパッケージ node-brace-expansion を選択しています。 .../33-node-brace-expansion_1.1.6-1+deb9u1_all.deb を展開する準備をしています ... node-brace-expansion (1.1.6-1+deb9u1) を展開しています... 以前に未選択のパッケージ node-delayed-stream を選択しています。 .../34-node-delayed-stream_0.0.5-1_all.deb を展開する準備をしています ... node-delayed-stream (0.0.5-1) を展開しています... 以前に未選択のパッケージ node-combined-stream を選択しています。 .../35-node-combined-stream_0.0.5-1_all.deb を展開する準備をしています ... node-combined-stream (0.0.5-1) を展開しています... 以前に未選択のパッケージ node-cookie-jar を選択しています。 .../36-node-cookie-jar_0.3.1-1_all.deb を展開する準備をしています ... node-cookie-jar (0.3.1-1) を展開しています... 以前に未選択のパッケージ node-forever-agent を選択しています。 .../37-node-forever-agent_0.5.1-1_all.deb を展開する準備をしています ... node-forever-agent (0.5.1-1) を展開しています... 以前に未選択のパッケージ node-mime を選択しています。 .../38-node-mime_1.3.4-1_all.deb を展開する準備をしています ... node-mime (1.3.4-1) を展開しています... 以前に未選択のパッケージ node-form-data を選択しています。 .../39-node-form-data_0.1.0-1_all.deb を展開する準備をしています ... node-form-data (0.1.0-1) を展開しています... 以前に未選択のパッケージ node-minimatch を選択しています。 .../40-node-minimatch_3.0.3-1_all.deb を展開する準備をしています ... node-minimatch (3.0.3-1) を展開しています... 以前に未選択のパッケージ node-glob を選択しています。 .../41-node-glob_7.1.1-1_all.deb を展開する準備をしています ... node-glob (7.1.1-1) を展開しています... 以前に未選択のパッケージ node-rimraf を選択しています。 .../42-node-rimraf_2.5.4-2_all.deb を展開する準備をしています ... node-rimraf (2.5.4-2) を展開しています... 以前に未選択のパッケージ node-mkdirp を選択しています。 .../43-node-mkdirp_0.5.0-1_all.deb を展開する準備をしています ... node-mkdirp (0.5.0-1) を展開しています... 以前に未選択のパッケージ node-graceful-fs を選択しています。 .../44-node-graceful-fs_4.1.11-1_all.deb を展開する準備をしています ... node-graceful-fs (4.1.11-1) を展開しています... 以前に未選択のパッケージ node-fstream を選択しています。 .../45-node-fstream_1.0.10-1+deb9u1_all.deb を展開する準備をしています ... node-fstream (1.0.10-1+deb9u1) を展開しています... 以前に未選択のパッケージ node-fstream-ignore を選択しています。 .../46-node-fstream-ignore_0.0.6-2_all.deb を展開する準備をしています ... node-fstream-ignore (0.0.6-2) を展開しています... 以前に未選択のパッケージ node-github-url-from-git を選択しています。 .../47-node-github-url-from-git_1.4.0-1_all.deb を展開する準備をしています ... node-github-url-from-git (1.4.0-1) を展開しています... 以前に未選択のパッケージ node-nopt を選択しています。 .../48-node-nopt_3.0.6-3_all.deb を展開する準備をしています ... node-nopt (3.0.6-3) を展開しています... 以前に未選択のパッケージ node-npmlog を選択しています。 .../49-node-npmlog_0.0.4-1_all.deb を展開する準備をしています ... node-npmlog (0.0.4-1) を展開しています... 以前に未選択のパッケージ node-osenv を選択しています。 .../50-node-osenv_0.1.0-1_all.deb を展開する準備をしています ... node-osenv (0.1.0-1) を展開しています... 以前に未選択のパッケージ node-tunnel-agent を選択しています。 .../51-node-tunnel-agent_0.3.1-1_all.deb を展開する準備をしています ... node-tunnel-agent (0.3.1-1) を展開しています... 以前に未選択のパッケージ node-json-stringify-safe を選択しています。 .../52-node-json-stringify-safe_5.0.0-1_all.deb を展開する準備をしています ... node-json-stringify-safe (5.0.0-1) を展開しています... 以前に未選択のパッケージ node-qs を選択しています。 .../53-node-qs_2.2.4-1_all.deb を展開する準備をしています ... node-qs (2.2.4-1) を展開しています... 以前に未選択のパッケージ node-request を選択しています。 .../54-node-request_2.26.1-1_all.deb を展開する準備をしています ... node-request (2.26.1-1) を展開しています... 以前に未選択のパッケージ node-semver を選択しています。 .../55-node-semver_5.3.0-1_all.deb を展開する準備をしています ... node-semver (5.3.0-1) を展開しています... 以前に未選択のパッケージ node-tar を選択しています。 .../56-node-tar_2.2.1-1_all.deb を展開する準備をしています ... node-tar (2.2.1-1) を展開しています... 以前に未選択のパッケージ node-which を選択しています。 .../57-node-which_1.2.11-1_all.deb を展開する準備をしています ... node-which (1.2.11-1) を展開しています... 以前に未選択のパッケージ node-gyp を選択しています。 .../58-node-gyp_3.4.0-1_all.deb を展開する準備をしています ... node-gyp (3.4.0-1) を展開しています... 以前に未選択のパッケージ node-ini を選択しています。 .../59-node-ini_1.1.0-1_all.deb を展開する準備をしています ... node-ini (1.1.0-1) を展開しています... 以前に未選択のパッケージ node-lockfile を選択しています。 .../60-node-lockfile_0.4.1-1_all.deb を展開する準備をしています ... node-lockfile (0.4.1-1) を展開しています... 以前に未選択のパッケージ node-lru-cache を選択しています。 .../61-node-lru-cache_4.0.2-1_all.deb を展開する準備をしています ... node-lru-cache (4.0.2-1) を展開しています... 以前に未選択のパッケージ node-mute-stream を選択しています。 .../62-node-mute-stream_0.0.7-1_all.deb を展開する準備をしています ... node-mute-stream (0.0.7-1) を展開しています... 以前に未選択のパッケージ node-normalize-package-data を選択しています。 .../63-node-normalize-package-data_2.3.5-2_all.deb を展開する準備をしています ... node-normalize-package-data (2.3.5-2) を展開しています... 以前に未選択のパッケージ node-read を選択しています。 .../64-node-read_1.0.7-1_all.deb を展開する準備をしています ... node-read (1.0.7-1) を展開しています... 以前に未選択のパッケージ node-read-package-json を選択しています。 .../65-node-read-package-json_1.2.4-1_all.deb を展開する準備をしています ... node-read-package-json (1.2.4-1) を展開しています... 以前に未選択のパッケージ node-retry を選択しています。 .../66-node-retry_0.6.0-1_all.deb を展開する準備をしています ... node-retry (0.6.0-1) を展開しています... 以前に未選択のパッケージ node-sha を選択しています。 .../67-node-sha_1.2.3-1_all.deb を展開する準備をしています ... node-sha (1.2.3-1) を展開しています... 以前に未選択のパッケージ node-slide を選択しています。 .../68-node-slide_1.1.4-1_all.deb を展開する準備をしています ... node-slide (1.1.4-1) を展開しています... 以前に未選択のパッケージ npm を選択しています。 .../69-npm_1.4.21+ds-2_all.deb を展開する準備をしています ... npm (1.4.21+ds-2) を展開しています... node-lockfile (0.4.1-1) を設定しています ... node-spdx-expression-parse (1.0.4-1) を設定しています ... node-qs (2.2.4-1) を設定しています ... node-osenv (0.1.0-1) を設定しています ... node-ansi (0.3.0-2) を設定しています ... libjs-node-uuid (1.4.0-1) を設定しています ... node-hosted-git-info (2.1.5-1) を設定しています ... node-delayed-stream (0.0.5-1) を設定しています ... libjs-inherits (2.0.3-1) を設定しています ... node-tunnel-agent (0.3.1-1) を設定しています ... node-balanced-match (0.4.2-1) を設定しています ... node-node-uuid (1.4.0-1) を設定しています ... node-yallist (2.0.0-1) を設定しています ... node-slide (1.1.4-1) を設定しています ... libssl-dev:armhf (1.1.0l-1~deb9u1) を設定しています ... node-github-url-from-git (1.4.0-1) を設定しています ... node-pseudomap (1.0.2-1) を設定しています ... node-spdx-license-ids (1.2.2-1) を設定しています ... node-combined-stream (0.0.5-1) を設定しています ... node-wrappy (1.0.2-1) を設定しています ... node-mime (1.3.4-1) を設定しています ... node-abbrev (1.0.9-1) を設定しています ... node-semver (5.3.0-1) を設定しています ... node-retry (0.6.0-1) を設定しています ... node-forever-agent (0.5.1-1) を設定しています ... node-underscore (1.8.3~dfsg-1) を設定しています ... gyp (0.1+20150913git1f374df9-1) を設定しています ... node-json-stringify-safe (5.0.0-1) を設定しています ... node-inherits (2.0.3-1) を設定しています ... node-graceful-fs (4.1.11-1) を設定しています ... node-archy (1.0.0-1) を設定しています ... node-path-is-absolute (1.0.0-1) を設定しています ... node-builtin-modules (1.1.1-1) を設定しています ... man-db (2.7.6.1-2) のトリガを処理しています ... node-isexe (1.1.2-1) を設定しています ... libssl-doc (1.1.0l-1~deb9u1) を設定しています ... node-spdx-correct (1.0.2-1) を設定しています ... node-async (0.8.0-1) を設定しています ... node-cookie-jar (0.3.1-1) を設定しています ... node-mute-stream (0.0.7-1) を設定しています ... node-form-data (0.1.0-1) を設定しています ... node-request (2.26.1-1) を設定しています ... node-concat-map (0.0.1-1) を設定しています ... node-ini (1.1.0-1) を設定しています ... node-mkdirp (0.5.0-1) を設定しています ... node-once (1.4.0-2) を設定しています ... node-sha (1.2.3-1) を設定しています ... node-fs.realpath (1.0.0-1) を設定しています ... libuv1-dev:armhf (1.18.0-3~bpo9+1) を設定しています ... node-brace-expansion (1.1.6-1+deb9u1) を設定しています ... node-ansi-color-table (1.0.0-1) を設定しています ... node-npmlog (0.0.4-1) を設定しています ... node-is-builtin-module (1.0.0-1) を設定しています ... node-nopt (3.0.6-3) を設定しています ... node-which (1.2.11-1) を設定しています ... node-lru-cache (4.0.2-1) を設定しています ... node-block-stream (0.0.9-1) を設定しています ... node-validate-npm-package-license (3.0.1-1) を設定しています ... node-inflight (1.0.6-1) を設定しています ... node-read (1.0.7-1) を設定しています ... node-minimatch (3.0.3-1) を設定しています ... nodejs-dev (8.11.1~dfsg-2~bpo9+1) を設定しています ... node-normalize-package-data (2.3.5-2) を設定しています ... node-glob (7.1.1-1) を設定しています ... node-rimraf (2.5.4-2) を設定しています ... node-read-package-json (1.2.4-1) を設定しています ... node-fstream (1.0.10-1+deb9u1) を設定しています ... node-fstream-ignore (0.0.6-2) を設定しています ... node-tar (2.2.1-1) を設定しています ... node-gyp (3.4.0-1) を設定しています ... npm (1.4.21+ds-2) を設定しています ...====
エラー出ず終わりました。バージョンチェックの結果は
pi@raspberrypi:~ $ npm -v 1.4.21 (node:3126) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
んん?npmは入ったようですがWarningが出てしまいました。一応Blynkを入れてみます。
pi@raspberrypi:~ $ sudo npm install blynk-library -g (node:2907) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead. /usr/local/bin/blynk-client -> /usr/local/lib/node_modules/blynk-library/bin/blynk-client.js /usr/local/bin/blynk-ctrl -> /usr/local/lib/node_modules/blynk-library/bin/blynk-ctrl.js blynk-library@0.5.4 /usr/local/lib/node_modules/blynk-library
やっぱり同様のWarningが出ていますね…。ググったところnpmのバージョンが古すぎるのが問題のようです。
npmの再インストール
とりあえず一つ目の処方として次のコードでnpmのインストールを試みます。
Node.js - npmのアップデートができない|teratail
pi@raspberrypi:~ $ npm i -g npm (node:4035) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead. npm ERR! tar.unpack untar error /home/pi/.npm/npm/6.14.4/package.tgz npm ERR! Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/npm' npm ERR! { Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/npm' npm ERR! errno: -13, npm ERR! code: 'EACCES', npm ERR! syscall: 'mkdir', npm ERR! path: '/usr/local/lib/node_modules/npm', npm ERR! fstream_type: 'Directory', npm ERR! fstream_path: '/usr/local/lib/node_modules/npm', npm ERR! fstream_class: 'DirWriter', npm ERR! fstream_stack: npm ERR! [ '/usr/lib/nodejs/fstream/lib/dir-writer.js:35:25', npm ERR! '/usr/lib/nodejs/mkdirp/index.js:46:53', npm ERR! 'FSReqWrap.oncomplete (fs.js:152:21)' ] } npm ERR! npm ERR! Please try running this command again as root/Administrator. npm ERR! System Linux 4.19.66-v7+ npm ERR! command "/usr/bin/node" "/usr/bin/npm" "i" "-g" "npm" npm ERR! cwd /home/pi npm ERR! node -v v8.11.1 npm ERR! npm -v 1.4.21 npm ERR! path /usr/local/lib/node_modules/npm npm ERR! syscall mkdir npm ERR! fstream_path /usr/local/lib/node_modules/npm npm ERR! fstream_type Directory npm ERR! fstream_class DirWriter npm ERR! code EACCES npm ERR! errno -13 npm ERR! stack Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/npm' npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/dir-writer.js:35:25 npm ERR! fstream_stack /usr/lib/nodejs/mkdirp/index.js:46:53 npm ERR! fstream_stack FSReqWrap.oncomplete (fs.js:152:21) npm ERR! npm ERR! Additional logging details can be found in: npm ERR! /home/pi/npm-debug.log npm ERR! not ok code 0
こちらの方法ではダメだったようです。別の方法を探します。
Raspberry PiにNode.jsとnpmの最新版をインストールする - Qiita
同様のエラーと対策について詳しく報告されています。これは行けそうです。一つずつ実行していきます。
pi@raspberrypi:~ $ sudo apt-get update ヒット:1 https://deb.nodesource.com/node_6.x stretch InRelease ヒット:2 http://archive.raspberrypi.org/debian stretch InRelease ヒット:3 http://raspbian.raspberrypi.org/raspbian stretch InRelease パッケージリストを読み込んでいます... 完了
pi@raspberrypi:~ $ sudo apt-get install -y nodejs npm パッケージリストを読み込んでいます... 完了 依存関係ツリーを作成しています 状態情報を読み取っています... 完了 npm はすでに最新バージョン (1.4.21+ds-2) です。 nodejs はすでに最新バージョン (8.11.1~dfsg-2~bpo9+1) です。 アップグレード: 0 個、新規インストール: 0 個、削除: 0 個、保留: 0 個。
pi@raspberrypi:~ $ sudo npm cache clean (node:4714) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
pi@raspberrypi:~ $ sudo npm install npm n -g (node:4753) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead. /usr/local/bin/n -> /usr/local/lib/node_modules/n/bin/n npm WARN package.json path-is-inside@1.0.2 No README data npm WARN package.json sorted-object@2.0.1 No README data /usr/local/bin/npx -> /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm-cli.js npm WARN package.json config-chain@1.1.12 No license field. npm WARN package.json cyclist@0.2.2 No license field. npm WARN package.json json-schema@0.2.3 No license field. npm WARN package.json punycode@1.4.1 punycode is also the name of a node core module. npm WARN package.json qrcode-terminal@0.12.0 No license field. npm WARN package.json string_decoder@1.3.0 string_decoder is also the name of a node core module. n@6.5.1 /usr/local/lib/node_modules/n npm@6.14.4 /usr/local/lib/node_modules/npm
pi@raspberrypi:~ $ sudo n stable installing : node-v12.16.3 mkdir : /usr/local/n/versions/node/12.16.3 fetch : https://nodejs.org/dist/v12.16.3/node-v12.16.3-linux-armv7l.tar.xz installed : v12.16.3 (with npm 6.14.4) Note: the node command changed location and the old location may be remembered in your current shell. old : /usr/bin/node new : /usr/local/bin/node To reset the command location hash either start a new shell, or execute PATH="$PATH"
途中またWarningが出ていますね‥。とりあえずバージョンチェックします。
pi@raspberrypi:~ $ node -v v8.11.1 pi@raspberrypi:~ $ npm -v 1.4.21 (node:4917) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
まだインストールが反映されていないようなので、ターミナルを再起動したのちもう一度チェックします。
pi@raspberrypi:~ $ exit ログアウト pi@raspberrypi:~ $ npm -v 6.14.4 pi@raspberrypi:~ $ node -v v12.16.3
npm6.14.をインスタトール出来たっぽいです。
Blynkをインストールします。
pi@raspberrypi:~ $ sudo npm install blynk-library -g /usr/local/bin/blynk-client -> /usr/local/lib/node_modules/blynk-library/bin/blynk-client.js /usr/local/bin/blynk-ctrl -> /usr/local/lib/node_modules/blynk-library/bin/blynk-ctrl.js + blynk-library@0.5.4 updated 1 package in 2.108s pi@raspberrypi:~ $ sudo npm install onoff -g + onoff@6.0.0 updated 1 package and moved 3 packages in 3.073s
エラーなくインストールできました!!
Blynkサーバーを立ち上げます。
pi@raspberrypi:~ $ export PATH=$PATH:/opt/nodejs/bin/ pi@raspberrypi:~ $ unset NODE_PATH pi@raspberrypi:~ $ blynk-client <トークン> ___ __ __ / _ )/ /_ _____ / /__ / _ / / // / _ \/ '_/ /____/_/\_, /_//_/_/\_\ /___/ Give Blynk a Github star! => https://github.com/vshymanskyy/blynk-library-js Connecting to: blynk-cloud.com 443 SSL authorization... Connected Authorized Blynk ready.
無事立ち上がりました!!スマホ側でもonlineと表示されており、接続がうまく行っているようです。
次はアプリのBlynkからGPIB18に信号を送ります。これでLEDが光るはずです。
No direct pin operations available. Maybe you need to install mraa or onoff modules? No direct pin operations available. Maybe you need to install mraa or onoff modules?
アプリでスイッチを押すと、ターミナルにこのようなエラーが表示されるだけでLEDは光りませんでした。
コネクション自体は上手く行ってるのであと一歩というような感じはします。エラー文でググると同様の報告はありましたが、遂に解決には至りませんでした…。
別のアプローチ
もはや何が問題だったのか分かりませんが、別な方法でBlynkをインストールするとあっさりとLチカが成功しました。
こちらの記事にまとめています。
学んだこと
・公式のチュートリアル通りに進めたとしても成功するとは限らない。
・根本的な部分を理解していないと苦労する。別の方法でうまく行ったとしても自分の知識レベルの問題は解決していない。
参考リンク
https://youtu.be/LJ3ic8C8CcA
How to install Node.js library on Linux | Blynk Help Center
[Ubuntu] apt-get まとめ - Qiita
不要になったパッケージを削除してくれる、autoremove - UNIX的なアレ
Node.js - npmのアップデートができない|teratail
Raspberry PiにNode.jsとnpmの最新版をインストールする - Qiita
Raspberry Piブログ : 第1回 IoTサービス「Blynk」を導入しよう - 連載 IoTサービス「Blynk」を使ってRaspberry Piをスマホからコントロールしよう