ESP32からGraphQLで通信します。
振り返れば、HTTPに加えて、SNMP、CoAP、WebSocket、MQTT、ESPNow、AWS、BLEペリフェラルなど、様々な通信プロトコルを実装してきました。
今回も、ESP32上で動作するJavascriptを使います。
GraphQLサーバとして、Strapiを使いました。
以下の例を示します。
・Query(引数無し)
・Query(引数あり)
・Mutation(引数有り)
Strapiに定義したコンテンツ
試しに、以下のコンテンツを作成しました。
表示名:観光スポット
API ID(単数形):sightseeing-spot
API ID(複数形):sightseeing-spots
フィールドとして以下の2つを持たせています。
name:text(短いテキスト)
message:text(長いテキスト)
Javascript:セットアップ
QueryやMutationを呼び出す前に、エンドポイントとHeaderを指定します。Headerは任意ですが、StrapiのGraphQL呼び出しではトークンの指定で必要です。
import * as graphql from "Graphql";
graphql.setEndpoint("http://[Strapiのホスト名]:1337/graphql");
graphql.setHeader("Authorization", "Bearer [Strapiのトークン]");
Javascript:Query(引数無し)
var query = `
query SightseeingSpots {
sightseeingSpots {
name
documentId
}
}
`;
var variables = {};
var result = graphql.query(query, variables);
console.log(JSON.stringify(result));
こんな感じで返ってきます。
{"data":{"sightseeingSpots":[{"name":"test1","documentId":"XXXXXXXXXXXXXXX"}]}}
Javascript:Query(引数あり)
var query2 = `
query SightseeingSpots($documentId: ID!) {
sightseeingSpot(documentId: $documentId) {
name
documentId
}
}
`;
var variables2 = {
"documentId": "XXXXXXXXXXXXXXX"
};
var result = graphql.query(query2, variables2);
console.log(JSON.stringify(result));
こんな感じで返ってきます。
{"data":{"sightseeingSpot":{"name":"test1","documentId":"XXXXXXXXXXXXXXX"}}}
Javacript:Mutation(引数有り)
var mutation = `
mutation UpdateSightseeingSpot($documentId: ID!, $data: SightseeingSpotInput!) {
updateSightseeingSpot(documentId: $documentId, data: $data) {
name
}
}
`;
var variables3 = {
"documentId": "XXXXXXXXXXXXXXX",
"data": {
"name": "test2"
}
};
var result = graphql.mutation(mutation, variables3);
console.log(JSON.stringify(result));
こんな感じで返ってきます。
{"data":{"updateSightseeingSpot":{"name":"test2"}}}
内部実装
HTTPClientを使っています。
static JSValue graphql_execute(JSContext *ctx, JSValueConst jsThis, int argc, JSValueConst *argv)
{
if( g_endpoint == NULL )
return JS_EXCEPTION;
JSValue obj = JS_NewObject(ctx);
JS_SetPropertyStr(ctx, obj, "query", JS_DupValue(ctx, argv[0]));
JS_SetPropertyStr(ctx, obj, "variables", JS_DupValue(ctx, argv[1]));
JSValue body_object = json_stringify(ctx, obj);
JS_FreeValue(ctx, obj);
const char *body = JS_ToCString(ctx, body_object);
if( body == NULL ){
JS_FreeValue(ctx, body_object);
return JS_EXCEPTION;
}
String result = processGraphql(body);
JS_FreeCString(ctx, body);
JS_FreeValue(ctx, body_object);
if( result.length() == 0 )
return JS_EXCEPTION;
JSValue result_object = json_parse(ctx, result.c_str());
return result_object;
}
static String processGraphql(const char *p_body)
{
HTTPClient http;
http.begin(g_endpoint);
http.addHeader("Content-Type", "application/json");
for (const auto& kv : g_headers) {
const std::string& key = kv.first;
const std::string& value = kv.second;
http.addHeader(key.c_str(), value.c_str());
}
int httpCode = http.POST(p_body);
if (httpCode > 0) {
String payload = http.getString();
http.end();
return payload;
}else{
http.end();
return String("");
}
}
(参考) ESP32で動作するJavascript実行環境
ESP32で動作するJavascript実行環境を公開しています。
Javascriptのコードを書き換えるのに、いちいち再コンパイル不要なので、らくちんです。
「電子書籍:M5StackとJavascriptではじめるIoTデバイス制御」
サポートサイト
ぜひ、手に取ってみてください。
以上