ゆるブロ

ゆる~くてちたのIT系?ブログ

スマートメーターから取得したデータをDBに書き込みまくる(更新)

はじめに/やりたいこと/注意点

DBにデータをガンガン書き込みたい。

どうして1つの機体でやってないかという点は突っ込んではいけない。

更新

TimeZoneの設定がイケてなくて、あとの処理で詰まってしまった。そのため、一部修正。

環境

参考文献

psycopg2の導入

raspberry pi 3にpsycopg2がインストールされていなかったので実施。
案の定エラー発生。

参考文献があったのでよかた。

yatta47.hateblo.jp

というかちゃんとエラーを見ればわかったことだったけどw

pi@rpi3-01:~/power $ sudo pip install psycopg2
Collecting psycopg2
  Downloading https://files.pythonhosted.org/packages/a8/8f/1c5690eebf148d1d1554fc00ccf9101e134636553dbb75bdfef4f85d7647/psycopg2-2.8.5.tar.gz (380kB)
    100% |████████████████████████████████| 389kB 684kB/s 
    Complete output from command python setup.py egg_info:
    /usr/lib/python2.7/distutils/dist.py:267: UserWarning: Unknown distribution option: 'project_urls'
      warnings.warn(msg)
    running egg_info
    creating pip-egg-info/psycopg2.egg-info
    writing pip-egg-info/psycopg2.egg-info/PKG-INFO
    writing top-level names to pip-egg-info/psycopg2.egg-info/top_level.txt
    writing dependency_links to pip-egg-info/psycopg2.egg-info/dependency_links.txt
    writing manifest file 'pip-egg-info/psycopg2.egg-info/SOURCES.txt'
    Error: You need to install postgresql-server-dev-X.Y for building a server-side extension or libpq-dev for building a client-side application.
    
    
    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-build-HWieD7/psycopg2/
pi@rpi3-01:~/power $ sudo apt-get install libpq-dev
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
以下の追加パッケージがインストールされます:
  libpq5
提案パッケージ:
  postgresql-doc-9.6
以下のパッケージが新たにインストールされます:
  libpq-dev
以下のパッケージはアップグレードされます:
  libpq5
アップグレード: 1 個、新規インストール: 1 個、削除: 0 個、保留: 188 個。
317 kB のアーカイブを取得する必要があります。
この操作後に追加で 815 kB のディスク容量が消費されます。
続行しますか? [Y/n] Y
取得:1 http://ftp.tsukuba.wide.ad.jp/Linux/raspbian/raspbian stretch/main armhf libpq5 armhf 9.6.17-0+deb9u1 [122 kB]
取得:2 http://ftp.tsukuba.wide.ad.jp/Linux/raspbian/raspbian stretch/main armhf libpq-dev armhf 9.6.17-0+deb9u1 [195 kB]
317 kB を 2秒 で取得しました (112 kB/s)
changelog を読んでいます... 完了
(データベースを読み込んでいます ... 現在 135871 個のファイルとディレクトリがインストールされています。)
.../libpq5_9.6.17-0+deb9u1_armhf.deb を展開する準備をしています ...
libpq5:armhf (9.6.17-0+deb9u1) で (9.6.13-0+deb9u1 に) 上書き展開しています ...
以前に未選択のパッケージ libpq-dev を選択しています。
.../libpq-dev_9.6.17-0+deb9u1_armhf.deb を展開する準備をしています ...
libpq-dev (9.6.17-0+deb9u1) を展開しています...
libpq5:armhf (9.6.17-0+deb9u1) を設定しています ...
libc-bin (2.24-11+deb9u4) のトリガを処理しています ...
man-db (2.7.6.1-2) のトリガを処理しています ...
libpq-dev (9.6.17-0+deb9u1) を設定しています ...
pi@rpi3-01:~/power $ sudo pip install psycopg2
Collecting psycopg2
  Using cached https://files.pythonhosted.org/packages/a8/8f/1c5690eebf148d1d1554fc00ccf9101e134636553dbb75bdfef4f85d7647/psycopg2-2.8.5.tar.gz
Building wheels for collected packages: psycopg2
  Running setup.py bdist_wheel for psycopg2 ... done
  Stored in directory: /root/.cache/pip/wheels/fb/85/a8/57f24b92b9554880384d00a84881c0ea80cbcee02d6dcede54
Successfully built psycopg2
Installing collected packages: psycopg2
Successfully installed psycopg2-2.8.5
pi@rpi3-01:~/power $ 

完成

SQLクライアントで確認したら、ちゃんと最新データが格納されていましたとさ。

それぞれの値の意味は以下の通り。
ID:シーケンス番号
date:取得日時
delta:瞬時電力計測値[W]
sumpower:積算電力量計測値[kWh]

ID=5のdelta=267[W]はドライヤー(冷風)をつけたとき。ID=10~13のdelta=1400[W]は電気ケトルをつけたときになります。こうやって見ると面白いね。

f:id:TeTiTa:20200505132831g:plain

DB書き込み

追記

dataのカラムを見ての通り、Timezoneが設定されていない。さらにDBのタイムゾーンは初期値であり、UTCだった!これでGrafanaと連携したときにうまく変換されなかったので修正する。おそらく、DB的にはJSTで表示しているんだけど、Grafanaから取得したときに謎にUTCJSTの変換が行われて9時間進んでしまっていた。

修正は、①DBのタイムゾーン設定、②タイムゾーンを含めたデータの作成を実施した。

①DBのタイムゾーン設定

scientre.hateblo.jp

うまく書き変わりますた。

SELECT NOW();
--> 2020-05-05 06:14:57.147651+00

SET timezone TO 'Asia/Tokyo'
--> 2020-05-05 15:16:07.283963+09 

タイムゾーンを含めたデータの作成

qiita.com

python2.7であることを意識して修正。3系にするときにもう一度修正せねば・・・

# Raspbessy piから明示的にUTCで送りつけるとうまくいった。
d_utc = datetime.datetime.now(pytz.utc)

これらを実行した結果、欲しい状態になりましたとさ。
IDが227と228がおかしい状態。IDが232以降が欲しい状態。

f:id:TeTiTa:20200505172610g:plain

修正後のDB

 

完走した感想

ここにくるまでいろいろとみちくさ食ったけども、良い勉強になりましたよん。

こっからはどうやってグラフで見るかを考えねば。

あとは、30分電力値をどのタイミングで取得することにするか、どう実装するか、考えよう。

追記

問題は発生したけど、GW前半に躓いていたところよりは全然だな。。。あの3日間はマジでもったいなかったな。。。

psycopg2を使ってpostgresqlDBにデータを書き込む

はじめに/やりたいこと

pythonを使ってDBにデータを流し込む機能を実装したい。
コード類は別途qiitaに乗せる予定。載せたらこっちの内容も更新しまする

開発環境

  • Win10 Pro 64bit 1909
  • Docker Desktop version 19.03.8, build afacb8b
  • docker-compose version 1.25.4, build 8d51620a
  • PostgreSQL 12.2
  • python 3.7 on spyder 4.0.1
  • psycopg2 2.8.4

参考文献

psycopg2の導入

Anaconda navigatorから更新できないので下記コマンドで実行。

conda install -c anaconda psycopg2

下記のエラーが発生してインストールできなかった。全文は取り損ねてしまったので、許してちょ。

Solving environment: failed

下記の記事が参考になった。

qiita.com

下記のコマンドでアップデートを実施。

conda update --all

そしたら入ってくれた。よかた。

