ESP32からHTTPSリクエスト例

ESP32のJavascript実行環境を使って、HTTPSリクエストを使ったIoTのためのライブラリを作成しました。

以下のESP32用のJavascript実行環境のファームウェアを使います。

「電子書籍：M5StackとJavascriptではじめるIoTデバイス制御」

https://poruruba.booth.pm/items/3735175

# 準備

以下を参考に、HTTPSのためのブリッジサーバを立ち上げます。

https://qiita.com/poruruba/items/6dd9356a94aa526444fb

そして、以下を1回実行しておきます。
```js:main.js
import * as http from "Http";
http.setHttpBridgeServer('http://【立ち上げたブリッジサーバ】:30080');
```


# サンプルライブラリ

(i)	LINE Notify

https://notify-bot.line.me/doc/ja/

```js:LineNotify.js
import * as http from "Http";

export default class LineNotify{
  constructor(accessToken){
    this.accessToken = accessToken;
  }

  notify(message){
    var body = {
      message: message
    };
    var headers = {
      Authorization: "Bearer " + this.accessToken
    };
    var url = "https://notify-api.line.me/api/notify";
    var result = http.fetch(http.method_post_urlencode | http.resp_json, url, null, body, headers );
    return result;
  }
}
```

使い方

```js:main.js
//import * as http from "Http";
//http.setHttpBridgeServer('http://【立ち上げたブリッジサーバ】:30080');

import LineNotify from "LineNotify.js";
var linenotify = new LineNotify("【アクセストークン】");

(async function(){
  try{
    var result = linenotify.notify("こんにちは");
    console.log(JSON.stringify(result));
  }catch(error){
    console.error(error);
  }
})();
```

(ii) Beebotte

https://beebotte.com/docs/write

```js:Beebotte.js
import * as http from "Http";

export default class Beebotte{
  constructor(channel, channelToken){
    this.channel = channel;
    this.channelToken = channelToken;
  }

  write(data){
    var body = {
      records: [
      ]
    };
    for( const [key, value] of Object.entries(data)){
      body.records.push({ resource: key, data: value });
    }
    var headers = {
      "X-Auth-Token": this.channelToken
    };
    var url = "https://api.beebotte.com/v1/data/write/" + this.channel;
    var result = http.fetch(http.method_post_json | http.resp_json, url, null, body, headers );
    return result;
  }
}
```

使い方

```js:main.js
//import * as http from "Http";
//http.setHttpBridgeServer('http://【立ち上げたブリッジサーバ】:30080');

import Beebotte from "Beebotte.js";
var beebotte = new Beebotte("【チャネル名】", "【チャネルトークン】");

(async function(){
  try{
    var data = {
      resource1: 5677,
      resource2: "テスト"
    };
    var result = beebotte.write(data);
    console.log(JSON.stringify(result));
  }catch(error){
    console.error(error);
  }
})();
```

(iii) OpenWeather

https://openweathermap.org/current

```js:OpenWeather.js
import * as http from "Http";

export default class OpenWeather{
  constructor(apikey){
    this.apikey = apikey;
  }

  current(lat, lon){
    var qs = {
      lat: lat,
      lon: lon,
      lang: "ja",
      appid: this.apikey
    };
    var url = "https://api.openweathermap.org/data/2.5/weather";
    var result = http.fetch(http.method_get | http.resp_json, url, qs );
    return result;
  }
}
```

使い方

```js:main.js
//import * as http from "Http";
//http.setHttpBridgeServer('http://【立ち上げたブリッジサーバ】:30080');

import OpenWeather from "OpenWeather.js";
var openWeather = new OpenWeather("【APIキー】");

(async function(){
  try{
    var result = openWeather.current(35.45289084467834, 139.64291548274204);
    console.log(JSON.stringify(result));
  }catch(error){
    console.error(error);
  }
})();
```

(iv) SwitchBot

https://github.com/OpenWonderLabs/SwitchBotAPI

```js:SwitchBot.js
import * as http from "Http";

export default class SwitchBot{
  constructor(token){
    this.token = token;
    this.base_url = "https://api.switch-bot.com/v1.0";
  }

  getDeviceList(){
    var headers = {
      "Authorization": this.token
    };
    var url = this.base_url + "/devices";
    var result = http.fetch(http.method_get | http.resp_json, url, null, null, headers );
    if( result.statusCode != 100 )
      throw new Error("statusCode is not 100");
    return result.body;
  }

  getDeviceStatus(deviceId){
    var headers = {
      "Authorization": this.token
    };
    var url = this.base_url + "/devices/" + deviceId + "/status";
    var result = http.fetch(http.method_get | http.resp_json, url, null, null, headers );
    if( result.statusCode != 100 )
      throw new Error("statusCode is not 100");
    return result.body;
  }

  sendDeviceControlCommand(deviceId, commandType, command, parameter){
    var params = {
      command: command,
      parameter: parameter,
      commandType: commandType
    };
    var headers = {
      "Authorization": this.token
    };
    var url = this.base_url + "/devices/" + deviceId + "/commands";
    var result = http.fetch(http.method_get | http.resp_json, url, params, null, headers );
    if( result.statusCode != 100 )
      throw new Error("statusCode is not 100");
    return result.body;
  }
}
```

使い方

```js:main.js
//import * as http from "Http";
//http.setHttpBridgeServer('http://【立ち上げたブリッジサーバ】:30080');

import SwitchBot from "SwitchBot.js";
var switchBot = new SwitchBot("【アクセストークン】");

(async function(){
  try{
    var result = switchBot.getDeviceList();
    console.log(JSON.stringify(result));
  }catch(error){
    console.error(error);
  }
})();
```

