REST-API

2020年12月27日 (日)

Wio-Terminal/M5Atom/ESP8622/ESP32ボードを共通のスケッチで動かす(v2)(REST-API編)

2020/12/27+
初版

board3 REST API v2

board3 REST API v2

概要

Wio-Terminal/M5Atom/ESP8622/ESP32ボードを共通のスケッチで動かす(v2)(REST-API編)
本記事は「 Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(REST-API編)」 の改版にあたり、wio-terminalのファームウェア・バージョンアップに対応している。

wio-terminalのファームウェアのバージョンアップで以下の不具合も解消している。

Wio-Terminalの場合、REST-APIは、起動後の1回しか動作しなかった。(原因不明)

wio-terminalのファームウェアのアップデート方法については以下を参照のこと:
wio-terminalのファームウェア・アップデートについて(v2)(linux版)

デモ・スケッチ

src/REST-API_test.ino

// select board ////#define M5ATOM ////#define WIO_TERMINAL ////#define ESP8266 ////#define ESP32 //------------------ // REST-API server for Wio-Terminal/ESP8266/ESP32 /* * Forked from the following code: * * Simple hello world Json REST response * by Mischianti Renzo <https://www.mischianti.org> * * https://www.mischianti.org/ * */ #ifdef M5ATOM #include "M5Atom.h" #define ESP32 #endif #ifdef WIO_TERMINAL //#include <AtWiFi.h> #include <rpcWiFi.h> #include <WebServer.h> #include <WiFiUdp.h> #include <ArduinoMDNS.h> #endif #ifdef ESP8266 #include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #include <ESP8266mDNS.h> #endif #ifdef ESP32 #include <WiFi.h> #include <WebServer.h> #include <ESPmDNS.h> #endif const char* ssid = "<your-ssid>"; const char* password = "<your-passwd>"; #ifdef WIO_TERMINAL WiFiUDP udp; MDNS mdns(udp); WebServer server(80); #endif #ifdef ESP8266 ESP8266WebServer server(80); #endif #ifdef ESP32 WebServer server(80); #endif // Serving Hello world void getHelloWord() { server.send(200, "text/json", "{\"name\": \"Hello world\"}\r\n"); } void ledOff() { // do something for LED off server.send(200, "text/json", "{\"led\": \"OFF\"}\r\n"); } void ledOn() { // do something for LED on server.send(200, "text/json", "{\"led\": \"ON\"}\r\n"); } // Define routing void restServerRouting() { server.on("/", HTTP_GET, []() { server.send(200, F("text/html"), F("Welcome to the REST Web Server")); }); server.on(F("/helloWorld"), HTTP_GET, getHelloWord); server.on(F("/api/v1/led=0"), HTTP_GET, ledOff); server.on(F("/api/v1/led=1"), HTTP_GET, ledOn); } // Manage not found URL void handleNotFound() { String message = "File Not Found\n\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; message += (server.method() == HTTP_GET) ? "GET" : "POST"; message += "\nArguments: "; message += server.args(); message += "\n"; for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; } server.send(404, "text/plain", message); } void setup(void) { Serial.begin(115200); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); Serial.println(""); // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP()); // Activate mDNS this is used to be able to connect to the server // with local DNS hostmane esp8266.local #ifdef WIO_TERMINAL mdns.begin(WiFi.localIP(), "wiot"); Serial.println("MDNS responder started(wiot)"); #endif #ifdef ESP8266 if (MDNS.begin("esp8266")) { Serial.println("MDNS responder started(esp8266)"); } #endif #ifdef ESP32 if (MDNS.begin("esp32")) { Serial.println("MDNS responder started(esp32)"); } #endif // Set server routing restServerRouting(); // Set not found response server.onNotFound(handleNotFound); // Start server server.begin(); Serial.println("HTTP server started"); } void loop(void) { #ifdef WIO_TERMINAL mdns.run(); // This actually runs the mDNS module. YOU HAVE TO CALL THIS PERIODICALLY #endif #ifdef ESP8266 MDNS.update(); #endif #ifdef ESP32 //MDNS.update(); // no need to update on ESP32 #endif server.handleClient(); }

wio-terminalのファームウェアのバージョン・アップにともない
以下のようにヘッダーが変更になっている:

//#include <AtWiFi.h> #include <rpcWiFi.h>

以下の#defineでボードを切り換えているがボードの種類を設定すると、 システムで設定されている定義が有効になるので特にソースを変更する必要はない。

#define WIO_TERMINAL #define ESP8266 #define ESP32 #define M5ATOM

以下については、自分の環境に合わせて変更すること:

const char ssid[] = "yours_ssid"; const char pass[] = "yours_passwd";

書き込み後に「picocom /dev/ttyACM0 -b115200」または「picocom /dev/ttyUSB0 -b115200」で通信ソフトを起動すると以下のような出力が表示される:

$ picocom /dev/ttyACM0 -b115200 # ESP8266の場合 ... Connected to xxxxxxxx IP address: 192.168.0.5 MDNS responder started(esp8266) HTTP server started # M5Atom/ESP32の場合 .. Connected to xxxxxxxx IP address: 192.168.0.15 MDNS responder started(esp32) HTTP server started # Wio-Terminalの場合 .. Connected to xxxxxxxx IP address: 192.168.0.15 MDNS responder started(wiot) HTTP server started

curlによるコマンド実行例:

# ESP8266の場合 $ curl 'http://esp8266.local:80/helloWorld' {"name": "Hello world"} $ curl 'http://esp8266.local:80/api/v1/led=1' {"led": "ON"} $ curl 'http://esp8266.local:80/api/v1/led=0' {"led": "OFF"} # ESP32の場合 $ curl 'http://esp32.local:80/helloWorld' {"name": "Hello world"} $ curl 'http://esp32.local:80/api/v1/led=0' {"led": "OFF"} $ curl 'http://esp32.local:80/api/v1/led=1' {"led": "ON"} # wio-terminalの場合 $ curl 'http://wiot.local:80/helloWorld' {"name": "Hello world"} $ curl 'http://wiot.local:80/api/v1/led=0' {"led": "OFF"} $ curl 'http://wiot.local:80/api/v1/led=1' {"led": "ON"}

mDNSによる名前解決には時間がかかることがあるので その場合、IPアドレスでアクセスすること。
また、M5Atomの場合、プログラム起動後、リセットボタンを押す必要があるようだ。

platformio.ini

platformio.iniは、ボードに合わせて以下を使用する:

wio-terminalの場合:

; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:seeed_wio_terminal] platform = atmelsam board = seeed_wio_terminal framework = arduino build_flags = -DWIO_TERMINAL upload_protocol = sam-ba monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = https://github.com/Seeed-Studio/Seeed_Arduino_mbedtls/archive/dev.zip https://github.com/Seeed-Studio/Seeed_Arduino_rpcUnified/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_rpcBLE/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_rpcWiFi/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_FreeRTOS/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_FS/archive/master.zip https://github.com/Seeed-Studio/Seeed_Arduino_SFUD/archive/master.zip # https://github.com/Seeed-Studio/Seeed_Arduino_LCD/archive/master.zip # # mDNS lib "ArduinoMDNS" 2848

M5Atomの場合:

; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:esp32dev] platform = espressif32 #board = esp32dev board = m5stick-c framework = arduino monitor_speed = 115200 lib_ldf_mode = deep+ lib_deps = # use M5Atom lib 3113 # use "FastLED" 126

ESP32の場合:

; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:esp32dev] platform = espressif32 board = esp32dev framework = arduino build_flags = -DESP32 monitor_speed = 115200 lib_ldf_mode = deep+

ESP8266の場合:

; PlatformIO Project Configuration File ; ; Build options: build flags, source filter ; Upload options: custom upload port, speed and extra flags ; Library options: dependencies, extra library storages ; Advanced options: extra scripting ; ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html [env:huzzah] platform = espressif8266 #board = huzzah board = esp_wroom_02 framework = arduino monitor_speed = 115200 lib_ldf_mode = deep+

wio-terminalのファームウェアを切り替えたときの注意

古いファームウェアのライブラリを動かした後は、古いライブラリがキャッシュで残っていると ビルド・エラーになるので以下を実行すること:

