WeMosを使ってみる

RaspberryとのSocket通信(WeMos→Raspberry)


最初に、Raspberry側がサーバー、WeMos側がクライアントのSocket通信を紹介します。

【Raspberry側】

以下のコード(server.c)をコンパイルして実行します。
クライアントから受信した大文字を小文字に、小文字を大文字に変換して送り返す単純なものです。
コンパイルは単純に「cc -o server server.c」で、実行は「sudo ./server」です。
なお、以下のコードはパケット分割に対応していません。
パケット分割に対応したコードはこちらで公開しています。
/*
 Simple Socket Server
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <limits.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

//待ち受けるポート番号
//クライアントプログラムとポート番号を合わせてください
int PORT = 9876;

int main(int argc, char **argv){
  int i;
  int srcSocket; //自分
  int dstSocket; //相手
  // sockaddr_in 構造体
  struct sockaddr_in srcAddr;
  struct sockaddr_in dstAddr;
  socklen_t dstAddrSize;
  // 各種パラメータ
  int numrcv;
  char buf[1024];
  int loopMax;
  int loopCnt;

  time_t start_time=0, end_time;
  double dtime;

  loopMax=INT_MAX;
  if (argc > 1) {
    loopMax=atoi(argv[1]);
  }
  if (argc == 3) {
    PORT = atoi(argv[2]);
  }
  printf("PORT=%d\n",PORT);

  // sockaddr_in 構造体のセット
  //bzero((char *)&srcAddr, sizeof(srcAddr));
  memset((char *)&srcAddr, 0, sizeof(srcAddr));
  srcAddr.sin_port = htons(PORT);
  srcAddr.sin_family = AF_INET;
  srcAddr.sin_addr.s_addr = INADDR_ANY;

  // ソケットの生成(ストリーム型)
  srcSocket = socket(AF_INET, SOCK_STREAM, 0);
  // ソケットのバインド
  bind(srcSocket, (struct sockaddr *)&srcAddr, sizeof(srcAddr));
  // 接続の許可
  listen(srcSocket, 5);

  for(loopCnt=0;loopCnt<loopMax;loopCnt++) {
    // 接続の受付け
    printf("接続を待っています\nクライアントプログラムを動かして下さい\n");
    dstAddrSize = sizeof(dstAddr);
    dstSocket = accept(srcSocket, (struct sockaddr *)&dstAddr, &dstAddrSize);
    printf("%s から接続を受けました\n",inet_ntoa(dstAddr.sin_addr));
    if (start_time == 0) time( &start_time );

    while(1) { // クライアントがSocketをクローズしてからこちらもクローズする
      //パケットの受信
      memset(buf,0,sizeof(buf));
      numrcv = read(dstSocket, buf, 1024);
      printf("numrcv=%d\n",numrcv);
      if(numrcv ==0 || numrcv ==-1 ){ // client close socket
        close(dstSocket); break;
      }
      printf("Recv=[%s]",buf);
      for (i=0; i< numrcv; i++){ // bufの中の小文字を大文字に変換
//        if(isalpha(buf[i])) buf[i] = toupper(buf[i]);
        if(isalpha(buf[i])) {
          if(islower(buf[i])) {
            buf[i] = toupper(buf[i]);
          } else {
            buf[i] = tolower(buf[i]);
          }
        }
      }
      // パケットの送信
      write(dstSocket, buf, numrcv);
      printf("->Send=[%s]\n",buf);
    } // end while
  } // end for
  time( &end_time );
  dtime=difftime( end_time, start_time );
  printf("loop=%d difftime=%f[sec] %f[min]\n",loopMax,dtime,dtime/60);
  return(0);
}

プログラムを起動すると以下の表示となります。


【WeMos側】

WeMos側のスケッチは以下の通りです。
相手側(今回はRaspberry)とポート番号(今回は9876番を使用)とIPアドレスを合わせて下さい。
ここが合っていないと正しく通信できません。
赤字の部分は自分の環境に合わせて変更してください。
/*
 *  This sketch sends a message to a TCP server
 *
 */

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

const char* ssid = "アクセスポイントのSSID";
const char* password = "アクセスポイントのパス ワード";

ESP8266WiFiMulti WiFiMulti;

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

    // We start by connecting to a WiFi network
    WiFiMulti.addAP(ssid, password);

    Serial.println();
    Serial.println();
    Serial.print("Wait for WiFi...");

    while(WiFiMulti.run() != WL_CONNECTED) {
        Serial.print(".");
        delay(500);
    }

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

    delay(500);
}


void loop() {
    const uint16_t port = 9876;
    const char * host = "192.168.111.101"; // ip or dns
    static int number=0;
   
   
    Serial.print("connecting to ");
    Serial.println(host);

    // Use WiFiClient class to create TCP connections
    WiFiClient client;

    if (!client.connect(host, port)) {
        Serial.println("connection failed");
        Serial.println("wait 5 sec...");
        delay(5000);
        return;
    }

    // This will send the request to the server
    char smsg[40];
    sprintf(smsg,"data from WeMos %05d",number++);
    client.print(smsg);
   

    //read back one line from server
    String line;
    line = client.readStringUntil('\0');
    Serial.print("[");
    Serial.print(smsg);
    Serial.print("]->[");
    Serial.print(line);
    Serial.println("]");
    Serial.println("closing connection");
    client.stop();
   
    Serial.println("wait 5 sec...");
    delay(5000);
}

このスケッチを実行するとRaspberry側の表示は以下のようになります。


Arduino-IDEのシリアルモニターはこのように表示されます。


しばらく放置しましたが、順調に動いています。


次は、Raspberryがクライアント、WeMosがサーバーのSocket通信を紹介します。

続く....