psycopg2-2.8.4 | 170 KB | ############################################################################# | 100%
Preparing transaction: done
Verifying transaction: done
Executing transaction: done

psycopg2の使い方

qiita.com

dev.classmethod.jp

qiita.com

実行

dockerで建てたローカルのDBにデータを流し込むことができました。いっちゃん最後に追加されていました。

スクリプト(抜粋)
date = "2020-05-05 11:02:28.013000"
data = 47
sql_insert = "INSERT INTO \"public\".\"SMDB_TEST_test1\" (\"date\", \"data\") VALUES (\'{0}\', \'{1}\')".format(date,data)
print ("INSERT start.")
csr.execute(sql_insert)
print ("INSERT end.");

スクリプトの実行結果
connected.
consor openedd.
INSERT start.
INSERT end.
COMMIT start.
COMMIT end.
SELECT start.
[(1, datetime.datetime(2020, 5, 5, 9, 25, 43), 1.0),
 (6, datetime.datetime(2020, 5, 5, 9, 42, 57), 1.0),
 (8, datetime.datetime(2020, 5, 5, 9, 45, 43), 3.0),
 (13, datetime.datetime(2020, 5, 5, 9, 50), 4.0),
 (14, datetime.datetime(2020, 5, 5, 10, 3, 51), 5.0),
 (16, datetime.datetime(2020, 5, 5, 10, 9, 39, 993708), 11.0),
 (17, datetime.datetime(2020, 5, 5, 10, 12, 24, 319767), 60.0),
 (18, datetime.datetime(2020, 5, 5, 11, 2, 2, 385562), 10.0),
 (19, datetime.datetime(2020, 5, 5, 11, 2, 28, 13550), 47.0)]
SELECT end.
psycopg2 cursor closed.
psycopg2 connection closed.

完走した感想

やっと本題ができましたとさ。

これでDBにデータを溜められるぞ~~~。

スマートメーターから100日分の積算電力量計測値を引っこ抜く

はじめに

プログラムを書いていくためにサンプルデータが欲しいので取ります。

基本の取得プログラムはあるので、一部改造です。

やりたいこと

  • 積算履歴収集日1(EPC=0xE5)で0~99を順繰り設定する
  • 積算電力量計測値1(EPC=0xE4)でデータを取得する

参考文献

順繰り電文作るところが一番大変でした。

まずは文字列をバイト列に変換する方法を探して~

teratail.com

文字列フォーマットの使い方をまじめに調べました。pythonあんまり知らんからな。。。

qiita.com

teratail.com

上記使ってできた、100日分のデータ作成コードは以下qiitaを参照くだしあ。

qiita.com

残念ながら完成しない・・・

元のプログラムがpython2系だから3系に書き直すも、一向にデータを受信できない。。。(というかそこをしっかり確認しないといけないじゃん)

しゃーないからpython2系でも取得電文を作成。

qiita.com

最終的な原因は、送信電文に間違いがあったからでした~~~~~~~~~。
かなしい😢

ひとまず、2系でデータを取得。そのうち3系に移植しないとな~。

取得電文の生データ(1日前)は下記。

E2C2000100007F8E00007F8E00007F8F00007F9000007F9100007F9200007F9200007F9300007F9400007F9400007F9500007F9500007F9600007F9600007F9700007F9700007F9800007F9800007F9900007F9900007F9A00007F9A00007F9B00007F9B00007F9C00007F9D00007F9E00007F9F00007FA000007FA000007FA100007FA200007FA300007FA400007FA500007FA600007FA600007FA700007FA800007FA900007FAA00007FAB00007FAC00007FAC00007FAD00007FAE00007FAE00007FAF(2020-05-04 12:24:43)

確認したところ、43日分のデータを取得することができました。43日より前のデータはFFFFFFFEが詰まっていました。一応1か月は保持しているみたいね。電力会社としては前月分のデータが上がってこないときは13日間程の間にメーターを読みに来ればどうにか電気料金の計算ができそう。それとも、電力値がロックされていて、裏に隠れているのかな?真相はわからんけど。

完走した感想

ひとまず取れたので、これをベースにどんな感じでデータ取ったりするのか考えよっと。とっただけなので、はきだされた生電文を処理するところからですが。。。

コーディングした結果はqiitaに上げてみたけどどうなんだろうか。こっちでコードも書いたほうが一貫しているから話の流れは切れない。でも、はてブは開発でいうところの上位側や調べものにいたほうがいいような。

悩みの種ですな。

WinマシンにDocker入れて開発環境を整える

はじめに

ラズパイでいろいろやってきたけどpythonでプログラミングするならばWinマシンに開発環境あるといいなーってなったので早速準備します。

環境

  • Win10 Pro 1909
  • Docker Desktop version 19.03.8, build afacb8b
  • docker-compose version 1.25.4, build 8d51620a
  • PostgreSQL 12.2

f:id:TeTiTa:20200503034617p:plain

Docker Desktop

参考文献

じつは数日前にdockerだけ入れてました。docker-composeも一緒に入った気がする。

qiita.com

ハロワしたらお決まりのエラー。

Unable to find image 'hellow-world:latest' locally
C:\Program Files\Docker\Docker\resources\bin\docker.exe: Error response from daemon: pull access denied for hellow-world, repository does not exist or may require 'docker login': denied: requested access to the resource is denied.

言われた通り、docker loginしたら出なくなりました。言われたことは守ろうね!

さて、Docker-composeを使ってpostgresを入れていきましょう

qiita.com

サクッとymlを書きましょ。中身はRaspberryPiで使っているものと同じような感じにしましょ。

version: "3"
services:
  postgres-sm:
    image: postgres:latest
    container_name: "postgres-sm"
    ports:
      - 15432:5432
    volumes:
      - "pgdata:/var/lib/postgresql/data"
      - "./pg_init.d:/docker-entrypoint-initdb.d"
    environment:
      - "POSTGRES_USER=dev"
      - "POSTGRES_PASSWORD=dev"
      - "POSTGRES_DB=SmartMeterDB"
    #restart: always
    
volumes:
  pgdata:

初期作成用sqlはこんな感じ。 ラズパイで使っているものをそのまま持ってきましたとさ。

/* CREATE DATABASE for Metabase*/
CREATE DATABASE  metabasedb;

/* CREATE TABLE for TEST*/
CREATE TABLE "SMDB_TEST_static1" (
	"ID" SERIAL NOT NULL,
	"delta" DOUBLE PRECISION NULL DEFAULT 0,
	"sumpower" DOUBLE PRECISION NULL DEFAULT 0,
	"date" TIMESTAMP NULL DEFAULT NULL,
	PRIMARY KEY ("ID")
)
;

ymlとsqlを書いたら保存。sqlの保存先はymlで指定している通り、ymlの保存されているディレクトリの下(pg_init.dの中)に保存。ymlが保存されているディレクトリでdocker-compose upを実行。標準出力を出さないようにdオプションを付けます。
ボリュームだけ先にdocker volume create pgdataで作っちゃってたのは内緒。