cd project_directory rm -r .pio/libdeps/seeed_wio_terminal/* rm -r .pio/build/seeed_wio_terminal/*

参考情報

PlatformIO Core (CLI)

以上

続きを読む "Wio-Terminal/M5Atom/ESP8622/ESP32ボードを共通のスケッチで動かす(v2)(REST-API編)"

| | コメント (0)

2020年8月 3日 (月)

Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチでWorld Time APIを使う(WorldTimeAPI編)

2020/8/3:
初版

board3 HTTP/JSON

board3 HTTP/JSON

概要

Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチでWorld Time APIを使う(WorldTimeAPI編)
本スケッチは、httpアクセスとJSONライブラリを使用してWorldTimeAPIを利用している。
(ホストPCとしてはubuntuを想定している)

外部ライブラリ(platformioの場合)

以下を実行してライブラリをインストールする:

# JSON lib インストール #pio lib install "ArduinoJson" pio lib install 64

または、platformio.iniに以下を追加する:

lib_deps = # use "ArduinoJson" lib 64

テスト・スケッチ

src/HTTP_JSON.ino

// select board ////#define WIO_TERMINAL ////#define ESP8266 ////#define ESP32 //------------------ // // HTTP/JSON access for Wio-Terminal/ESP8266/ESP32 // #ifdef WIO_TERMINAL #include <AtWiFi.h> #endif #ifdef ESP8266 #include <ESP8266WiFi.h> #endif #ifdef ESP32 #include <WiFi.h> #endif #include <WiFiClientSecure.h> #include <ArduinoJson.h> #define BODY_SIZE 1024 char bodyBuff[BODY_SIZE]; // Allocate the JSON document StaticJsonDocument<400> doc; // change size if error happen const char* ssid = "your_ssid"; const char* passwd = "your_passwd"; // prototype void ConvertUnixTimeToLocalTime(uint64_t unixtime, uint32_t *pyear, uint8_t *pmonth, uint8_t *pday, uint8_t *phour, uint8_t *pminute, uint8_t *psecond); char *weekday[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; uint32_t year; uint8_t month, day, hour, minu, sec; void setup() { // Initialize serial port Serial.begin(115200); while (!Serial) continue; Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, passwd); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } bool Http_Get_access(String host, String url, String argument){ WiFiClient client; client.setTimeout(500); const int httpPort = 80; const char* host2 = host.c_str(); if (!client.connect(host2, httpPort)) { Serial.println("connection failed"); return false; } client.print(String("GET ") + url + "?" + argument + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "User-Agent: ESP8266/1.0\r\n" + "Connection: close\r\n\r\n"); unsigned long timeout = micros(); while (client.available() == 0) { if ( micros() - timeout > 5000000) { Serial.println(">>> Client Timeout !"); client.stop(); return false; } } Serial.println("--- Header ---"); while (1) { String line = client.readStringUntil('\n'); Serial.println(line); if (line == "\r") { break; // end of header } } //Serial.println("--- Body ---"); // for debug int bc = 0; while (client.available()) { bodyBuff[bc] = client.read(); bc++; } bodyBuff[bc] = 0; //Serial.println(bodyBuff); // display body for debug return true; } void loop() { String host = "worldtimeapi.org"; String url = "/api/timezone/Asia/Tokyo"; String argument = ""; Http_Get_access( host, url, argument); Serial.println("accessed BODY:"); Serial.println(bodyBuff); // Deserialize the JSON document DeserializationError errorJson = deserializeJson(doc, bodyBuff); const char* abbreviation = doc["abbreviation"]; const char* client_ip = doc["client_ip"]; const char* datetime = doc["datetime"]; long day_of_week = doc["day_of_week"]; long day_of_year = doc["day_of_year"]; long raw_offset = doc["raw_offset"]; const char* timezone = doc["timezone"]; long unixtime = doc["unixtime"]; const char* utc_datetime = doc["utc_datetime"]; const char* utc_offset = doc["utc_offset"]; long week_number = doc["week_number"]; Serial.println(); Serial.printf("Deserialized:\r\n"); Serial.printf("abbreviation:%s\r\n",abbreviation); Serial.printf("client_ip:%s\r\n",client_ip); Serial.printf("datetime:%s\r\n",datetime); Serial.printf("day_of_week:%d\r\n",day_of_week); Serial.printf("day_of_year:%d\r\n",day_of_year); Serial.printf("raw_offset:%d\r\n",raw_offset); Serial.printf("timezone:%s\r\n",timezone); Serial.printf("unixtime:%d\r\n",unixtime); Serial.printf("utc_datetime:%s\r\n",utc_datetime); Serial.printf("utc_offset:%s\r\n",utc_offset); Serial.printf("week_number:%d\r\n",week_number); Serial.println(); // display current clock from unixtime Serial.printf("Current Time from unixtime:\r\n"); ConvertUnixTimeToLocalTime(unixtime, &year, &month, &day, &hour, &minu, &sec); Serial.printf("%4d/%02d/%02d(%s): %02d:%02d:%02d\r\n", year, month, day, weekday[day_of_week], hour, minu, sec); Serial.println(); // stop Serial.println("Done!"); delay(1000); //while(1){ //} } //<---------------------------------------------------------- // Definition of ConvertUnixTimeToLocalTime function // derived/forked from http://mrkk.ciao.jp/memorandom/unixtime/unixtime.html #define ARRAYSIZE(_arr) (sizeof(_arr) / sizeof(_arr[0])) #define TIME_OFFSET 9*60*60 #define SECONDS_IN_A_DAY (24*60*60) #define EPOCH_DAY (1969*365L + 1969/4 - 1969/100 + 1969/400 + 306) // days from 0000/03/01 to 1970/01/01 #define UNIX_EPOCH_DAY EPOCH_DAY #define YEAR_ONE 365 #define YEAR_FOUR (YEAR_ONE * 4 + 1) // it is YEAR_ONE*4+1 so the maximum reminder of day / YEAR_FOUR is YEAR_ONE * 4 and it occurs only on 2/29 #define YEAR_100 (YEAR_FOUR * 25 - 1) #define YEAR_400 (YEAR_100*4 + 1) // it is YEAR_100*4+1 so the maximum reminder of day / YEAR_400 is YEAR_100 * 4 and it occurs only on 2/29 void ConvertUnixTimeToLocalTime(uint64_t unixtime, uint32_t *pyear, uint8_t *pmonth, uint8_t *pday, uint8_t *phour, uint8_t *pminute, uint8_t *psecond) { uint32_t unixday; uint16_t year = 0; uint8_t leap = 0; uint32_t n; uint8_t month, day, weekday; uint8_t hour, minute, second; static const uint16_t monthday[] = { 0,31,61,92,122,153,184,214,245,275,306,337 }; unixtime += TIME_OFFSET; second = unixtime % 60; minute = (unixtime / 60) % 60; hour = (unixtime / 3600) % 24; unixday = (uint32_t)(unixtime / SECONDS_IN_A_DAY); weekday = (uint8_t)((unixday + 3) % 7); // because the unix epoch day is thursday unixday += UNIX_EPOCH_DAY; // days from 0000/03/01 to 1970/01/01 year += 400 * (unixday / YEAR_400); unixday %= YEAR_400; n = unixday / YEAR_100; year += n * 100; unixday %= YEAR_100; if (n == 4){ leap = 1; } else { year += 4 * (unixday / YEAR_FOUR); unixday %= YEAR_FOUR; n = unixday / YEAR_ONE; year += n; unixday %= YEAR_ONE; if (n == 4) { leap = 1; } } if (leap != 0) { month = 2; day = 29; } else { month = (unixday * 5 + 2) / 153; day = unixday - monthday[month] + 1; // month += 3; if (month > 12) { ++year; month -= 12; } } *psecond = second; *pminute = minute; *phour = hour; *pyear = year; *pmonth = month; *pday = day; } //>----------------------------------------------------------

以下の#defineでボードを切り換えているがボードの種類を設定すると、 システムで設定されている定義が有効になるので特にソースを変更する必要はない。

#define WIO_TERMINAL #define ESP8266 #define ESP32

以下は、自分の環境に応じて変更する:

const char* ssid = "your_ssid"; const char* passwd = "your_passwd";

書き込み後に「picocom /dev/ttyACM0 -b115200」または「picocom /dev/ttyUSB0 -b115200」で通信ソフトを起動すると以下のような出力が表示される:

$ picocom /dev/ttyACM0 -b115200 Terminal ready --- Header --- HTTP/1.1 200 OK Connection: close Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: * Access-Control-Expose-Headers: Cache-Control: max-age=0, private, must-revalidate Content-Length: 345 Content-Type: application/json; charset=utf-8 Cross-Origin-Window-Policy: deny Date: Mon, 03 Aug 2020 06:39:09 GMT Server: Cowboy X-Content-Type-Options: nosniff X-Download-Options: noopen X-Frame-Options: SAMEORIGIN X-Permitted-Cross-Domain-Policies: none X-Request-Id: c368a196-c927-43e2-b741-c3ab7ce11336 X-Runtime: 2ms X-Xss-Protection: 1; mode=block Via: 1.1 vegur accessed BODY: {"abbreviation":"JST","client_ip":"218.231.243.62","datetime":"2020-08-03T15:39:10.171382+09:00","day_of_week":1,"day_of_year":216,"dst":false,"dst_from":null,"dst_offset":0,"dst_until":null,"raw_offset":32400,"timezone":"Asia/Tokyo","unixtime":1596436750,"utc_datetime":"2020-08-03T06:39:10.171382+00:00","utc_offset":"+09:00","week_number":32} Deserialized: abbreviation:JST client_ip:218.231.243.62 datetime:2020-08-03T15:39:10.171382+09:00 day_of_week:1 day_of_year:216 raw_offset:32400 timezone:Asia/Tokyo unixtime:1596436750 utc_datetime:2020-08-03T06:39:10.171382+00:00 utc_offset:+09:00 week_number:32 Current Time from unixtime: 2020/08/03(Mon): 15:39:10 Done!

出力には、WorldTimeAPIで取得した時刻が出力される。

参考情報

World Time API
Simple JSON/plain-text API to obtain the current time in, and related data about, a timzone.

Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(HTTP-ACCESS編)
ESP8266 Arduino CoreでGETアクセス。HTTP/HTTPS&プロクシを使ったHTTP通信
ESP8266+ArduinoでHTTPS接続

PlatformIO Core (CLI)

以上

続きを読む "Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチでWorld Time APIを使う(WorldTimeAPI編)"

| | コメント (0)

Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(HTTP-ACCESS編)

2020/8/2:
初版

board3 HTTP ACCESS

board3 HTTP ACCESS

概要

Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(HTTP-ACCESS編)
(ホストPCとしてはubuntuを想定している)

デモ・スケッチ

src/HTTP-ACCESS.ino

// select board ////#define WIO_TERMINAL ////#define ESP8266 ////#define ESP32 //------------------ // // HTTP access for Wio-Terminal/ESP8266/ESP32 // #ifdef WIO_TERMINAL #include <AtWiFi.h> #endif #ifdef ESP8266 #include <ESP8266WiFi.h> #endif #ifdef ESP32 #include <WiFi.h> #endif #include <WiFiClientSecure.h> #define BODY_SIZE 1024 char bodyBuff[BODY_SIZE]; const char* ssid = "your_ssid"; const char* passwd = "your_passwd"; void setup() { // Initialize serial port Serial.begin(115200); while (!Serial) continue; Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, passwd); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } bool Http_Get_access(String host, String url, String argument){ WiFiClient client; client.setTimeout(500); const int httpPort = 80; const char* host2 = host.c_str(); if (!client.connect(host2, httpPort)) { Serial.println("connection failed"); return false; } client.print(String("GET ") + url + "?" + argument + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "User-Agent: ESP8266/1.0\r\n" + "Connection: close\r\n\r\n"); unsigned long timeout = micros(); while (client.available() == 0) { if ( micros() - timeout > 5000000) { Serial.println(">>> Client Timeout !"); client.stop(); return false; } } Serial.println("--- Header ---"); while (1) { String line = client.readStringUntil('\n'); Serial.println(line); if (line == "\r") { break; // end of header } } //Serial.println("--- Body ---"); // for debug int bc = 0; while (client.available()) { bodyBuff[bc] = client.read(); bc++; } bodyBuff[bc] = 0; //Serial.println(bodyBuff); // display body for debug return true; } void loop() { String host = "worldtimeapi.org"; String url = "/api/timezone/Asia/Tokyo"; String argument = ""; Http_Get_access( host, url, argument); Serial.println("accessed BODY:"); Serial.println(bodyBuff); // stop Serial.println("Done!"); while(1){ } }

スケッチのテスト用urlなどはWorld Time APIのものを使用している。 ここも必要に応じて変更できる。

以下の#defineでボードを切り換えているがボードの種類を設定すると、 システムで設定されている定義が有効になるので特にソースを変更する必要はない。

#define WIO_TERMINAL #define ESP8266 #define ESP32

以下については、自分の環境に合わせて変更すること:

const char* ssid = "your_ssid"; const char* passwd = "your_passwd";

書き込み後に「picocom /dev/ttyACM0 -b115200」または「picocom /dev/ttyUSB0 -b115200」で通信ソフトを起動すると以下のような出力が表示される:

$ picocom /dev/ttyACM0 -b115200 Terminal ready Connecting to xxxxxxxxxxxx ............... WiFi connected IP address: 192.168.0.4 --- Header --- HTTP/1.1 200 OK Connection: close Access-Control-Allow-Credentials: true Access-Control-Allow-Origin: * Access-Control-Expose-Headers: Cache-Control: max-age=0, private, must-revalidate Content-Length: 345 Content-Type: application/json; charset=utf-8 Cross-Origin-Window-Policy: deny Date: Sun, 02 Aug 2020 14:42:08 GMT Server: Cowboy X-Content-Type-Options: nosniff X-Download-Options: noopen X-Frame-Options: SAMEORIGIN X-Permitted-Cross-Domain-Policies: none X-Request-Id: 0813b454-28fa-44f7-a705-76c3b42eb739 X-Runtime: 1ms X-Xss-Protection: 1; mode=block Via: 1.1 vegur accessed BODY: {"abbreviation":"JST","client_ip":"218.231.243.62","datetime":"2020-08-02T23:42:09.116136+09:00","day_of_week":0,"day_of_year":215,"dst":false,"dst_from":null,"dst_offset":0,"dst_until":null,"raw_offset":32400,"timezone":"Asia/Tokyo","unixtime":1596379329,"utc_datetime":"2020-08-02T14:42:09.116136+00:00","utc_offset":"+09:00","week_number":31} Done!

Arduino-IDEのボードマネージャーのURL

以下のURLを設定することで3つのボード(Wio-Terminal/ESP8266/ESP32)が使用可能になる。

https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json http://arduino.esp8266.com/stable/package_esp8266com_index.json https://dl.espressif.com/dl/package_esp32_index.json

参考情報

World Time API
Simple JSON/plain-text API to obtain the current time in, and related data about, a timzone.

ESP8266 Arduino CoreでGETアクセス。HTTP/HTTPS&プロクシを使ったHTTP通信
ESP8266+ArduinoでHTTPS接続

PlatformIO Core (CLI)

以上

続きを読む "Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(HTTP-ACCESS編)"

| | コメント (0)

2020年7月25日 (土)

Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(REST-API2編)

2020/7/25:
初版

board3 REST API 2

board3 REST API 2

概要

Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(REST-API2編)
Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(REST-API編)」で、Wio-Terminalのスケッチが動作しなかったので、その代わりのスケッチを提供する。 (ホストPCとしてはubuntuを想定している)

外部ライブラリ(platformioの場合)

以下を実行してライブラリをインストールする:

# mDNS lib インストール #pio lib install "ArduinoMDNS" pio lib install 2848

デモ・スケッチ

src/REST-API2_test.ino

// select board ////#define WIO_TERMINAL ////#define ESP8266 ////#define ESP32 //------------------ // REST-API server2 for Wio-Terminal/ESP8266/ESP32 /* Rest-API server Forked from arduino-esp32 on 04 July, 2018 by Elochukwu Ifediora (fedy0) */ #ifdef WIO_TERMINAL #include <AtWiFi.h> #include <WiFiUdp.h> #include <ArduinoMDNS.h> #endif #ifdef ESP8266 #include <ESP8266WiFi.h> #include <ESP8266mDNS.h> #endif #ifdef ESP32 #include <WiFi.h> #include <ESPmDNS.h> #endif //#define LED 2 // Set the GPIO pin where you connected your test LED // Change to your setting const char* ssid = "your_ssid"; const char* password = "your_passwd"; #ifdef WIO_TERMINAL WiFiUDP udp; MDNS mdns(udp); #endif WiFiServer server(80); void setup() { //set LED of your board //pinMode(LED, OUTPUT); Serial.begin(115200); while(!Serial); // Wait for Serial to be ready delay(1000); Serial.println(); Serial.println("Configuring access point..."); // set your SoftAP if you need //WiFi.softAP(ssid, password); //IPAddress myIP = WiFi.softAPIP(); //or // set for station mode WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } IPAddress myIP = WiFi.localIP(); Serial.println(); Serial.print("AP IP address: "); Serial.println(myIP); server.begin(); Serial.println("Server started"); // Activate mDNS this is used to be able to connect to the server // with local DNS hostmane esp8266.local etc #ifdef WIO_TERMINAL mdns.begin(WiFi.localIP(), "wiot"); Serial.println("MDNS responder started(wiot)"); #endif #ifdef ESP8266 if (MDNS.begin("esp8266")) { Serial.println("MDNS responder started(esp8266)"); } #endif #ifdef ESP32 if (MDNS.begin("esp32")) { Serial.println("MDNS responder started(esp32)"); } #endif } void loop() { WiFiClient client = server.available(); // listen for incoming clients if (client) { // if you get a client, Serial.println("New Client."); // print a message out the serial port String currentLine = ""; // make a String to hold incoming data from the client while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then /////Serial.write(c); // print it out the serial monitor if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: ////client.println("HTTP/1.1 200 OK"); ////client.println("Content-type:text/html"); ////client.println(); // the content of the HTTP response follows the header: ////client.print("Click <a href=\"/H\">here</a> to turn ON the LED.<br>"); ////client.print("Click <a href=\"/L\">here</a> to turn OFF the LED.<br>"); // The HTTP response ends with another blank line: client.println(); // break out of the while loop: break; } else { // if you got a newline, then clear currentLine: currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } // Check to see if the client request was "GET /H" or "GET /L": //if (currentLine.endsWith("GET /H")) { if (currentLine.endsWith("/H")) { //digitalWrite(LED, HIGH); // GET /H turns the LED on Serial.println("****ON****"); currentLine =""; client.println("{ \"LED\" : \"on\" }"); } //if (currentLine.endsWith("GET /L")) { if (currentLine.endsWith("/L")) { //digitalWrite(LED, LOW); // GET /L turns the LED off Serial.println("****OFF****"); currentLine =""; client.println("{ \"LED\" : \"off\" }"); } if (currentLine.endsWith("/api/v1/led=1")) { //digitalWrite(LED, HIGH); Serial.println("led: ON"); currentLine =""; client.println("{ \"LED\" : \"on\" }"); } if (currentLine.endsWith("/api/v1/led=0")) { //digitalWrite(LED, LOW); Serial.println("led: OFF"); currentLine =""; client.println("{ \"LED\" : \"off\" }"); } } } // close the connection: client.stop(); Serial.println("Client Disconnected."); } #ifdef WIO_TERMINAL mdns.run(); // This actually runs the mDNS module. YOU HAVE TO CALL THIS PERIODICALLY #endif #ifdef ESP8266 MDNS.update(); #endif #ifdef ESP32 //MDNS.update(); // no need to update on ESP32 #endif }