(v) Gemini

https://ai.google.dev/gemini-api/docs?hl=ja

```js:Gemini.js
import * as http from "Http";

export default class Gemini{
  constructor(apikey){
    this.apikey = apikey;
    this.base_url = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent";
  }

  generateContent(text){
    var qs = {
      key: this.apikey
    };
    var body = {
      contents: [{
          parts : [{
              text: text
          }]
      }]
    };
    var result = http.fetch(http.method_post_json | http.resp_json, this.base_url, qs, body );
    return result;
  }
}
```

使い方

```js:main.js
//import * as http from "Http";
//http.setHttpBridgeServer('http://【立ち上げたブリッジサーバ】:30080');

import Gemini from "Gemini.js";
var gemini = new Gemini("【APIキー】");

(async function(){
  try{
    var result = gemini.generateContent("こんにちは");
    console.log(JSON.stringify(result));
  }catch(error){
    console.error(error);
  }
})();
```


(vi) Slack

https://api.slack.com/messaging/sending

```js:Slack.js
import * as http from "Http";

export default class Slack{
  constructor(token){
    this.token = token;
    this.base_url = "https://slack.com/api";
  }

  postMessage(channel, text){
    var params = {
      token: this.token,
      channel: channel,
      text: text
    };
    var url = this.base_url + "/chat.postMessage";
    var result = http.fetch(http.method_post_formdata | http.resp_json, url, null, params );
    return result;
  }
}
```

使い方

```js:main.js
//import * as http from "Http";
//http.setHttpBridgeServer('http://【立ち上げたブリッジサーバ】:30080');

import Slack from "Slack.js";
var slack = new Slack("【OAuth Token】");

(async function(){
  try{
    var result = slack.postMessage("#general", "こんにちは");
    console.log(JSON.stringify(result));
  }catch(error){
    console.error(error);
  }
})();
```

(vii) Chatwork

https://developer.chatwork.com/reference/get-rooms

```js:Chatwork.js
import * as http from "Http";

export default class Chatwork{
  constructor(apitoken){
    this.apitoken = apitoken;
    this.base_url = "https://api.chatwork.com/v2";
  }

  getChatList(){
    var headers = {
      "x-chatworktoken": this.apitoken
    };
    var url = this.base_url + "/rooms";
    var result = http.fetch(http.method_get | http.resp_json, url, null, null, headers );
    return result;
  }

  postMessage(room_id, message){
    var headers = {
      "x-chatworktoken": this.apitoken
    };
    var body = {
      body: message
    };
    var url = this.base_url + "/rooms/" + room_id + "/messages";
    var result = http.fetch(http.method_post_urlencode | http.resp_json, url, null, body, headers );
    return result;
  }
}
```

使い方

```js:main.js
//import * as http from "Http";
//http.setHttpBridgeServer('http://【立ち上げたブリッジサーバ】:30080');

import Chatwork from "Chatwork.js";
var chatWork = new Chatwork("【APIトークン】");

(async function(){
  try{
    var result = chatWork.getChatList();
    console.log(JSON.stringify(result, null, "\t"));
    var result = chatWork.postMessage(result[0].room.id, "こんにちは");
    console.log(JSON.stringify(result, null, "\t"));
  }catch(error){
    console.error(error);
  }
})();
```

(viii) GAS SpreadSheet

https://developers.google.com/apps-script/guides/web?hl=ja

```js:Chatwork.js
import * as http from "Http";

export default class GasSpreadsheet{
  constructor(url){
    this.url = url;
  }

  call(data){
    var result = http.fetch(http.method_post_json | http.resp_json, this.url, null, data );
    return result;
  }
}
```

使い方

```js:main.js
//import * as http from "Http";
//http.setHttpBridgeServer('http://【立ち上げたブリッジサーバ】:30080');

import GasSpreadsheet from "GasSpreadsheet.js";
var gasSpreadsheet = new GasSpreadsheet("【ウェブアプリのURL】");

(async function(){
  try{
    var data = ["value1", "value2"];
    var result = gasSpreadsheet.call(data);
    console.log(JSON.stringify(result, null, "\t"));
  }catch(error){
    console.error(error);
  }
})();
```

GASのスクリプト例

```gs:code.gs
//var ss = SpreadsheetApp.openById("【スプレッドシートID】");
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("【シート名】");

function doPost(e) {
  try{
    var data = JSON.parse(e.postData.contents);
    sheet.appendRow(data);
    SpreadsheetApp.flush();

    var out = ContentService.createTextOutput();
    out.setMimeType(ContentService.MimeType.JSON);
    out.setContent(JSON.stringify({ status: "OK" }));
    return out;
  }catch(error){
    var out = ContentService.createTextOutput();
    out.setMimeType(ContentService.MimeType.JSON);
    out.setContent(JSON.stringify({ status: "ERROR" }));
    return out;
  }
}
```


# 本ファームウェアのサポートサイト

〇電子書籍：M5StackとJavascriptではじめるIoTデバイス制御

https://poruruba.booth.pm/items/3735175

〇ファームウェアのサポートサイト

https://github.com/poruruba/QuickJS_ESP32_IoT_Device_M5Unified

〇ファームウェアダウンロードサイト

https://poruruba.github.io/EspWebDownloader/quickjs_esp32_firmware/

◯参考

https://qiita.com/poruruba/items/9ae64c878ce65f569961

以上