UE4　初めの一歩　M5stack-Wifi 接続

## UE4を学習して初めて公開した映像です 
　　　　　　　　　　　　　　　　　　　　　　　　　　　　Dmx-Input-Wifi　2021/03/23

https://youtu.be/BDmcKNjoYQ4

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/72dece7a-e505-8a37-c460-6c060e0b7937.png)

#### (M5stack-Wifi-Udp) --> (Python-Udp-Aetnet)  --> ( UE4-dmx-input )
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378482/0096f4c0-a662-674a-9d31-4dddc26032db.png)

#### M5stack-joystick-Arduino
```C
#include <Adafruit_NeoPixel.h>
#include <WiFi.h>
#include <WiFiUDP.h>
#include <M5Stack.h>

#define FACE_JOY_ADDR 0x5e
#define M5STACK_FIRE_NEO_NUM_LEDS 10
#define M5STACK_FIRE_NEO_DATA_PIN 15

const char ssid[] = "xxxxxx"; //WiFIのSSIDを入力
const char pass[] = "xxxxxx"; // WiFiのパスワードを入力

WiFiUDP wifiUdp; 
const char *pc_addr = "192.168.0.7";  //"192.168.0.6";
const int pc_port = 50007; //送信先のポート
const int my_port = 50008;  //自身のポート

const int bx = 240;//ABC bottan
const int by = 200;

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(M5STACK_FIRE_NEO_NUM_LEDS, M5STACK_FIRE_NEO_DATA_PIN, NEO_GRB + NEO_KHZ800);
uint8_t x_data_L;
uint8_t x_data_H;
uint16_t x_data;
uint16_t x_d_bk;
uint8_t y_data_L;
uint8_t y_data_H;
uint16_t y_data;
uint16_t y_d_bk;
uint8_t button_d;
uint8_t button_b;
uint16_t cou;
char data[100];

void Led(int indexOfLED, int r, int g, int b){
  Wire.beginTransmission(FACE_JOY_ADDR);
  Wire.write(indexOfLED);
  Wire.write(r);
  Wire.write(g);
  Wire.write(b);
  Wire.endTransmission();
}

void Led2(int r, int g, int b){
  pixels.begin(); 
  static int pixelNumber=0;// = random(0, M5STACK_FIRE_NEO_NUM_LEDS - 1);
  for (int i = 0; i < 10 ;i++)
  {
    if((i==0)|(i==9)){
      pixels.setPixelColor(pixelNumber, pixels.Color(r,g,b));     
    }else{
      pixels.setPixelColor(pixelNumber, pixels.Color(0,0,0));     
    }
    pixelNumber++;
  }
  pixels.show();
}

void Init(){
  Wire.begin();
  for (int i = 0; i < 256; i++)
  {
    Wire.beginTransmission(FACE_JOY_ADDR);
    Wire.write(i % 4);
    Wire.write(random(256) * (256 - i) / 256);
    Wire.write(random(256) * (256 - i) / 256);
    Wire.write(random(256) * (256 - i) / 256);
    Wire.endTransmission();
    delay(2);
  }
  Led(0, 0, 0, 0);
  Led(1, 0, 0, 0);
  Led(2, 0, 0, 0);
  Led(3, 0, 0, 0);
  Led2(0,1,1);
}

void setup() {
  M5.begin();
  M5.Power.begin();
  M5.Lcd.setTextSize(2);
  M5.Lcd.clear();
  WiFi.begin(ssid, pass);
  while( WiFi.status() != WL_CONNECTED) {
    delay(500); 
    M5.Lcd.print("."); 
  }  
  M5.Lcd.println("WiFi connected");
  M5.Lcd.println("");
  M5.Lcd.print("IP = ");
  M5.Lcd.println(WiFi.localIP());
  wifiUdp.begin(my_port);
  M5.Lcd.println("");
  M5.Lcd.setTextSize(3);
  Init();
  cou=0;
}

void loop() {
  M5.update();
  // if you want to use Releasefor("was released for"), use .wasReleasefor(int time) below
  if (M5.BtnA.wasReleased() || M5.BtnA.pressedFor(1000, 200)) {
    M5.Lcd.setCursor(bx,by);
    M5.Lcd.print('A');
    Led2(1,0,0);
  } else if (M5.BtnB.wasReleased() || M5.BtnB.pressedFor(1000, 200)) {
    M5.Lcd.setCursor(bx,by);
    M5.Lcd.print('B');
    Led2(0,1,0);
  } else if (M5.BtnC.wasReleased() || M5.BtnC.pressedFor(1000, 200)) {
    M5.Lcd.setCursor(bx,by);
    M5.Lcd.print('C');
    Led2(0,0,1);
  }
  Wire.requestFrom(FACE_JOY_ADDR, 5);
  if (Wire.available()) {
    
    y_data_L = Wire.read();
    y_data_H = Wire.read();
    x_data_L = Wire.read();
    x_data_H = Wire.read();
    
    button_d = Wire.read();// Z(0: released 1: pressed)
    
    x_data = x_data_H << 8 |x_data_L;
    y_data = y_data_H << 8 |y_data_L;

    if (x_data > 600){
      Led(2,  0, 0, 50);
      Led(0, 0, 0, 0);
    }
    else  if (x_data < 400){
      Led(0,  0, 0, 50);
      Led(2, 0, 0, 0);
    }else{
      x_data=518;
      Led(0,  0, 0,0);
      Led(2, 0, 0, 0);
    }
  
    if (y_data > 600) {
      Led(3,  0, 0, 50);
      Led(1, 0, 0, 0);
    }
    else if (y_data < 400){
      Led(1,  0, 0, 50);
      Led(3, 0, 0, 0);
    }else{
      y_data=540;
      Led(1,  0, 0, 0);
      Led(3, 0, 0, 0);
    }

    if((x_data!=x_d_bk)|(y_data!=y_d_bk)|(button_b!=button_d)){
      x_d_bk=x_data; y_d_bk=y_data;button_b=button_d;
      sprintf(data,"x:%d y:%d b%d %02d\n",x_data,y_data,button_d,cou);
      Serial.print(data);
      wifiUdp.beginPacket(pc_addr, pc_port);
      //wifiUdp.write(data);
      for (int i = 0; i < 17 ;i++){
        wifiUdp.write(data[i]);
      }
      wifiUdp.endPacket();
      if(cou<99){cou++;}else{cou=0;}
    }
    M5.Lcd.setCursor(0,100);    
    M5.Lcd.println(data);

    if(button_d==0){
      //終了コマンド送信
      wifiUdp.beginPacket(pc_addr, pc_port);
      sprintf(data,"x:%d y:%d b%d %02d\n",x_data,y_data,button_d,cou);
      Serial.print(data);
      wifiUdp.beginPacket(pc_addr, pc_port);
      for (int i = 0; i < 17 ;i++){
        wifiUdp.write(data[i]);
      }
      //wifiUdp.write('&');
      wifiUdp.endPacket();
      delay(500);
    }
  }
  delay(100);
  //wifiUdp.endPacket();
}
```

