Androidのメモとか

ポキオの日記です。今日も遅延してない。

人生初のHHKB購入

ハッピー?

ポキオ HHKB Lite2

出来心で購入

マツコの知らない世界でキーボード特集をやっていた影響もあって、どうせテレワークだしキーボードでも買ったろうっていう機運が高まってきてたわけなんですが。

ポキオ HHKB Lite2

AmazonのセールでLite2が3800円だったので、つい購入してしましました。macOS用だしUS配列だし、試しに使ってみようかなと思って、ね。

とりあえず使ってみる

予定より早く届いてしまったので、早速開梱。

ポキオ HHKB Lite2

USB接続タイプで、ケーブルは本体から直接生えてるタイプ。キーボード側にUSBポートが2つ付いてるので、秒でLogicoolのUnifying差し込み余裕でした。いやー、パット見普通じゃん?って思いながら、実際に仕事で使ってみました。

ポキオ HHKB Lite2

あえてネガティブな点から言えば、コイツら。バックスラッシュとバッククオートの場所が変。特にバッククオート。おまえ、左側の隅が定位置じゃなかったのかな?って小一時間問い詰めたくなりますが、これはHHKBなんだなと思い体をこれから慣らしていこうと思います。

あとは、打鍵音。控えめに言ってもちょっとにぎやかですね。どうせテレワークで、一人でタイピングするので、まぁうるさくてもいいです。HHKBの独特なキー配列に早くなれて、カタカタカタタッターンってやってみたいものです。

ポキオ HHKB Lite2

とはいえ、3800円でHHKBの雰囲気が味わえればなによりです。キーの押し具合も嫌いじゃないです。ControlもAの左で調子いいですし。矢印キーもついてて素人にはぴったりです。まだまだ使い始めたばかりですが、このキーボードになれてきたら、高級HHKBにも手を出してみようかなぁ。

PFU HHKB Professional BT 英語配列/墨 PD-KB600B

PFU HHKB Professional BT 英語配列/墨 PD-KB600B

  • 発売日: 2016/04/12
  • メディア: Personal Computers

Node-REDとESP32で神奈川県内のCovid-19の新規陽性者数を表示してみる

オープンデータ様様。

ポキオ Covid-19 Node-RED ESP32

tl;dr

  • Githubや神奈川県HPでCovid-19関係のデータが公開されている
  • Node-REDでそれらをパースする仕組みを作りWebAPI化
  • それをESP32から叩いてOLEDに表示
  • 陽性者数だけ見てていいのかは分からない

コロナ禍

テレビを付けると、嫌でもコロナの話題が耳に入ってくるんですが、たいてい東京の新規陽性者数の話題ばっかりでちょっとうんざり。自分が住んでる都道府県はどうなのか気になるのですが、どうしてもピーキーなデータが出てる部分ばかり報道されるんですよねぇ。

というわけで今回は、私が住んでいる神奈川県の新規陽性者数のデイリーデータを表示できるガジェットを作ってみました。

データはどこから?

ざっくりググると、以下の2ヶ所から取れそう。

Github

kaz-ogiwara氏がまとめている下記のリポジトリで、国内の詳細なデータが公開されている。

github.com

特に、都道府県別のデータはこちらのCSVファイルで取得可能。検査数と陽性者数を得ることができます。

covid19/prefectures.csv at master · kaz-ogiwara/covid19 · GitHub

神奈川県HP

こちらは神奈川県が独自に公開しているデータ。

www.pref.kanagawa.jp

こちらもCSVデータで取得可能だが、陽性者のひとりひとりの属性(性別や年代)も取得可能。今回は使ってませんが、これはこれで可視化できると楽しそう。

CSVをNode-REDで取得してみる

さて、先程のCSVをNode-REDで取得してみます。

ポキオ Covid-19 Node-RED ESP32

普通にHTTP-GETで文字列を取得して、CSVノードでJavaScriptのObjectデータに変換すれば便利に使えそうです。ただし、神奈川県のデータは日本語が含まれていてShift-JISでエンコードされているため、HTTP-GETでバイナリバッファとして取得し、その後node-red-contrib-iconvで変換してからCSVノードに渡しています。あとはよしなーにパースするだけ。

