0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

赤外線リモコンを自作する - その5クライアント編

Last updated at Posted at 2022-10-20

目次

  1. 赤外線リモコンを自作する - その1データ解析編
  2. 赤外線リモコンを自作する - その2データ送信編
  3. 赤外線リモコンを自作する - その3温度/湿度センサー編
  4. 赤外線リモコンを自作する - その4サーバサイド編
  5. 赤外線リモコンを自作する - その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記事と長くなってしまいましたが、赤外線通信は多くの家電で使われているため、ハックできると汎用性が高く、生活を豊かにできると思います。是非お試しあれ!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?