Watchy by SQFMI をハックしよう

![IMG_1953.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129361/00c27f39-a854-32f3-1c14-2c554dbb8f2b.jpeg)



去年(2023年)の8月に購入した Watchy by SQFMI がようやく2024年7月1日に届きました。
ほとんど忘れていました。

 https://watchy.sqfmi.com/

今はほとんど待たずに Mouser.jp で購入できるようです。

https://www.mouser.jp/ProductDetail/SQFMI/SQFMI-WATCHY-10?qs=DRkmTr78QARN9VSJRzqRxw%3D%3D


今回はデフォルトではNTP時刻合わせや天気がニューヨークになっているので、そのへんの設定を変更するところまで説明したいと思います。

ところで、開発は Windows でもできるようですが、わたしが Linux しか持っていないので、今回は Linux 上で行うこととします。

## Watchy by SQFMI でできること

標準の Watchy by SQFMI でできることは次のような内容です。

* 時間が表示できます
* 日付が表示できます
* WIFIにつなげて、NTP 時刻合わせができます (手動でも時刻を設定できます)
* 天気が表示できます
* 歩数が表示できます
* 振動させることができます
* **自分でプログラムできます**


## 必要なもの
 * Linux
 * USB Micro B ケーブル
 * Arduino IDE
 * Watchy by SQFMI

それぞれインストールするなり、購入するなりしてください。
Watchy by SQFMI の組み立て方法は SQFMI の YouTube をご覧ください。

https://www.youtube.com/watch?v=ftLTrr_HTpI

## Arduino IDE の設定

https://watchy.sqfmi.com/docs/getting-started#arduino-setup

上記に記載されているとおりですが、一応説明しておきます。

### Arduino IDE のインストール 

まず、Arduino IDE をインストールします。
ダウンロードは下記から行います。

https://www.arduino.cc/en/software

わたしはバージョン 2.3.2 の zip 版を利用しました。

zip ファイルを解凍して、arduino-ide_2.3.2_Linux_64bit ディレクトリに移動します。

```
~/arduino-ide_2.3.2_Linux_64bit$ ls
arduino-ide              libffmpeg.so            resources
chrome_100_percent.pak   libGLESv2.so            resources.pak
chrome_200_percent.pak   libvk_swiftshader.so    snapshot_blob.bin
chrome_crashpad_handler  libvulkan.so.1          v8_context_snapshot.bin
chrome-sandbox           LICENSE.electron.txt    vk_swiftshader_icd.json
icudtl.dat               LICENSES.chromium.html
libEGL.so                locales
~/arduino-ide_2.3.2_Linux_64bit$ 
```

arduino-ide があるので実行してみますが、エラーになり起動できません。
エラーの詳細にかかれている通り、chrome-sandbox を root 所有にし、4755の権限にします。

```
~/arduino-ide_2.3.2_Linux_64bit$ sudo chown root chrome-sandbox
~/arduino-ide_2.3.2_Linux_64bit$ sudo chmod 4755 chrome-sandbox
```

./arduino-ide を再度実行すると、今度は正常に起動します。

### esp32 ボードのインストール

File -> Preferences を開いて Additional Board Manager URLs に下記 URL を追加します。

```
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
```

Tools -> Board -> Border Manager を開き、esp32 バージョン 2.0.17 をインストールします。3.x.x 系では不具合が起きるようなので気をつけてください。下図のように esp32 は by Espressif Systems のものです。

![Screenshot from 2024-07-11 12-59-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129361/e3e26d61-3584-39a5-c535-2f9bfa78666d.png)

### Watchy とその他ライブラリのインストール

Sketch -> Include Library -> Manage Libraries で Watchy ライブラリを検索し最新版をインストールします。

依存関係でおそらくインストールされると思いますが、GxEPD2、WiFiManager、rtc_pcf8563などもインストールされたか確認します。

### USB 接続設定

USB Micro B ケーブルを Watchy に差し込んで、もう一方を Linux の USB ポートに繋ぎます。

#### ブートローダモード