ポキオ Covid-19 Node-RED ESP32

とりあえず、神奈川県のデータを使って、WebAPI化してみました。

これをESP32から叩いてみる

このWebAPIを前回触ったOLED付きのESP32から叩いてみます。

relativelayout.hatenablog.com

表示内容はNode-RED側ですべて準備してしまうので、ESP32側はHTTP-GETしてそれをそのまま表示するだけです。

#include <SSD1306.h>
#include <WiFi.h>
#include <HTTPClient.h>

#define SSID "xxxxx"
#define PASSWORD "xxxxx"
#define URL "xxxxx"
#define DELAY 5 * 60 * 1000

SSD1306 display(0x3c, 5, 4);

void setup() {
  Serial.begin(115200);
  Serial.println();
  Serial.println();

  connectWiFi();

  display.init();
  display.setFont(ArialMT_Plain_16);
}

void loop() {
  show(get());
  delay(DELAY);
}

void connectWiFi() {
  WiFi.begin(SSID, PASSWORD);
  Serial.print("connecting...");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(100);
  }
  Serial.print("connected : ");
  Serial.println(WiFi.localIP());
}

String get() {
  HTTPClient http;
  http.begin(URL);
  int httpCode = http.GET();

  if (httpCode != HTTP_CODE_OK) {
    Serial.println("http-get failed.");
    return "http-get failed.";
  }

  String body = http.getString();
  Serial.println(body);
  return body;
}

void show(String message) {
  display.clear();
  display.setTextAlignment(TEXT_ALIGN_CENTER);
  display.drawString(64, 4, message);
  display.display();
}

これを実行すると・・・

ポキオ Covid-19 Node-RED ESP32

おー。表示できました。今日は33人のようですねぇ。

これで陽性者をウォッチできますね!

まだまだ神奈川県の陽性者数は少ないようですが、気を抜けませんねぇ。

あとは、陽性者数だけ見てても良いわけはなくて、陽性率だったり重症患者数、医療体制の逼迫具合なども勘案して総合的に判断していきたいものです。それらもよしなにNode-REDのダッシュボードなどで可視化できるといいですねぇ。

Node-REDのフローはこちら

