ChinoDuino(Chino × Arduino)

自発性のないプログラマーがArduinoと出会って悪戦苦闘する様を綴っていく⇒今はいろいろ(^^;

FitbitのWeb APIで睡眠を振り返る😴

この記事は 日本システム技研 - Qiita Advent Calendar 2025 - Qiita の3日目の記事です📅

私はFitbitを数年前から愛用しています⌚ FitbitのWeb APIを使用すると睡眠データ等が取得できますので、それを使用して睡眠を振り返ってみたいと思い、まずはお試しで触ってみました!その時の備忘録です!😴

FitbitのWeb APIを使用するときの参考になればうれしいです!

やること

  • FitbitのWeb APIへアクセスするための認証情報を取得
  • 取得した睡眠データを表示するWebアプリを開発(生成AIを使用)
  • 睡眠を振り返る

FitbitのWeb APIへアクセスするための認証情報を取得

これはFitbitのDeveloperサイトから取得できます!

https://dev.fitbit.com/apps

上記のURLにアクセスしログイン→「MANAGE MY APPS」のタブを選択→「+Register a new app」を選択

アプリの登録ページが開くので必要な情報を入力し登録(今回はお試しで一次的なものなのでWebサイトはlocalhostとしていますがお勧めしません)

Client ID、Client Secretが取得でき、Webアプリで使用します

取得した睡眠データを表示するWebアプリを開発(生成AIを使用)

Webアプリは「Github Copilot(Agentモード | モデルは「Claude Sonnet 4.5」)」で作成しました(Next.js/TypeScript)

ソースはこちら → GitHub - peacemaker07/fitbit-app

起動( npm run dev )しアクセスするとログインページが表示されるのでログインを行う

アクセス許可のページが表示されるので許可を行う

検索ページが表示されました!よさそうです🙌

睡眠を振り返る

使用しているWeb API(※)の仕様を参照すると「期間上限が100日(Maximum range: 100 days)」となっています

Get Sleep Log by Date Range

このため、3ヶ月ごと取得してみました!

⚠️ ちなみに、1時間の上限リクエスト数が「150」なので注意!

Rate Limiting

The Fitbit API has rate limiting in place to protect the service from abuse. Developers can make up to 150 requests per hour per user. If the ?rate limit is exceeded, the API will respond with a 429 Too Many Requests status code.

Fitbit API - PublicAPI

1月から3月末(左から2023年、2024年、2025年)

4月から6月末(左から2023年、2024年、2025年)

7月から9月末(左から2023年、2024年、2025年)

10月から12月末(左から2023年、2024年、2025年)

結果

  • 大体、平均睡眠時間は3年間通して6時間くらいで安定している
  • 凸凹は平日が短めで週末を長く寝ているから(^^;
    • あまりよろしくなさそう。。。
  • ちょっとわかりづらいですが、床上時間と睡眠時間の差が大きいところは休日
    • これはベッドの上で休日は動画みていたりするので。。。(ちょっとした楽しみ)

結果として、新しい発見があったというよりは、普段の生活習慣が数値で表されて納得した感じ📝 今後、他要素(睡眠スコア?天気?他)と組み合わせて再検証してみると面白いかも🥱

Sigfoxデバイスの初回通信時に回線停止日を設定してみる

この記事は 日本システム技研 - Qiita Advent Calendar 2025 - Qiita 2日目の記事です!

個人的にSigfox Backend Cloudを触っています。そのなかで、Sigfox回線を使用しているデバイスの初回通信時に回線停止日の設定を行いたいと思い、そのときにやったことの備忘録です。

Sigfox Backend Cloudを利用しているひとの参考になればうれしいです🙏

Sigfoxとは|IoTネットワーク「Sigfox」|KCCS

Sigfoxとは

  • Sigfox(シグフォックス)はフランスのUnaBiz SAS社が各国のオペレーターを通じて提供しているLPWA(0G)ネットワーク
  • 低価格・低消費電力・長距離伝送が特長で、一定間隔で通信をしたい用途に適していると思います(農業用ハウスの室温を一定間隔で送信するなど)

Sigfox Backend CloudではSigfox回線のデバイス管理やAPI連携、Callback機能で特定のイベント発生時に別クラウドAWS、Azure等)へデータ転送等できます。ブラウザから各操作、設定等行えます

どうやって実現するか

今回はSigfox Backend CloudにあるCallback機能を使用して実現します

⚠️ まだ未完成のため、Webアプリケーションサーバ側、Sigfox Backend Cloud側ともに途中経過になりますのでご了承を 🙏

構成

Sigfoxを始めよう|Sigfoxとは|IoTネットワーク「Sigfox」|KCCS

上記ページの「Callback」の図を引用

やること

Webアプリケーションサーバ

  • Basic認証を使用したWebAPIを作成
    • このWebAPIのなかで回線停止日を設定
    • ⚠️ 認証方法に関しては今後変更する可能性があります

Sigfox Backend Cloud

  • 「Event configuration」にある「Custom callback」を使用
    • 「Event Type」の「Receive first payable message」が初回通信時なので、このイベント発生時にWebアプリケーションサーバ側のWebAPIを呼び出す

Basic認証を使用したWebAPIを作成

WebAPIを作成

WebフレームワークはDjangoを使用しているので、今回はDjango Rest Frameworkを使用します

  • BasicAuthentication を使用することで実現ができます。
  • Sigfox Backend CloudからPOSTでリクエストされるので post とします
・・・
from rest_framework import views, status
from rest_framework.response import Response
from rest_framework.authentication import BasicAuthentication
from rest_framework.permissions import IsAuthenticated
・・・
class SigfoxCallbackAPIView(views.APIView):
    """
    Sigfox Backend Cloudからのコールバックを受け取るAPIビュー
    Basic認証を使用してSigfoxからの初回通信の対象メッセージを受信

    https://support.sigfox.com/docs/receive-first-payable-message
    """

    authentication_classes = [BasicAuthentication]
    permission_classes = [IsAuthenticated]

    def post(self, request, *args, **kwargs):
        """
        Sigfoxからのコールバックデータを受信

        Expected payload from Sigfox:
        {
            "device": "device_id",
            "time": "unix_timestamp",
            "data": "payload_data",
・・・
        }
        """
        logger.info(f"Received Sigfox callback: {request.data}")

        # シリアライザでバリデーション
        serializer = SigfoxCallbackSerializer(data=request.data)
        if not serializer.is_valid():
            logger.error(f"Validation error: {serializer.errors}")
            return Response(
                {"detail": "Invalid payload", "errors": serializer.errors},
                status=status.HTTP_400_BAD_REQUEST
            )

        validated_data = serializer.validated_data
        device_id = validated_data.get('device')

        # デバイスの存在確認
        try:
            sigfox_device = SigfoxDevice.objects.get(imsi=device_id)
            device = Device.objects.get(imsi=sigfox_device.imsi)
        except (SigfoxDevice.DoesNotExist, Device.DoesNotExist):
            logger.warning(f"Device not found: {device_id}")
            return Response(
                {"detail": f"Device {device_id} not found"},
                status=status.HTTP_404_NOT_FOUND
            )
・・・

ブラウザからAPIにアクセスしてみると認証を求められることを確認 👍️

それと疎通確認として以下のコードでアクセスしusername、passowrdが存在するユーザーの時にViewが実行されることを確認 👍️

import requests
from requests.auth import HTTPBasicAuth

response = requests.post(
    'http://127.0.0.1:8000/api/sigfox/callback/',
    auth=HTTPBasicAuth('username', 'password'),
    data={'device': '12345'}
)

print(response)

回線停止日の設定

こちらはSigfox Backend Cloudが提供するAPIを使用します

上記のAPIをWebAPIからリクエストして、該当の端末の回線停止日を設定します

リクエストのPayloadはこのようなかたち 📝

{
  "data": [
    {
      "id": "12345",  # sigfox回線を利用しているデバイスの端末ID
      "unsubscriptionTime": 1534165000000  # 回線停止日時(UnixTime形式)
    }
  ]
}

リクエスト用に作成したメソッドはこちら

class SigfoxApi:

    api_base_url = "https://api.sigfox.com/v2"

・・・

    def request_devices_bulk_unsubscribe(self, unsubscribes, sigfox_api_user_key_name, sigfox_api_password_key_name):
        """
        https://support.sigfox.com/apidocs#operation/deviceBulkUnsubscribe
        """
        path = "/devices/bulk/unsubscribe"

        # リクエストのPayload形式に変更
        data = {
            "data": [
                {
                    "id": unsubscribe[0],
                    "unsubscriptionTime": unsubscribe[1],
                } for unsubscribe in unsubscribes
            ]
        }
        headers = {
            "Content-Type": "application/json"  # JSON形式を指定
        }

        return self._post(path, [認証情報], data=json.dumps(data), headers=headers)

・・・

    def _post(self, path, auth, data=None, json_param=None, headers=None):

        if not auth:
            raise Exception("No auth")

        response = requests.post(
            f"{self.api_base_url}{path}", data, json_param, headers=headers, auth=auth)
        response.raise_for_status()

        return response
・・・

「Event configuration」にある「Custom callback」を使用

この「Event configuration」を使用すると、特定のイベントが発生したときのcallbackを登録できます。

Event type | Sigfox Resources

今回使用する「初回通信」以外にもcallbackを登録できるイベントがいくつかあります。

設定を行う

  • Sigfox Backend Cloudにログインします
  • 上段にある「DEVICE TYPE」を選択
  • DEVICE TYPE一覧が表示されるので、「Name」列の該当のDEVICE TYPEを選択
  • 「EVENT CONFIGURATION」を選択
  • 右上の「new」を選択
  • 「Custom callback」を選択するとcallbackの設定ページが表示されます

イベント(Event type)と通知方法(Channel)などを選択、設定します

  • Event type:Receive first payable message
  • Channel:URL
  • Url pattern:https://・・・/api/sigfox/callback/ (作成したWebAPIのエンドポイント)
  • Headers
    • キー名:Authorization
    • 値:Basic [「ユーザ名:パスワード」のbase64エンコードしたもの]
  • Content type:application/json
  • Body:{"time":"{time}", "severity":"{severity}", "sourceId":"{sourceId}", "sourceType":"{sourceType}", "eventType":"{eventType}", "deviceTypeId":"{deviceTypeId}", "groupId":"{groupId}", "deviceInfo":"{deviceInfo}", "deviceMessageTime":"{deviceMessageTime}"}

「OK」で設定完了です!

補足:「ユーザ名:パスワード」のbase64エンコードしたものの出し方

Djangoのカスタムコマンドで作成しました

コードは以下です!

import base64
from django.core.management.base import BaseCommand


class Command(BaseCommand):
    """
    python manage.py generate_basic_auth <username> <password>
    """
    help = 'Generate Base64 encoded credentials for Basic Authentication'

    def add_arguments(self, parser):
        parser.add_argument('username', type=str, help='Username for authentication')
        parser.add_argument('password', type=str, help='Password for authentication')

    def handle(self, *args, **options):
        username = options['username']
        password = options['password']

        # username:password の形式で結合
        credentials = f"{username}:{password}"

        # Base64エンコード
        encoded_credentials = base64.b64encode(credentials.encode('utf-8')).decode('utf-8')

        # 結果を出力
        self.stdout.write(self.style.SUCCESS(f'Authorization Header: Basic {encoded_credentials}'))

実行はこんな感じ

$ python manage.py generate_basic_auth [username(ユーザ名)] [password(パスワード)]

参考

参考になればうれしいです!

AmplifyでPythonのfunctionを追加したけど2回目のpushができない😇

AmplifyでPythonのfunctionを追加し amplify push をして、プログラムを修正後、もう一度、 amplify push したらエラーがでてpushできなかったときの対処方法の備忘録📝

環境

  • macOS Ventura バージョン13.5.2
  • @aws-amplify/cli:12.4.0

エラー内容

$ amplify push  
✖ There was an error pulling the backend environment dev.
🛑 ENOENT: no such file or directory, stat '/xxxx/react-ts-workspace-amplified/amplify/.temp/#current-cloud-backend/function/samplePythonFunction/.venv/bin/python'

#current-cloud-backend 内にPythonの仮想環境の .venv があり、その中にシンボリックリンクがあることが悪さをしているらしい。

#current-cloud-backend は現在のクラウド状態が格納されている。

#current-cloud-backend

対処方法

Pipenvの2つの環境変数.env に記載し対処

  1. プロジェクト配下に仮想環境を配置するか指定できる環境変数PIPENV_VENV_IN_PROJECT
  2. 仮想環境の独自の配置場所を指定できる環境変数 WORKON_HOME

Amplifyでは「PIPENV_VENV_IN_PROJECT」がデフォルトで「true」になっているようなので、 amplify push を行うと作成したfunction配下に仮想環境( .venv )が作成される

これが #current-cloud-backend にはいってしまう。

このため、 Pipenvの.env の自動読み込み機能を利用するため .envPipfile と同じ場所に配置し以下を記載

PIPENV_VENV_IN_PROJECT=false
WORKON_HOME=../../../../.venvs
  • .envの記載内容の補足
    • PIPENV_VENV_IN_PROJECTtrue のままだと WORKON_HOME が有効にならなかった
    • このため PIPENV_VENV_IN_PROJECTfalse に設定し
    • 仮想環境の配置場所を #current-cloud-backend に含まれない場所に変更

無事、2回目以降も amplify push できるようになりました🙌

懸念点

ただ、この方法だとPythonのfunctionが複数になった場合、仮想環境が被ってしまうので、 amplify/backend/function とは別の場所でPipfileを統一した方がよさそう

補足:エラーが出た場合の復帰方法

こちら参考にさせていただきました!ありがとうございます🙏

以下ページの「amplify pushができなくなったら」です!

https://strip.koatech.info/articles/amplify-function/

SORACOM Beamのプラットフォームバージョン変更ではまなったこと

「プラットフォームバージョン 201509 は 2022 年 8 月 1 日にサポートを終了します」ということで少し遅くなってしまいましたが「201912」に変更したところエラーがでたのでその備忘録です!(ちなみにちゃんと以下ドキュメントを読んでいればはまらなかった・・・)

users.soracom.io

プラットフォームバージョンを変更

SORACOMコンソールで該当グループのBeamのプラットフォームバージョンを「201912」に変更し保存

他設定はこんな感じ

  • 転送先
    • 種別:Standard
    • プロトコル:MQTT
    • ホスト名:xxxxx.iot.ap-northeast-1.amazonaws.com
      • AWSのIoT Coreに転送しています
    • ポート番号:8883
  • 証明書 (key と cert) を利用しています

エラー

データをBeamに送ったところ以下エラーが発生

{
  "time": xxxxxxxxxxxxx,
  "service": "Beam",
  "resourceType": "Subscriber",
  "resourceId": "xxxxxxxxxxxxxxx",
  "body": {
    "message": "[MQTT] Destination error mqtt://xxxxx.iot.ap-northeast-1.amazonaws.com:8883: Cannot parse protocolId"
  }
}

原因

以下ちゃんと記載があるのに、転送先プロトコルを「MQTT」のまま変更していませんでした😇

「201509」のときに転送先プロトコルを「MQTT」にしていましたが、証明書 (key と cert) を利用していたので、「MQTTS」で接続してくれていたんですね!今回、プラットフォームバージョンを変更したことにより「MQTT」で接続するようになりエラーが発生したようです📝

プラットフォームバージョン 201509 においては、証明書 (key と cert) を利用している場合、転送先に接続するプロトコルの設定に関わらず MQTTS プロトコルで転送先に接続されます。プラットフォームバージョン 201912 においては、証明書の利用有無に関わらず、転送先に指定されたプロトコルで接続します。転送先のプロトコルが正しく設定されているかを事前に確認ください。

リファレンス: 制限事項と注意事項 | SORACOM Beam | ソラコムユーザーサイト - SORACOM Users

対処

SORACOMコンソールで該当グループのBeamの転送先プロトコルを「MQTTS」に変更したところ無事解決🙌

(ちなみに、別アカウントではプラットフォームバージョンを変更しても特にエラーがでなかったのでそちらとBeamの設定を比較したところ気がつきました(^^; )

Notionで進捗状況を可視化してみる

スケジュール管理するときに、予定日、開始日、終了日を入力しいちいち状況を「着手中」とか「完了」とか変更するのがめんどいし、遅れているのかオンスケなのかわからない・・・

なのでNotionのpropertyにある Formula を使って日付を入力すると現状の進捗状況が自動で切り替わるようにしてみました🙌

前提

property: Formulaについて

ExcelGoogle Sheetsの関数と同じような機能です。合計値や様々な値の算出が可能です。

詳細はこちら!

extns.notion.site

このように prop("[property名]") でpropertyの値を参照できたり、分岐やいろいろな関数等が用意されています🙌

youtu.be

完成イメージはこちら

予定、開始日、終了日により 状態状況 がかわります👀

※ 進捗バー、進捗率は「おまけ」で説明します🙏

作成していきましょう!

まずは各propertyを用意

名前 タイプ 内容
状態 Formula empty(prop("終了日")) ? (empty(prop("開始日")) ? "" : "👨‍💻") : "🔚"
状況 Formula if(empty(prop("終了日")) == false, "🔚", if(start(prop("予定")) > now(), if(empty(prop("開始日")) == false, "🆒", ""), if(empty(prop("開始日")), "🔥", if(end(prop("予定")) < now(), "🔥", "✅"))))
予定 Date 予定日を入力。 End date をONにしてrangeで設定。
開始日 Date 該当のタスクに着手開始した日を入力
終了日 Date 該当のタスクが完了した日を入力

状態状況 の判定については以下を参照

状態の判定について

状況の判定について

完成したもの

youtu.be

おまけ

進捗バー、進捗率については以下を参考に作成させてもらいました🙏

ただ、進捗率により進捗バーを変更するようにした簡易版です!

【Notion】進捗を可視化したガントチャートの作成手順 - Qiita

property
名前 タイプ 内容
進捗バー Formula slice("▓▓▓▓▓▓▓▓▓▓", 0, prop("進捗率") * 10) + slice("░░░░░░░░░░", 0, 10 - prop("進捗率") * 10)
進捗率 Number Number formatPercent に設定
完成したもの

youtu.be

Let's Enjoy Notion🙌

Flutterインストール📝 to Mac

自分のMacに以下サイトを参考にFlutterをインストールしたときの備忘録📝

docs.flutter.dev

環境

  • macOS Monterey
  • バージョン:12.4
  • プロセッサ:Intel Core i5
  • メモリ:32G
  • ログインシェル:zsh

インストール

Get the Flutter SDK

Intel用のFlutter SDKファイル(zip)をダウンロードし解凍

解凍したファイルはホームディレクトリ配下に以下のように配置

$ cd
$ cd Documents
$ mkdir development
$ cd development
$ pwd
/Users/chino/Documents/development
# 解凍したファイルを移動
$ mv ~/Downloads/flutter ./
$ ls -la
total 0
drwxr-xr-x   3 chino  staff    96  7 24 10:49 .
drwx------@ 58 chino  staff  1856  7 24 10:49 ..
drwxr-xr-x@ 27 chino  staff   864  7 14 05:40 flutter

Flutterのパスを設定

$ vi ~/.zshrc

# 以下を追記し保存

---
# flutter
export FLUTTER_HOME="$HOME/Documents/development/flutter"
export PATH="$PATH:$FLUTTER_HOME/bin"
---

Run Flutter Doctor

flutterの doctor というコマンドでFlutterに必要な開発環境が準備できているか確認できるので実行💻

$ flutter doctor

  ╔════════════════════════════════════════════════════════════════════════════╗
  ║                 Welcome to Flutter! - https://flutter.dev                  ║
  ║                                                                            ║
  ║ The Flutter tool uses Google Analytics to anonymously report feature usage ║
  ║ statistics and basic crash reports. This data is used to help improve      ║
  ║ Flutter tools over time.                                                   ║
  ║                                                                            ║
  ║ Flutter tool analytics are not sent on the very first run. To disable      ║
  ║ reporting, type 'flutter config --no-analytics'. To display the current    ║
  ║ setting, type 'flutter config'. If you opt out of analytics, an opt-out    ║
  ║ event will be sent, and then no further information will be sent by the    ║
  ║ Flutter tool.                                                              ║
  ║                                                                            ║
  ║ By downloading the Flutter SDK, you agree to the Google Terms of Service.  ║
  ║ Note: The Google Privacy Policy describes how data is handled in this      ║
  ║ service.                                                                   ║
  ║                                                                            ║
  ║ Moreover, Flutter includes the Dart SDK, which may send usage metrics and  ║
  ║ crash reports to Google.                                                   ║
  ║                                                                            ║
  ║ Read about data we send with crash reports:                                ║
  ║ https://flutter.dev/docs/reference/crash-reporting                         ║
  ║                                                                            ║
  ║ See Google's privacy policy:                                               ║
  ║ https://policies.google.com/privacy                                        ║
  ╚════════════════════════════════════════════════════════════════════════════╝


Running "flutter pub get" in flutter_tools...                      10.3s
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.0.5, on macOS 12.4 21F79 darwin-x64, locale ja-JP)
[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from: https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK components.
      (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.

[!] Xcode - develop for iOS and macOS (Xcode 13.4.1)
    ✗ CocoaPods not installed.
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your
        plugin usage on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To install see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.
[✓] Chrome - develop for the web
[!] Android Studio (not installed)
[✓] VS Code (version 1.69.1)
[✓] Connected device (2 available)
[✓] HTTP Host Availability

! Doctor found issues in 3 categories.

以下がまだ準備できていなかった

CocoaPodsのインストール

To install see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.

ということなのでCocoaPods Guides - Getting Startedを参照しインストール👀

$ sudo gem install cocoapods

パスを設定

$ vi ~/.zshrc

# 以下を追記し保存

---
export GEM_HOME=$HOME/.gem
export PATH=$GEM_HOME/bin:$PATH
---

もう一度、 doctor を実行!

$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.0.5, on macOS 12.4 21F79 darwin-x64, locale ja-JP)
[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from: https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK components.
      (or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.

[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
[✓] Chrome - develop for the web
[!] Android Studio (not installed)
[✓] VS Code (version 1.69.1)
[✓] Connected device (2 available)
[✓] HTTP Host Availability

! Doctor found issues in 2 categories.

Xcodeについては準備完了🙆

Android関連のインストール

(or visit https://flutter.dev/docs/get-started/install/macos#android-setup for detailed instructions).

ということなのでmacOS install | Flutterを参照しセットアップ!

まずはAndroid Studioをインストール

インストール後、Android Studioを起動し初期セットアップも完了

再び doctor を実行!

flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.0.5, on macOS 12.4 21F79 darwin-x64, locale ja-JP)
[!] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/docs/get-started/install/macos#android-setup for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.2)
[✓] VS Code (version 1.69.1)
[✓] Connected device (2 available)
[✓] HTTP Host Availability

! Doctor found issues in 1 category.

✗ cmdline-tools component is missing

macOS install | FlutterのページでAndroid Studioの初期セットアップ時にインストールされると記載があったがなぜかインストールされず。。。一応、 sdkmanager を実行してみたが command not found になってしまった・・・

このため、こちらのDownload Android Studio & App Tools - Android Developersからzipファイルをダウンロードできるようなのでダウンロード、解凍してSDK配下に配置

# SDK配下に移動
$ cd /Users/chinoyuuji/Library/Android/sdk

# ダウンロードして解凍したcommand-toolsをsdk配下に配置
$ sudo mv ~/Downloads/cmdline-tools ./

SDKの場所はAndroid Studioを起動し確認しました

sdkmanagerのパスを設定

$ vi ~/.zshrc

# 以下を追記し保存

---
# Android
export ANDROID_USER_HOME="/Users/chinoyuuji/Library/Android"
export ANDROID_HOME="$ANDROID_USER_HOME/sdk"
export ANDROID_CMDLINE_TOOLS="$ANDROID_HOME/cmdline-tools"
export PATH="$PATH:$ANDROID_CMDLINE_TOOLS/bin"
---

sdkmanagerの最新をインストール

$ sdkmanager --install "cmdline-tools;latest"
The operation couldn’t be completed. Unable to locate a Java Runtime.
Please visit http://www.java.com for information on installing Java.

JAVAがインストールしていなかったので、http://www.java.comからjavaをインストールしてから再度、コマンドを実行

$ sdkmanager --install "cmdline-tools;latest"
Error: Could not determine SDK root.
Error: Either specify it explicitly with --sdk_root= or move this package into its expected location: <sdk>/cmdline-tools/latest/

SDKのパスを指定が必要だったので指定して再実行!

$ sdkmanager --install "cmdline-tools;latest" --sdk_root=/Users/chinoyuuji/Library/Android/sdk
[=======================================] 100% Unzipping... cmdline-tools/lib/RE

できたみたいなので、 doctor で出力されていたもうひとつのコマンドを実行(すべて「y」で承諾)

$ flutter doctor --android-licenses
・・・
All SDK package licenses accepted

再び、 doctor を実行👀

$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.0.5, on macOS 12.4 21F79 darwin-x64, locale ja-JP)
Checking Android licenses is taking an unexpectedly long time...[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.2)
[✓] VS Code (version 1.69.1)
[✓] Connected device (2 available)
[✓] HTTP Host Availability

• No issues found!

No issues found! になり準備完了🙌

TWELITEをいじってみる(センサデータをみてみる)

この記事は↓の続きになります!

chinoppy.hatenablog.com

今回は、TWELITE DIPにセンサを繋いで、MONOSTICKで受信したセンサデータをみてみます!

こちらのページが参考になりますが、スイッチサイエンスで購入したBME280は配線が違うため、あわせて記載していきます📝

mono-wireless.com

前提

センサデータをみてみる

準備

ハード側

配線はこちら

f:id:chinoppy:20220321134957j:plain:w800

ソフトの書き換え、設定の編集・変更

手順としては無線タグアプリ (App_Tag) - MONO-WIRELESS.COMをMONOSTICK、TWELITE DIPに書き込み、設定等をインタラクティブモードで編集・設定します!

  • TWELITE DIPに子機用の「App_Tag_EndDevice_Input」を書き込み
  • MONOSTICKにOTAでTWELITE DIP側の設定を変更する「App_Tag_EndDevice_Input_OTA」を書き込み
  • インタラクティブモードで子機用の設定を行う
  • 子機(TWELITE DIP)の設定を変更
  • MONOSTICKでデータを受信するための「App_Tag_Parent_MONOSTICK」を書き込み
TWELITE DIPに子機用の「App_Tag_EndDevice_Input」を書き込み
  • TWELITE DIPをTWELITE R2に装着して、PCとUSB接続
    • ⚠⚠⚠差し込む方向を間違えるとTWELITE DIP側が壊れてしまう可能性があるので注意!⚠⚠⚠
  • TWELITE STAGEを起動
  • シリアルポートは「TWELITE R2」を選択
  • 「アプリ書き換え」⇒「TWELITE_APPSビルド&書換」⇒「App_Tag」⇒「App_Tag_EndDevice_Input」を選択
  • ⇒アプリがTWELITE DIPに書き込まれます

youtu.be

  • 書き込みが完了したら、TWELITE STAGEを終了させて、TWELITE R2もPCから外し、TWELITE DIPをブレッドボードに装着する
  • ブレッドボード装着後、まだ電源はいれない!
MONOSTICKにOTAでTWELITE DIP側の設定を変更する「App_Tag_EndDevice_Input_OTA」を書き込み
  • MONOSTICKをPCとUSB接続
  • TWELITE STAGEを起動
  • シリアルポートは「MONOSTICK」を選択
  • 「アプリ書き換え」⇒「TWELITE_APPSビルド&書換」⇒「App_Tag」⇒「App_Tag_EndDevice_Input_OTA」を選択
  • ⇒アプリがMONOSTICKに書き込まれます

youtu.be

インタラクティブモードで子機用の設定を行う

次にインタラクティブモードで子機に設定する内容を編集します

  • 上記の続き
  • TWELITE STAGEの「インタラクティブモード」を選択
  • 設定を変更する
    • 「b」キーでUART baundを変更:115200
    • 「o」キーでOption Bitsを変更:0x00010001
    • 「d」キーでSleep Durを変更(ms):60000(※ 1分ごと送信するようにする)
    • 「w」キーでSensor Waitを変更(ms):30
    • 「m」キーでSensor Modeを変更:0x39
    • 「p」キーでParameterを変更:0
  • 「Shift + S」キーで設定を保存

各設定の詳細はこちらを参照

無線タグアプリ インタラクティブモード - MONO-WIRELESS.COM

youtu.be

子機(TWELITE DIP)の設定を変更

上記に引き続き、TWELITE STAGEを起動したままで、子機に電源をいれて、以下のように表示されれば、TWELITE DIP側に設定が反映されたことになるようです!

SUCCESS [TWELITE DIPのED]

f:id:chinoppy:20220321151846p:plain

youtu.be

⚠障害物などに弱いので、なるべくMONOSTICKとTWELITE DIPを近い距離にして、TWELITE DIPの電源をいれてください⚠

MONOSTICKでデータを受信するための「App_Tag_Parent_MONOSTICK」を書き込み
  • MONOSTICKをPCとUSB接続
  • TWELITE STAGEを起動
  • シリアルポートは「MONOSTICK」を選択
  • 「アプリ書き換え」⇒「TWELITE_APPSビルド&書換」⇒「App_Tag」⇒「App_Tag_Parent_MONOSTICK」を選択
  • ⇒アプリがMONOSTICKに書き込まれます

youtu.be

センサデータを確認!📈

TWELITE STAGEを起動して、シリアルポートは「MONOSTICK」を選択をすると1分ごと、センサデータを確認できます!🙌

  • tm: 温度(100倍されているので、22.44℃)
  • hu: 湿度(こちらも100倍されているので、39.08%)
  • at: 気圧(975hPa)
::rc=80000000:lq=183:ct=0018:ed=82015460:id=0:ba=3180:a1=1138:a2=0689:tm=2244:hu=3908:at=0975

youtu.be

Pythonで確認してみる

Raspberry PiにMONOSTICKを装着すると /dev/ttyUSBx として認識されます

$ ls -la /dev/ttyUSB*
crw-rw---- 1 root dialout 188, 0  3月 19 23:19 /dev/ttyUSB0

Pythonでserial関連のライブラリをインストールします

$ pip3 install pyserial

コードはこんな感じ

import serial
import time

ser = serial.Serial('/dev/ttyUSB0', 115200)

while True:

    time.sleep(1)

    recv_list = ser.readline().decode('utf-8').split(':')
    if len(recv_list) < 13:
        # いったん、受信データの要素数で不要なデータ時は出力しないようにする
        continue

    print(recv_list)

実行すると以下のように受信したデータを確認できます🙌

$ python3 app_tag_loop.py
['', '', 'rc=80000000', 'lq=159', 'ct=0002', 'ed=8201C109', 'id=0', 'ba=3190', 'a1=0916', 'a2=0612', 'tm=2270', 'hu=4060', 'at=0975\r\n']

Let's Enjoy センシング!!!!!!!! 📊