#### パソコンでUDP-DMX-->Art-net変換しています（Python）
Unreal Engine DMX Art-net Input Wifi stick

```python
# -*-coding:utf-8-*-
# 2021 2/4
import sys
from socket import *
import time
import numpy as np

packet = bytearray()
pack = np.zeros((512),dtype = np.byte)
DMX_Universe = 0
tx_ip0 = '192.168.0.5'
tx_ip1 = '192.168.0.7'
to_send_addr0 = (tx_ip0, 6454)
to_send_addr1 = (tx_ip1, 6454)
Udp = socket(AF_INET, SOCK_DGRAM)

pan = np.zeros((8),dtype = np.uint16)
til = np.zeros((8),dtype = np.uint16)

dim_d = 0xFFFF
dim2d = 0xFFFF
sel0j = 0
sel_j = 0
sel_b = 0
sel_n = 0
#pack[2]= 0xff & til_d>>8
#pack[3]= 0xff & til_d

#これがないと文字を入力することができません。
def func(v):
    var1.set(var1.get() + v)

def pack_put():
        #player.note_on(64, 127)
    #1  ID[8]  Int8  -  Array of 8 characters, the final character is a null termination. 
    #                   Value = puthon ‘A’ ‘r’ ‘t’ ‘-‘ ‘N’ ‘e’ ‘t’ 0x00 
    packet.extend(map(ord, "Art-Net"))
    packet.append(0x00)          # Null terminate Art,-Net
    #2  OpCode  Int 16  -  The OpCode defines the class of data following 
    #                      ArtPoll within this UDP packet. 
    #                      Transmitted low byte first. See Table 1 for the 
    #                      OpCode listing. Set to OpPoll. 
    packet.extend([0x00, 0x50])  # Opcode ArtDMX 0x5000 (Little endian)
    #3  ProtVerHi  Int8  -  High byte of the Art-Net protocol revision number. 
    packet.append(0x00)          # Null terminate Art-Net
    #4  ProtVerLo  Int8  - Low byte of the Art-Net protocol revision number. 
    #                      Current value 14. Controllers should 
    #                      ignore communication with nodes using a protocol version lower than 14.  
    #packet.extend([0x00, 0x0e])  # Protocol version 14
    packet.append(0x0e)           # Protocol version 14
    packet.append(0x1f)           # Protocol version 14
    packet.append(0x00)           # Protocol version 13
    packet.append(DMX_Universe)   # Protocol version 14
    packet.append(0x00)           # Protocol version 15
 
    #https://www.isc.meiji.ac.jp/~mizutani/python/intro6_python.html
    #"https://www.aipacommander.com/entry/2017/12/27/155711
    #5  TalkToMe  Int8  -  Set behaviour of Node 
    #   7-5  Unused, transmit as zero, do not test upon receipt.  __sequence_counter)  Sequence, 
    #   4   0 = Enable VLC transmission. 
    #       1 = Disable VLC transmission. 
    #   3   0 = Diagnostics messages are broadcast. (if bit 2). 
    #       1 = Diagnostics messages are unicast. (if bit 2). 
    #   2   0 = Do not send me diagnostics messages. 
    #       1 = Send me diagnostics messages. 
    #   1   0 = Only send ArtPollReply in response to an ArtPoll or ArtAddress. 
    #       1 = Send ArtPollReply whenever Node conditions change. This selection allows the 
    #           Controller to be informed of changes without the need to continuously poll. 
    #   0   0 = Deprecated.  
    packet.append(0x02)                 # Physical
    #6  Priority  Int8  -  The lowest priority of diagnostics message that should be sent. See Table 5. 
    packet.append(0x00)
    cou=0
    ccc=0
    #with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as udp:


def out_put():
    global pack
    global pan
    global til
    for n in range(0,2): 
        pack[n*25+0]= 0xff & pan[n]>>8
        pack[n*25+1]= 0xff & pan[n]
        pack[n*25+2]= 0xff & til[n]>>8
        pack[n*25+3]= 0xff & til[n]
        pack[n*25+4]= 255
        pack[n*25+5]= 255
        pack[n*25+6]= 255
        pack[n*25+7]= 255
        pack[n*25+8]= 255 #CTC0 255
        pack[n*25+9]= 0
        pack[n*25+10]= 0
        pack[n*25+11]= 0
        pack[n*25+12]= 0
        pack[n*25+13]= 0
        pack[n*25+14]= 0
        pack[n*25+15]= 0
        pack[n*25+16]= 0
        pack[n*25+17]= 127 #iris
        pack[n*25+18]= 255 #zoom
        pack[n*25+19]= 0xff
        pack[n*25+20]= 0xff
        pack[n*25+21]= 0xff & dim_d>>8 #Dim
        pack[n*25+22]= 0xff & dim_d    #Dim_F
        pack[n*25+23]= 0xff
        pack[n*25+24]= 0xff
    data = pack.tostring()
    #Udp.sendto(packet + data, to_send_addr0)
    Udp.sendto(packet + data, to_send_addr1)
    Udp.sendto(packet + data, to_send_addr0)

def put_jpy(dp,dt):
    global pack
    global pan
    global til
    n = 0
    if sel_n == 0:
        n = 0
    else:
        n = 1
    if (dp>0) & ((dp+pan[n])<0xffff):
        pan[n]= pan[n] + dp
    if (dp<0) & ((dp+pan[n])>0):
        pan[n]= pan[n] + dp
    if (dt>0) & ((dt+til[n])<0xffff):
        til[n]= til[n] + dt
    if (dt<0) & ((dt+til[n])>0):
        til[n]= til[n] + dt
    pack[n*25+0]= 0xff & pan[n]>>8
    pack[n*25+1]= 0xff & pan[n]
    pack[n*25+2]= 0xff & til[n]>>8
    pack[n*25+3]= 0xff & til[n]
    #print(f"{dp}:{dt}-{pack[n+0]}:{pack[n+1]}")

    
def joy_put(joy_x,joy_y):
    mn=5
    dp = 0
    dt = 0
    x = int(joy_x -520)/1
    y = int(joy_y -538)/1
    #print(x)
    #print(y)
    if (x>mn)|(y>mn)|(x<-mn)|(y<-mn):
        dp = int(x/1)
        dt = int(y/1)
        put_jpy(dp,dt)
        out_put()
        time.sleep(0.005)

def main():
    global sel0j
    global sel_j
    global sel_b
    global sel_n
    global pack
    global pan
    global tilpython
    joy_x=520
    joy_y=538
    pan[0]= 0x8000
    til[0]= 0xb000
    pan[1]= 0x8000
    til[1]= 0xb000
    pack_put()
    print("start network")
    # ホスト名を取得、表示
    host = gethostbyname(gethostname())
    #print(host)
    #ipアドレスを取得、表示
    SrcIP  = gethostbyname(gethostbyname(host))
    #addr = ("192.168.0.7", 50007)  # 192.168.0.9
    addr = (SrcIP, 50007)  # 192.168.0.9

    print("network setup started")
    UDPSock = socket(AF_INET, SOCK_DGRAM)
    UDPSock.settimeout(0.0001)
    print("Connected !!")
    print("Network info -->" + str(addr))
    UDPSock.bind(addr) 

    
    print("setup finished")

    while True:
        joy_put(joy_x,joy_y)
        try:
            UDPSock.settimeout(0.0001)
            (dat, addr) = UDPSock.recvfrom(1024)
        except timeout:
           continue
        if addr !=0:
            if len(dat)>13 :
                str_data = dat.decode('utf-8')
                #print(f"from{addr}--> {str_data}")
                #print(str_data)
                #print("end!")
                #Udp.sendto(packet + data, to_send_addr1)
                if (dat[0]==120)&(dat[6]==121):
                    #print(data[15:17]) #cou
                    joy_x = int(dat[2:5])    #x
                    joy_y = int(dat[8:11])   #y
                    sel_b = int(dat[12])-96  #b
                    sel_j = int(dat[13])-48  #b
                    if (sel0j != sel_j) & (sel0j == 1) &( sel_j == 0):
                        if sel_n < 1:
                            sel_n = sel_n +1
                        else:
                            sel_n = 0
                    sel0j = sel_j
                    if sel_b>9:
                        sel_b=0
                    #print(f"{sel_n}:{joy_x}-{joy_x}:{sel_b}")
                    #print(f"{joy_x}-{joy_x}_{sel_j}:{sel_b}-{str_data}")
if __name__ == "__main__":
    main()

```
####  UE4のプログラムは以下　参考にさせていただきました。ありがとうございました。

https://qiita.com/xxJulexx/items/6e8742d58511ad925f52

https://qiita.com/oOtanl/items/1a86cd5b53ade4e9920d