[
    {
        "id": "e16d9838.5519a",
        "type": "tab",
        "label": "Covid-19",
        "disabled": false,
        "info": ""
    },
    {
        "id": "6092239b.0dbd9c",
        "type": "inject",
        "z": "e16d9838.5519a",
        "name": "Githubから取得",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 180,
        "y": 80,
        "wires": [
            [
                "48ec884a.e861f"
            ]
        ]
    },
    {
        "id": "48ec884a.e861f",
        "type": "http request",
        "z": "e16d9838.5519a",
        "name": "",
        "method": "GET",
        "ret": "txt",
        "paytoqs": false,
        "url": "https://raw.githubusercontent.com/kaz-ogiwara/covid19/master/data/prefectures.csv",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "",
        "x": 170,
        "y": 120,
        "wires": [
            [
                "82278aeb.234d4"
            ]
        ]
    },
    {
        "id": "82278aeb.234d4",
        "type": "csv",
        "z": "e16d9838.5519a",
        "name": "",
        "sep": ",",
        "hdrin": true,
        "hdrout": "",
        "multi": "mult",
        "ret": "\\n",
        "temp": "",
        "skip": "0",
        "strings": true,
        "x": 150,
        "y": 160,
        "wires": [
            [
                "3b7e8bd6.48c4a4"
            ]
        ]
    },
    {
        "id": "bfd441d3.dbdd18",
        "type": "debug",
        "z": "e16d9838.5519a",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "x": 170,
        "y": 280,
        "wires": []
    },
    {
        "id": "3b7e8bd6.48c4a4",
        "type": "function",
        "z": "e16d9838.5519a",
        "name": "神奈川だけフィルタ",
        "func": "var kanagawaList = [];\n\nmsg.payload.forEach(element => {\n   if(element.prefectureNameE === \"Kanagawa\"){\n       kanagawaList.push(element);\n   } \n});\n\nmsg.payload = kanagawaList;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 200,
        "y": 200,
        "wires": [
            [
                "cbcbd716.db236"
            ]
        ]
    },
    {
        "id": "cbcbd716.db236",
        "type": "function",
        "z": "e16d9838.5519a",
        "name": "最新のデータだけ抽出",
        "func": "var data = msg.payload.slice();\nvar todayData = data[data.length - 1];\nvar yesterdayData = data[data.length - 2];\n\nvar testedPositive = todayData.testedPositive - yesterdayData.testedPositive;\n\nmsg.payload = {};\nmsg.payload.date = todayData.year + \"/\" + todayData.month + \"/\" + todayData.date;\nmsg.payload.testedPositive = testedPositive;\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 200,
        "y": 240,
        "wires": [
            [
                "bfd441d3.dbdd18"
            ]
        ]
    },
    {
        "id": "e6bec6cf.0856a",
        "type": "http request",
        "z": "e16d9838.5519a",
        "name": "",
        "method": "GET",
        "ret": "bin",
        "paytoqs": false,
        "url": "https://www.pref.kanagawa.jp/osirase/1369/data/csv/patient.csv",
        "tls": "",
        "persist": false,
        "proxy": "",
        "authType": "",
        "x": 490,
        "y": 120,
        "wires": [
            [
                "be7264f5.2fbbc"
            ]
        ]
    },
    {
        "id": "1c08950f.ec2513",
        "type": "csv",
        "z": "e16d9838.5519a",
        "name": "",
        "sep": ",",
        "hdrin": true,
        "hdrout": "",
        "multi": "mult",
        "ret": "\\n",
        "temp": "",
        "skip": "0",
        "strings": true,
        "x": 470,
        "y": 200,
        "wires": [
            [
                "c3f97218.b9c768"
            ]
        ]
    },
    {
        "id": "a11490b1.e1df38",
        "type": "inject",
        "z": "e16d9838.5519a",
        "name": "神奈川県HPから取得",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "x": 520,
        "y": 80,
        "wires": [
            [
                "e6bec6cf.0856a"
            ]
        ]
    },
    {
        "id": "2cdc0310.c76f24",
        "type": "debug",
        "z": "e16d9838.5519a",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "x": 490,
        "y": 280,
        "wires": []
    },
    {
        "id": "be7264f5.2fbbc",
        "type": "converter",
        "z": "e16d9838.5519a",
        "name": "Shift_JIS変換",
        "from": "Shift_JIS",
        "x": 500,
        "y": 160,
        "wires": [
            [
                "1c08950f.ec2513"
            ]
        ]
    },
    {
        "id": "c3f97218.b9c768",
        "type": "function",
        "z": "e16d9838.5519a",
        "name": "最新のデータだけ抽出",
        "func": "var data = msg.payload.slice();\nvar lastData = data[data.length - 1];\nvar lastDate = lastData[\"発表日\"];\n\nvar testedPositive = 0;\ndata.forEach(element => {\n    if(element[\"発表日\"] === lastDate){\n        testedPositive++;\n    }\n})\n\nmsg.payload = {};\nmsg.payload.date = lastDate.split('-').join('/').split('/0').join('/');\nmsg.payload.testedPositive = testedPositive;\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 520,
        "y": 240,
        "wires": [
            [
                "2cdc0310.c76f24",
                "f5d3f833.c57c78"
            ]
        ]
    },
    {
        "id": "6ee2fb46.fcd2ec",
        "type": "http in",
        "z": "e16d9838.5519a",
        "name": "",
        "url": "/covid",
        "method": "get",
        "upload": false,
        "swaggerDoc": "",
        "x": 160,
        "y": 440,
        "wires": [
            [
                "e6bec6cf.0856a"
            ]
        ]
    },
    {
        "id": "eccb91a6.147fb8",
        "type": "http response",
        "z": "e16d9838.5519a",
        "name": "",
        "statusCode": "",
        "headers": {},
        "x": 590,
        "y": 440,
        "wires": []
    },
    {
        "id": "f5d3f833.c57c78",
        "type": "function",
        "z": "e16d9838.5519a",
        "name": "レスポンス作成",
        "func": "var message = '';\n\nmessage += 'Positive Tests\\nReported : ';\nmessage += msg.payload.testedPositive + '\\n';\nmessage += '( ' + msg.payload.date + ' )'\n\n\nmsg.payload = message;\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "x": 380,
        "y": 440,
        "wires": [
            [
                "eccb91a6.147fb8"
            ]
        ]
    }
]