以下の#defineでボードを切り換えているがボードの種類を設定すると、 システムで設定されている定義が有効になるので特にソースを変更する必要はない。

#define WIO_TERMINAL #define ESP8266 #define ESP32

以下については、自分の環境に合わせて変更すること:

const char ssid[] = "yours_ssid"; const char pass[] = "yours_passwd";

書き込み後に「picocom /dev/ttyACM0 -b115200」または「picocom /dev/ttyUSB0 -b115200」で通信ソフトを起動すると以下のような出力が表示される:

$ picocom /dev/ttyACM0 -b115200 # ESP8266の場合 Configuring access point... ............ AP IP address: 192.168.0.5 Server started MDNS responder started(esp8266) # ESP32の場合 Configuring access point... .. AP IP address: 192.168.0.15 Server started MDNS responder started(esp32) # Wio-Terminalの場合 Configuring access point... .............. AP IP address: 192.168.0.29 Server started MDNS responder started(wiot)

curlによるコマンド実行例:

# ESP8266の場合 $ curl 'http://esp8266.local:80/api/v1/led=1' {"LED": "on"} $ curl 'http://esp8266.local:80/api/v1/led=0' {"LED": "off"} # ESP32の場合 $ curl 'http://esp32.local:80/api/v1/led=0' {"LED": "off"} $ curl 'http://esp32.local:80/api/v1/led=1' {"LED": "on"} #Wio-Terminalの場合 $ curl 'http://192.168.0.29:80/api/v1/led=0' { "LED" : "off" } $ curl 'http://192.168.0.29:80/api/v1/led=1' { "LED" : "on" } $ curl 'http://wiot.local:80/api/v1/led=0' curl: (6) Could not resolve host: wiot.local

