::class-exe

Software

nuxt/contentとVuetifyでコードブロックのスタイルがおかしくなる件

本ブログをnuxt/contentとVuetifyで作り直してみました。しかしながら、nuxt/contentで利用しているPrismJSとVuetifyが両方とも適用されたためかコードブロックのスタイルがおかしくなってしまいました。

シンタックスハイライトされたコードブロック

使用しているバージョンはこちら

Nuxt.js 2.14.7
Vuetify 1.11.2

とくにテキストの背景色が不要です。Chromeのデベロッパーツールで確認すると.v-application codeセレクタで背景色が適用されていました。

.v-application code

Stack Overflow1でも同様の質問があったので、解決策通りにunsetします。

.v-application code {
  all: unset
}

結果、PrismJSだけのスタイルになったようです。

修正後

October 16, 2020 作成

トラッキングアプリにGASでカレンダー対応する

最後はいつ?というトラッキングアプリはシンプルなUIで使いやすいが、カレンダーに対応していない。GASでカレンダー対応してみる。

‎「最後はいつ? - あなたの大切な出来事をトラッキング」をApp Storeで

"1年経過: トイレ掃除"といった内容のカレンダーイベントを作成するのが目標。

同期化の設定を有効にして、Dropboxに保存されるファイルをカレンダーの登録に利用する。

"Dropbox⁩/アプリ/Last Time/⁨MainStore.V2/⁨baselines⁩"に同期するために必要なファイルが保存されていた。

ファイルの中身はJSON形式で、以下のような内容が記載されている(関係ない要素は省いている)。

    "changesByEntity": {
        "Event": [
            {
                "properties": [
                    {
                        "propertyName": "lasttime",
                        "value": [
                            "date",
                            1537707955000
                        ],
                        "type": 0
                    },
                    {
                        "propertyName": "name",
                        "value": "トイレ掃除",
                        "type": 0
                    },
                ],
            },
        ]
    }
}

nameプロパティにはイベント名、lasttimeプロパティには直近のイベント更新時のミリ秒のUNIX timeが記載されていた。

このファイルをDropboxの公開リンクからアクセスして、GASでカレンダ ー登録を処理する。

コードは以下の通り。

function getLastTimeJSON() {
  var url = "Dropbox 公開リンクURL";
  var response = UrlFetchApp.fetch(url);
  var content = response.getContentText("UTF-8");
  var json = JSON.parse(content);
  
  return json;
}

function makeLastTimeEvent() {
  var json = getLastTimeJSON();
  var events = json.changesByEntity.Event;
  
  var calendarEvents = [];
  
  for (var i in events) {
    var properties = events[i].properties;
    var _name;
    var _lasttime;
    for (var j in properties) {
      var property = properties[j];
      if (property.propertyName == "name") {
        _name = property.value;
      }
      if (property.propertyName == "lasttime") {
        _lasttime = property.value[1];
      }
    }
    var calendarEvent = {
      name: _name,
      lasttime: new Date(_lasttime)
    };
    calendarEvents.push(calendarEvent);
  }
  return calendarEvents;
}