リングフィットアドベンチャーをついに全面クリア?(ネタバレあり)

ガッキーになれるかな。

ポキオ リングフィットアドベンチャー

ようやく

去年末に買ったリングフィットアドベンチャーですが、ようやく全面クリアができたっぽいです。

relativelayout.hatenablog.com

リングフィット アドベンチャー -Switch

リングフィット アドベンチャー -Switch

  • 発売日: 2019/10/18
  • メディア: Video Game

途中、サボった期間もありましたが、おおよそ90日くらいでクリアできました。

ポキオ リングフィットアドベンチャー

84kmも(しか?)走ってました。

生活のリズムとリングフィットアドベンチャー

一時期サボりがちになってしまったわけですが、幸か不幸かテレワークのおかげで「業務開始前に20分程度体を動かす」という日課として定着できたので、なんとかここまでやってこれました。

毎朝の日課として定着できたので、

  • コンスタントに続けられる
  • 雨でも運動できる
  • 汗をかくので必ず着替えざるを得ない(パジャマで仕事することがない)
  • 「さぁ、仕事するぞー」みたいな感じで気持ちの切り替えができる

こんな感じで良さみを感じています。また、コンスタントに続けてこれたこともあり、

  • 胸筋・腹筋がついてきた気がする(個人の感想です)
  • 腹筋系の技が楽にできるようになった
  • 自転車に乗ってるときの安定感が増した(ダンシングが楽になった)

みたいな感じで、着実に結果を体感できています。ただし、シックスパックはまだまだこれからのようで、お腹の厚い脂肪はまだクリアできてません・・・(笑)

あれ、全クリじゃない?

という感じで、リングフィットアドベンチャーは非常に良い日課として定着してるんですが・・・。

ラスボスであるドラゴを倒したので、これで全クリかと思ってたんですが。

エクストラフィットネスと言う名の裏面がUnlockされただけで、まだまだ筋トレ生活は続きそうです・・・(笑)

ポキオ リングフィットアドベンチャー

いやー、でも逆に言えば、長い期間に渡って楽しめるという意味では、よくできたゲームだなぁとつくづくと。本当の全クリを目指してがんばります。

Wemos Lolin ESP32 OLEDのケースを作ってみた

まずは形から。

ポキオ Wemos Lolin ESP32 OLED

今回はESP32系ボード

Wemos Lolin ESP32 OLEDって、文字通りESP32が乗ったボードなんですが、OLEDディスプレイもついているので、色々と面白そうなやつなんです。

ポキオ Wemos Lolin ESP32 OLED

今回は、こいつのケースを3Dプリンターで作ってみようと思います。

Fusion360でモデル作成

ノギスでボードのサイズを測りながら、Fusion360でモデルを作っていきます。

ポキオ Wemos Lolin ESP32 OLED

排熱を考えて、少し隙間を多めにとっています。また、サポート材が要らないようなシンプルな形で作っていきます。

ポキオ Wemos Lolin ESP32 OLED

モデルをCuraに渡して、3Dプリンタ用のファイルを作成。ここまではいい感じ。

印刷するよー

3Dプリンターは、この前買ったAnycubic Mega-S。

ポキオ Wemos Lolin ESP32 OLED

だんだん慣れてきました。フィラメントも防湿庫で管理しているせいか、特に劣化してる感じもなく調子いい感じです。