不具合

mDNSが動作していないので、wiot.localではなく、IPアドレスでアクセスすることになる。(原因不明)

Arduino-IDEのボードマネージャーのURL

以下のURLを設定することで3つのボード(Wio-Terminal/ESP8266/ESP32)が使用可能になる。

https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json http://arduino.esp8266.com/stable/package_esp8266com_index.json https://dl.espressif.com/dl/package_esp32_index.json

参考情報

PlatformIO Core (CLI)

以上

続きを読む "Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(REST-API2編)"

| | コメント (0)

2020年7月24日 (金)

Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(REST-API編)

2020/7/24:
初版

board3 REST API

board3 REST API

概要

Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(REST-API編)
(ホストPCとしてはubuntuを想定している)

外部ライブラリ(platformioの場合)

以下を実行してライブラリをインストールする:

# mDNS lib インストール #pio lib install "ArduinoMDNS" pio lib install 2848

デモ・スケッチ

src/REST-API_test.ino

// select board ////#define WIO_TERMINAL ////#define ESP8266 ////#define ESP32 //------------------ // REST-API server for Wio-Terminal/ESP8266/ESP32 /* * Forked from the following code: * * Simple hello world Json REST response * by Mischianti Renzo <https://www.mischianti.org> * * https://www.mischianti.org/ * */ #ifdef WIO_TERMINAL #include <AtWiFi.h> #include <WebServer.h> #include <WiFiUdp.h> #include <ArduinoMDNS.h> #endif #ifdef ESP8266 #include <ESP8266WiFi.h> #include <ESP8266WebServer.h> #include <ESP8266mDNS.h> #endif #ifdef ESP32 #include <WiFi.h> #include <WebServer.h> #include <ESPmDNS.h> #endif const char* ssid = "<your_ssid>"; const char* password = "<your_passwd>"; #ifdef WIO_TERMINAL WiFiUDP udp; MDNS mdns(udp); WebServer server(80); #endif #ifdef ESP8266 ESP8266WebServer server(80); #endif #ifdef ESP32 WebServer server(80); #endif // Serving Hello world void getHelloWord() { server.send(200, "text/json", "{\"name\": \"Hello world\"}\r\n"); } void ledOff() { // do something for LED off server.send(200, "text/json", "{\"led\": \"OFF\"}\r\n"); } void ledOn() { // do something for LED on server.send(200, "text/json", "{\"led\": \"ON\"}\r\n"); } // Define routing void restServerRouting() { server.on("/", HTTP_GET, []() { server.send(200, F("text/html"), F("Welcome to the REST Web Server")); }); server.on(F("/helloWorld"), HTTP_GET, getHelloWord); server.on(F("/api/v1/led=0"), HTTP_GET, ledOff); server.on(F("/api/v1/led=1"), HTTP_GET, ledOn); } // Manage not found URL void handleNotFound() { String message = "File Not Found\n\n"; message += "URI: "; message += server.uri(); message += "\nMethod: "; message += (server.method() == HTTP_GET) ? "GET" : "POST"; message += "\nArguments: "; message += server.args(); message += "\n"; for (uint8_t i = 0; i < server.args(); i++) { message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; } server.send(404, "text/plain", message); } void setup(void) { Serial.begin(115200); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); Serial.println(""); // Wait for connection while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected to "); Serial.println(ssid); Serial.print("IP address: "); Serial.println(WiFi.localIP()); // Activate mDNS this is used to be able to connect to the server // with local DNS hostmane esp8266.local #ifdef WIO_TERMINAL mdns.begin(WiFi.localIP(), "wiot"); Serial.println("MDNS responder started(wiot)"); #endif #ifdef ESP8266 if (MDNS.begin("esp8266")) { Serial.println("MDNS responder started(esp8266)"); } #endif #ifdef ESP32 if (MDNS.begin("esp32")) { Serial.println("MDNS responder started(esp32)"); } #endif // Set server routing restServerRouting(); // Set not found response server.onNotFound(handleNotFound); // Start server server.begin(); Serial.println("HTTP server started"); } void loop(void) { #ifdef WIO_TERMINAL mdns.run(); // This actually runs the mDNS module. YOU HAVE TO CALL THIS PERIODICALLY #endif #ifdef ESP8266 MDNS.update(); #endif #ifdef ESP32 //MDNS.update(); // no need to update on ESP32 #endif server.handleClient(); }

以下の#defineでボードを切り換えているがボードの種類を設定すると、 システムで設定されている定義が有効になるので特にソースを変更する必要はない。

#define WIO_TERMINAL #define ESP8266 #define ESP32

以下については、自分の環境に合わせて変更すること:

const char ssid[] = "yours_ssid"; const char pass[] = "yours_passwd";

書き込み後に「picocom /dev/ttyACM0 -b115200」または「picocom /dev/ttyUSB0 -b115200」で通信ソフトを起動すると以下のような出力が表示される:

$ picocom /dev/ttyACM0 -b115200 # ESP8266の場合 ... Connected to xxxxxxxx IP address: 192.168.0.5 MDNS responder started(esp8266) HTTP server started # ESP32の場合 .. Connected to xxxxxxxx IP address: 192.168.0.15 MDNS responder started(esp32) HTTP server started # Wio-Terminalの場合 Terminal ready No ACK, R00 Device reset detected! ESP-AT Lib initialized! .................. Connected to xxxxxxxx IP address: 192.168.0.29 MDNS responder started(wiot) HTTP server started

curlによるコマンド実行例:

# ESP8266の場合 $ curl 'http://esp8266.local:80/helloWorld' {"name": "Hello world"} $ curl 'http://esp8266.local:80/api/v1/led=1' {"led": "ON"} $ curl 'http://esp8266.local:80/api/v1/led=0' {"led": "OFF"} # ESP32の場合 $ curl 'http://esp32.local:80/helloWorld' {"name": "Hello world"} $ curl 'http://esp32.local:80/api/v1/led=0' {"led": "OFF"} $ curl 'http://esp32.local:80/api/v1/led=1' {"led": "ON"}

不具合

Wio-Terminalの場合、REST-APIは、起動後の1回しか動作しなかった。(原因不明) mDNSも動作していないので、wiot.localではなく、IPアドレスでアクセスすることになる。

Arduino-IDEのボードマネージャーのURL

以下のURLを設定することで3つのボード(Wio-Terminal/ESP8266/ESP32)が使用可能になる。

https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json http://arduino.esp8266.com/stable/package_esp8266com_index.json https://dl.espressif.com/dl/package_esp32_index.json

参考情報

PlatformIO Core (CLI)

以上

続きを読む "Wio-Terminal/ESP8622/ESP32ボードを共通のスケッチで動かす(REST-API編)"