PS C:\Users\<user>\Documents\Docker> docker-compose up -d
Creating network "docker_default" with the default driver
Creating volume "docker_pgdata" with default driver
Pulling postgres-sm (postgres:latest)...
latest: Pulling from library/postgres
54fec2fa59d0: Pull complete
30a95add0890: Pull complete
57bc798d3c84: Pull complete
a41bedb2c5de: Pull complete
589548c3abb4: Pull complete
c4c6b75d5deb: Pull complete
8f8c045a6a99: Pull complete
69f9dd86b24d: Pull complete
45bbaba740ff: Pull complete
1761ca7befa0: Pull complete
57feb34018f4: Pull complete
bede8373accc: Pull complete
6e4c69fbe63b: Pull complete
8a7949704ab2: Pull complete
Digest: sha256:d96835c9032988c8a899cb8a3c54467dae81daaa99485de70e8c9bddd5432d92
Status: Downloaded newer image for postgres:latest
Creating postgres-sm ... done
PS C:\Users\<user>\Documents\Docker>
PS C:\Users\<user>\Documents\Docker> docker-compose ps -a
   Name                  Command              State            Ports
-----------------------------------------------------------------------------
postgres-sm   docker-entrypoint.sh postgres   Up      0.0.0.0:15432->5432/tcp
PS C:\Users\<user>\Documents\Docker>
PS C:\Users\<user>\Documents\Docker> docker-compose exec postgres-sm /bin/bash
root@1507efcef0c5:/#
root@1507efcef0c5:/# psql -V
psql (PostgreSQL) 12.2 (Debian 12.2-2.pgdg100+1)
root@1507efcef0c5:/#

立ちました。ちゃんと内部にも入れました。

外部クライアントから接続して、できるか確認。

f:id:TeTiTa:20200503023653p:plain

localhostに立てたDBに接続@HeidiSQL

できていますね~。

イメージの状態を確認。試しに取ったalpine版と容量を比較。

PS C:\Users\<user>\Documents\Docker> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
postgres alpine ae192c4d3ada 8 days ago 152MB
postgres latest 0f10374e5170 9 days ago 314MB
hello-world latest bf756fb1ae65 4 months ago 13.3k

alpineはほんと軽いですね。半分か。

とはいえ、RaspberryPiにはオリジナルで建ててしまったので、そのまま使うことに。問題がなければ早々にalpineに移行したほうがよいかもなぁ。

volumeってどこに保存されているんだろうかと気になってしまったので探してみたら、C:\ProgramData\DockerDesktop\vm-dataにDockerDesktop.vhdxとして保存されていました。いったんdockerを止めてマウントさせようとしましたができませんでした。

追加で確認していたらCドライブが枯渇する人を発見。

wand-ta.hatenablog.com

ちゃんと管理しないと、ストレージを急に食われてびっくりすることがあるみたい。初期設定はMAXになっているので、16GBにしました。使用領域を増やす分には設定変更とrestartsするだけみたいですが、減らす場合には全てが消えるみたいです。減らすならば最初ですね。外部ドライブあればもっと大きい容量を指定できますが、あいにく無いのでしかたないです。image、containr、volume等はいらなくなったら削除しないとですね。

f:id:TeTiTa:20200503035526p:plain

リサイズ時の警告

f:id:TeTiTa:20200503043127p:plain

Docker Desktopの設定

その他

コンソールの画面をずーっと引用でごまかしてきたんですが、見づらいなぁとおもったので、コンソール風のCSSを導入しました。

www.halu7.com

スマホ版でうまく反映されていなかったので、下記を参考にしてみましたが、うまくいかず。Pro入れろってことですよね~。アフィでもやろうかしら。

highso.hatenablog.com

レスポンシブデザインなるものを設定してみたけど、表示が小さくなってしまうのね。ちょっと考え物だなぁ

完走した感想

環境整備はサクッと終わらせて、さっさと本題をやりたいとこですが、環境作るのたーのしー。めっちゃ丁寧に書いてしもた。
これPCでいったん全てできるようにしてからラズパイに実装させるべきだな。。。armとx86pythonの動きは変わらんっしょ。

いろいろ調べてて、Windows Subsystem for Linux(WSL)に出会いました。WSLについて知らなかったのですが、進化版のWSL2がWin10-2004で来るとかちょっと面白くなってきていますね。高性能マシンほしいなぁ。

Dockerではないコンテナとしてsingularityなるものがあるみたいです。こっちは科学計算系、GPUパワーを使う際に有効だとか。Jetson NanoがあるのでAI系をやりだしたらつかってみたいところ。

ゴミスペックのwinマシンに適当なlinux入れてサーバー化するのもやりたい。Docker運用するつもりなので軽めのやつなんか探してやってみたいけど時間かかりそうでござる。

やりたい祭りでつらい~~~1年間ぐらいGWにならないかな。

docker-composeで立てたPostgreSQLのVolume(保存先)をUSBメモリ(外部)にする@RaspberryPi4(できなかったけど、、)

はじめに

SDカードは死にやすいとグーグル先生が仰っているため、USBメモリ(128GB)を購入してそちらにDBを保存することにした。

結論、3日頑張ってもできなかったので諦め。
SDカードに溜めて、周期的にUSBにバックアップすることにする。
周期は1日なのか1時間なのか、今後確認だな~。

参考文献

まずは、USBを自動マウントさせるところからやりましょう。

www.raspberrypirulo.net

/etc/fstabをいじったらラズパイ4が起動しなくなりました。
同じようなコトをしちゃう人が多いみたいですね…

qiita.com

上記を参考にしました。うちには幸いなことにラズパイ3が動いていたので、ラズパイ4からSDカードを抜いてさしました。
/media/pi/rootfs/ にルート以下がマウントされているので、/etc/fstabを修正することに。

PARTUUID=54FF-D402 /mnt/usb/str1 exfat auto,rw,async,dev,suid,exec,noatime 0 2

上記ではだめだったみたいなので、下記に直してみたところ、

UUID="54FF-D402" /mnt/str1 exfat defaults,noatime,nofail 0 0

これでちゃんと上がってきました。

あとは、docker-compose-ymlのvolumesを下記にすればOK。

volumes:
    - "/mnt/str1/postgresql/data/:/var/lib/postgresql/data"

ということでdocker起動しましたが、・・・が、以下のエラーが…

postgres-sm | chown: changing ownership of '/var/lib/postgresql/data': Operation not permitted

qiita.com

chmodしても、zオプション付けてもダメ。
上記のエラーでググると死ぬほど出てくるけどなんか有用な回答が無いぞ。。。

所有者が何なのか、他のディレクトリで適当に作成したVolumesの中身をのぞいてみると、

drwxr-x--- 1 999 root 128K 4月 30 17:44 data

 のようになっていた。

999なんてユーザいねーぞ。。。しゃーないからuseraddでuid=999をdockerにして、再度/etc/fstabを編集。追加でdefault表記を外してみた。

UUID="54FF-D402" /mnt/str1 exfat user,rw,suid,dev,exec,suid,auto,async,noatime,nofail,uid=999 0 0

起動させたら何やら違うエラーが・・・

FATAL: data directory "/var/lib/postg
resql/data" has invalid permissions

DETAIL: Permissions should be u=rwx (0700) or u=rwx,g=rx (0750).

進展してよかた。パーミッションがデフォルトだったので、fstabにマスクを追加。

UUID="54FF-D402" /mnt/str1 exfat user,rw,suid,dev,exec,suid,auto,async,noatime,nofail,uid=999,dmask=027,fmask=027,umask=027 0 0

再起動して、パーミッションが変わっていることを確認

drwxr-x--- 1 docker root 128K 1月 1 1970 str1

して再度実行。またまたエラー。。。

postgres-sm | running bootstrap script ... 2020-04-30 14:21:18.040 UTC [24] LOG: could not link file "pg_wal/xlog
temp.24" to "pg_wal/000000010000000000000001": Function not implemented
postgres-sm | 2020-04-30 14:21:18.044 UTC [24] FATAL: could not open file "pg_wal/000000010000000000000001": No s
uch file or directory
postgres-sm | child process exited with exit code 1