ブートローダモードに入るには下記の図の SW2 と SW3 を同時に押し、4秒間押しつづけたあと、SW2 から指を離します。

https://watchy.sqfmi.com/assets/images/watchy_buttons_map-71dac914a78e2fb2d6c23cb2dad06802.png


Linux で下記のコマンドを実行し、/dev/ttyACM0 が表示されたら OK です。

```
~/arduino-ide_2.3.2_Linux_64bit$  ls /dev/tty*
/dev/tty    /dev/tty23  /dev/tty39  /dev/tty54      /dev/ttyS1   /dev/ttyS25
/dev/tty0   /dev/tty24  /dev/tty4   /dev/tty55      /dev/ttyS10  /dev/ttyS26
/dev/tty1   /dev/tty25  /dev/tty40  /dev/tty56      /dev/ttyS11  /dev/ttyS27
/dev/tty10  /dev/tty26  /dev/tty41  /dev/tty57      /dev/ttyS12  /dev/ttyS28
/dev/tty11  /dev/tty27  /dev/tty42  /dev/tty58      /dev/ttyS13  /dev/ttyS29
/dev/tty12  /dev/tty28  /dev/tty43  /dev/tty59      /dev/ttyS14  /dev/ttyS3
/dev/tty13  /dev/tty29  /dev/tty44  /dev/tty6       /dev/ttyS15  /dev/ttyS30
/dev/tty14  /dev/tty3   /dev/tty45  /dev/tty60      /dev/ttyS16  /dev/ttyS31
/dev/tty15  /dev/tty30  /dev/tty46  /dev/tty61      /dev/ttyS17  /dev/ttyS4
/dev/tty16  /dev/tty31  /dev/tty47  /dev/tty62      /dev/ttyS18  /dev/ttyS5
/dev/tty17  /dev/tty32  /dev/tty48  /dev/tty63      /dev/ttyS19  /dev/ttyS6
/dev/tty18  /dev/tty33  /dev/tty49  /dev/tty7       /dev/ttyS2   /dev/ttyS7
/dev/tty19  /dev/tty34  /dev/tty5   /dev/tty8       /dev/ttyS20  /dev/ttyS8
/dev/tty2   /dev/tty35  /dev/tty50  /dev/tty9       /dev/ttyS21  /dev/ttyS9
/dev/tty20  /dev/tty36  /dev/tty51  /dev/ttyACM0    /dev/ttyS22
/dev/tty21  /dev/tty37  /dev/tty52  /dev/ttyprintk  /dev/ttyS23
/dev/tty22  /dev/tty38  /dev/tty53  /dev/ttyS0      /dev/ttyS24

```


#### リセット

アップロードができたら、Watchy をリセットしますが、それは後のはなし。ですが、リセットしたい場合はつぎのようにおこないます。

先程のブートローダモードに入ったのと同じ要領で SW2 と SW3 を同時に押し、4秒間押しつづけ、今度は SW3 の方から先に指を離します。


### アップロード設定

https://watchy.sqfmi.com/docs/getting-started#uploading-new-watchfacesfirmware

これも上記通りですが、説明します。

Tools -> Board -> esp32 > ESP32S3 Dev Module を選択します。

Tools -> Port で /dev/ttyACM0 を選択します。

Tools -> Flash Size -> 8MB (64Mb) を選択します。

Tools -> Partition Scheme -> 8M with spiffs... を選択します。

これで準備は完了です。

### アップロード

ためしに Pokemon のウォッチフェイスをアップロードしてみましょう。

File -> Examples -> Watchy -> WatchFaces -> Pokemon を選択するとファイルが開きます。

settings.h のタブを選択します。

CITY_ID がニューヨーク市(5128581)になっているので、わたしの場合は彦根市(1862636)にします。
この都市情報は下記で定義されています。

https://bulk.openweathermap.org/sample/city.list.json.gz

settings.h のコメントには GMT_OFFSET_SEC は天気情報で上書きされると書いてありますが、一応、日本のGMT+9を設定します。書式は下記のとおりです。

```
#define GMT_OFFSET_SEC 3600 * 9
```