| | コメント (0)

2020年7月12日 (日)

Wio-TerminalでWiFiで使う(その3: REST-API)

2020/7/11

PlatformIO cli Wio Terminal WiFi3

PlatformIO cli Wio Terminal WiFi3

概要

Wio-TerminalでWiFiで使う(その3: REST-API)
本記事は、[Wio-TerminalでWiFiで使う(その2: STARTWARS,WEB_ACCESS)]の続きになる。
(ホストPCとしてはubuntuを想定している)

wifi_rest_api

REST-APIのwebサーバーのスケッチ:

src/wifi_rest_api.ino

/* Rest-API server Forked from arduino-esp32 on 04 July, 2018 by Elochukwu Ifediora (fedy0) */ #include <AtWiFi.h> #include <WiFiClient.h> #include <WiFiAP.h> #define LED 2 // Set the GPIO pin where you connected your test LED // Set these to your desired credentials. const char* ssid = "MyAP"; const char* password = "mypasswd"; WiFiServer server(80); void setup() { pinMode(LED, OUTPUT); Serial.begin(115200); while(!Serial); // Wait for Serial to be ready delay(1000); Serial.println(); Serial.println("Configuring access point..."); // You can remove the password parameter if you want the AP to be open. WiFi.softAP(ssid, password); IPAddress myIP = WiFi.softAPIP(); /* * Note 1 * Record this IP, will used by Client (such as Web Browser) */ Serial.print("AP IP address: "); Serial.println(myIP); server.begin(); Serial.println("Server started"); } void loop() { WiFiClient client = server.available(); // listen for incoming clients if (client) { // if you get a client, Serial.println("New Client."); // print a message out the serial port String currentLine = ""; // make a String to hold incoming data from the client while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then /////Serial.write(c); // print it out the serial monitor if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: ////client.println("HTTP/1.1 200 OK"); ////client.println("Content-type:text/html"); ////client.println(); // the content of the HTTP response follows the header: ////client.print("Click <a href=\"/H\">here</a> to turn ON the LED.<br>"); ////client.print("Click <a href=\"/L\">here</a> to turn OFF the LED.<br>"); // The HTTP response ends with another blank line: client.println(); // break out of the while loop: break; } else { // if you got a newline, then clear currentLine: currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } // Check to see if the client request was "GET /H" or "GET /L": //if (currentLine.endsWith("GET /H")) { if (currentLine.endsWith("/H")) { digitalWrite(LED, HIGH); // GET /H turns the LED on Serial.println("****ON****"); currentLine =""; client.println("{ \"LED\" : \"on\" }"); } //if (currentLine.endsWith("GET /L")) { if (currentLine.endsWith("/L")) { digitalWrite(LED, LOW); // GET /L turns the LED off Serial.println("****OFF****"); currentLine =""; client.println("{ \"LED\" : \"off\" }"); } if (currentLine.endsWith("/api/v1/led=1")) { digitalWrite(LED, HIGH); Serial.println("led: ON"); currentLine =""; client.println("{ \"LED\" : \"on\" }"); } if (currentLine.endsWith("/api/v1/led=0")) { digitalWrite(LED, LOW); Serial.println("led: OFF"); currentLine =""; client.println("{ \"LED\" : \"off\" }"); } } } // close the connection: client.stop(); Serial.println("Client Disconnected."); } }

スケッチ実行後、SSIDとして「MyAP」が見えるので パスワードとして"mypasswd"を入力してWiFi接続する。 その後、以下のようなコマンドでwio-terminalを制御できる: (curlによる)コマンド実行例:

$ curl 'http://192.168.43.1:80/api/v1/led=0' { "LED" : "off" } $ curl 'http://192.168.43.1:80/api/v1/led=1' { "LED" : "on" } $ curl 'http://192.168.43.1:80/api/v1/led=0' { "LED" : "off" } $ curl 'http://192.168.43.1:80/api/v1/led=1' { "LED" : "on" } $ curl 'http://192.168.43.1:80/L' { "LED" : "off" } $ curl 'http://192.168.43.1:80/H' { "LED" : "on" }

出力例:

picocom /dev/ttyACM0 -b115200 Configuring access point... AP IP address: 192.168.43.1 Server started New Client. led: OFF Client Disconnected. New Client. led: ON Client Disconnected. New Client. led: OFF Client Disconnected. New Client. led: ON Client Disconnected.

参考情報

Platform/Wio Terminal Network/Wi-Fi - example sketches

Wio Terminalをはじめよう(ピン配置、データシート、回路図など)

Platform/Wio Terminal/Network/Overview
download url:
https://files.seeedstudio.com/wiki/Wio-Terminal/res/ameba-image-Tool-v2.4.1.zip
https://files.seeedstudio.com/wiki/Wio-Terminal/res/20200601-rtl8720d-images-v2.2.0.0.zip

PlatformIO Core (CLI)

以上

続きを読む "Wio-TerminalでWiFiで使う(その3: REST-API)"

| | コメント (0)

2020年6月21日 (日)

Wio_Lite_RISC-VボードでWiFiを動かす(その2:STARWARS,REST-API)

2020/6/22+:
初版

PlatformIO Wio Lite RISC-V WiFi2

PlatformIO Wio Lite RISC-V WiFi2

概要

Wio_Lite_RISC-VボードでWiFiを動かす(その2:STARWARS,REST-API)。 これは「Wio_Lite_RISC-VボードでWiFiを動かす」の続きになる。
開発ツール(PlatformIOなど)のインストールについては「開発ツールPlatformIOをcliで使う(Wio_Lite_RISC-V版)」を参照のこと、ここでは、WiFiを動かすためのプログラムについて記載する。 (ホストPCとしてはubuntuを想定している)

接続

wio-lite-rvボードのPA9(TX). PA10(RX)、GNDをUSBシリアルに接続する。
ちなみに、XIAOをUSBシリアルとして使用する場合は以下のように接続する:

wio-lite-rv XIAO
PA10(RX) D6(TX)
PA9(TX) D7(RX)
GND GND

starwars_test

telnetでASCIIアートの「StarWars」アニメを表示するプログラム:
src/starwars_test.cpp

