WeMosを使ってみる

RaspberryとのSocket通信(Raspberry→WeMos)


前回、Raspberry側がサーバー、WeMos側がクライアントのSocket通信 を紹介しました。
そこで、今回はRaspberry側がクライアント、WeMos側がサーバーのSocket通信を紹介します。

【WeMos側】

WeMos側のスケッチは以下の通りです。
クライアントから受信した大文字を小文字に変換して送り返す単純なものです。
サーバー側なのでIPアドレスを固定にしています。
相手側(今回はRaspberry)とポート番号(今回は9876番を使用)を合わせて下さい。
ここが合っていないと正しく通信できません。
赤字の部分は自分の環境に合わせて変更してください。

/*
 *  This sketch receive a message from a TCP client
 *
 */

#include <ESP8266WiFi.h>

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

// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(9876);

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

// config static IP
  Serial.println();
  Serial.println();
  IPAddress ip(192, 168, 111, 90);
  IPAddress gateway(192, 168, 111, 1);
  Serial.print(F("Setting static ip to : "));
  Serial.println(ip);
  IPAddress subnet(255, 255, 255, 0);
  WiFi.config(ip, gateway, subnet);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
 
  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.println(WiFi.localIP());
}

void loop() {
  char smsg[128];

  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
 
  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }
 
  // Read the first line of the request
  String rmsg = client.readStringUntil('\0');
  Serial.print(rmsg);
  client.flush();

  // Prepare the response
  memset(smsg,0,sizeof(smsg));
  for(uint32_t i = 0; i < rmsg.length(); i++) {
    if(isalpha(rmsg[i])) {
      smsg[i] = toupper(rmsg[i]);
    } else {
      smsg[i] = rmsg[i];
    } // end if
  } // end for

  Serial.print("->");
  Serial.println(smsg);

  // Send the response to the client
  client.print(smsg);
  delay(1);
  Serial.println("Client disonnected");

  // The client will actually be disconnected
  // when the function returns and 'client' object is detroyed
}

このスケッチを実行するとArduino-IDEのシリアルモニターはこのように表示されます。
固定のIPアドレスがアサインされています。


【Raspberry側】

以下のコード(client.c)をコンパイルして実行します。
コンパイルは単純に「cc -o client client.c」で、実行は「sudo ./client」です。

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>
#include <limits.h>

int retryTotal=0;

#define PORT 9876 //サーバープログラムとポート番号を合わせてください

int connect2(struct sockaddr_in * dstAddr, int dstAddrLen) {
  int dstSocket;
  int retry = 0;
  int retryMax = 10;
  time_t start_time, end_time;
  double dtime;

  while (1) {
    //ソケットの生成
    dstSocket = socket(AF_INET, SOCK_STREAM, 0);
 
    //接続
    write(1,"Connecting...",13);
    time( &start_time );
    if (connect(dstSocket, (struct sockaddr *)dstAddr, dstAddrLen) == 0) return(dstSocket);
    time( &end_time );
    dtime=difftime( end_time, start_time );
    retry++;
    printf("接続できませんでした retry=%d difftime=%f\n",retry,dtime);
    retryTotal++;
    close(dstSocket);
    if (retry > retryMax) return(-1);
    sleep(10);
  }
}

int main(int argc, char **argv){
  // IP アドレス,ソケット,sockaddr_in 構造体
  char destination[32];
  int dstSocket;
  struct sockaddr_in dstAddr;

  //struct sockaddr_in addr;
  struct hostent *hp;
  char  buf[1024];
  int number = 0;
  int numrcv;
  int retry = 0;
  int loopMax;
  int loopCnt;

  time_t start_time=0, end_time;
  double dtime;

  loopMax=INT_MAX;
  if (argc == 2) {
    loopMax=atoi(argv[1]);
  }
  // 相手先アドレスの入力と送る文字の入力
  printf("サーバーマシンのIPは?:");
  scanf("%s", destination);
 
  //sockaddr_in 構造体のセット
  bzero((char *)&dstAddr, sizeof(dstAddr));
  dstAddr.sin_family = AF_INET;
  dstAddr.sin_port = htons(PORT);
 
  hp = gethostbyname(destination);
  bcopy(hp->h_addr, &dstAddr.sin_addr, hp->h_length);

  for(loopCnt=0;loopCnt<loopMax;loopCnt++) {
//  while (0) {
    dstSocket = connect2(&dstAddr, sizeof(dstAddr));
    printf("dstSocket=%d\n",dstSocket);
    if (dstSocket < 0) {
      printf("%s に接続できませんでした\n",destination);
      return(-1);
    }
    printf("%s に接続しました\n",destination);
    if (start_time == 0) time( &start_time );
 
    memset(buf,0,sizeof(buf));
    sprintf(buf,"data from raspberry %05d",number);
    number++;
    printf("Send=[%s]",buf);
    //パケットの送信
    write(dstSocket, buf, strlen(buf));
    //パケットの受信
    memset(buf,0,sizeof(buf));
    numrcv = read(dstSocket, buf, 1024);
    printf("→Recv=[%s]\n",buf);
    close(dstSocket);
    sleep(5);
  } // end for
  time( &end_time );
  dtime=difftime( end_time, start_time );
  printf("loop=%d difftime=%f[sec] %f[min] retry=%d\n",loopMax,dtime,dtime/60,retryTotal);
  return(0);
}

プログラムを起動すると以下の表示となりますので、サーバ側(WeMos)のIPアドレスを指定します。



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


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



次は、MQTTを使った通信を紹介します。

続く....