目次
- 赤外線リモコンを自作する - その1データ解析編
- 赤外線リモコンを自作する - その2データ送信編
- 赤外線リモコンを自作する - その3温度/湿度センサー編
- 赤外線リモコンを自作する - その4サーバサイド編
- 赤外線リモコンを自作する - その5クライアント編
赤外線リモコンを自作する - その5クライアント編
今回は、Arduinoで取得した温湿度をサーバに送信し、レスポンスとして赤外線データを受信した場合の処理について説明します。
全体の流れ
全体の流れとしては前回の 赤外線リモコンを自作する - その4サーバサイド編 を参考にしてください。
Arduinoプログラム
#include <Wire.h>
#include <CRC8.h>
#include <Arduino.h>
#include <Arduino_JSON.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#define PIN_SEND 32
#define IR_SEND_PIN PIN_SEND
#include <IRremote.hpp>
const int KHZ = 38;
const int I2C_SDA = 14;
const int I2C_SCL = 13;
const byte AHT25_ADDR = 0x38;
const double ERROR_VALUE = 999.0;
CRC8 crc;
double temperature;
double humidity;
const char* rootCACertificate = \
"-----BEGIN CERTIFICATE-----\n" \
"MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF\n" \
"ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\n" \
"b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL\n" \
"MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\n" \
"b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj\n" \
"ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM\n" \
"9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw\n" \
"IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6\n" \
"VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L\n" \
"93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm\n" \
"jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\n" \
"AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA\n" \
"A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI\n" \
"U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs\n" \
"N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv\n" \
"o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU\n" \
"5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy\n" \
"rqXRfboQnoZsG4q5WTP468SQvvG5\n" \
"-----END CERTIFICATE-----\n";
WiFiMulti WiFiMulti;
void init_aht25(void) {
delay(100);
Wire.beginTransmission(AHT25_ADDR);
Wire.write(0x71);
Wire.endTransmission();
delay(10);
crc.setPolynome(0x31);
crc.setStartXOR(0xFF);
}
void update_aht25(void) {
byte buf[7];
uint32_t humidity_raw;
uint32_t temperature_raw;
byte state;
Wire.beginTransmission(AHT25_ADDR);
Wire.write(0xAC);
Wire.write(0x33);
Wire.write(0x00);
Wire.endTransmission();
do {
delay(80);
Wire.requestFrom(AHT25_ADDR, 7);
if (Wire.available() >= 7) {
for(int i=0; i<7; i++) {
buf[i] = Wire.read();
}
}
} while((buf[0] & 0x80) != 0);
crc.restart();
crc.add(buf, 6);
if (buf[6] == crc.getCRC()) {
state = buf[0];
humidity_raw = ((uint32_t)buf[1] << 12)|((uint32_t)buf[2] << 4)|(((uint32_t)buf[3] >> 4) & 0x0F);
temperature_raw = (((uint32_t)buf[3] & 0x0F) << 16)|((uint32_t)buf[4] << 8)|((uint32_t)buf[5]);
humidity = humidity_raw / 1048576.0 * 100;
temperature = temperature_raw / 1048576.0 * 200 - 50;
} else {
// error
humidity = ERROR_VALUE;
temperature = ERROR_VALUE;
}
}
void connectWifi() {
WiFi.mode(WIFI_STA);
WiFiMulti.addAP("YOUR_WIFI_SSID", "YOUR_WIFI_PASSWORD");
// wait for WiFi connection
Serial.print("Waiting for WiFi to connect...");
while ((WiFiMulti.run() != WL_CONNECTED)) {
Serial.print(".");
}
Serial.println(" connected");
}
String ipToStr(uint32_t ipAddress){
String result = "";
result += String((ipAddress & 0xFF), 10);
result += ".";
result += String((ipAddress & 0xFF00) >> 8, 10);
result += ".";
result += String((ipAddress & 0xFF0000) >> 16, 10);
result += ".";
result += String((ipAddress & 0xFF000000) >> 24, 10);
return result;
}
void sendSensorValues() {
if (temperature == ERROR_VALUE || humidity == ERROR_VALUE) return;
WiFiClientSecure client;
client.setCACert(rootCACertificate);
HTTPClient http;
http.setTimeout(60000);
http.begin(client, "https://XXXXX.execute-api.ap-northeast-1.amazonaws.com/v1/send");
JSONVar body;
body["temperature"] = (int)temperature;
body["humidity"] = (int)humidity;
body["macAddress"] = (String)WiFi.macAddress();
body["localIP"] = ipToStr(WiFi.localIP());
String str = JSON.stringify(body);
Serial.println(str);
int httpResponseCode = http.POST(str);
if (httpResponseCode <= 0) {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
Serial.println(http.errorToString(httpResponseCode).c_str());
http.end();
return;
}
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
String response = http.getString();
http.end();
Serial.println(response);
JSONVar json = JSON.parse(response);
int len = json["length"];
if (len == 0) return;
sendCommand((const char*) json["command"], len);
}
void sendCommand(String commandStr, int len) {
uint16_t command[len];
stringToIntValues(commandStr, command, ',' );
IrSender.sendRaw(command, len, KHZ);
}
void stringToIntValues(String str, uint16_t value[], char delim) {
int k = 0;
int j = 0;
char text[8];
for (int i = 0; i <= str.length(); i++) {
char c = str.charAt(i);
if ( c == delim || i == str.length() ) {
text[k] = '\0';
value[j] = atoi(text);
j++;
k = 0;
} else {
text[k] = c;
k++;
}
}
}
void setup(void) {
Serial.begin(115200);
Wire.begin(I2C_SDA, I2C_SCL);
init_aht25();
connectWifi();
IrSender.begin();
}
void loop() {
update_aht25();
sendSensorValues();
delay(60 * 1000);
}
プログラム説明
rootCACertificate
サーバサイドはAWS上で動いているため、SSLでの通信のために、ルート証明書をHTTPクライアントに設定する必要があります。
詳しくはAWS IoT Core サーバー認証をご覧ください。
connectWifi
WiFiに接続します。YOUR_WIFI_SSIDとYOUR_WIFI_PASSWORDを変更してください。
sendSensorValues
センサデータを送信します。通信先を変更してください。
センサデータを送信した結果、サーバより赤外線データを受信した際は、sendCommandを呼び出して、対象の機器を操作します。
stringToIntValues
サーバからの赤外線データはカンマ区切りの文字列となっているため、IrSender.sendRawに引数として渡せるようにuint16_t型の配列に変換します。
おわりに
全部で5記事と長くなってしまいましたが、赤外線通信は多くの家電で使われているため、ハックできると汎用性が高く、生活を豊かにできると思います。是非お試しあれ!