#include <Arduino.h> #include <stdio.h> #include <stdarg.h> #define MY_SSID "your_ssid" #define MY_PASSWD "your_passwd" char ipAddress [20]; static void wio_serial_init(void) { // enable GPIO clock for USART0 rcu_periph_clock_enable(RCU_GPIOA); // enable USART clock rcu_periph_clock_enable(RCU_USART0); /* connect port to USARTx_Tx(PA9) */ gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); /* connect port to USARTx_Rx(PA10) */ gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10); // enable GPIO clock for USART1 rcu_periph_clock_enable(RCU_GPIOA); // enable USART clock rcu_periph_clock_enable(RCU_USART1); /* connect port to USARTx_Tx(PA2) */ gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2); /* connect port to USARTx_Rx(PA3) */ gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_3); // USART0 configure usart_deinit(USART0); usart_baudrate_set(USART0, 115200U); usart_word_length_set(USART0, USART_WL_8BIT); usart_stop_bit_set(USART0, USART_STB_1BIT); usart_parity_config(USART0, USART_PM_NONE); usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE); usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE); usart_receive_config(USART0, USART_RECEIVE_ENABLE); usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); usart_enable(USART0); // USART1 configure usart_deinit(USART1); usart_baudrate_set(USART1, 115200U); usart_word_length_set(USART1, USART_WL_8BIT); usart_stop_bit_set(USART1, USART_STB_1BIT); usart_parity_config(USART1, USART_PM_NONE); usart_hardware_flow_rts_config(USART1, USART_RTS_DISABLE); usart_hardware_flow_cts_config(USART1, USART_CTS_DISABLE); usart_receive_config(USART1, USART_RECEIVE_ENABLE); usart_transmit_config(USART1, USART_TRANSMIT_ENABLE); usart_enable(USART1); } int _get0_char(void) { while ( usart_flag_get(USART0, USART_FLAG_RBNE)== RESET){ } return (uint8_t)usart_data_receive(USART0); } int _get1_char(void) { while ( usart_flag_get(USART1, USART_FLAG_RBNE)== RESET){ } return (uint8_t)usart_data_receive(USART1); } int _put0_char(int ch) { usart_data_transmit(USART0, (uint8_t) ch ); while ( usart_flag_get(USART0, USART_FLAG_TBE)== RESET){ } return ch; } int _put1_char(int ch) { usart_data_transmit(USART1, (uint8_t) ch ); while ( usart_flag_get(USART1, USART_FLAG_TBE)== RESET){ } return ch; } void usart0_printf(const char *fmt, ...) { char buf[100]; va_list args; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); char *p = buf; while( *p != '\0' ) { _put0_char(*p); p++; } } void usart0_print(const char *s) { while( *s != '\0' ) { _put0_char(*s); s++; } } void usart0_println(const char *s) { while( *s != '\0' ) { _put0_char(*s); s++; } _put0_char('\r'); _put0_char('\n'); } void usart1_printf(const char *fmt, ...) { char buf[100]; va_list args; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); char *p = buf; while( *p != '\0' ) { _put1_char(*p); p++; } } void usart1_print(const char *s) { while( *s != '\0' ) { _put1_char(*s); s++; } } void usart1_println(const char *s) { while( *s != '\0' ) { _put1_char(*s); s++; } _put1_char('\r'); _put1_char('\n'); } int usart1_available(void) { return ( usart_flag_get(USART1, USART_FLAG_RBNE)== SET); } //------------------------------------------------------- //char res[500]; char res[3000]; // need big buffer for StarWars void get_res(void) { int cpos = 0; for(int cc=0; cc<24000000; cc++) { while ( usart_flag_get(USART1, USART_FLAG_RBNE)== SET) { //res[cpos] = (char) _get1_char(); cpos++; res[cpos] = (char) usart_data_receive(USART1); cpos++; }; }; res[cpos] = 0; } void get_res2(void) { int cpos = 0; for(int cc=0; cc<500000; cc++) { while ( usart_flag_get(USART1, USART_FLAG_RBNE)== SET) { //res[cpos] = (char) _get1_char(); cpos++; res[cpos] = (char) usart_data_receive(USART1); cpos++; }; }; res[cpos] = 0; } void setup() { wio_serial_init(); //Serial.begin(115200); //serial port of GD32 //Serial1.begin(115200); //serial port of ESP8266 pinMode(LED_BUILTIN, OUTPUT); delay(3000); usart0_print("\r\n\r\n\r\n\r\n\r\n"); // get firmware version usart0_println("SEND:"); usart0_print("AT+GMR\r\n"); usart1_print("AT+GMR\r\n"); get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); usart0_println("SEND:"); usart0_print("AT+CWQAP\r\n"); usart1_print("AT+CWQAP\r\n"); get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); usart0_println("SEND:"); usart0_print("AT+CWMODE=1\r\n"); usart1_print("AT+CWMODE=1\r\n"); get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); //Serial1.println("AT+CWJAP=\"Your WiFi SSID\",\"Password\""); // add your own wifi usart0_println("SEND:"); usart0_print("AT+CWJAP=\""); usart0_print(MY_SSID); usart0_print("\",\""); usart0_print(MY_PASSWD); usart0_print("\"\r\n"); usart1_print("AT+CWJAP=\""); usart1_print(MY_SSID); usart1_print("\",\""); usart1_print(MY_PASSWD); usart1_print("\"\r\n"); get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); usart0_println("SEND:"); usart0_print("AT+CIFSR\r\n"); usart1_print("AT+CIFSR\r\n"); get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); //-- get IP Address -- int len = strlen( res ); bool done=false; bool error = false; int pos = 0; while (!done) { if ( res[pos] == '\"') { done = true;} pos++; if (pos > len) { done = true; error = true;} } if (!error) { int buffpos = 0; done = false; while (!done) { if ( res[pos] == '\"' ) { done = true; } else { ipAddress[buffpos] = res[pos]; buffpos++; pos++;} } ipAddress[buffpos] = 0; } else { strcpy(ipAddress,"ERROR"); } //usart0_printf("ipAddress:%s\r\n",ipAddress); //----------------- usart0_println("SEND:"); usart0_print("AT+CIPMUX=1\r\n"); usart1_print("AT+CIPMUX=1\r\n"); get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); usart0_println("SEND:"); usart0_print("AT+CIPSERVER=1,80\r\n"); usart1_print("AT+CIPSERVER=1,80\r\n"); get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); usart0_printf("\r\nipAddress: %s\r\n\r\n",ipAddress); // telnet access usart0_print("AT+CIPSTART=1,\"TCP\",\"towel.blinkenlights.nl\",23\r\n"); usart1_print("AT+CIPSTART=1,\"TCP\",\"towel.blinkenlights.nl\",23\r\n"); /*** get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); ***/ /**** usart0_print("AT+CIPSTART=\"TCP\",\"imaoca.webcrow.jp\",80\r\n"); usart1_print("AT+CIPSTART=\"TCP\",\"imaoca.webcrow.jp\",80\r\n"); ****/ } //------------ void dispatch(void) { // setup string pointer table char *h[20]; for(int i=0; i<20; i++) h[i]=NULL; h[0] = &res[0]; int pi = 1; int cp; int len = (int)strlen(res); // keep length of res[] for (int i=0; i<len; i++) { if ((res[i]=='+') && (res[i+1]=='I') && (res[i+2]=='P') && (res[i+3]=='D') ) { // check +IPD for (cp = i+4; cp<len; cp++) { if (res[cp]==':') break; } res[i] = 0; // make string terminator h[pi] = &res[cp+1]; pi++; } }; // display removed IPD header for(int i=0; i<20; i++) { if (h[i] != NULL) usart0_print(h[i]); } } //------------ void loop() { digitalWrite(LED_BUILTIN, HIGH); // debug: for indicate in-loop /** // test loop while(true) { if ( usart_flag_get(USART1, USART_FLAG_RBNE)== SET) _put0_char(_get1_char()); if ( usart_flag_get(USART0, USART_FLAG_RBNE)== SET) _put1_char(_get0_char()); }; **/ while(true) { get_res2(); if ((int)strlen(res) != 0) { //usart0_print("\r\nRES:\r\n"); //usart0_println(res); dispatch(); } else { //usart0_print("."); // indicating input wait } } }

以下については、自分の環境に合わせて変更すること:
#define MY_SSID "your_ssid"
#define MY_PASSWD "your_passwd"

書き込み後に「picocom /dev/ttyACM0 -b115200」で通信ソフトを起動すると以下のような出力が表示される:

$ picocom /dev/ttyACM0 -b115200 SEND: AT+GMR RES: AT+GMR AT version:2.1.0.0-dev(d25f6d2 - Oct 15 2019 12:03:04) SDK version:v3.2-192-g81655f39 compile time(525fbfe):Oct 17 2019 05:39:13 Bin version:2.0.0(WROOM-02) ... <省略> ... ----------- ipAddress: 192.168.0.14 # StarWarsのASCIIアートのアニメが表示される

実行するとStarWarsのASCIIアートのアニメが表示される。

restapi_test

RESI-APIでボードを制御するサーバープログラム。
src/restapi_test.cpp