ポキオ Wemos Lolin ESP32 OLED

とりあえず下側作成完了。いい感じですね。続いて、蓋も作成。

ポキオ Wemos Lolin ESP32 OLED

ESP32部分は排熱を考慮して、あみあみにしてみました。

この投稿をInstagramで見る

ケースできたお。 #lolin32 #esp32 #anycubic #anycubicmegas

pokio(@pokiiiiio)がシェアした投稿 -

いざ実装

ケースができたので、早速動かしてみます。

ポキオ Wemos Lolin ESP32 OLED

こんな感じでコーディングします。

#include "SSD1306.h"
SSD1306  display(0x3c, 5, 4);

void setup() {
  display.init();
  display.setFont(ArialMT_Plain_24);
  display.setTextAlignment(TEXT_ALIGN_CENTER);
  display.drawString(64, 0, "Hello!");
  display.drawString(64, 20 - 4, "My name is");
  display.drawString(64, 40 - 4, "@pokiiio");
  display.display();
}

void loop() {
}

フォントも英数だけですが準備されているのでかんたんに文字表示可能です。

今回はWi-Fi/BLEを使っていない実装ですが、表示内容を動的に変えられると楽しそうですよねー。

テレワーク用の椅子(4脚目)

スレタイみたいになってきた。

ポキオ テレワーク 椅子

色々試した結果

テレワークがこんなに長引くとは夢にも思っていなかったわけで、色々な椅子やバランスボールを試したりしました。

椅子1:IKEA MARIUS

IKEAの激安スツール。意外と好きなんですが、座面が高いのと、長時間座ってるとお尻が痛くなるという、まぁそうだろうなという症状に見舞われました。

椅子2:バランスボール

まぁ、バランスボールにしておけば問題ないだろうと思ってたんですが、こちらも思いの外座面が高く、ディスプレイを見下ろす感じになってしまい、首が痛くなってしまいました。また、床の材質との相性が悪く、少し動くだけでギュッギュと鳴ってしまい、会議中に「絶対音を出してはいけない24時」みたいに鳴ってしまったのも非常に残念なポイントです。

椅子3:Colemanの小さい椅子

座面が高ければ低くすればいいじゃない、ということで家にあった低めのアウトドア用の椅子にチェンジ。ただ、過ぎたるは及ばざるが如し、低すぎてもタイピングしづらく速攻却下。

椅子4:ポンコタン ハイバックチェア

で、最終的にこれに落ち着いている。だいたい1ヶ月前に購入して、その後ずっと使ってるんですが、割と調子いいです。パット見Helinoxですが、値段がおかしいくらいに安い。

ポキオ テレワーク 椅子

問題の座面の高さは丁度良く、今使っているテーブルに対してはパーフェクトの高さ。

ポキオ テレワーク 椅子

ハイバックタイプなので、背中の高さは高く、頭もキャッチしてくれるくらい高いです。

ポキオ テレワーク 椅子

折りたたみタイプの椅子をなめていましたが、ホールド感が心地よく、柔らかいバケットシートに座ってるような感覚。あまりにもホールド感が良すぎて、立ち上がったり座ったりがちょっとだけ面倒なのが玉に瑕。

コスパ最高だけど本家も気になる

Amazonレビューで「すぐに壊れた」みたいなコメントがあったけど、1ヶ月毎日使ってて全然壊れる気配がしない・・・。

コスパ最強の折りたたみ型ハイバックチェアかなと思いつつ、もし壊れたら、今度は本家のHelinoxのハイバックチェアでも買ってみようかしら。

3Dプリンタの工具置き場を3Dプリンタで作っちゃうよ

よ!

ポキオ 3Dプリンター Anycubic Mega-S

ないものは作ればいい

マリー・アントワネットも同じようなこと言ってましたよね。

ポキオ 3Dプリンター Anycubic Mega-S

3Dプリンタを買って思ったのは、ステージから印刷物を剥がすのにヘラを使ったり、フィラメントを切ったりするのにニッパーをつかったり、意外と工具を使うんですよね。ただ、3Dプリンタにはそういう工具をしまっておく場所がないので、今回は工具置き場を作ってみます。