なんでファイルがみつからんのだ。downやってコンテナ消してるから再度ファイル作られると思ってたんだけど…

しゃーなしなので、いつだったか間違って作ってしまった、本来ならば初期時に作られるだろうファイルをごっそり移動。

docker@raspberrypi4:/mnt/str1/postgresql/data$ ls -alh
合計 3.2M
drwxr-x--- 1 docker root 128K 4月 30 23:44 .
drwxr-x--- 1 docker root 128K 4月 30 23:44 ..
-rwxr-x--- 1 docker root 3 4月 30 23:44 PG_VERSION
drwxr-x--- 1 docker root 128K 4月 30 23:44 base
drwxr-x--- 1 docker root 128K 4月 30 23:44 global
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_commit_ts
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_dynshmem
-rwxr-x--- 1 docker root 4.5K 4月 30 23:44 pg_hba.conf
-rwxr-x--- 1 docker root 1.6K 4月 30 23:44 pg_ident.conf
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_logical
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_multixact
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_notify
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_replslot
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_serial
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_snapshots
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_stat
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_stat_tmp
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_subtrans
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_tblspc
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_twophase
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_wal
drwxr-x--- 1 docker root 128K 4月 30 23:44 pg_xact
-rwxr-x--- 1 docker root 88 4月 30 23:44 postgresql.auto.conf
-rwxr-x--- 1 docker root 26K 4月 30 23:44 postgresql.conf
-rwxr-x--- 1 docker root 36 4月 30 23:44 postmaster.opts

docker-compose.ymlのDB先もしっかり修正。そして、実行。

f:id:TeTiTa:20200501001721p:plain

いやーついに動いた。。。

1日かかってしもた。。。

ちゃんとDBが見えるかどうかもチェックする⇒なんかおかしい。

そう、リードはできてもライトができないのである。

Postgresqlのinitdbを実行するユーザで初期ファイルの書き込みがどうにもうまくいかない。

mrkmyki.com

こんなブログもあった。

マウントを/postgres/dataから/postgresに変えるものだが、これだとデータの永続化はできない。/mnt/str1/postgres:/var/lib/postgresの部分は確かにそこにマウントするけれどもdata部分は別のvolumeが作成されてそちらにマウントされる。

pi@raspberrypi4:~ $ docker volume ls
DRIVER VOLUME NAME
local docker-settings_sm-db
local e1be6dd7630d21c1a5697df0b690be16cb46f7fb26c2da95075d7e68762a666c
pi@raspberrypi4:~ $
pi@raspberrypi4:~ $ docker volume inspect e1be6dd7630d21c1a5697df0b690be16cb46f7fb26c2da95075d7e68762a666c
[
{
"CreatedAt": "2020-05-02T05:18:11+09:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/e1be6dd7630d21c1a5697df0b690be16cb46f7fb26c2da95075d7e68762a666c/_data",
"Name": "e1be6dd7630d21c1a5697df0b690be16cb46f7fb26c2da95075d7e68762a666c",
"Options": null,
"Scope": "local"
}
]
pi@raspberrypi4:~ $
pi@raspberrypi4:~ $ docker volume inspect docker-settings_sm-db
[
{
"CreatedAt": "2020-05-02T16:30:30+09:00",
"Driver": "local",
"Labels": {
"com.docker.compose.project": "docker-settings",
"com.docker.compose.version": "1.25.5",
"com.docker.compose.volume": "sm-db"
},
"Mountpoint": "/var/lib/docker/volumes/docker-settings_sm-db/_data",
"Name": "docker-settings_sm-db",
"Options": {
"device": "/mnt/str1/psgr/data/",
"o": "bind",
"type": "none"
},
"Scope": "local"
}
]

つまるところ、保存したかったところには保存できていない。

この後、uid=999をpostgresにしてみたり、docker-entrypoint.sh読んでみたりしたけど、よくわからんし、これ以上時間かけてもしゃーないからひとまず諦めて前に進めることにしました。ローカル環境の/etc/passwd /etc/groupをマウントしてしまうという手もあるらしいけど、そこまで変わりがないので今回はパス

一通りできたら、ラズパイのSDカードをそっくりバックアップしておこうと思う。

権限問題はlinuxでよくある話らしいが、こんなにも沼にはまってしまうとは。。。

 

完走できなかった感想

3日かけたのは時間のかけすぎだったかもしれない。
結局やりたいことは、急なデータ消失時のバックアップなので、わざわざやらなくてもと言ったところだった。
USBメモリへの保存は、周期的にクーロンかなにかでdata以下をtar.gzipすればいいかな。
zipしちゃえば200MBを超えるDBの生データも10Mぐらいになっちゃうし、当分は差分しなくてもOKと思う。

仮にデータ量が圧縮後に100MBあったとしても、1日1回のバックアップで3G/月(30points)、36.5G/年(365points)となる。

保存方法も1週間は全て残すけど、それ以降は1週間毎にするとかすれば、1日1回バックアップよりも細かい頻度で(1時間とか?)とったとしてもラズパイの寿命よりは長く保存できそう。
1週間*1時間毎*1回100MBだとしたら、7*24*0.1G=16.8G
それ以後は1週間毎に保存するとして、16.8+52週*0.1G=22GB/年
1回100MBならば5年以上、200MBになったとしても2年以上は持つ
正直そこまででかくなったら、毎回フルバックアップは無理なので、フルバックアップと差分バックアップを使い分けないといけないかと感じているけど、まだまだ先になりそうなので今は良しとする。

スマートメーターからとれる情報を引っこ抜いてみる

はじめに

スマートメーターのBルートを使って電気の見える化を進めてみたけども、とってみていた値は、その中の一部なんですよね。

なので、実際にどんなデータが取れて入っているのかこの目で確かめてみようとおもったわけですよっと。

データのフォーマット等は仕様書見ればいいんだけど、実際のところどんなデータなのかって気になるじゃん?ということで、とってみましょ。

ちなみに筆者は某東京電力管内のスマートメーターからとっています。

参考文献

参考はもちろん公式が一番ですよね。

(なんかリンクの画像表示されないけど・・・)

echonet.jp

スマートメーターからとれる情報は、「APPENDIX ECHONET機器オブジェクト詳細規定」の3.3.25 低圧スマート電力量メータクラス規定に書かれています。

執筆時、M版がリリースされており、低圧スマート電力量メータクラス固有のデータが15種類あるみたいです。それ以外に、スーパークラスというオブジェクトがあります。スーパークラスは全ての機器に備わっているデータとなります。スーパークラスには対象機器がどの仕様書に適合しているのか確認するプロパティがあるので、それを見て読む仕様書が変わります。気を付けてね!!!*1

ちなみにうちのスマートメーターはM版ではありませんでした!!!!

あとは、めっちゃいろんな方が参考にしている、引っこ抜きブログからプログラムをパクリスペクトさせてもらって、データを抜きましょう。

 

qiita.com

機器のメーカーコードは下記のサイトにある「IOTで利用できる機器リスト」に書いてあったのを参考にしました。低圧スマートメータは東芝三菱電機(中部、四国、北海道、中国)、NEC富士通のベンダがいるみたいですね。

sh-center.org

データの中身

上で書いた規定順にうえからとってみましょ。