```
#ifndef SETTINGS_H
#define SETTINGS_H

//Weather Settings
#define CITY_ID "5128581" //New York City https://openweathermap.org/current#cityid

//You can also use LAT,LON for your location instead of CITY_ID, but not both
//#define LAT "40.7127" //New York City, Looked up on https://www.latlong.net/
//#define LON "-74.0059"

#ifdef CITY_ID
    #define OPENWEATHERMAP_URL "http://api.openweathermap.org/data/2.5/weather?id={cityID}&lang={lang}&units={units}&appid={apiKey}" //open weather api using city ID
#else
    #define OPENWEATHERMAP_URL "http://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&lang={lang}&units={units}&appid={apiKey}" //open weather api using lat lon
#endif

#define OPENWEATHERMAP_APIKEY "f058fe1cad2afe8e2ddc5d063a64cecb" //use your own API key :)
#define TEMP_UNIT "metric" //metric = Celsius , imperial = Fahrenheit
#define TEMP_LANG "en"
#define WEATHER_UPDATE_INTERVAL 30 //must be greater than 5, measured in minutes
//NTP Settings
#define NTP_SERVER "pool.ntp.org"
#define GMT_OFFSET_SEC 3600 * -5 //New York is UTC -5 EST, -4 EDT, will be overwritten by weather data

watchySettings settings{
    #ifdef CITY_ID
        .cityID = CITY_ID,
    #else
        .cityID = "",
        .lat = LAT,
        .lon = LON,
    #endif
    .weatherAPIKey = OPENWEATHERMAP_APIKEY,
    .weatherURL = OPENWEATHERMAP_URL,
    .weatherUnit = TEMP_UNIT,
    .weatherLang = TEMP_LANG,
    .weatherUpdateInterval = WEATHER_UPDATE_INTERVAL,
    .ntpServer = NTP_SERVER,
    .gmtOffset = GMT_OFFSET_SEC,
    .vibrateOClock = true,
};

#endif
```

あとは Update するだけです。

Arduino IDE の左上にある -> をクリックします。

Output 欄に次のような出力があれば、アップロード完了です。

```
Writing at 0x001826bf... (96 %)
Writing at 0x001881a1... (98 %)
Writing at 0x0018ddb9... (100 %)
Wrote 1567888 bytes (936023 compressed) at 0x00010000 in 10.2 seconds (effective 1233.4 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
```

USB ケーブルをはずして、Watchy をリセットしましょう。

## NTP 設定

### WiFi 設定

NTP で時刻合わせをするには、WiFi に接続する必要があります。

ふたたび下記の図を見ながら説明します。

https://watchy.sqfmi.com/assets/images/watchy_buttons_map-71dac914a78e2fb2d6c23cb2dad06802.png

SW1 -> メニュー -> Setup WiFi でもう一度 SW1 を押します。

下記のような画面になりますので、パソコンかスマホの WiFi 設定を SSID: Watchy AP に設定し、ブラウザでhttp://192.168.4.1 に接続します。

![IMG_1956.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129361/6f84f73c-11ea-ee7f-83b6-9a3ab66b070c.jpeg)


次のような画面になるので、Configure WiFi を選択し、自宅の WiFi の設定情報を入力します。

![IMG_1957.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129361/4b445ade-b362-fbb4-9a54-39bc9ebb2c6a.png)

### NTP 時刻合わせ

あとは NTP 時刻合わせだけです。

SW1 -> メニュー -> Sync NTP でもう一度 SW1 を押すと日本の時刻に設定できます。

![IMG_1958.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129361/39134a63-8594-3b47-e478-f9383f5aa717.jpeg)


## おまけ

わたしが設定したときには、画面がリフレッシュされないという問題がありました。
ですが、組み立て時に差し込みが弱かったようで、接触不良が起こっていたようです。

![IMG_1952.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129361/42659607-b45b-816c-0621-a6759a0b987d.jpeg)

あと何度も失敗したので文鎮化するかもと思ったのですが、どうやらそういうことにはならないようです。たぶん。