function setLastTimeItem(toCalId) {
  var calendarEvents = makeLastTimeEvent();
  var targetCal = CalendarApp.getCalendarById(toCalId);
  
  for (var i in calendarEvents) {
    var next = new Date();
    var lasttime = calendarEvents[i].lasttime;
    var name = calendarEvents[i].name;

    next.setTime(lasttime);
    next.setYear(lasttime.getYear() + 1);

    var title = "1年経過: " + name;
    targetCal.createAllDayEvent(title, next);
}

var lastTimeCalId = "GoogleカレンダーID";
function main(){
  setLastTimeItem(lastTimeCalId);
}

参考

September 1, 2019 作成

October 16, 2020 リンク切れを修正、サンプルコードを一部修正

電子ペーパー名札をつくる その3

デモも動いたので名札っぽく自分の名前を表示してみましょう。

画像を用意する

せっかくの3色の電子ペーパーなので、黒色だけでなく赤色も用意します。デモコードをそのまま利用するので2枚画像を用意します。

市販の名札ケースに逆さに入れると、こんな感じに。これだけでもアイコンが表示できてオフ会とかで便利そうです。

しかし、Raspberry Piの電源用にUSBケーブルが見えてたり、裏側がやっつけだったりします。

December 13, 2018 作成

電子ペーパー名札をつくる その2

さてRaspberry Piと接続して動作確認してみます。

ライブラリの準備

ありがたいことに開発に関してはWikiがあるのでさらっと一読しておきます。

4.2inch e-Paper Module (B) - Waveshare Wiki

今回はPythonでディスプレイを制御したかったので、まずは後述のデモを動かすのに必要なライブラリをいれておきます。同じくWikiに記載されています。

https://www.waveshare.com/wiki/Pioneer600#Install_Python_Library

Raspberry Piとの接続

Raspberry Pi上のGPIOとディスプレイのHATを繋げましょう。動作確認につかったRaspberry Piは古い世代なのかHATがそのままGPIOピンに刺さらず、コネクタ付きのワイヤで接続しました。

デモの確認

Wikiからたどってデモを準備しましょう。

https://www.waveshare.com/wiki/File:4.2inch-e-paper-module-b-code.7z

デモをダウンロードでして、7zを展開して動かしてみましょう。

pi@raspberrypi:~/demo/RaspberryPi/python2 $ sudo python main.py

フォントが無いとか怒られたら、適当なものに変えてみてください。

font = ImageFont.truetype('/opt/vc/src/hello_pi/hello_font/Vera.ttf', 24)

GPIOピンの接続がもし間違っていると、

接続も、デモもうまく動作するとこんなかんじです。

参考にしたのはこちら

ありがとうございます。

RaspberryPiによる電子ペーパーの制御 – Isaax Camp

December 6, 2018 作成

電子ペーパー名札をつくる その1

電子ペーパー名札をつくってみました。まずは電子ペーパー選びです。

電子ペーパー

購入したのはWaveshareというブランドの4.2inchの電子ペーパーです。解像度は400x300で、赤黒白と3色表示ができます。

400x300, 4.2inch E-Ink raw display, three-color, SPI interface, without PCB | WFT0420CZ15

これはディスプレイだけです。Raspberry Piと接続したかったので、追加でHATも必要でした。

Universal e-Paper Driver HAT, supports various Waveshare SPI e-Paper raw panels

注文してみる

ディスプレイ、HAT、送料で$40.48でした。

2018/2/6に支払いをして、2/14には届きました。シンガポールからだったのですぐでしたね。

December 6, 2018 作成

iOSヘルスケアアプリに体重データを一括入力する

利用していた体重記録アプリがiOSヘルスケアアプリに対応しませんでした。そこでエクスポートした体重データをヘルスケアアプリに一括入力してみました。

体重データをエクスポートする

シンプル・ダイエットというアプリから体重データをエクスポートします。データはGoogleドライブに保存されます。‎エクスポート元アプリはこちらです。

「シンプル・ダイエット 〜 記録するだけ!かんたん体重管理 〜」

以下のようなカラムでエクスポートされました。

エクスポートデータを編集する

今回はエクスポートしたデータを、ヘルスケアアプリに対応した別の体重記録アプリにインポートさせます。インポート先アプリはこちらです。

「RecStyle -ダイエット・体重管理-」

RecStyleは以下のようなフォーマットで扱われています。

体重、体脂肪率のデータをRecStyleData.csvの対応するカラムに貼り付けます。SimpleWeight-Export.csvとRecStyleData.csvのフォーマット違いは以下3点ぐらいでした。

  • A3セルにデータ数を入れる。
  • RecStyleData.csvの日時にはSimpleWeight-Export.csvと違い日付しかない。つまりインポート時に時刻は落ちてしまう点に注意。
  • RecStyleData.csvにはBMIのデータがある。

編集した体重データをインポートする

Dropboxに保存した編集済みRecStyleData.csvをRecSytleにコピーするかたちでインポートさせます。

うまくRecStyleにインポートできました。

インポートできたら、ヘルスケア連携を有効にします。

ヘルスケアアプリで体重データを確認する

体重データがインポートされたらヘルスケアアプリで確認してみます。うまくいけば以下のように表示されます。

さいごに

ヘルスケアに対応していないシンプル・ダイエットですが、詳しい経緯は公式サポートページに記載されていました。

iOSの「ヘルスケア」の対応について | シンプル・ダイエット

October 13, 2018 作成

LINEのリッチメニューの表示期間を変更する

LINEのリッチメニューが便利なので設定していますが、表示期間を過ぎると再設定が必要です。いつもどこで設定するのか忘れてしまうのでメモを残します。

LINE@マネージャーにログインします

LINE@マネージャー

リッチメニューを編集します

  1. アカウント一覧から編集したいBotを選択します。000f9bfee871b5d9e757024ca39092a9
  2. 左ペインからリッチコンテンツ作成を選択します。679d1f6ebf4c853a94e53283aba2437c
  3. 編集したいリッチメニューを選択します。select_the_rich_menu

表示期間を変えます

適切な表示期間に変えましょう。

33e31752d8060e061a9a32f06f897bbc

ドキュメントに書いてありました

リッチメニューを設定したくて、LINE@マネージャーではなくLINE Developersにログインしてしまうことが多かったです。探してみたらデフォルトのリッチメニューについてはドキュメントに書いてありました。

LINE@マネージャーで設定する

October 6, 2018 作成

LINEでベクターキャノンを準備してもらう

LINEのMessaging APIで、ボットにセリフを喋ってもらいます。

ボット用アカウントをつくる

LINE Business Centerでボット用アカウントを作ります。詳しくは割愛しますが、個人用だったのでDeveloper Trialで作っています。

LINE Business Center

bot_account

HTTPSが使えるサーバを準備する

Webhook使ってメッセージを受け取るので、HTTPSで受け取れるようなサーバを準備してください。

ボット用のSDKを手に入れて、実装する

便利なSDKがあるのでinstallしましょう。

line/line-bot-sdk-python: SDK of the LINE Messaging API for Python.

Usage:にサンプルがあるので利用します。セリフを喋るためにちょっと手を加えたのがこちらです。

from flask import Flask, request, abort
from dotenv import load_dotenv, find_dotenv
import time
import os

from linebot import (
    LineBotApi, WebhookHandler
)
from linebot.exceptions import (
    InvalidSignatureError
)
from linebot.models import (
    MessageEvent, TextMessage, TextSendMessage,
)

app = Flask(__name__)
load_dotenv(find_dotenv())

line_bot_api = LineBotApi(os.environ.get('CHANNEL_ACCESS_TOKEN'))
handler = WebhookHandler(os.environ.get('CHANNEL_SECRET'))


@app.route("/ada", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)
    print(body)

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        abort(400)

    return 'OK'


@handler.add(MessageEvent, message=TextMessage)
def handle_message(event):
    to = ''
    if event.source.type == 'group':
        to = event.source.group_id
    if event.source.type == 'user':
        to = event.source.user_id
    if event.message.text == "ベクターキャノン":
        line_bot_api.push_message(to, TextSendMessage(text='ベクターキャノンモードへ移行'))
        time.sleep(3)
        line_bot_api.push_message(to, TextSendMessage(text='エネルギーライン全段直結'))
        time.sleep(2)
        line_bot_api.push_message(to, TextSendMessage(text='ランディングギア、アイゼン、ロック'))
        time.sleep(3)
        line_bot_api.push_message(to, TextSendMessage(text='チャンバー内、正常加圧中'))
        time.sleep(2)
        line_bot_api.push_message(to, TextSendMessage(text='ライフリング回転開始'))
        time.sleep(7)
        line_bot_api.push_message(to, TextSendMessage(text='撃てます'))


if __name__ == "__main__":
    app.run()

できました

こちらが「ベクターキャノン」と言うと、ボットは某ゲームのセリフを喋ります。

line_ada_bot

September 18, 2017 作成