EPCというのは、各データ(プロパティ)に割り当てられたIDです。実は必須ではないプロパティもいくつかあります。

基本的に取得できる値はHEX値なので、読み替える必要があります。

スーパークラスからとってみましょう。

スーパークラス

No.1 動作状態 (EPC=0x80, 必須)

ON/OFFの状態を示します。
ON=0x30、OFF=0x31

取得電文

80 01 30

内容解析

80:EPC
01:データ長⇒1バイト
30:値

ONですね~
これってOFFになるときあるんですかね・・・?

No.2 設置場所(EPC=0x81, 必須)

設置場所を示します。1バイトのビットマップで表されます。

f:id:TeTiTa:20200429164248p:plain

設置場所プロパティ
取得電文

81 01 61

内容解析

81:EPC
01:データ長⇒1バイト
61:値

61はビット列に直すと 0110 0001 なので、
b7:0⇒表で決まる
b3~b6:1100⇒庭、外周
b0~b2:001⇒場所番号1

場所番号は同じ種類の空間が複数あるときに区別する番号みたいです。1つしかないので、これであっていますね。

No.3 規格Version情報 (EPC=0x82, 必須)

対応するAPPENDIXのリリース番号を示します。

1 バイト目:0x00 固定(for futurereserved)
2 バイト目:0x00 固定(for futurereserved)
3 バイト目:リリース順.を ASCIIで示す。
4 バイト目:0x00 固定(for futurereserved)

取得電文

82 04 00 00 46 00

内容解析

82:EPC
04:データ長
00 00 46 00:値⇒46は「F」ですね~~~最新版のMではないですね~~。

F版がリリースされたのが2014年9月3日になります。東京電力スマートメーターを設置開始したのが同年4月、Bルートサービスの提供が2015年7月ということみたいです。G版がリリースされたのが2015年5月29日ですので、さすがにBルートのサービス提供には間に合わなかったでしょうね。

No.4 識別番号(EPC=0x83)

オブジェクトを固有に識別する番号です。

1 バイト目:下位通信層 ID フィールド
0x01~0xFD:下位通信層で使用される通信プロトコルで固有の番号が振られている場合、プロトコル種別に応じて、任意に設定(ECHONETLite では使用しない)
0x11~0x1F:電灯線 a,d 方式
0x31~0x3F:特定小電力無線
0x41~0x4F:拡張 HBS
0x51~0x5F:IrDA
0x61~0x6F:LonTalk
0x71~0x7F:Bluetooth
0x81~0x8F:イーサネット
0x91~0x9F:IEEE802.11/11b
0xA1:電灯線 c 方式
0xB1:IPv6/Ethernet
0xB2:IPv6/6LoWPAN
0xFE:2~17 バイトをメーカ規定。形式により設定(詳細説明参照)
0xFF:2~9 バイトを乱数により生成するプロトコルを下位通信層で使用する場合に設定
0x00:識別番号未設定
2 バイト目以降:固有番号フィールド

取得電文

83 00

内容解析

83:EPC
00:データ長⇒0
取得不可プロパティなので、だめですね~。

No.5 瞬時消費電力計測値(EPC=0x84)

機器の瞬時消費電力をWで示す。
0x0000~0xFFFD(0~65533W)

取得電文

84 00

内容解析

84:EPC
00:データ長⇒0

取得不可プロパティなのでだめですね~。スマートメーターの消費電力見たかったな・・・!

No.6 積算消費電力計測値(EPC=0x85)

機器の積算消費電力を0.001kWhで示す。

0x00000000~0x3B9AC9FF
(0~999,999.999kWh)

取得電文

85 00

内容解析

85:EPC
00:データ長⇒0
取得不可プロパティなので見れませんね。見たかったなぁ~

No.7 メーカ異常コード(EPC=0x86)

各メーカ独自の異常コードを示す。

取得電文

86 00

内容解析

82:EPC
00:データ長⇒0

取得不可プロパティなので、しかたないですね。

No.8 電流制限設定(EPC=0x87)

電流制限の設定値を示す(0~100%)。

取得電文

87 00

内容解析

82:EPC
00:データ長⇒0

取得不可プロパティなので、しかたないですね。

No.9 異常発生状態(EPC=0x88, 必須)

何らかの異常(センサトラブル等)の発生状況を示す。
異常発生有=0x41,異常発生無=0x42

取得電文

88 01 42

内容解析

88:EPC
01:データ長⇒01
42:値⇒異常発生無

異常は発生していないですね。

No.10 異常発生状態(EPC=0x89) 

異常内容を示す。

取得電文

89 00

内容解析

88:EPC
00:データ長⇒0

取得不可プロパティなので見れませんね。

No.11 メーカコード(EPC=0x8A, 必須)

3バイトで指定します。ECHONETコンソーシアムで規定されているとのこと。

取得電文

8A 03 00 00 16

内容解析

82:EPC
03:データ長⇒3バイト
00 00 16:値⇒16

0x000016は東芝みたいですね。東京電力管内は東芝みたいです~。

No.12 事業場コード(EPC=0x8B, 必須)

3バイトで事業所コードを指定します。

取得電文

8B 00

内容解析

8B:EPC
00:データ長⇒0

取得不可プロパティなので見れませんね。

No.13 商品コード(EPC=0x8C)

ASCIIコードで指定する。

取得電文

8C 00

内容解析

8C:EPC
00:データ長⇒0

取得不可プロパティなので見れませんね。

No.14 製造番号(EPC=0x8D)

ASCIIコードで指定します。

取得電文

8D 0C 533134473132333435360000

内容解析

82:EPC
0C:データ長⇒12バイト
53 31 34 47 31 32 33 34 35 36 00 00⇒値

ASCIIコードに直すと、「S14G123456」になります。
スマートメーターの表面に書いてある番号になります。この値を公開すると、どこに設置されているスマートメーターなのかガチでわかっちゃうので、フェイクにしています。

f:id:TeTiTa:20200429194519p:plain

No.15 製造年月日(EPC=0x8E)

4バイトで指定。

YYMD(1 文字 1 バイト) で示す。
YY:西暦年 (1999 年の場合 0 x 07 CF)
M:月 (12 月の場合= 0 x 0 C)
D:日 (20 日の場合= 0 x 1 4)

取得電文

8E 00

内容解析

8E:EPC
00:データ長0

取得不可プロパティなので見れませんね。

No.16 節電動作設定 (EPC=0x8F, 必須)

機器の節電動作状態を示す。

節電動作中=0x41
通常動作中=0x42

取得電文

8F 00

内容解析

8F:EPC
00:データ長⇒0

取得不可プロパティなので見れませんね。

No.17 遠隔操作設定(EPC=0x93)

公衆回線を介した操作か否かを示す。

公衆回線未経由操作=0x41
公衆回線経由操作=0x42

取得電文

93 00

内容解析

93:EPC
00:データ長⇒0

取得不可プロパティなので見れませんね。

No.18 現在時刻設定(EPC=0x97)

現在時刻 HH:MMを示す。
0x00~0x17:0x00~0x3B(=0~23):(=0~59)

取得電文

97 02 1204

内容解析

97:EPC
02:データ長⇒2バイト
12:18時
04:4分

取得した時間がこんなもんでしたね。

No.19 現在年月日設定(EPC=0x98)

現在年月日 YYYY:MM:DD
1~0x270F:1~0x0C:1~0x1F
(=1~9999):(=1~12):(=1~31)

取得電文

98 04 07E4041D

内容解析

