この記事は、ゆめみ Advent Calendar 2021 の14日目の記事です。
概要
個人プロジェクトでInfluxDBを読み取るAndroidアプリをKMMで作ろうとした。
しかし、InfluxDBの公式SDKを追加すると、エラーでビルドができなくなってしまった。
色々調べた結果、KMMでは公式SDKが使えない事が分かった。
なぜ公式SDKを使わないのか?
GitHubで公式SDKである influxdb-client-kotlin を見ると、Java版をKotlinでwrapしているだけだった。
その何が問題かというと、KMMでKotlin SDKが使えない のである。
(KMMではJavaライブラリは使えず、全てKotlinで書かれたライブラリしか使えない)
InfluxDB APIを使えばいけそう
公式SDKを使わずAPIで値を取れないかと調べたところ、
「InfluxDB APIでFluxクエリーを使えば取得できる」という情報を見つけた。
このページを見て驚いたのは以下の2つ
- レスポンスが
CSV形式
である - Fluxクエリを送信する必要がある
「え?CSVなの・・・?」
「Fluxクエリってなに・・・」
という驚きを今でも覚えている。
(Jsonが良かったな...)
InfluxDBから値を取得できたコード
以下が公式SDKを使わず、Kotlin値を取得できたコードである。
Ktor Clinetを使ってAPI通信している。
// APIクライアント
private val client: HttpClient by lazy {
HttpClient(CIO) {
defaultRequest {
headers {
append(HttpHeaders.ContentType, "application/json")
append(HttpHeaders.Authorization, "Token ${InfluxCloudApiConfig.TOKEN}")
append(HttpHeaders.Accept, "application/csv")
}
url(InfluxCloudApiConfig.URL) // API URLは固定
}
}
}
// API通信処理
suspend fun fetchInfluxDB(): String {
// kotlinx.serializationでFluxクエリをJsonにする
val json = Json.encodeToString(Query(query = firstRowQuery, org = InfluxCloudApiConfig.ORG))
// InfluxDBにAPI通信スタート
val response: HttpResponse = client.post {
body = json
}
// レスポンス文字列を取得
val stringBody: String = response.receive()
println(stringBody) // CSVが表示される
// あとはCSVをModelクラスに変換したりする
return stringBody
}
/**
* Queryクラス
* FluxクエリをJsonに変換するクラス
*/
@Serializable
internal class Query(
// 登録メールアドレス
val org: String,
// Fluxクエリ
val query: String,
)
// Flux Query
private val firstRowQuery = """
from(bucket: "dev")
|> range(start: -12h)
|> filter(fn: (r) => r.location == "BedRoom" )
|> filter(fn: (r) => r["_field"] == "pressure" or r["_field"] == "temperature" or r["_field"] == "humidity")
|> sort(columns: ["_time"], desc: true)
|> first()
""".trimIndent()
Flux Queryを軽く説明しておくと
- GraphQLのようにクライアント側で取得する値を指定できる
-
|>
のパイプ演算子?で取得した値を任意の条件で絞り込める - 上記のクエリだと「12時間前のデータを、指定した値に絞り込み、途中で並び替えて、最後に1件に絞る」
感想
- とりあえず目的は達成できたので良かった。
- InfluxDBの公式SDKのKotlin版がとても微妙なので、これを機にKotlinライブラリを作ってもいいかもしれない。
- Fluxクエリは初めて使ったが、なかなか慣れない
- ここまで書いておいてアレだが、クライアント側でInfluxDBを直接参照せず、Lambda等でCSV→Jsonに変換する処理を挟んだほうがい絶対にいい。
CSVの変換が超絶めんどくさすぎる...- その時にこそ、この記事のコードが役立つと思う。