WeMosを使ってみる

RaspberryとのMQTT通信(WeMos→Raspberry)+SD-CARD


WeMos→RaspberryのMQTT通信で、必要な情報(APのSSIDやパスワードなど)をSD-CARDから取り込んでみます。
SD-CARDには「config.txt」のファイル名で以下を書き込んでおきます。
ssid=APのSSID
password=APのパスワード
mqtt_server=MQTTサーバ名、またはIPアドレス
topic=nopnop2002/test1
message=power on

使用したSD-CARDリーダーは標準サイズのSD-CARDリーダーで、WeMosとはSPIで接続します。
SD-Card
Reader
WeMos
MOSI D7(GPIO_13)(*1)
MISO D6(GPIO_12)(*1)
CLK D5(GPIO_14)(*1)
CS D0(GPIO_16)(*2)
VSS 3.3V
GND GND

(*1)このピンは変更できません。
(*2)このピンは自由に変更することができます。

WeMosのスケッチは以下の通りです。
ファイルが無い時などのエラー処理はかなり省略しています。
/*
 Basic ESP8266 MQTT example

 The circuit:
  * SD card attached to SPI bus as follows:
 ** MOSI - D7(GPIO_13)
 ** MISO - D6(GPIO_12)
 ** CLK  - D5(GPIO_14)
 ** CS   - D0(GPIO_16)

*/
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <SPI.h>
#include <SD.h>

File myFile;

WiFiClient espClient;
PubSubClient client(espClient);

char myip[20];  // connect idとして使う
long lastTime = 0;
const int chipSelect = 16;
char ssid[64];
char password[64];
char mqtt_server[64];
char topic[64];
char message[64];

int ReadConfig(char * id, char * value) {
  char buf[2];
  char ch;
  char line[64];
  int pos=0;
  int idlen;

  idlen=strlen(id);
 
  myFile.seek(0);
  while (myFile.available()) {
    myFile.read(buf,1);
    ch = buf[0];
    if (ch == 0x0d) {
    } else if (ch == 0x0a) {
      if (strncmp(line,id,idlen) == 0) {
        strcpy(value,&line[idlen]);
        return 1;
      }
      pos=0;
    } else {
      line[pos++]=ch;
      line[pos]=0;
    }
  }
  return 0;
}

void DumpConfig(char * id, char * value) {
  Serial.print(id);
  Serial.print("[");
  Serial.print(value);
  Serial.println("]"); 
}

void MissConfig(char * id) {
  Serial.print(id);
  Serial.println(" is NOT found");
}

void setup_wifi() {
  IPAddress _address;

  delay(10);

  // We start by connecting to a WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Wait for WiFi...");
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  _address = WiFi.localIP();
  String str = String(_address[0]);
  str += ".";
  str += String(_address[1]);
  str += ".";
  str += String(_address[2]);
  str += ".";
  str += String(_address[3]);
  str.toCharArray(myip, 20);
  Serial.print("myip=");
  Serial.println(myip);
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
//    if (client.connect(ssid)) {
    if (client.connect(myip)) {
      Serial.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic", "hello world");
      // ... and resubscribe
      client.subscribe("inTopic");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  delay(10);
  Serial.begin(9600);

  Serial.print("Initializing SD card...");
  if (!SD.begin(chipSelect)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  // open the file for reading:
  myFile = SD.open("config.txt");
  if (myFile) {
    Serial.println("config.txt:");

    // read from the file until there's nothing else in it:
    if (ReadConfig("ssid=",ssid)) {
      DumpConfig("ssid=",ssid);
    } else {
      MissConfig("ssid=");
    }
    if (ReadConfig("password=",password)) {
      DumpConfig("password=",password);
    } else {
      MissConfig("passowrd=");
    }
    if (ReadConfig("mqtt_server=",mqtt_server)) {
      DumpConfig("mqtt_server=",mqtt_server);
    } else {
      MissConfig("mqtt_server=");
    }
    if (ReadConfig("topic=",topic)) {
      DumpConfig("topic=",topic);
    } else {
      MissConfig("topic=");
    }
    if (ReadConfig("message=",message)) {
      DumpConfig("message=",message);
    } else {
      MissConfig("message=");
    }
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening config.txt");
  }

  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {
  static int counter=0;

  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  long now = millis();
  if (now - lastTime > 1000) {
    lastTime = now;
    counter++;
    if (counter > 10) {
      Serial.print("Publish message: ");
      Serial.print(message);
      Serial.print("/Publish topic: ");
      Serial.println(topic);
      client.publish(topic, message);
      counter=0;
    }
  }
}

このスケッチを実行するとSD-CARDから読み込んだ情報でサーバーに接続し、
SD-CARDから読み込んだトピックとメッセージをPublishします。

topicとmessageだけが異なるPublisherをたくさん作りたい場合、
1つのスケッチで、たくさんのPublisherを作ることができます。

続く....