98:EPC
04:データ長⇒4バイト
07 E4:2020年
04:4月
1D:29日

今日取得したので、あっていますね。

No.20 電力制限設定(EPC=0x99)

電力制限の設定値を W で示す。
0x0000~0xFFFF(0~65535W)

取得電文

99 00

内容解析

99:EPC
00:データ長⇒0

取得不可プロパティなので見れませんね。

No.21 積算運転時間(EPC=0x9A)

現在までの運転時間の積算値を単位 1 バイト、時間 4 バイトで示す。
1 バイト目:単位を示す
秒:0x41、分:0x42
時:0x43、日:0x44
2~5 バイト目:1 バイト目に示される時間単位における経過時間を示す。
0x00000000~0xFFFFF

取得電文

9A 00

内容解析

9A:EPC
00:データ長⇒0
取得不可プロパティなので見れませんね。

No.22 SetMプロパティマップ(EPC=0x9B, 必須)

ECHONET Lite機器は搭載不可らしいですよ。

取得電文

9B 00

内容解析

9B:EPC
00:データ長⇒0

搭載不可なので、取れなくて当然ですな。取得不可プロパティでもあります。

No.23 GetMプロパティマップ(EPC=0x9C, 必須)

ECHONET Lite機器は搭載不可らしいですよ。

取得電文

9C 00

内容解析

9C:EPC
00:データ長⇒0

搭載不可なので、取れなくて当然ですな。取得不可プロパティでもあります。

No.24 状変アナウンスプロパティマップ(EPC=0x9D, 必須)

状態が変化した際にブロードキャストでアナウンスされるプロパティの一覧を示します。

取得電文

9D 04 03 80 81 88

内容解析

9D:EPC
04:データ長
03:プロパティ数⇒3つ
80、81、88⇒プロパティコード

今回はプロパティ数が16より少ないので、1バイト目にプロパティ数(バイナリ表示)がきます。2バイト目以降にプロパティのコードが来ます。
80が動作状態、81が設置場所、88が異常発生状態になります。これらの値が変化したときには、アナウンスされるようです。

No.25 Setプロパティマップ(EPC=0x9E, 必須)

Setできるプロパティの一覧を示します。

取得電文

9E 04 03 81 E5 ED

内容解析

9E:EPC
04:データ長
03:プロパティ数⇒3つ
81、E5、ED⇒プロパティコード

プロパティ数が16より少ないので、1バイト目にプロパティ数(バイナリ表示)がきます。2バイト目以降にプロパティのコードが来ます。
81が設置場所、E5が積算履歴収集日1、EDが積算履歴収集日2になります。これらの値はSetが可能みたいですね。設置場所って変えられていいのか・・・

No.26 Getプロパティマップ(EPC=0x9F, 必須)

Getできるプロパティの一覧を示します。

取得電文

9F 11 19 41 41 41 60 40 40 00 62 43 00 41 40 40 43 02 02

内容解析

9E:EPC
11:データ長
19:プロパティ数⇒19つ
41 41 41 60 40 40 00 62 43 00 41 40 40 43 02 02⇒プロパティマップ表記

プロパティ数が16以上なので、1バイト目にプロパティ数(バイナリ表示)がきます。2バイト目以降にプロパティマップが来ます。
1:0001
2:0010
3:0011
4:0100
6:0110

これらの値の組み合わせでプロパティマップの色塗りをします。
プロパティマップはAppendixの付録についているので、その通りに塗ってみたのか下記になります。

実際にこれらの値だけ取れました。

f:id:TeTiTa:20200429203952p:plain

プロパティマップ(色塗り)

低圧スマート電力量メータクラス

No.1 動作状態(EPC=0x80, 必須)

スーパークラスで取得しているので省きます。これはONのデータがはいっていましたね。

No.2 係数(EPC=0xD3)

積算電力量計測値、履歴を実使用量に換算する係数を10進表記において 6 桁で示すらしいです。取得できないときは係数を1として取り扱うみたい。
0x00000000~0x000F423F
(000000~999999)

取得電文

D3 04 00 00 00 01

内容解析

D3:EPC
04:データ長⇒4バイト
00 00 00 01:値⇒1

係数は1ですね。必須ではないですが、取れました。

No.3 積算電力量有効桁数(EPC=0xD7, 必須)

積算電力量計測値の有効桁数を示す。
0x01~0x08
(1~8)

取得電文

D7 01 06 

内容解析

D7:EPC
01:データ長⇒1バイト
06:値⇒6

積算電力量計測値の有効桁数は6桁みたいですね。
下位側から6桁なので、積算電力量は 0x000F423F(999999)でオーバーフローし、0x00000000(0)から再インクリメントすることになります。

No.4 積算電力量計測値(正方向計測値)(EPC=0xE0, 必須)

積算電力量[kWh]を10 進表記において、最大 8 桁で示す。
0x00000000~0x05F5E0FF
(0~99,999,999)

取得電文

E0 04 00 00 7F 0E

内容解析

E0:EPC
04:データ長⇒1バイト
00 00 7F 0E:値⇒32526

実はこの値を係数(EPC=D3)と積算電力量単位(EPC=E1)で補正させてあげることで実測値になります。
私の環境では、係数=1、積算電力量単位=0.1kWhなので、欲しい値は、
積算電力量計測取得値×係数×積算電力量単位=32526×1×0.1=3252.6kWhとなります。

No.5 積算電力量単位(正方向、逆方向計測値)(EPC=0xE1, 必須)

積算電力量計測値、履歴の単位(乗率)を示す。
0x00:1kWh
0x01:0.1kWh
0x02:0.01kWh
0x03:0.001kWh
0x04:0.0001kWh
0x0A:10kWh
0x0B:100kWh
0x0C:1000kWh
0x0D:10000kWh

取得電文

E1 01 01

内容解析

E1:EPC
01:データ長⇒1バイト
01:値⇒0.1kWh

これは1回取っておけばOKなプロパティですね。

No.6 積算電力量計測値履歴1(正方向計測値)(EPC=0xE2, 必須)

積算履歴収集日1と該当収集日の 24 時間 48 コマ分(0 時 0 分~23 時 30 分)の正方向の定時積算電力量計測値の履歴データを時系列順に上位バイトからプロパティ値として示す。
1~2 バイト目:積算履歴収集日
0x0000~0x0063(0~99)
3 バイト目以降:積算電力量計測値
0x00000000~0x05F5E0FF
(0~99,999,999)

取得電文(1回目)

E2 C2 00 FF FF FF FF FE FF FF FF FE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFE

内容解析

E2:EPC
C2:データ長⇒194バイト
00 FF:値⇒積算履歴収集日
FF FF FF FE:値⇒計測データなし

積算履歴収集日1(EPC=0xE5)を設定していない初期値の場合は、積算履歴収集日に0x00FF、30 分毎の積算電力量計測値に全て 0xFFFFFFFE をセットする仕様です。SET電文を作ってから送るしかないですね。
下記に、積算履歴収集日1に0x00(当日)をセットしてみてから取得した電文を載せます。

取得電文

E2 C2 00 00
00 00 7F 0A 00 00 7F 0B
00 00 7F 0C 00 00 7F 0D
00 00 7F 0D 00 00 7F 0E
00 00 7F 0F 00 00 7F 0F
00 00 7F 10 FF FF FF FE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFEFFFFFFFEFFFFFFFE
FFFFFFFEFFFFFFFE

内容解析