まずはヘラ置き場

3Dプリンターの肩の部分にボルトが飛び出ているので、それに引っ掛けるタイプの工具置き場を作ってみます。

ポキオ 3Dプリンター Anycubic Mega-S

上面の2つの穴でボルトに引っ掛けます。側面の2つの穴はネジ山を作って、もう一つのパーツをボルトで固定しようという魂胆です。

ポキオ 3Dプリンター Anycubic Mega-S

で、できたのがこちら。薄々気づいていましたが、ネジ山は思ったように印刷できておらず、ボルトをねじ込んでみましたが、全然だめでした・・・。

ポキオ 3Dプリンター Anycubic Mega-S

なので、ネジ穴にピッタリハマるようにもう一つのパーツを作って印刷。最後は接着剤でくっつけました・・・(笑)まじで接着剤は神です。

で、こんな感じ。

ポキオ 3Dプリンター Anycubic Mega-S

いい感じですね。

次はニッパー置き場

前回の失敗を踏まえて、

  • 1つのパーツでモデルを作成
  • サポート材不要な形状

こんな感じでモデルを作ってみました。

ポキオ 3Dプリンター Anycubic Mega-S

せっかくなので、ポキオマークを入れてみました(笑)

ポキオ 3Dプリンター Anycubic Mega-S

どうですかねー、変に凝らずにワンピースでシンプルに作ったほうがいいですね。

というわけで

今回の気付きですが、

  • ネジ山はそんなに精度が出ないので諦める
  • できるだけサポート材は使わない形状を作る
  • できるだけ1つのパーツでできるように考える

このあたり。モデル作成から頭を使って作る。楽しいですねぇ。

3DプリンターでArduinoケースを作ってみたんだけど

どう見ても怪しいデバイス

ポキオ 3Dプリンター Arduino ケース

今回はケース作成

先日買った3Dプリンターですが、今回はArduino互換機向けのケースを作ってみました。

relativelayout.hatenablog.com

と、いうのも、以前「他意はないけどArduinoでPCがスリープしないように」するデバイスを作ってみたんですが・・・。

relativelayout.hatenablog.com

その後、基板むき出しのまま使っていました。ちょっと見た目も怖いので、ケースを作ってみようかと。

この投稿をInstagramで見る

マウスエミュレーション、これだけでいいな。

pokio(@pokiiiiio)がシェアした投稿 -

つくるよー。

まず、ケースに収めたいのは

で、これらのサイズをざっくり採寸していきます。

たまたまカインズホームに行ったら、デジタルノギスが激安で売られていたので、それを使ってチャチャッと採寸できましたー。ノギスまじ便利。

ポキオ 3Dプリンター Arduino ケース

で、早速Fusion 360でモデルを作成して、即印刷。テキトーにやった割には結構ぴったり。

ポキオ 3Dプリンター Arduino ケース

ツーピースで作ったものの、接合のことを一切考えていなかったので、接着剤で力技接合。

なんとか完成

じゃーん。なんかいい感じに怪しいですね(笑)

ポキオ 3Dプリンター Arduino ケース

雑感として、

  • 思い立ったらすぐ作れるスピート感が良い
  • ノギスはマジ便利だし、デジタルノギスは素敵
  • 接合部分の設計をちゃんとできるようにしたい
  • 排熱のことを一切考えてなかった(てへぺろ

こんな感じ。ラズパイケースも作ってみたいですねぇ。

「Androidのメモとか」は、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、Amazonアソシエイト・プログラムの参加者です。

このブログは個人的なメモ書きであったり、考えを書く場所であります。執筆者の所属する団体や企業のコメントや意向とは無関係であります。また、このブログは必ずしも正しいことが書かれているとは限らず、誤字脱字や意図せず誤った情報を載せる場合がありえます。それが原因で読者が不利益を被ったとしても、執筆者はいかなる責任も負いません。ありがとうございます。