「せばな」は言わない

綱の上を歩き、岩を登るエンジニア

【Raspberry Pi】IoT入門 Azure+Noderedで環境データを見える化作戦 Part1

はじめに

前回の記事でラズパイとBME280を使用して温度、湿度、気圧がとれました!
今度は取得したデータをAzureにアップします。なんだかそれっぽいですよね(それって何だ)
※タイトルにNoderedと入っていますが、このPartではまだ出てきません!!ごめんね!

環境用意

さて、まずはMicrosoftのAzureに環境を用意しなければいけませんね。
これらの記事を見ながら設定しました。

DBの作成はこの記事で。
tamafuyou.hatenablog.com

DBができたらテーブルを作ろう。
Azureのクエリエディタを使うならこんな感じ。


そんでクエリを書いて、実行を押せばテーブルができます。テーブルの名前は任意でつけてください。

CREATE TABLE test_table
(
     tempreture  float DEFAULT NULL
    ,humidity float DEFAULT NULL
    ,pressure float DEFAULT NULL
    ,regiater_at datetime DEFAULT getdate()
    ,CONSTRAINT regiater_at PRIMARY KEY CLUSTERED 
    (
      regiater_at
    )
)

pythonからAzureに接続

怒りのインストール編

まずは、odbcドライバをインストール

pythonで使用できるodbcドライバを検索

$ apt-cache search odbc | grep python

ラズパイにドライバインストール

$ sudo apt-get install python-pyodbc

pythonのライブラリをインストール

$ sudo pip3 install pyodbc


ここでお待ちかねのエラー発生!!

src/pyodbc.h:56:17: fatal error: sql.h: そのようなファイルやディレクトリはありません
#include
^
compilation terminated.
error: command 'arm-linux-gnueabihf-gcc' failed with exit status 1

Command "/usr/bin/python3 -u -c "import setuptools, tokenize;__file__='/tmp/pip-build-pn8_m4v_/pyodbc/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-in8uz67z-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-build-pn8_m4v_/pyodbc/

 

以下stack overflowを参考に足りないモノを追加でインストール
stackoverflow.com

ワイ氏、怒りのインストール

$ sudo apt-get install unixodbc
$ sudo apt-get install unixodbc-dev
$ sudo apt-get install freetds-dev
$ sudo apt-get install tdsodbc
$ sudo apt-get install freetds-bin

ふえぇ…泣きそう。

でもこれでやっとインストールできるよ!ヤッター

$sudo pip3 install pyodbc

できた(白目

Successfully built pyodbc
Installing collected packages: pyodbc
Successfully installed pyodbc-4.0.22

絶望のDB接続編

さて接続。ここからがとてつもなく長かった。
まずはFreeTDSの接続用ファイルを作成する。

こちらの記事を参考にして dsn.template を用意。

qiita.com

参考に。

[AZURE] ←データソースの名前
Description=AZURE
Driver=/usr/lib/arm-linux-gnueabihf/odbc/libtdsodbc.so
Setup=/usr/lib/arm-linux-gnueabihf/odbc/libtdsS.so
Trace=No
Server=xxxxxxxxxx.database.windows.net(Azule上のサーバ名)
Database=xxxxxx(接続するDB名)
Port=1433
TDS_Version=8.0
ClientCharset=UTF-8

ドライバの場所は記事とは違ったのでみなさんも適宜修正してください。
作成できたら下記のコマンドでインストール(内容を)

$sudo odbcinst -i -s -l -f dsn.template


手始めに isql で接続確認。

$isql -v データソースの名前 ユーザ名 パスワード

上記を入力して…よし実行だ!

Connected!

sql-statement
help [tablename]
quit

SQL>

うおおおおおおおおお、きたああああああああ!!

試しにSQLにAzureのデータベースバージョンを出力してみる。

SQL> SELECT @@version

Microsoft SQL Azure (RTM) - 12.0.2000.8
Nov 29 2017 09:37:51
Copyright (C) 2017 Microsoft Corporation

や っ た ぜ !

もしもここでエラーが出る場合、下記の理由が考えられます。

  • dsn.templateの設定にミスがある。

もう一度内容を確認してください。ここでハマると少々やっかいです

  • AzureのファイアウォールにクライントIPを許可していない

Azureダッシュボード→SQLデータベース→該当のDBをクリック→詳細画面上部のサーバーファイアウォールの設定
→クライアントIPをコピーして開始、終了にコピーしたIPを入力。接続の名前をつけて保存

ここまできたら、あとはラズパイで取得した環境データをPythonからDBに流し込むだけだろう…と楽観視していたときが私にもありました。

よもやここから実働6時間くらいハマることになるとは、この時の僕はまだ知らない。

まずはPythonでDBにアクセスするプログラムを作成する。
最終的にgitに上げた感じになりました。
何かあっても責任はとれませんが、ご自由に利用してください。

・bme280db.py(メインプログラム これを実行します)
・connect_ms.py(ご自身が使用するDBの設定に書き換えてください)

github.com


さてここで問題発生。
上記のプログラムは正常に動作するが、ある一部分の間違いにより下記のエラーを1000回くらい見る羽目になった。

Traceback (most recent call last):
File "connect_ms.py", line 41, in
(中略)
pyodbc.InterfaceError: ('IM002', '[IM002] [unixODBC][Driver Manager]Data source name not found, and no default driver specified (0) (SQLDriverConnect)')

いつもより2時間も夜更かしした上に結局解決しないし。モヤモヤして夜中に目が覚めるしで最悪のユーザ体験だった。
さて問題の部分は下記である。

# 接続文字列作成
con_string = 'DSN = %s;UID = %s;PWD = %s;DATABASE = %s;' % (dsn, user, password, database)

さて、どこが間違っているか分かりますかな??

じゃあ見比べてみよう!(ブチギレ)

正:con_string = 'DSN=%s;UID=%s;PWD=%s;DATABASE=%s;' % (dsn, user, password, database)
誤:con_string = 'DSN = %s;UID = %s;PWD = %s;DATABASE = %s;' % (dsn, user, password, database)

気が付きましたか?そう、接続文字列のイコール前後に空白が入っていたんです!

ふぁーーーーーwwwwwwwwwwwwwwwwwwwwww

こんなことで一晩悩んだなんて意味が分からん!!!!

さて、気を取り直して続きをやりましょう。
Part2へ続く。