E2:EPC
C2:データ長⇒194バイト
00 00:値⇒積算履歴収集日0x00⇒当日なので、4/29
00 00 7F 0A :1コマ目(0時0分)
00 00 7F 0B :2コマ目(0時30分)
00 00 7F 0C :3コマ目(1時0分)
00 00 7F 0D :4コマ目(1時30分)
00 00 7F 0D :5コマ目(2時0分)
00 00 7F 0E:6コマ目(2時30分)
00 00 7F 0F :7コマ目(3時0分)
00 00 7F 0F :8コマ目(3時30分)
00 00 7F 10 :9コマ目(4時0分)
FF FF FF FE:10コマ目(4時30分)

取得したのは4時26分なので、4時半以降のデータが入っていないことであっていますね。

No.7 積算電力量計測値(逆方向計測値)(EPC=0xE3, 必須)

積算電力量[kWh]を 10 進表記におい最大 8 桁で示す。
逆方向なので、売電している人向けですね。
0x00000000~0x05F5E0FF
(0~99,999,999)

取得電文

E3 04 00 00 00 0A

内容解析

E3:EPC
04:データ長⇒4バイト
00 00 00 0A:値⇒10

単位はEPC=E1の結果から0.1kWhなので、1.0kWhになります。たしかに、スマートメーターの表示は逆方向1.0kWhになっていました。ライン検査中なのか、設置後の設置検査なのかで少しだけ回されているみたいですね。

No.8 積算電力量計測値履歴1(逆方向計測値)(EPC=0xE4, 必須)

積算履歴収集日1と該当収集日の 24 時間 48 コマ分(0 時 0 分
~23 時 30 分)の逆方向の定時積算電力量計測値の履歴データ
を時系列順に上位バイトからプロパティ値として示す。
1~2 バイト目:積算履歴収集日
0x0000~0x0063(0~99)
3 バイト目以降:積算電力量計測値
0x00000000~0x05F5E0FF
(0~99,999,999)

取得電文

E4 C2 00 01
00 00 00 0A 00 00 00 0A
00 00 00 0A 00 00 00 0A
0000000A0000000A0000000A0000000A
0000000A0000000A0000000A0000000A
0000000A0000000A0000000A0000000A
0000000A0000000A0000000A0000000A
0000000A0000000A0000000A0000000A
0000000A0000000A0000000A0000000A
0000000A0000000A0000000A0000000A
0000000A0000000A0000000A0000000A
0000000A0000000A0000000A0000000A
0000000A0000000A0000000A0000000A
0000000A0000000A0000000A0000000A

内容解析

E4:EPC
C2:データ長⇒194バイト
00 01:値⇒積算履歴収集日0x01⇒1日前なので、4/28
00 00 00 0A:値⇒10
4/28は既に計測済みのはずなので、そりゃ取れるわな、といったところですね。
これfor文で回したらどこまで前に遡れるのかなあ?

No.9 積算履歴収集日(EPC=0xE5)

30 分毎の計測値履歴データを収集する日を示す。
0x00~0x63
( 0~99)
0:当日 1~99:前日の日数

取得電文

E5 01 FF

内容解析

E5:EPC
01:データ長⇒1バイト
FF:値

FFは初期値でした。
積算計測値履歴1(EPC=0xE2,0xE4)で呼び出す日を 0x00~0x63(0~99)でSETするためのプロパティですね。

No.10 瞬時電力計測値(EPC=0xE7, 必須)

電力実効値の瞬時値を 1W 単位で示す。
0x80000001~0x7FFFFFFD
(-2,147,483,647~2,147,483,645)

取得電文

E7 04 00 00 00 5E

内容解析

E7:EPC
04:データ長⇒1バイト
00 00 00 5E:値⇒94

このときは94Wの電力を使用していたみたいですね。
冷蔵庫、照明、ノーパソ、NAS、ラズパイ。。。まぁこんなもんかな?

No.11 瞬時電流計測値(EPC=0xE8, 必須)

実効電流値の瞬時値を 0.1A 単位で R 相 T 相を並べて示す。
単相 2 線式の場合は、T 相に0x7FFE をセット。
0x8001~0x7FFD(R 相):0x8001~0x7FFD(T 相)
(-3,276.7~3,276.5):(-3,276.7~3,276.5)

取得電文

E8 04 00 0A 00 0A

内容解析

E8:EPC
04:データ長⇒4バイト
00 0A 00 0A:値

R相が1.0A、T相が1.0Aということですかね。3相交流の世界はよくわからんぞ。。。

No.12 定時積算電力量計測値(正方向計測値)(EPC=0xEA,必須)

最新の 30 分毎の計測時刻における積算電力量(正方向計測値)を、計測
年月日を 4 バイト、計測時刻を 3 バイト、積算電力量(正方向計測値)4
バイトで示す。
・計測年月日 YYYY:MM:DD
・計測時刻 hh:mm:ss
・積算電力量[kWh] 10進表記で最大8桁
1~4バイト目:計測年月日
YYYY:0x0001~0x270F
(1~9999)
MM:0x01~0x0C(1~12)
DD:0x01~0x1F(1~31)
5~7バイト目:計測時刻
hh:0x00~0x17(0~23)
mm:0x00~0x3B(0~59)
ss:0x00~0x3B(0~59)
8~11 バイト目:積算電力量計測値
0x00000000~0x05F5E0FF
(0~99,999,999)

取得電文

EA 0B 07 E4 04 1D 03 00 00 00 00 7F 0F

内容解析

EA:EPC
0B:データ長⇒11バイト
07 E4 :2020年
04 : 4月
1D : 29日
03 : 3時
00 : 0分
00 : 0秒
00 00 7F 0F :32639⇒3263.9kWh

なんでこんな時間にやってんだって思われちゃうね!!!いろいろな形態で30分値を取得できるんですね。

No.13 定時積算電力量計測値(逆方向計測値)(EPC=0xEB, 必須)

最新の 30 分毎の計測時刻における積算電力量(逆方向計測値)を、計測年月日を 4 バイト、計測時刻を3 バイト、積算電力量(逆方向計測値)4 バイトで示す。

・計測年月日 YYYY:MM:DD
・計測時刻 hh:mm:ss
・積算電力量[kWh] 10 進表記で最大 8 桁
1~4バイト目:計測年月日
YYYY:0x0001~0x270F
(1~9999)
MM:0x01~0x0C(1~12)
DD:0x01~0x1F(1~31)
5~7バイト目:計測時刻
hh:0x00~0x17(0~23)
mm:0x00~0x3B(0~59)
ss:0x00~0x3B(0~59)
8~11 バイト目:積算電力量計測値
0x00000000~0x05F5E0FF
(0~99,999,999)

取得電文

EB 0B 07 E4 04 1D 03 1E 00 00 00 00 0A

内容解析

EB:EPC
0B:データ長⇒11バイト
07 E4 :2020年
04 : 4月
1D : 29日
03 : 3時
1E : 30分
00 : 0秒
00 00 00 0A :10⇒1.0kWh

当たり前にとれていますね。

No.14 積算電力量計測履歴2(正方向、逆方向計測値)(EPC=0xEC)

積算履歴収集日時、収集コマ数及び積算電力量(最大 8 桁)の計測結果履歴を、正・逆 30 分毎のデータで過去最大 6時間分示す。
・積算履歴収集日時
YYYY:MM:DD:hh:mm
・収集コマ数
・積算電力量[kWh] 10 進表記において最大 8 桁、最大 6 時間分