#include <Arduino.h> #include <stdio.h> #include <string.h> #include <stdarg.h> #define MY_SSID "your_ssid" #define MY_PASSWD "your_passwd" char ipAddress [20]; static void wio_serial_init(void) { // enable GPIO clock for USART0 rcu_periph_clock_enable(RCU_GPIOA); // enable USART clock rcu_periph_clock_enable(RCU_USART0); /* connect port to USARTx_Tx(PA9) */ gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); /* connect port to USARTx_Rx(PA10) */ gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10); // enable GPIO clock for USART1 rcu_periph_clock_enable(RCU_GPIOA); // enable USART clock rcu_periph_clock_enable(RCU_USART1); /* connect port to USARTx_Tx(PA2) */ gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2); /* connect port to USARTx_Rx(PA3) */ gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_3); // USART0 configure usart_deinit(USART0); usart_baudrate_set(USART0, 115200U); usart_word_length_set(USART0, USART_WL_8BIT); usart_stop_bit_set(USART0, USART_STB_1BIT); usart_parity_config(USART0, USART_PM_NONE); usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE); usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE); usart_receive_config(USART0, USART_RECEIVE_ENABLE); usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); usart_enable(USART0); // USART1 configure usart_deinit(USART1); usart_baudrate_set(USART1, 115200U); usart_word_length_set(USART1, USART_WL_8BIT); usart_stop_bit_set(USART1, USART_STB_1BIT); usart_parity_config(USART1, USART_PM_NONE); usart_hardware_flow_rts_config(USART1, USART_RTS_DISABLE); usart_hardware_flow_cts_config(USART1, USART_CTS_DISABLE); usart_receive_config(USART1, USART_RECEIVE_ENABLE); usart_transmit_config(USART1, USART_TRANSMIT_ENABLE); usart_enable(USART1); } int _get0_char(void) { while ( usart_flag_get(USART0, USART_FLAG_RBNE)== RESET){ } return (uint8_t)usart_data_receive(USART0); } int _get1_char(void) { while ( usart_flag_get(USART1, USART_FLAG_RBNE)== RESET){ } return (uint8_t)usart_data_receive(USART1); } int _put0_char(int ch) { usart_data_transmit(USART0, (uint8_t) ch ); while ( usart_flag_get(USART0, USART_FLAG_TBE)== RESET){ } return ch; } int _put1_char(int ch) { usart_data_transmit(USART1, (uint8_t) ch ); while ( usart_flag_get(USART1, USART_FLAG_TBE)== RESET){ } return ch; } void usart0_printf(const char *fmt, ...) { char buf[100]; va_list args; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); char *p = buf; while( *p != '\0' ) { _put0_char(*p); p++; } } void usart0_print(const char *s) { while( *s != '\0' ) { _put0_char(*s); s++; } } void usart0_println(const char *s) { while( *s != '\0' ) { _put0_char(*s); s++; } _put0_char('\r'); _put0_char('\n'); } void usart1_printf(const char *fmt, ...) { char buf[100]; va_list args; va_start(args, fmt); vsprintf(buf, fmt, args); va_end(args); char *p = buf; while( *p != '\0' ) { _put1_char(*p); p++; } } void usart1_print(const char *s) { while( *s != '\0' ) { _put1_char(*s); s++; } } void usart1_println(const char *s) { while( *s != '\0' ) { _put1_char(*s); s++; } _put1_char('\r'); _put1_char('\n'); } int usart1_available(void) { return ( usart_flag_get(USART1, USART_FLAG_RBNE)== SET); } //------------------------------------------------------- char html[50]; char command[20]; //char LED[30]; int lenHtml = 0; char temp[5]; char res[500]; void get_res(void) { int cpos = 0; for(int cc=0; cc<24000000; cc++) { while ( usart_flag_get(USART1, USART_FLAG_RBNE)== SET) { //res[cpos] = (char) _get1_char(); cpos++; res[cpos] = (char) usart_data_receive(USART1); cpos++; }; }; res[cpos] = 0; } void get_resCmd(void) { int cpos = 0; for(int cc=0; cc<100000; cc++) { while ( usart_flag_get(USART1, USART_FLAG_RBNE)== SET) { //res[cpos] = (char) _get1_char(); cpos++; res[cpos] = (char) usart_data_receive(USART1); cpos++; }; }; res[cpos] = 0; } void get_resHtml(void) { int cpos = 0; for(int cc=0; cc<1000000; cc++) { while ( usart_flag_get(USART1, USART_FLAG_RBNE)== SET) { //res[cpos] = (char) _get1_char(); cpos++; res[cpos] = (char) usart_data_receive(USART1); cpos++; }; }; res[cpos] = 0; } void setup() { wio_serial_init(); //Serial.begin(115200); //serial port of GD32 //Serial1.begin(115200); //serial port of ESP8266 pinMode(LED_BUILTIN, OUTPUT); delay(3000); usart0_print("\r\n\r\n\r\n\r\n\r\n"); // get firmware version usart0_println("SEND:"); usart0_print("AT+GMR\r\n"); usart1_print("AT+GMR\r\n"); get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); usart0_println("SEND:"); usart0_print("AT+CWQAP\r\n"); usart1_print("AT+CWQAP\r\n"); get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); usart0_println("SEND:"); usart0_print("AT+CWMODE=1\r\n"); usart1_print("AT+CWMODE=1\r\n"); get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); //Serial1.println("AT+CWJAP=\"Your WiFi SSID\",\"Password\""); // add your own wifi usart0_println("SEND:"); usart0_print("AT+CWJAP=\""); usart0_print(MY_SSID); usart0_print("\",\""); usart0_print(MY_PASSWD); usart0_print("\"\r\n"); usart1_print("AT+CWJAP=\""); usart1_print(MY_SSID); usart1_print("\",\""); usart1_print(MY_PASSWD); usart1_print("\"\r\n"); get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); usart0_println("SEND:"); usart0_print("AT+CIFSR\r\n"); usart1_print("AT+CIFSR\r\n"); get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); //-- get IP Address -- int len = strlen( res ); bool done=false; bool error = false; int pos = 0; while (!done) { if ( res[pos] == '\"') { done = true;} pos++; if (pos > len) { done = true; error = true;} } if (!error) { int buffpos = 0; done = false; while (!done) { if ( res[pos] == '\"' ) { done = true; } else { ipAddress[buffpos] = res[pos]; buffpos++; pos++;} } ipAddress[buffpos] = 0; } else { strcpy(ipAddress,"ERROR"); } //usart0_printf("ipAddress:%s\r\n",ipAddress); //----------------- usart0_println("SEND:"); usart0_print("AT+CIPMUX=1\r\n"); usart1_print("AT+CIPMUX=1\r\n"); get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); usart0_println("SEND:"); usart0_print("AT+CIPSERVER=1,80\r\n"); usart1_print("AT+CIPSERVER=1,80\r\n"); get_res(); usart0_println("RES:"); usart0_println(res); usart0_println("-----------"); usart0_printf("\r\nipAddress: %s\r\n\r\n",ipAddress); } //------------ int count = 0; // test variable void dispatch(void) { bool foundIPD = false; for (int i=0; i<(int)strlen(res); i++) { if ( (res[i]=='I') && (res[i+1]=='P') && (res[i+2]=='D')) { foundIPD = true;} } bool foundGET = false; int pGET; if (foundIPD) { for (int i=0; i<(int)strlen(res); i++) { // check 'GET' if ((res[i]=='G') && (res[i+1]=='E') && (res[i+2]=='T')) { foundGET = true; pGET = i+3; break; } } } bool foundApi = false; char api[24]; for(int i=0; i<24; i++) api[i]=0; int dp = 0; if (foundGET) { for (int i=pGET; i<(int)strlen(res); i++) { // check '/api/v1/' if ((res[i]=='/') && (res[i+1]=='a') && (res[i+2]=='p') && (res[i+3]=='i') && (res[i+4]=='/') && (res[i+5]=='v') && (res[i+6]=='1') && (res[i+7]=='/') ) { foundApi = true; int sp = i+8; while (res[sp]!=' ') { api[dp]= res[sp]; dp++; sp++; } api[dp]=0; } // if check '/api/v1/' } } if (foundApi) { usart0_printf("API: %s\r\n", api); // if(strcmp(api,"led=0")==0){ usart0_print("LED:off\r\n"); digitalWrite(LED_BUILTIN, LOW); // sprintf(html,"{ \"LED\" : \"off\" }\r\n"); sprintf(command,"AT+CIPSEND=0,%d\r\n",(int)strlen(html)); usart0_print("DEBUG-CMD:\r\n"); usart0_print(command); usart0_print("\r\n-------------\r\n"); usart0_print("DEBUG-HTML:\r\n"); usart0_print(html); usart0_print("\r\n=============\r\n\r\n"); usart1_print(command); get_resCmd(); usart1_print(html); get_resHtml(); } if(strcmp(api,"led=1")==0){ usart0_print("LED:on\r\n"); digitalWrite(LED_BUILTIN, HIGH); // sprintf(html,"{ \"LED\" : \"on\" }\r\n"); sprintf(command,"AT+CIPSEND=0,%d\r\n",(int)strlen(html)); usart0_print("DEBUG-CMD:\r\n"); usart0_print(command); usart0_print("\r\n-------------\r\n"); usart0_print("DEBUG-HTML:\r\n"); usart0_print(html); usart0_print("\r\n=============\r\n\r\n"); usart1_print(command); get_resCmd(); usart1_print(html); get_resHtml(); } if(strcmp(api,"count")==0){ usart0_printf("count:%d\r\n",count); // sprintf(html,"{ \"count\" : %d}\r\n", count); sprintf(command,"AT+CIPSEND=0,%d\r\n",(int)strlen(html)); usart0_print("DEBUG-CMD:\r\n"); usart0_print(command); usart0_print("\r\n-------------\r\n"); usart0_print("DEBUG-HTML:\r\n"); usart0_print(html); usart0_print("\r\n=============\r\n\r\n"); usart1_print(command); get_resCmd(); usart1_print(html); get_resHtml(); } } // if (foundApi) // close connection (is needed for displaying JSON data on the web) strcpy(command,"AT+CIPCLOSE=0\r\n"); // usart0_print("DEBUG-CMD:\r\n"); usart0_print(command); usart0_print("\r\n=============\r\n\r\n"); // usart1_print(command); get_resCmd(); //----- count++; // update test variable return; } void loop() { /*** // test loop while(true) { if ( usart_flag_get(USART1, USART_FLAG_RBNE)== SET) _put0_char(_get1_char()); if ( usart_flag_get(USART0, USART_FLAG_RBNE)== SET) _put1_char(_get0_char()); }; ****/ while(true) { get_resHtml(); if ((int)strlen(res) != 0) { usart0_print("\r\nRES:\r\n"); usart0_println(res); dispatch(); } else { usart0_print("."); // indicating input wait } } }

以下については、自分の環境に合わせて変更すること:
#define MY_SSID "your_ssid"
#define MY_PASSWD "your_passwd"

「picocom /dev/ttyACM0 -b115200」を起動すると以下が表示される:

$ picocom /dev/ttyACM0 -b115200 SEND: AT+GMR RES: lAT+GMR AT version:2.1.0.0-dev(d25f6d2 - Oct 15 2019 12:03:04) SDK version:v3.2-192-g81655f39 compile time(525fbfe):Oct 17 2019 05:39:13 Bin version:2.0.0(WROOM-02) ... <省略> ... ----------- ipAddress: 192.168.0.14 ....................................................................... RES: 0,CONNECT +IPD,0,88:GET /api/v1/led=1 HTTP/1.1 Host: 192.168.0.14 User-Agent: curl/7.60.0 Accept: */* API: led=1 LED:on DEBUG-CMD: AT+CIPSEND=0,19 ------------- DEBUG-HTML: { "LED" : "on" } ============= DEBUG-CMD: AT+CIPCLOSE=0 ============= ... ...

起動してIPが確定した後、REST-APIをサポートしているので以下のようなコマンドでボードを制御できる:

$ curl 'http://192.168.0.14:80/api/v1/led=1' { "LED" : "on" } #ここの時点でオンボードのLEDが光る $ curl 'http://192.168.0.14:80/api/v1/led=0' { "LED" : "off" } #ここの時点でオンボードのLEDが消える $ curl 'http://192.168.0.14:80/api/v1/led=1' { "LED" : "on" } #ここの時点でオンボードのLEDが光る $ curl 'http://192.168.0.14:80/api/v1/count' { "count" : 18} #現在の変数countの内容が表示される $ curl 'http://192.168.0.14:80/api/v1/count' { "count" : 20} #現在の変数countの内容が表示される $ curl 'http://192.168.0.14:80/api/v1/count' { "count" : 22} #現在の変数countの内容が表示される $ curl 'http://192.168.0.14:80/api/v1/count' { "count" : 24} #現在の変数countの内容が表示される

上で使用していると同じurlをウェブブラウザーに入力してアクセスしても 同様に制御できる。 IPが「192.168.0.14」の場合なので、実際に使うときは割り当てられたIPでアクセスすること。

参考情報

Wio Lite RISC-V(GD32VF103)

Wio Lite RISC V GD32VF103 with ESP8266
Blink with a Wio Lite RISC-V with ESP8266

PlatformIO Core (CLI)

ESP8266をTCPサーバとTCPクライアントにするATコマンド実例 (1/4)
esp8266_at_command_examples_en.pdf

ESP8266をWifiモデムとして使う - ATコマンドによるMQTT通信
MQTT_via_ESP01
Arduino WiFi library for ESP8266 modules

espressif/ESP8266_AT - examples
Espressif Documentation

以上

続きを読む "Wio_Lite_RISC-VボードでWiFiを動かす(その2:STARWARS,REST-API)"

| | コメント (0)

2020年6月 7日 (日)

Adafruit-IOのMQTT(REST-APIも含む)を利用してみる

2020/6/7

Adafruit IO MQTT REST-API

Adafruit IO MQTT REST-API

概要

AdafruitのクラウドサービスであるAdafruit-IOのMQTT(REST-APIも含む)を利用してみる。 (ホストPCとしてはubuntuを想定している)

準備

adafruitのアカウントを用意する必要があるので 以下にアクセスしてアカウントを作る。(無償)

https://accounts.adafruit.com

アカウントを作成したら、Adafruit-IOにアクセスするための アクセスキー(Adafruit IO KEY)を取得する必要があるので 以下にアクセスする:

https://io.adafruit.com/USERNAME/dashboards
(USERNAMEは作ったアカウントのユーザー名になる)

ブラウザー画面の最上行の右端「Adafruit IO KEY」をクリックすると アクセスキーが表示される。

以下、このアクセスキー(IO_KEY)とアカウントのユーザー名(IO_USERNAME)を プログラムに設定して使用する。

以下にアクセスライブラリ(Arduino,Python,CircuitPython,MicroPython,Ruby)が載っているが

https://io.adafruit.com/api/docs/mqtt.html#client-libraries

このうちPython3を使用してみる。

ライブラリのインストール:

python3 -m venv aio_env source aio_env/bin/activate pip3 install adafruit-io

mqtt_time.py

MQTTを利用する形で時刻を提供しているので、それを利用するデモプログラム。

get https://raw.githubusercontent.com/adafruit/Adafruit_IO_Python/master/examples/mqtt/mqtt_time.py # 取得したソースのIO_USERNAME,IO_KEYの部分を取得したものに置き換える。

出力例:

$ python3 mqtt_time.py * Subscribing to time/seconds * Subscribing to time/millis * Subscribing to time/ISO-8601 Connected to Adafruit IO! Feed time received new value: 2020-06-05T03:19:29.402Z Feed time received new value: 1591327169402 Feed time received new value: 1591327169 Feed time received new value: 2020-06-05T03:19:30.403Z Feed time received new value: 1591327170403 Feed time received new value: 1591327170 Feed time received new value: 2020-06-05T03:19:31.404Z Feed time received new value: 1591327171404 Feed time received new value: 1591327171 Feed time received new value: 2020-06-05T03:19:32.405Z Feed time received new value: 1591327172405 Feed time received new value: 1591327172

mqtt_client_class.py

トピックDemoFeedにsubscribe/publishするプログラム。

wget https://raw.githubusercontent.com/adafruit/Adafruit_IO_Python/master/examples/mqtt/mqtt_client_class.py # 取得したソースのIO_USERNAME,IO_KEYの部分を取得したものに置き換える。

出力例:

$ python3 mqtt_client_class.py Publishing a new message every 10 seconds (press Ctrl-C to quit)... Connected to Adafruit IO! Connected to Adafruit IO! Listening for DemoFeed changes... Publishing 6 to DemoFeed. #送信 Feed DemoFeed received new value: 6 #受信 Publishing 60 to DemoFeed. #送信 Feed DemoFeed received new value: 60 #受信 Publishing 63 to DemoFeed. #送信 Feed DemoFeed received new value: 63 #受信

mqtt_subscribe.py

MQTTの受信プログラム。

wget https://raw.githubusercontent.com/adafruit/Adafruit_IO_Python/master/examples/mqtt/mqtt_subscribe.py # 取得したソースのIO_USERNAME,IO_KEYの部分を取得したものに置き換える。

出力例:

$ python3 mqtt_subscribe.py Connected to Adafruit IO! Connected to Adafruit IO! Listening for DemoFeed changes... Subscribed to DemoFeed with QoS 0 Feed DemoFeed received new value: 5 Feed DemoFeed received new value: 97 Feed DemoFeed received new value: 18 Feed DemoFeed received new value: 44 Feed DemoFeed received new value: 87 Feed DemoFeed received new value: 60 Feed DemoFeed received new value: 1

別の端末から送信プログラムを動かしている必要がある。 (mqtt_client_class.pyでも良い)

REST-APIによるアクセス(curl)

https://io.adafruit.com/api/docs/#get-feed のドキュメントより REST-APIとしては以下であることが分かる:

GET /api/v2/{username}/feeds/{feed_key}

curlを使用して実際に利用するには以下のようになる:

curl -X GET 'https://io.adafruit.com/api/v2/USERNAME/feeds/demofeed?X-AIO-Key=aio_xxxxx' #USERNAMEでフィードキーdemofeedにアクセスする具体例になる。(aio_xxxxxは、aioのアクセスキーになる) なお、''で囲まれた部分をURLとしてブラウザーに与えると同様の出力が表示される。

出力例:

{"username":"USERNAME","owner":{"id":44xxxx,"username":"USERNAME"},"id":138xxxx,"name":"DemoFeed","description":null,"license":null, "history":true,"enabled":true,"visibility":"private","unit_type":null,"unit_symbol":null, "last_value":"41","created_at":"2020-06-05T02:15:31Z","updated_at":"2020-06-06T15:16:53Z", "status_notify":false,"status_timeout":4320,"status":"online","key":"demofeed","writable":true, "group":{"id":36xxxx,"key":"default","name":"Default","user_id":44xxxx},"groups":[{"id":36xxxx,"key":"default","name":"Default","user_id":44xxxx}],"feed_webhook_receivers":[],"feed_status_changes":[]} 一部伏せ文字にしてある

上の情報から フィードキーは、DemoFeedで "updated_at":"2020-06-06T15:16:53Z"時点での 値が"last_value":"41"であることが分かる。

REST-APIによるアクセス(html+javascript)

fetch_aio.html

<!DOCTYPE html> <head> <meta charset="utf-8"> <title>Fetch Adafruit IO</title> </head> <body > <div id="text0">Fetch Adafruit IO</div> <div id="text1"></div> <script> let IO_USERNAME='username' let IO_KEY='aio_xxxxxx' let IO_URL='https://io.adafruit.com' let FEED_KEY='demofeed' let feed; fetch(IO_URL+'/api/v2/'+IO_USERNAME+'/feeds/'+FEED_KEY+'?X-AIO-Key='+IO_KEY).then(function (response) { return response.text(); }).then(function (text) { console.log('RESULT: ' + text); feed=JSON.parse(text); console.log(feed['name']+': '+feed['last_value']+' @'+feed['updated_at']); text1.innerHTML = feed['name']+': '+feed['last_value']+' @'+feed['updated_at']; }); </script> </body> </html>

以下の部分は、自分の環境にあわせて書き換える:

let IO_USERNAME='username' let IO_KEY='aio_xxxxxx'

アクセス時のweb画面(例)

Fetch Adafruit IO DemoFeed: 94 @2020-06-07T02:20:30Z

別端末で送信プログラム(mqtt_client_class.py)を動かしておく。 ブラウザー画面をリフレッシュするたびに、最新の(受信した)値が表示される。 ブラウザーのconsoleにもアクセスした情報が出力される。

参考情報

Client Libraries
Adafruit IO HTTP API

JavaScriptのFetch APIを利用してリクエストを送信する
javascript.info - Fetch
fetch の使い方

以上

続きを読む "Adafruit-IOのMQTT(REST-APIも含む)を利用してみる"

| | コメント (0)