1~6 バイト目:積算履歴収集日時
YYYY:0x0001~0x270F
(1~9999 年)
MM:0x01~0x0C(1~12 月)
DD:0x01~0x1F(1~31 日)
hh:0x00~0x17(0~23 時)
mm:0x00/0x1E(0/30 分)
7 バイト目:収集コマ数
0x01~0x0C(1~12 コマ)
8 バイト目以降:
積算電力量計測値(正方向)
0x00000000~0x05F5E0FF
(0~99,999,999)
積算電力量計測値(逆方向)
0x00000000~0x05F5E0FF
(0~99,999,999)

取得電文

EC0FFFFFFFFFFFFF01FFFFFFFEFFFFFFFE

内容解析

EC:EPC
0F:データ長⇒15バイト
FF FF FF FF FF FF:積算履歴収集日時
01:収集コマ数
FF FF FF FE:積算電力量計測正方向
FF FF FF FE:積算電力量計測逆方向

積算履歴収集日2(EPC=0xED)が設定されていない初期値の場合は、積算履歴収集日時に0xFFFFFFFFFFFF、収集コマ数に 0x01 をセットし、30 分値は正方向、逆方向それぞれ 1 コマ分に0xFFFFFFFE をセットするとのことなので、やはりEDをセットしてからですな。

というわけで、EDに2020年4月29日5時から12コマ取得でセットして、データを取得してみました。

取得電文

EC6707E4041D05000C
00007F110000000A00007F110000000A
00007F100000000A00007F0F0000000A
00007F0F0000000A00007F0E0000000A
00007F0D0000000A00007F0D0000000A
00007F0C0000000A00007F0B0000000A
00007F0A0000000A00007F0A0000000A

内容解析

EC:EPC
67:データ長⇒103バイト
07E4 04 1D 05 00 0C:2020年4月29日5時00分12コマ
00 00 7F 11:1つめ(5:00)
00 00 00 0A
00 00 7F 11:2つめ(4:30)
00 00 00 0A
00 00 7F 10:3つめ(4:00)
00 00 00 0A
00 00 7F 0F:4つめ(3:30)
00 00 00 0A
00 00 7F 0F:5つめ(3:00)
00 00 00 0A
00 00 7F 0E:6つめ(2:30)
00 00 00 0A
00 00 7F 0D:7つめ(2:00)
00 00 00 0A
00 00 7F 0D:8つめ(1:30)
00 00 00 0A
00 00 7F 0C:9つめ(1:00)
00 00 00 0A
00 00 7F 0B:10つめ(0:30)
00 00 00 0A
00 00 7F 0A:11つめ(0:00)
00 00 00 0A
00 00 7F 0A:12つめ(23:30)
00 00 00 0A

遡って取ることができるので、とり忘れちゃった時用ですね。
いつまでさかのぼれるのか気になるね。

No.15 積算履歴収集日2(EPC=0xED)

30 分毎の計測値履歴データを収集する日時(30 分単位)、及び 30分毎の計測値履歴データを 1 コマとし、収集するコマ数を示す。
1~6 バイト目:積算履歴収集日時
YYYY:0x0001~0x270F(1~9999 年)
MM:0x01~0x0C(1~12 月)
DD:0x01~0x1F(1~31 日)
hh:0x00~0x17(0~23 時)
mm:0x00/0x1E(0/30 分)
7 バイト目:収集コマ数
0x01~0x0C(1~12 コマ)

取得電文

ED 07 FF FF FF FF FF FF 01

内容解析

ED:EPC
07:データ長⇒7バイト
FF FF FF FF FF FF:積算履歴収集日時(初期値)
01:収集コマ数(初期値)

本プロパティの初期値は、積算履歴収集日時を 0xFFFFFFFFFFFF、収集コマ数を 0x01 なので、初期値がはいっておりますね。

 

完了した感想

結構大変だったけど、気になっていたのでちょうどよかったです。

 

結局取れるのは瞬時値と積算値ですね。30分値を集めれば、毎月の電気代計算を自分でできるはずなので、検算ができそう!

 

*1:後になって気が付いたのは内緒

metabaseでデータを可視化する

はじめに

昨日(というか今朝)いろいろ試したラズパイ4にmeabase入れてみましょって眠りにつきながら思っていたのでやってみる。

動作環境

  • Win10 Pro 1909
    *Rlogin 2.24.4
    *HeidiSQL 10.0.0.5919(64bit)
    *Spyder 4
  • Raspberry pi4(4GBモデル)
    *Docker version 19.03.8, build afacb8b
    *docker-compose version 1.25.5, build unknown
    PostgreSQL
    *metabase

参考文献

metabase

まずはmetabaseをupする。

qiita.com

qiita.com

metabaseのRestartingが止まらない。

pi@raspberrypi4:~/docker-db $ docker-compose ps
Name Command State Ports
---------------------------------------------------------------------------------
metabase /app/run_metabase.sh Restarting
postgresql docker-entrypoint.sh postgres Up 0.0.0.0:15432->5432/tcp

下記を参考にrestart: alwaysをコメントアウト

kana-linux.info

それでも直らないのでログを見てみることにした。

pi@raspberrypi4:~/docker-db $ docker-compose logs |grep metabase
Attaching to metabase, postgresql
metabase | standard_init_linux.go:211: exec user process caused "exec format error"

イメージがarm系じゃなかったことに気が付いたので、余っているwinマシンでarm用にコンパイルしてうにゃうにゃするかと思ったけど時間がかかりそうなので断念。

DockerHubをうろうろしてたら、arm用イメージが置いてあったので、ひとまず使ってみることに。(危なそうだし、バージョン古いのが気になるけども)

Docker Hub

 

dataをposetgresに流し込む

最終目標は、データの生成時にそのままDBに書き込むことだけども、今回はひとまずデータが見たいので成形したデータをDBに突っ込む。

まずはAnacondaにpsycopg2を導入

qiita.com

なんだけど、検索でみつからなかった。そんなときはUpdate index すればよさそう!

PostgresはCOPY文でcsvを流し込むのが速そうだとわかったので、適当にデータ加工して流し込むことにしてみました。

DELTA:114[W](2020/04/19 07:39:51)

SUM_P:3218.3[kWh](2020/04/19 07:39:51)

データはこんな形で入っているので、日付と値に分解して、

DATE, DELTA, SUM_P

2020/04/19 07:39:51, 114, 3218.3

のようにしました。

だったら最初から書けばいいじゃんってのは内緒

 

下記あたりを参考にDBにデータのインサートを試みてみた。

qiita.com

datumstudio.jp

memoyoushi.blog24.fc2.com

 

なんかうまくいかないので、SQLクライアントでCSVを流してDBにデータを登録。

IDが3からになっているけど、気にしないこと。

metadataで表示

初期設定を適当に済ませて、突っ込んだデータを表示させる。

使い方がわからなくてめっちゃ試行錯誤した結果、それらしい結果が得られてよかた。

 

完走した感想

めっちゃ時間かかっちゃったけど、納得がいくところまでできたからよかった。

これで安心して眠れる。

今後やりたいこととしては、

  • データをDBに直接書いて、どんどん溜める
  • 溜めたデータを1日1回NASにバックアップさせる(差分バックアップがいいね)
  • 取得スクリプトが落ちてるときがあるので、自動復帰させる仕組みを入れる
    ⇒なんで落ちているのか原因を探る。3日ぐらい実行していると落ちていることが多い
  • データを分析してうにゃうにゃする仕組みを作る

あたりですかね。

今年のGWは外出自粛ですし、この辺進めていきたいですねぇ~